JVM基础知识总结
2021-01-30 17:47:44 1 举报
AI智能生成
JVM基础知识、JVM入门到放弃之基本概念、JVM调优
作者其他创作
大纲/内容
JVM内存区域
程序计数器:当前线程执行字节码的行号指示器
虚拟机栈(JVM执行Java方法)
java方法执行的内存模型,每个方法执行都会创建一个栈帧,每个方法从开始调用到结束都对应一个栈帧在虚拟机栈中入栈到出站的过程。
本地方法栈(JVM执行本地方法)
虚拟机栈为执行 Java 方法服务, 而本地方法栈则为Native 方法服务, 如果一个VM 实现使用C-linkage 模型来支持Native 调用, 那么该栈将会是一个C 栈,但 HotSpot VM 直接就把本地方法栈和虚拟机栈合二为一
直接内存
直接内存并不是 JVM 运行时数据区的一部分, 但也会被频繁的使用: 在 JDK 1.4 引入的 NIO 提供了基于 Channel 与 Buffer 的 IO 方式
方法区
即我们常说的永久代(Permanent Generation)用于存储被 JVM 加载的类信息、常量、静态变量、即时编译器编译后的代码等数据,在Java8 中,永久代已经被移除,被一个称为“元数据区”(元空间)的区域所取代。元空间的本质和永久代类似,元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。
JAVA 堆
新生代
Eden
Java 新对象的出生地(如果新创建的对象占用内存很大,则直接分配到老年代)。当 Eden 区内存不够的时候就会触发 MinorGC,对新生代区进行一次垃圾回收。
Survivor (From )
上一次 GC 的幸存者,作为这一次 GC 的被扫描者
Survivor (To)
保留了一次 MinorGC 过程中的幸存者
老年代
主要存放应用程序中生命周期长的内存对象。
JVM GC
如何确定垃圾
引用计数法
对象如果没有任何与之关联的引用,即他们的引用计数都不为 0,则说明对象不太可能再被用到,那么这个对象就是可回收对象。
可达性分析
为了解决引用计数法的循环引用问题,Java 使用了可达性分析的方法。通过一系列的“GC roots”对象作为起点搜索。如果在“GC roots”和一个对象之间没有可达路径,则称该对象是不可达的。
要注意的是,不可达对象不等价于可回收对象,不可达对象变为可回收对象至少要经过两次标记过程。两次标记后仍然是可回收对象,则将面临回收
垃圾收集算法
标记清除算法(Mark-Sweep)
最基础的垃圾回收算法,分为两个阶段,标注和清除。标记阶段标记出所有需要回收的对象,清除阶段回收被标记的对象所占用的空间。该算法最大的问题是内存碎片化严重,后续可能发生大对象不能找到可利用空间的问题。
复制算法(copying)(新生代使用)
为了解决 Mark-Sweep 算法内存碎片化的缺陷而被提出的算法。按内存容量将内存划分为等大小的两块。每次只使用其中一块,当这一块内存满后将尚存活的对象复制到另一块上去,把已使用的内存清掉
标记整理算法(Mark-Compact) (老年代使用)
标记阶段和 Mark-Sweep 算法相同,标记后不是清理对象,而是将存活对象移向内存的一端。然后清除端边界外的对象。
分代收集算法
分代收集法是目前大部分 JVM 所采用的方法,其核心思想是根据对象存活的不同生命周期将内存划分为不同的域,一般情况下将 GC 堆划分为老生代(Tenured/Old Generation)和新生代(Young Generation)。
老生代的特点是每次垃圾回收时只有少量对象需要被回收,新生代的特点是每次垃圾回收时都有大量垃圾需要被回收,因此可以根据不同区域选择不同的算法。
JVM 参数配置
官方指导配置
Java堆大小设置,Xms 和 Xmx设置为老年代存活对象的3-4倍,即FullGC之后的老年代内存占用的3-4倍
永久代 PermSize和MaxPermSize(元空间)设置为老年代存活对象的1.2-1.5倍。
年轻代Xmn的设置为老年代存活对象的1-1.5倍。
老年代的内存大小设置为老年代存活对象的2-3倍。
Java1.7的jvm参数
https://docs.oracle.com/javase/7/docs/technotes/tools/windows/java.html
Java1.8的jvm参数
https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html
JVM调优
必要性
一般项目肯定是不需要进行 JVM 调优的,因为 JVM 本身就是为这种低延时、高并发、大吞吐的服务设计和优化的,我们很少需要去改变什么。所以,我们往往更偏重于应用服务本身的调优。
调优的目标
对JVM内存的系统级的调优主要的目的是减少GC的频率和Full GC的次数。
Full GC
会对整个堆进行整理,包括Young、Tenured和Perm。Full GC因为需要对整个堆进行回收,所以比较慢,因此应该尽可能减少Full GC的次数。
导致Full GC的原因
1)年老代(Tenured)被写满
调优时尽量让对象在新生代GC时被回收、让对象在新生代多存活一段时间和不要创建过大的对象及数组避免直接在旧生代创建对象 。
2)持久代Pemanet Generation空间不足
增大Perm Gen空间,避免太多静态对象 , 控制好新生代和旧生代的比例
3)System.gc()被显示调用
垃圾回收不要在代码中触发,尽量依靠JVM自身的机制
调优工具
jconsole
Jconsole(Java Monitoring and Management Console)是在JDK中自带的java监控和管理控制台,用于对JVM中内存,线程和类等的监控。jdk/bin目录下点击jconsole.exe即可启动。可以以选择本机的监控本机的java应用,也可以选择远程的java服务来监控。
VisualVM
VisualVM 是一个工具,它提供了一个可视界面,用于查看 Java 虚拟机 (Java Virtual Machine, JVM) 上运行的基于 Java 技术的应用程序(Java 应用程序)的详细信息。
调优步骤
监控GC的状态
使用各种JVM工具,查看当前日志,分析当前JVM参数设置,并且分析当前堆内存快照和gc日志,根据实际的各区域内存划分和GC执行时间,觉得是否进行优化。
生成堆的dump文件
java提供了jmap命令(位于jdk/bin目录下),如下:
jmap -dump:format=b,file=/path/heap.dump 进程ID
jmap -dump:live,format=b,file=/path/heap.dump 进程ID
分析dump文件
得到dump文件后我们可以使用jvisualvm来分析,文件比较大我们使用专门的工具打开分析它
分析完毕-判断是否需要优化
如果各项参数设置合理,系统没有超时日志出现,GC频率不高,GC耗时不高,那么没有必要进行GC优化,如果GC时间超过1-3秒,或者频繁GC,则必须优化。
注:如果满足下面的指标,则一般不需要进行GC:
Minor GC执行时间不到50ms;
Minor GC执行不频繁,约10秒一次;
Full GC执行时间不到1s;
Full GC执行频率不算频繁,不低于10分钟1次;
调整GC类型和内存分配
如果内存分配过大或过小,或者采用的GC收集器比较慢,则应该优先调整这些参数。
不断的分析和调整
通过不断的试验和试错,分析并找到最合适的参数,如果找到了最合适的参数,则将这些参数应用到所有服务器。
0 条评论
下一页