目录
什么是Minor GC?Full GC?GC? stop the world
JVM内存管理:

程序计数器:每个线程都有它自己的程序计数器,并且任何时间一个线程都只有一个方法在执行,也就是所谓的当前方法。程序计数器会存储当前线程正在执行的 Java 方法的 JVM 指令地址;或者,如果是在执行本地方法,则是未指定值(undefined)。(唯一不会抛出OutOfMemoryError)
Java 虚拟机栈:早期也叫 Java 栈。每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧(Stack Frame),对应着一次次的 Java 方法调用。
前面谈程序计数器时,提到了当前方法;同理,在一个时间点,对应的只会有一个活动的栈帧,通常叫作当前帧,方法所在的类叫作当前类。如果在该方法中调用了其他方法,对应的新的栈帧会被创建出来,成为新的当前帧,一直到它返回结果或者执行结束。JVM 直接对 Java 栈的操作只有两个,就是对栈帧的压栈和出栈。
栈帧中存储着局部变量表、操作数(operand)栈、动态链接、方法正常退出或者异常退出的定义等。
本地方法栈:它和 Java 虚拟机栈是非常相似的,支持对本地方法的调用,也是每个线程都会创建一个。在 Oracle Hotspot JVM 中,本地方法栈和 Java 虚拟机栈是在同一块儿区域,这完全取决于技术实现的决定,并未在规范中强制。
堆:它是 Java 内存管理的核心区域,用来放置 Java 对象实例,几乎所有创建的 Java 对象实例都是被直接分配在堆上。堆被所有的线程共享,在虚拟机启动时,我们指定的“Xmx”之类参数就是用来指定最大堆空间等指标。( 编译器通过逃逸分析,确定对象是在栈上分配还是在堆上分配)堆也是垃圾收集器重点照顾的区域,所以堆内空间还会被不同的垃圾收集器进行进一步的细分,最有名的就是新生代、老年代的划分。
方法区:这也是所有线程共享的一块内存区域,用于存储所谓的元(Meta)数据,例如类结构信息,以及对应的运行时常量池、字段、方法代码等。
由于早期的 Hotspot JVM 实现,很多人习惯于将方法区称为永久代(Permanent Generation)。Oracle JDK 8 中将永久代移除,同时增加了元数据区(Metaspace)。
运行时常量池:这是方法区的一部分。如果仔细分析过反编译的类文件结构,你能看到版本号、字段、方法、超类、接口等各种信息,还有一项信息就是常量池。Java 的常量池可以存放各种常量信息,不管是编译期生成的各种字面量,还是需要在运行时决定的符号引用,所以它比一般语言的符号表存储的信息更加宽泛。
JVM性能调优参数
-Xss:规定了每个线程虚拟机栈的大小
-Xms:堆的初始值
-Xmx:堆能达到的最大值
-server -Xmx3g -Xms3g -XX:MaxPermSize=128m
-XX:NewRatio=1 新生代(Eden + 2*S)与老年代(不包括永久区)的比值
-XX:SurvivorRatio=8 2个Survivor区和Eden区的比值
-XX:+UseParallelGC
-XX:ParallelGCThreads=8
-XX:+UseParallelOldGC 这个是JAVA 6出现的参数选项
-XX:LargePageSizeInBytes=128m 内存页的大小, 不可设置过大, 会影响Perm的大小。
-XX:+UseFastAccessorMethods 原始类型的快速优化
-XX:+Disable‘’ExplicitGC 关闭System.gc()
-server
-XX:+UseContainerSupport
-XX:MaxRAMPercentage=70.0
-XX:InitialRAMPercentage=70.0
-XX:MaxMetaspaceSize=1g
-XX:MaxDirectMemorySize=1g
-XX:-UseZGC
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/bankapp/deploy/work/logs/heapdump
-Xlog:async
-Xlog:gc*:file=/bankapp/deploy/work/logs/gc.log:time:filecount=5,filesize=20m
--add-opens java.base/java.lang=ALL-UNNAMED
--add-opens java.base/java.lang.reflect=ALL-UNNAMED
-Dfile.encoding=UTF-8
-Djava.awt.headless=true
-Dspringfox.documentation.auto-startup=false
-Dswagger.service.enabled=false
-Dapollo.namespace.dynamic.enabled=false
-Ddpscn.config.default.enabled=false
堆内存和堆内存的回收过程

主要流程有4步:
(1)当Eden满了以后出发一次轻GC(Minor GC),没有死亡的对象,年龄+1,存放到from区域
(2)当Eden再次满了以后再次触发一次GC,没有死亡的对象放置于to区域,然后将from区域中没有死亡的对象全部置于to区域,年龄+1。之后每一次GC都会触发一次from和to的交换,哪个区域是空的那个区域就是to
(3)当survivor区域满了以后,再次触发GC,当存在对象的年龄等于15的时候,就会将该对象移入老年区, MaxTenuringThreshold通过这个参数设置当年龄为多少的时候移入
(4)老年区满了以后触发一次Full GC,如果老年区无法再存放对象直接报OOM
注意:每一次GC都会给存活的对象的年龄+1
JVM调优
查看堆空间大小分配(年轻代、年老代、持久代分配)
垃圾回收监控(长时间监控回收情况)
线程信息监控:系统线程数量
线程状态监控:各个线程都处在什么样的状态下
线程详细信息:查看线程内部运行情况,死锁检查
CPU热点:检查系统哪些方法占用了大量CPU时间
内存热点:检查哪些对象在系统中数量最大
jvm问题排查和调优:
jps主要用来输出JVM中运行的进程状态信息。
jstat命令可以用于持续观察虚拟机内存中各个分区的使用率以及GC的统计数据
jmap可以用来查看堆内存的使用详情。
jstack可以用来查看Java进程内的线程堆栈信

最低0.47元/天 解锁文章
557

被折叠的 条评论
为什么被折叠?



