Java虚拟机

  

内存分配以及回收

  

Java虚拟机运行时数据区,分为以下几个模块,包含所有线程共有的数据区和线程单独享有的数据区。
癑ava虚拟机"

  
      <李>程序计数器:字节码行号,通过这个计数器来选取下一条需要执行的指令,线程独有。   <李>虚拟机栈:线程私有。方法在执行时会创建一个栈帧,用于存储局部变量表等。局部变量表中存放了编译器可知的基本数据类型,对象引用,returnAddress(指向了一条字节码指令的地址)   <李>本地方法栈:与虚拟机栈类似,只不过这个地方是为本地方法服务。   <李>堆:线程共用。存放对象实例。   <李>方法区:线程共用。存储已经被虚拟机加载的类信息,常量、静态变量等。   <李>运行时常量池:用于存放编译期生成的字面量和符合引用。字面量就是我们所说的常量概念,如文本字符串,被声明为最终的常量值等。符号引用是一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可,一般包括下面三类常量:类和接口的全限定名,字段的名称和描述符,方法的名称和描述符。   
  <人力资源/>   

癑ava虚拟机”
JVM通过根搜索算法来判定对象是否可以回收,一般对于不能从根(GC根)搜索到的对象是可以被回收的。
能够被作为GC根对象有:虚拟机栈本地变量表中引用的对象(也就是正在调用的方法中引用的),方法区中静态属性或常量引用的对象,本地方法栈引用的对象。

  <人力资源/>   

可以被回收的对象并不一定绝对被回收,JVM先做一次标记和筛选,把那些覆盖了完成方法的对象筛选出来然后触发完成方法,如果在完成方法中对象复活,则不回收,否则回收,且完成方法仅会被触发一次。

  <人力资源/>   

<强>垃圾回收算法

  
      <李>标记——清除:把标记为待回收的对象空间清除,容易造成大量空间碎片;李   <李>复制算法:将内存分为三个区域,一个较大的伊甸园区和两个较小的幸存者区。每次GC都把存活的对象挪到其中一个servivor区,然后把伊甸园全部清除。只对每次GC时存活对象较少时比较有效,适用于新生代;李   <李>标记——整理:把标记后存活的对象向一个方向移动,然后清除其它空间。比较适合老年代。   
  <人力资源/>   

<强>内存分配与回收策略

  
      <李>对象默认优先分配在新生代;李   <李>大对象直接分配到老年代,李   <李>长期存活的对象转移到老年代:虚拟机给每个对象定义一个对象年龄,没发生一次轻微的GC,年龄就增加一次,超过默认值之后就会进入到老年代。   <李>动态对象年龄判定:对象不一定是必须到了默认年龄才能进入老年代,如果一个伊甸园区中所有相同年龄的对象大小综合超过伊甸园一半的空间,那么大于等于这个年龄的对象也会进入老年代。   
  

类文件结构

  

类文件是二进制组成的,类有两种数据类型:无符号数和表。
无符号数是基础数据类型,其中u1表示1个字节,u2表示2个字节(一个字节8个,而4个比特可以表示1个16进制的数,也就是说1个字节可以用2个16进制数表示);
表是由多个无符号数或其它表构成的。
癑ava虚拟机"

  
      <李>魔法是4个字节,也就是8个16进制数,固定为CAFEBABE;后面分别是两个版本号。   <李>常量池:跟着版本号之后的就是常量池(字面量和符号引用)。由于无法确认一个类中常量池有多少常量,所有先有一个值来标志有多少个,然后再是常量具体信息。   <李>访问标志:常量池之后跟着的是2个字节的访问标志。需要被标志的内容包括:是否,是否决赛,是否抽象,是类或接口   <李>访问标志之后是类索引(用于确定该类的全限定名),父类索引(用于确定父类的全限定名),接口所有集合(实现的接口可能不止一个)   <李>字段表集合:描述接口或类中声明的变量,包含类变量和实例变量。   <李>方法表集合:描述类或接口中声明的fangfa。   <李>属性表结合:
    代码属性:java方法体中的代码经javac编译后会存储在代码属性中(接口中方法或抽象方法没有代码属性)

    Java虚拟机