JVM的内存结构
- 程序计数器:线程私有。代表当前线程所执行字节吗的行号指示器
- 虚拟机栈:线程私有。
- 本地方法栈:线程私有。
- Java堆:线程共享。
-Xms=-Xmx可以避免堆的自动扩展
-XX:+HeapDumpOnOutOfMemoryError可以让虚拟机在内存溢出的时候dump出内存快照。 - 方法区:线程共享。(永久代)
存储已被虚拟机加载的类信息、常量、静态变量等。
运行时常量池是方法区的一部分。 - 直接内存
判定对象是否存活
- 引用计数法
- 给对象添加一个引用计数器,每当有一个地方引用它时,计数加1;
- 引用失效时,计数减1;
- 计数为0时,可被回收。
该方法不能解决对象相互循环引用的问题,即使它们都已失效。 - 可达性分析法
通过一些称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索的路径称为引用链。当一个对象到GC Roots没有任何引用链相连时,认为此对象是不可用的。
可以作为GC Roots的对象包括:
- 虚拟机栈(栈桢中的本地变量表)中引用的对象;
- 方法区类静态属性引用的对象;
- 方法区中常量引用的对象;
- 本地方法栈中JNI引用的对象。
垃圾回收算法
- 标记-清除算法
原理:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。
缺点:容易产生内存碎片。 - 复制算法(现代的虚拟机实现基本都采用这种算法来回收新生代)
原理:先把内存分为大小相等的二个部分,每次只使用其中的一块,当这一块内存回收时,就把还存活的对象规则的复制到另一块内存中,以此循环。
缺点:需要复制,效率降低、浪费空间。 - 标记-整理算法
原理:类似于标记-清除,但后续步骤不是直接对可回收对象进行清理,而是让所有存活对象都向一端移动,然后直接清理掉端边界以外的内存。 - 分代收集算法
原理:根据对象存活周期的不同将内存划分为几块。一般是java堆分为新生代和老年代,这样就可以根据各个年代的特点采用合适的收集算法。
回收方法区
方法区的垃圾回收主要回收两部分:废弃常量 和 无用的类。
-回收废弃常量和java堆中的对象非常类似。当没有对象引用它时即可回收。
-回收无用的类则比较苛刻,需满足:
- 该类所有的实例都已经被回收,即java堆中不存在该类的任何实例。
- 加载该类的ClassLoader已经被回收。
- 该类对应的java.lang.Class对象没有在任何地方被引用。
-- EOF --
网友评论