JVM学习笔记(一)------基本结构

从Java平台的逻辑结构上来看,我们可以从下图来了解JVM:



 

JVM自身的物理结构



 

在了解JVM的结构之前,让我们先了解一下操作系统的内存基本结构


JVM在操作系统中



 
 为什么jvm的内存是分布在操作系统的堆中呢??因为操作系统的栈是操作系统管理的,它随时会被回收,所以如果jvm放在栈中,那java的一个null对象就很难确定会被谁回收了,那gc的存在就一点意义都莫有了,而要对栈做到自动释放也是jvm需要考虑的,所以放在堆中就最合适不过了。

 

操作系统+jvm的内存布局




 
 从这个图,你应该不难发现,原来jvm的设计的模型其实就是操作系统的模型,基于操作系统的角度,jvm就是个该死的java.exe/javaw.exe,也就是一个应用,而基于class文件来说,jvm就是个操作系统,而jvm的方法区,也就相当于操作系统的硬盘区。而java栈和操作系统栈是一致的,无论是生长方向还是管理的方式,至于堆嘛,虽然概念上一致目标也一致,分配内存的方式也一直(new,或者malloc等等),但是由于他们的管理方式不同,jvm是gc回收,而操作系统是程序员手动释放,所以在算法上有很多的差异,gc的回收算法,估计是jvm里面的经典啊,后面我们也会一点点的学习的。

所谓pc寄存器,无论是在虚拟机中还是在我们虚拟机所寄宿的操作系统中功能目的是一致的,计算机上的pc寄存器是计算机上的硬件,本来就是属于计算机,计算机用pc寄存器来存放“伪指令”或地址,而相对于虚拟机pc寄存器它表现为一块内存(一个字长,虚拟机要求字长最小为32位)虚拟机的pc寄存器的功能也是存放伪指令,更确切的说存放的是将要执行指令的地址,它甚至可以是操作系统指令的本地地址,当虚拟机正在执行的方法是一个本地方法的时候,jvm的pc寄存器存储的值是undefined,所以你现在应该很明确的知道,虚拟机的pc寄存器是用于存放下一条将要执行的指令的地址(字节码流)

当一个classLoder启动的时候,classLoader的生存地点在jvm中的堆,然后它会去主机硬盘上将A.class装载到jvm的方法区,方法区中的这个字节文件会被虚拟机拿来new A字节码(),然后在堆内存生成了一个A字节码的对象,然后A字节码这个内存文件有两个引用一个指向A的class对象,一个指向加载自己的classLoader,如下图。

方法区中的字节码内存块存放了哪个内容呢?


你仔细将这个字节码和我们的类对应,是不是和一个基本的java类惊人的一致?下面你看我贴出的一个类的基本结构。


 

package test;import java.io.Serializable;public final class ClassStruct extends Object implements Serializable {//1.类信息
 //2.对象字段信息
 private String name;
 private int id;
 
 //4.常量池
 public final int CONST_INT=0;
    public final String CONST_STR="CONST_STR";
    
    //5.类变量区
    public static String static_str="static_str";
    
 
 //3.方法信息
 public static final String getStatic_str ()throws Exception{
  return ClassStruct.static_str;
 }}

 
 

当一个程序启动之前,它的class会被类装载器装入方法区执行引擎读取方法区的字节码自适应解析,边解析就边运行(其中一种方式),然后pc寄存器指向了main函数所在位置,虚拟机开始为main函数在java栈中预留一个栈帧(每个方法都对应一个栈帧),然后开始跑main函数,main函数里的代码被执行引擎映射成本地操作系统里相应的实现,然后调用本地方法接口,本地方法运行的时候,操纵系统会为本地方法分配本地方法栈,用来储存一些临时变量,然后运行本地方法,调用操作系统API等等。


 

猜你喜欢

转载自cl-java.iteye.com/blog/2101360