首页 > 代码库 > JVM——Java内存区域相关2
JVM——Java内存区域相关2
一. 对象的创建
在语言层面上,创建对象的方式有克隆、反序列化、new等方法。
1.1 检查类是否被加载
虚拟机遇到一条new指令时,首先去检查这个指令的参数是否能够在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,那必须先执行相应的类加载过程。
1.2 分配内存
- 指针碰撞(Bump the Pointer):同步(CAS或者TLAB),内存碎片问题。
- 空闲列表(Free List)
1.3 初始化为零值(不包括对象头)。
1.4 设置对象信息
这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息,这些信息存放在对象的对象头中。
1.5 执行类的构造函数
二. 可达性分析算法
在主流的商用程序语言都是通过可达性分析来判定对象是否存活。引用技术算法很难解决对象之间的循环引用问题。
这个算法的基本思想是通过一系列称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,就证明此对象是不可用的。
在Java语言中,可作为GC Roots的对象包括下面几种:
- 虚拟机栈(栈帧中的本地变量表)中的引用对象。
- 方法区中的类静态属性引用的对象。
- 方法区中常亮引用的对象。
- 本地方法栈中JNI(即一般说的Native方法)引用的对象。
在可达性分析中不可达的对象,也并不会被立即销毁。要真正宣告一个对象死亡,至少(多??)要经历两次标记过程。覆盖了finalize()方法且没有被调用的类的实例将会被放到一个队列中依次执行finalize()方法。第二次被扫描到该对象就会被真正销毁。
三. 回收方法区
永久代的垃圾回收主要回收两部分内容:废弃常量和无用的类。回收废弃常量与回收Java堆中的对象非常类似。只要这个常量没有被引用,那么必要的话这个常量就会被系统清理出常量池。而要判定一个类是否是“无用的类”的条件就苛刻得多:
- 该类所有的实例都已经被回收,也就是Java堆中不存在该类的任何实例。
- 加载该类的ClassLoader已经被回收。
- 该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。
虚拟机可以对满足了上述3个条件的无用类进行回收,但同时还它也受HotSopt虚拟机提供的-Xnoclassgc参数控制。
在使用大量反射、动态代理、CGLib等ByteCode框架、动态生成JSP以及OSGi这类频繁自定义ClassLoader的场景都需要虚拟机具备类卸载的功能,以保证永久代不会溢出。
JVM——Java内存区域相关2