一. JVM概念
Java虚拟机,JAVA程序自己独立运行环境; 有自己完善的硬件架构,如类加载器、堆栈、寄存器等,还具有相应的指令系统
二 .JVM 原理
Java源文件经javac编译器,编译成字节码程序,通过JVM执行引擎将每一条指令翻译成不同平台机器码,通过特定平台运行。
java编译器只需面向JVM,生成JVM能理解的代码或字节码文件。这也是java能跨平台,“一次编译,到处运行”的原因
原理图:
三. JVM组成
主要由类加载器子系统、运行时数据区(内存空间)、执行引擎以及与本地方法接口等组成。
模型:
四. JVM组成--类加载器
1)Bootstrap ClassLoader(启动类加载器)
负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类
2)Extension ClassLoader(标准扩展类加载器)
负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包
3)App ClassLoader(应用程序类加载器)
负责将系统类路径classpath中指定的jar包及目录中class加载到内存
4)Custom ClassLoader(自定义类加载器)
属于应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行实现ClassLoader
五. JVM组成--运行时数据区
包括:栈、堆、方法区、pc寄存区、本地方法栈
名称 | 特征 | 作用 | 配置参数 | 异常 |
程序计数器 | 占用内存小,线程私有, | 多线程下,为了记录线程的执行情况,便于下次切换后进行线程恢复 | 无 | 无 |
java栈 | 线程私有,生命周期与线程相同,使用连续的内存空间 | 主要存放 局部变量、基本类型的变量和对象的引用变量 | -Xss | StackOverflowError |
java堆 | 线程共享,生命周期与虚拟机相同 | 主要存放存放由new创建的对象和数组 | -Xms | OutOfMemoryError |
方法区 | 线程共享,生命周期与虚拟机相同 | 存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据 | -XX:PermSize: | OutOfMemoryError |
常量池 | 方法区(1.7前)/堆(1.7后)的一部分,具有动态性 | 存放常量量 |
|
|
模型图:
六. 堆内存
概要
堆内存划分为三个代:年轻代(Young Generation)、老年代(Old Generation)和持久代(Permanent Generation)也就是常量池
模型图
年轻代
·所有新生成的对象首先都是放在年轻代的。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象
·年轻代分三个区。一个Eden区,一个Survivor(from/to)幸存区,默认8:1:1
·过程:
当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当这个Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,当这个Survivor去也满了的时候,从第一个Survivor区复制过来的并且此时还存活的对象,将被复制“年老区(Tenured)”。
·注意:
Survivor的两个区是对称的,没先后关系,但复制到年老区的只有从第一个Survivor去过来的对象
老年代
在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象
持久代
就是1.8后的常量池,用于存放静态文件,如今Java类、方法等。持久代对垃圾回收没有显著影响
Scavenge GC
当新对象生成,并且在Eden申请空间失败时,就会触发Scavenge GC,对Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区。然后整理Survivor的两个区。这种方式的GC是对年轻代的Eden区进行,不会影响到年老代
Eden区的GC会频繁进行
Full GC
·对整个堆进行整理,包括Young、Tenured和Perm
·Full GC因为需要对整个对进行回收,所以比Scavenge GC要慢,因此应该尽可能减少Full GC的次数
·导致原因
年老代(Tenured)被写满
持久代(Perm)被写满
System.gc()被显示调用
上一次GC之后Heap的各域分配策略动态变化
七. JVM常见参数配置
内存 | 参数 | 作用 | 说明 |
GC | -verbose:gc -XX:+PrintGCDetails | 打印GC日志信息
|
|
-Xloggc:d:/gc.log | GC日志文件目录 |
| |
-XX:+PrintHeapAtGC | 打印堆信息(每一次GC后) |
| |
-XX:+TraceClassLoading | 打印类加载信息 |
| |
堆 | -Xms 如:-Xms5m | 最小堆内存 | 在Xms 和 Xmx配置相同的时候,初始化堆内存就是最大内存 在Xms 和 Xmx配置不相同的时候,JVM会尽可能维持最小堆内存,当内存不足的时候,会重新分配增加部分内存
|
Xmx 如:-Xmx10m | 最大堆内存 | ||
-Xmn 如:-Xmn10m | 设置年轻代大小 |
| |
-XX:SurvivorRatio | Survivor(from和to)和eden的比例值 | 默认为8,survivor:eden=2:8 , from survivor占年轻代的1/10 | |
-XX:NewRatio | 年轻代和老年代的比值 | 默认值为4,表示年轻代:老年代=1:4,也就是说年轻代占堆 的1/5 | |
方法区 | -XX:PermSize | 初始化空间 |
|
-XX:MaxPermSize | 最大空间 |
| |
栈 | -Xss | 每个线程都有独立的栈空间,保存方法中的局部变量,参数等 |