@wxf
2018-03-10T19:19:07.000000Z
字数 1526
阅读 890
面试系列
JDK1.6-JDK1.7 | JDK1.8 |
---|---|
JDK1.6 | JDK1.7 | JDK1.8 |
---|---|---|
java栈:线程私有,每个方法在执行的同时都会创建一个栈帧用于存放局部变量等。局部变量表[1]存放了编译器可知的各种基本数据类型和对象引用。
本地方法栈:线程私有,和java栈类似,但是它是为Native方法服务的。
程序计数器:线程私有,当前线程所执行的字节码的指示器,用于记录下一条要运行的指令。
堆:线程共享,它是Java开发者需要重点关注的一块区域,因为它会涉及到内存的分配(new关键字,反射等)与回收(回收算法,收集器等)
方法区:线程共享,也叫永久区,在JDK1.6时方法区用于存储已被虚拟机加载的类信息、常量、静态变量等数据。在JDK1.7时常量被存储到堆中了,在JDK1.8时甚至没有了方法区,增加了元空间(本地内存)。
运行时常量池:运行时常量池是方法区的一部分(JDK1.6),用于存储编译器生成的各种字面量和符号引用。
类加载器的作用就是通过一个类的全限定类名来获取描述此类的二进制字节流
加载->检查->准备->解析->初始化->使用->卸载
JVM 类加载机制深入浅出
在Java开发过程中,内存都是由虚拟机进行管理的,不管是申请内存还是释放内存都不需要程序员自己处理。但是如果在高并发情况下遇到了相应瓶颈时,我们就需要对程序进行优化其中垃圾回收就是一个重要关注点。那么下面我们主要探讨如下几个问题:
如何判断对象为垃圾对象
- 引用计数法
- 可达性分析法
如何回收垃圾对象
- 回收策略
- 标记-清除算法
- 复制算法
- 标记-整理算法
- 分代收集算法
- 垃圾回收器
- serial
- parnew
- cms
- g1
何时回收
如何判断对象为垃圾对象
引用计数法
思想:在对象中添加一个引用计数器,当该对象被引用时,计数器加1;当对象引用失效时,计数器减1。
这种方式实现简单判定效率高,但是目前垃圾回收器并没有采用这种方式。
通过代码来查看垃圾回收信息
public class GCTest {
private Object obj;
public static void main(String[] args) {
GCTest gc1 = new GCTest();
GCTest gc2 = new GCTest();
gc1.obj = gc2;
gc2.obj = gc1;
gc1 = null;
gc2 = null;
System.gc();
}
}
打印垃圾回收信息
-verbose:gc (简单信息)
-verbose:gc -XX:+PrintGCDetails (详细日志信息)
可达性分析法
思想:通过GCRoot节点向下搜索,其所走过的这些路径被称为引用链。那么当一个节点没有与引用链相连接的时候就认为该节点是不可用的。
目前主流垃圾回收器都采用可达性分析法进行垃圾对象的判断。
如何回收垃圾对象
回收策略
标记-清除算法
空间问题:会出现越来越多的不连续空间,当再次分配大对象时会影响对象寻址效率。另外如果找不到合适的内存空间会再次触发虚拟机的垃圾回收。
效率问题
复制算法(可以解决标记-清除算法的效率问题)
内存区域划分
图解复制算法(内存浪费的解决方案)
标记-整理算法
分代收集算法
在JDK1.8以后垃圾回收主要回收的是对内存,它是基于分代思想:
注意:在JDK1.6、JDK1.7中堆内存分为新生代、老年代和永久代(方法区)。