CreateArtTechnology / Blog

  • 类的生命周期加载主要是将类从一个文件或流转化为Class对象的过程。
    读取类的定义字节流将类的定义结构保存到方法区生成一个java.lang.Class对象作为类的数据访问入口
    验证主要是确保类定义完整且符合虚拟机要求。
    准备主要是分配内存并设置static属性即静态变量的默认值和final static属性即常量的初始值。这个好理解,常量不可变,可以提前预设;静态变量在类初始化时完成。
    解析将类文件中常量池的符号引用替换为直接引用。
    类文件编译后数据分离了,只能使用符号引用类文件加载后,数据、方法等在内存中有了物理地址,这样就可以将符号引用与实际位置关联即替换为直接引用
    ......



  • Java内存区域与内存溢出异常JVM运行时数据区
    Java使用的内存大致被划分为5个部分
    程序计数器参考计算机组成原理,程序计数器跟线程是绑定的,因此是线程私有的。虚拟机栈参考计算机组成原理,是运行Java方法时使用的栈,每个静态或非静态方法执行时会创建一个栈帧用于存储方法信息、局部变量(包括基本类型和对象引用,至于引用指向的对象则保存在堆中)等,线程私有。很明显,如果递归层次过深会导致StackOverflowError。本地方法栈运行Native方法时使用的栈,线程私有。方法区也就是Perm Generation,永久代。用于存放已被加载的类信息、每个对象保存的类型数据、常量(Java7开始已不包括字符串常量池)、静态变量等,JVM加载类后将Class文件中定义的常量保存在这里。由于存放的信息基本是常量性质的,因此是非线程私有的。堆保存对象实例,非线程私有。如果持有对象过多内存不足会导致OutOfMemoryError。
    对象的定位通过句柄部分虚拟机实现中,非常量或静态变量的引用(也就是方法栈帧中保存的局部变量)指向的是句柄池中的指针,而句柄池中的指针指向的是真正的对象实例数据(堆中)或对象类型数据(方法区中)。这种方式的好处是引用直接指向的句柄池地址是不变的,而在句柄池中的指针由于GC的移动或复制等可能经常变化。
    句柄访问
    通过直接指针引用直接指向目标对象的对象实例数据(堆中)或对象类型数据(方法区中),在对象访问非常频繁的情况下减少一次寻址开销。HotSpot使用到的是直接指针定位。
    ......

    共8张