ref:http://www.cnblogs.com/ityouknow/p/6482464.html
看了大神:纯洁的微笑的JVM系列篇,发现好多地方还是似懂非懂,理解的并不透彻,jvm的调优部分更是稀里糊涂;
本片主要整理下jvm部分的知识点,方便以后的面试使用,(权且死记硬背了 !>_<!)
jvm的体系梳理
- 类的加载机制
- JVM的内存结构
- GC算法 垃圾回收
- GC分析 命令调优
底部给出思维导图参考
1、类的加载机制
1.1:什么是类的加载:
(1)将类的.class文件以二进制读入到内存,放入运行时数据区的方法区,然后在堆区创建一个java.lang.Class对象,以封装类在方法区的数据结构。
(2)类加载的最终产品是位于堆区的Class对象,该Class对象封装类在方法区的数据结构,并向JAVA程序员提供了访问方法区内数据解耦的接口。
1.2:类的生命周期:
####: 类的生命周期:
#---- 类的加载
|---- 装载(Loading)(为了区分加载,这里称其为装载):查找并导入类的Class文件,在堆区创建java.lang.Class的对象。
|---- 连接过程分为三块:
|---- 验证:文件的格式、元数据、字节码、符号引用验证,确保被装载的类的正确性,该阶段虽然重要但不是必须的;
|---- 准备:为类的静态变量(static)分配内存,并将其初始化为默认值;如 public static int value=3 ,此时value的值是0而不是3;而对于: public static final int value=3 ,该阶段value的值是3,而不是0,可以认为final static 常量在javac的编译期间,为value生成了ConstantValue属性,准备阶段jvm根据ConstantValue的值为value指定值。
|---- 解析:将符号引用转换为直接引用;
|---- 初始化:为类的静态变量,静态代码块等赋予正确的初始值。
#---- 类的使用:new出对象供程序使用。
#---- 类的卸载:执行垃圾回收。
补充问题:
1.2.1:JVM的初始化步骤(初始化过程):
-
- 假如这个类还没有被加载和连接,则程序先加载并连接该类;
- 假如这个类的父类还没有被初始化,则先初始化其直接父类;
- 假如类中有初始化语句,则系统依次执行这些初始化语句。
1.2.2:类的初始化时机:
-
- new创建类的实例时;
- 访问某个类或接口的静态变量,或者对该静态变量赋值;
- 调用类的静态方法;
- 反射(Class.forName("com.wht.Test"));
- 初始化某个类的子类时,父类也会进行初始化;
- JVM启动时被标明为启动类的类
1.2.3:哪几种情况下,JVM会结束生命周期:
1、执行了system.exit();
2、程序正常结束;
3、执行过程中发生异常或错误而终止;
4、操作系统的错误导致JVM的进程终止;
1.3:类加载器
- 启动类加载器:Bootstrap ClassLoader,负责加载JDK\jre\lib目录下或被-Xbootclasspath指定位置处,可悲jvm识别的类库;
- 扩展类加载器:Extension ClassLoader,负责加载JDK\jre\lib\ext目录下或由java.ext.dirs系统变量所指定路径中的所有类库;开发者可以直接使用该加载器;
- 应用程序加载器:ApplicationClassLoader,负责加载用户类路径(Classpath)所指定的类,开发者可以直接使用该类加载器;
类的加载机制:
- 全盘负责:某个类加载器负责加载某个Class,对该Class所依赖和引用的其他Class都由该加载器负责加载,除非显示指定。
- 父类委托(双亲委托机制):某个类加载器收到Class加载请求时,现将该请求转至父类加载器,对Class进行加载,父类找不到该类无法完成加载,才尝试自己加载。
- 缓存机制:所有加载过的Class都会被缓存,当程序中需要使用某个类时,类加载器先从缓存区寻找该Class,不存在,才会读取Class的二进制,生成Class对象存入缓存区。这就是为什么修改了Class后,必须重启JVM,程序的修改才会生效。
2、JVM内存结构
方法区和堆是所有线程共享的内存区域;而java栈、本地方法栈和程序计数器是运行是线程私有的内存区域。 |
- 堆Heap:存放实例对象,是JVM内存中最大的一块,也是GC的主要区域。
-
- 年轻代(8:1:1)
- Eden空间
- From Survivor空间
- To Survivor空间
- 老年代
- 年轻代(8:1:1)
-
- 方法区Method Area:存放被jvm加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
- 程序计数器(Program Counter Register):是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器。
- 栈:
-
- JVM栈:描述方法执行的内存模型,每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
- 本地方法栈(Native Method Stacks):同JVM栈,只不过它是为JVM的Native方法服务;
-
对象分配规则:
- 对象优先分配在Eden区,