首先,JVM是什么?
JAVA字节码是在JRE(java runtime environment)中运行,而JRE是由JavaAPI和JVM组成。
JVM (Java Virtual Machine) 是JRE的核心组成,承担了其分析和执行Java字节码的工作,JVM是通过类加载器(Class Loader)加类Java应用,并通过Java API进行执行。
引申: 类加载机制及双亲委托模型?
Java类的生命周期:
加载 --> 链接(验证 --> 准备 --> 解析 )--> 初始化 -->使用 --> 卸载 (细节自行体会)
双亲委托机制:当一个类收到了类加载请求,他首先不会尝试自己去加载这个类,而是把这个请求委派给父类去完成,每一个层次类加载器都是如此,因此所有的加载请求都应该传送到启动类加载其中,只有当父类加载器反馈自己无法完成这个请求的时候(在它的加载路径下没有找到所需加载的Class),子类加载器才会尝试自己去加载。
如下图:
JVM内存管理及垃圾回收
JVM内存组成结构:堆/栈/本地方法栈/方法区
堆:所有new的对象都在此,堆的大小可以通过一些配置项来控制(-Xmx和-Xms)堆分为新生代,老年代。(具体可参看垃圾回收机制)
栈:每个线程在执行方法时会在栈中申请栈帧,包括局部变量区和操作数栈,用来存放此方法调用过程中的临时变量,参数,结果等。
本地方法栈:支持native方法的执行。
方法区:存放了要加载的类信息,静态变量,final常量,属性,方法信息等。JVM用持久代来存放方法区,可通过-XX:PermSize和-XX:MaxPermSize来指定最小值和最大值。
垃圾回收机制:
哪些内存需要回收?
未被引用的对象/作用域发生未捕获异常/程序在作用域正常执行完毕/程序执行System.exit()/程序发生意外终止(被杀进程等)
什么时候触发GC?
(1)当应用程序空闲时,即没有应用线程在运行时,GC会被调用。
(2)Java堆内存不足时,GC会被调用。
怎么判断对象是否可被回收?
两种算法:
引用计数
给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。
优点:简单,高效,现在的objective-c用的就是这种算法。
缺点:很难处理循环引用,相互引用的两个对象则无法释放。
可达性分析(根搜索)
从GC Roots作为起点,向下搜索它们引用的对象,可以生成一棵引用树,树的节点视为可达对象,反之视为不可达。
在Java中,可以作为GC Roots的对象包括下面几种:
虚拟机栈(栈帧中的本地变量表)中的引用对象。
方法区中的类静态属性引用的对象。
方法区中的常量引用的对象。
本地方法栈中JNI(Native方法)的引用对象
回收算法有哪些?
引用计数/标记-清除/复制/标记-整理
JVM在不同的时代用的是不同的回收机制,新时代存活时间端,基于复制算法来进行回收,新生代采用空闲指针的方式来触发GC,当有新的对象需要分配内存时,检查空间是否足够,不够就触发GC。
旧生代存活时间较长,较稳定,采用标记算法来进行回收,标记即找出存活的对象,然后再进行回收未被标记的对象。
方法区的对象也能被回收,只是条件非常苛刻,需要同时满足以下三个条件:
所有实例被回收/加载该类的ClassLoader被回收/Class对象无法通过任何途径访问(包括反射)
JVM内存调优
内存查看工具:JConsole和Java VisualVM
调优目的:减少GC的频率和FULLGC的次数(占有CPU资源,影响吞吐量),尤其避免FULL GC。
出现fullGC的几种情况:
旧生代的空间不足/Pemanet Generation空间不足/System.gc()被显示调用
JVM提供的GC策略设置方式:
吞吐量优先-XX:GCTimeRatio=n/暂停时间优先-XX:MaxGCPauseRatio=n
性能调优的原则:
MinorGC回收原则: 每次minor GC 都要尽可能多的收集垃圾对象。以减少应用程序发生Full GC的频率。
GC内存最大化原则:处理吞吐量和延迟问题时候,垃圾处理器能使用的内存越大,垃圾收集的效果越好,应用程序也会越来越流畅。
GC调优3选2原则: 在性能属性里面,吞吐量、延迟、内存占用,我们只能选择其中两个进行调优,不可三者兼得。
JVM常见配置
堆设置
-Xms:初始堆大小
-Xmx:最大堆大小
-XX:NewSize=n:设置年轻代大小
-XX:NewRatio=n:设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4
-XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5
-XX:MaxPermSize=n:设置持久代大小
收集器设置
-XX:+UseSerialGC:设置串行收集器
-XX:+UseParallelGC:设置并行收集器
-XX:+UseParalledlOldGC:设置并行年老代收集器
-XX:+UseConcMarkSweepGC:设置并发收集器
垃圾回收统计信息
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:filename
并行收集器设置
-XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数。并行收集线程数。
-XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间
-XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)
并发收集器设置
-XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况。
-XX:ParallelGCThreads=n:设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。
网友评论