JVM底层原理及调优之笔记一
JVM底层原理及调优
1.java虚拟机内存模型(JVM内存模型)

1.堆(-Xms -Xmx -Xmn)
java堆,也称为GC堆,是JVM中所管理的内存中最大的一块内存区域,是线程共享的,在JVM启动时创建。存放了对象的实例及数组(所有new的对象),
无论是成员变量,局部变量,还是类变量,它们指向的对象都存储在堆内存中;
2.线程栈
每个线程存在一个独立的线程栈内存区域,每个线程栈内存中会为每个方法创建各自的栈帧,栈帧中包含:局部变量表、操作数栈、动态链接、方法出口等;
栈中存放:方法调用过程中基本数据类型的变量(int、short、long、byte、float、double、boolean、char等)以及对象的引用变量;
其中64位长度的long和double类型的数据会占用两个局部变量的空间,其余数据类型只占一个;
3.方法区(元空间/永久代)
存放常量、静态变量、类信息、即时编译器后的代码,运行时常量池:方法区的一部分,Class文件中除了有类的版本,字段,方法,接口等描述信息外,
还有一项信息就是常量池,用于存放编译器生成的各种符号引用,这部分内容将在类加载后放到方法区的运行时常量池中,
元空间取代永久代,隔离堆和元空间的垃圾回收,避免频繁Full GC以及OOM等问题;
4.程序计数器
当前线程所执行的字节码的行号指示器,程序计数器的意义:
1.确保多线程程序的正常运行
2.java是多线程的,意味着线程存在上下文切换
2.GC的基础知识
2.1 什么是垃圾? 没有任何引用指向的一个对象或者多个对象(循环引用)
2.2 如何定位垃圾? 引用计数和roots可达性分析 (java使用的是根可达性分析算法)
在Java语言中,GC Roots包括:
线程栈变量
静态变量
常量池
JNI指针
2.3 GC垃圾回收算法比较
|
GC回收算法比较 |
特性 |
|
标记清除算法 |
位置分散,容易产生碎片 |
|
复制算法 |
浪费空间 |
|
标记压缩算法 |
效率低(适用老年代) |
|
分代收集算法 |
算法搭配灵活(new-复制,old-标记压缩) |
2.4 新生代 = Eden + 2个survivor区 new:old = 1: 2
2.5 新生代、老年代数据流转大致过程
新生代 = Eden + 2个survivor区
1. YGC回收之后,大多数的对象会被回收,活着的进入s0
2. 再次YGC,活着的对象eden + s0 -> s1
3. 再次YGC,eden + s1 -> s0
4. 年龄足够 -> 老年代 (15 CMS 6)
5. s区装不下 -> 老年代
老年代
1. 顽固分子
2. 老年代满了FGC Full GC
GC回收
1.尽量减少FGC
2 minorGC = YoungGC
3 majorGC = FullGC
Minor GC触发条件:当Eden区满时,触发Minor GC。
Full GC触发条件:
a.调用System.gc时,系统建议执行Full GC,但是不必然执行
b.老年代空间不足
c.方法去空间不足
d.通过Minor GC后进入老年代的平均大小大于老年代的可用内存
e.由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小
2.6 常见的垃圾回收器

1. Serial 年轻代 串行回收 GC线程回收,其他线程暂停
2. PS 年轻代 并行回收
3. ParNew 年轻代 配合CMS的并行回收 Serial收集器新生代的并行版本
4. SerialOld
5. ParallelOld
6. ConcurrentMarkSweep(CMS) 老年代 并发的, 垃圾回收和应用程序同时运行,降低STW的时间(200ms)
CMS问题较多,一般都需要手动指定。CMS采用标记清除算法回收,所以就会存在产生碎片的问题,当老年代分配的对象分配不下的情况,需要配合SerialOld进行老年代的回收
7. G1(10ms)
8. ZGC (1ms) 相当于 C++
9. Shenandoah
10.Eplison
1.8默认的垃圾回收:PS + ParallelOld
3.GC调优准备
3.1 了解生产环境下的垃圾回收器组合 打印JVM内存信息 java -XX:+PrintCommandLineFlags

3.2 JVM的命令行参数参考:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
* JVM参数分类
> 标准: - 开头,所有的HotSpot都支持
> 非标准:-X 开头,特定版本HotSpot支持特定命令
> 不稳定:-XX 开头,下个版本可能取消
1. java -XX:+PrintCommandLineFlags
2. java -Xmn10M -Xms40M -Xmx60M -XX:+PrintCommandLineFlags
3. java -XX:+UseConcMarkSweepGC -XX:+PrintCommandLineFlags
4. java -XX:+PrintFlagsInitial 默认参数值
5. java -XX:+PrintFlagsFinal 最终参数值
6. java -XX:+PrintFlagsFinal | grep xxx 找到对应的参数
7. java -XX:+PrintFlagsFinal -version |grep GC

* 常见垃圾回收器组合参数设定:(1.8)
* -XX:+UseSerialGC = Serial New (DefNew) + Serial Old
* 小型程序。默认情况下不会是这种选项,HotSpot会根据计算及配置和JDK版本自动选择收集器
* -XX:+UseParNewGC = ParNew + SerialOld
* 这个组合已经很少用(在某些版本中已经废弃)
* https://stackoverflow.com/questions/34962257/why-remove-support-for-parnewserialold-anddefnewcms-in-the-future
* UseConcMarkSweepGC = ParNew + CMS + Serial Old
* UseParallelGC = Parallel Scavenge + Parallel Old (1.8默认) 【PS + SerialOld】
* UseParallelOldGC = Parallel Scavenge + Parallel Old
* UseG1GC = G1
常用的GC组合
|
参数 |
描述 |
|
UseSerialGC |
Serial New+ Serial Old |
|
UseParNewGC |
ParNew+Serial Old(rarely dispose) |
|
UseConcMarkSweepGC |
ParNew+CMS+Serial Old |
|
UseParallelGC/UseParallelOldGC |
Parallel Scavenge+Parallel Old(1.8默认) |
|
UseG1GC |
G1 |
2.3 JVM调优的步骤
* 步骤:
. 熟悉业务场景(没有最好的垃圾回收器,只有最合适的垃圾回收器)
. 响应时间、停顿时间
. 吞吐量 = 用户时间 / 用户时间 + GC时间
响应时间和吞吐量无法同时调优 响应时间快 == GC停顿时间短
. 选择回收器组合
. 计算内存需求
. 设定年代大小、升级年龄
. 设定日志参数
. -Xloggc:/opt/xxx/logs/xxx-xxx-gc-%t.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles= -XX:GCLogFileSize=20M -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCCause
. 观察日志情况
4.GC日志查看
通过在java命令种加入参数来指定对应的gc类型,打印gc日志信息并输出至文件等策略
java -XX:+PrintGCDateStamaps -XX:+PrintGCDetails GCTest
-XX:+PrintGC 输出GC日志
-XX:+PrintGCDetails 输出GC的详细日志
-XX:+PrintGCTimeStamps 输出GC的时间戳(以基准时间的形式)
-XX:+PrintGCDateStamps 输出GC的时间戳(以日期的形式,如 --04T21::59.234+)
-XX:+PrintHeapAtGC 在进行GC的前后打印出堆的信息
-Xloggc:../logs/gc.log 日志文件的输出路径
2019-11-19T11:50:42.352+0800[当前时间戳]: 0.169[时间戳]: [GC[Young GC (Allocation Failure) [PSYoungGen: 63744K[回收前年轻代大小]->9680K[回收后年轻代大小](74240K)总年轻代大小] 63744K回收前堆大小->62928K回收后堆大小(243712K分配堆的总大小), 0.0092841【消耗总时间】 secs] [Times: user=0.02【用户花费时间】 sys=0.03【系统花费时间】,real =0.01 secs [总消耗时间]】
2019-11-19T11:50:42.369+0800: 0.186: [GC (Allocation Failure) [PSYoungGen: 73412K->9728K(138240K)] 126661K->126473K(307712K), 0.0106607 secs [Times: user=0.03 sys=0.03, real=0.01 secs】
2019-11-19T11:50:43.326+0800: 1.142: [Full GC (Ergonomics) [PSYoungGen: 798012K->797708K(808960K)] [ParOldGen: 2708855K->2708855K(2708992K)] 3506867K->3506564K(3517952K), [Metaspace: 2735K->2735K(1056768K)], 0.0182299 secs] [Times: user=0.04 sys=0.00, real=0.02 secs]
2019-11-19T11:50:43.344+0800: 1.160: [Full GC (Allocation Failure) [PSYoungGen: 797708K->797708K(808960K)] [ParOldGen: 2708855K->2708844K(2708992K)] 3506564K->3506552K(3517952K), [Metaspace: 2735K->2735K(1056768K)], 0.6587112 secs] [Times: user=6.22 sys=0.02, real=0.66 secs]
Heap
PSYoungGen total 808960K, used 798720K [0x000000076d580000【起始地址】, 0x000000079fa00000【占用空间结束地址】, 0x00000007c0000000【整体空间结束地址】)
eden space 798720K, 100% used [0x000000076d580000,0x000000079e180000,0x000000079e180000)
from space 10240K, 0% used [0x000000079eb00000,0x000000079eb00000,0x000000079f500000)
to space 9728K, 0% used [0x000000079e180000,0x000000079e180000,0x000000079eb00000)
ParOldGen total 2708992K, used 2708845K [0x00000006c8000000, 0x000000076d580000, 0x000000076d580000)
object space 2708992K, 99% used [0x00000006c8000000,0x000000076d55b440,0x000000076d580000)
Metaspace used 2770K, capacity 4486K, committed 4864K, reserved 1056768K
class space used 264K, capacity 386K, committed 512K, reserved 1048576K
JVM底层原理及调优之笔记一的更多相关文章
- JDK记录-JVM原理与调优(转载)
转载自<https://www.cnblogs.com/andy-zhou/p/5327288.html> 一.什么是JVM JVM是Java Virtual Machine(Java虚拟 ...
- Java 面试题 三 <JavaWeb应用调优线程池 JVM原理及调优>
1.Java Web应用调优线程池 不论你是否关注,Java Web应用都或多或少的使用了线程池来处理请求.线程池的实现细节可能会被忽视,但是有关于线程池的使用和调优迟早是需要了解的.本文由浅入深,介 ...
- 深入理解JVM虚拟机10:JVM常用参数以及调优实践
转自http://www.rowkey.me/blog/2016/11/02/java-profile/?hmsr=toutiao.io&utm_medium=toutiao.io&u ...
- SQL运行内幕:从执行原理看调优的本质
相信大家看过无数的MySQL调优经验贴了,会告诉你各种调优手段,如: 避免 select *: join字段走索引: 慎用in和not in,用exists取代in: 避免在where子句中对字段进行 ...
- [Spark性能调优] 第一章:性能调优的本质、Spark资源使用原理和调优要点分析
本課主題 大数据性能调优的本质 Spark 性能调优要点分析 Spark 资源使用原理流程 Spark 资源调优最佳实战 Spark 更高性能的算子 引言 我们谈大数据性能调优,到底在谈什么,它的本质 ...
- 一文读懂Java GC原理和调优
概述 本文介绍GC基础原理和理论,GC调优方法思路和方法,基于Hotspot jdk1.8,学习之后将了解如何对生产系统出现的GC问题进行排查解决 阅读时长约30分钟,内容主要如下: GC基础原理,涉 ...
- 老大难的GC原理及调优,这下全说清楚了
概述 本文介绍GC基础原理和理论,GC调优方法思路和方法,基于Hotspot jdk1.8,学习之后将了解如何对生产系统出现的GC问题进行排查解决 阅读时长约30分钟,内容主要如下: GC基础原理,涉 ...
- JVM基本配置与调优
JVM基本配置与调优 JVM调优,一般都是针对堆内存配置调优. 如图:堆内存分新生代和老年代,新生代又划分为eden区.from区.to区. 一.区域释义 JVM内存模型,堆内存代划分为新生代和老年代 ...
- 艾编程coding老师:深入JVM底层原理与性能调优
1. Java内存模型JMM,内存泄漏及解决方法:2. JVM内存划分:New.Tenured.Perm:3. 垃圾回收算法:Serial算法.并行算法.并发算法:4. JVM性能调优,CPU负载不足 ...
随机推荐
- JS基础语法---函数---介绍、定义、函数参数、返回值
函数: 把一坨重复的代码封装,在需要的时候直接调用即可 函数的作用: 代码的重用 函数需要先定义,然后才能使用 函数名字:要遵循驼峰命名法 函数一旦重名,后面的会把前面的函数覆盖 Ctrl +鼠标左键 ...
- RiscV汇编介绍(1)-编译过程
从c/c++源文件,到可以执行文件,需要以下几个步骤: 预处理/编译 汇编 链接 下面我们以hello world程序为例,展示整个编译链接过程. 1. 编写hello.c代码 #include &l ...
- [转]JVM系列五:JVM监测&工具[整理中]
原文地址:http://www.cnblogs.com/redcreen/archive/2011/05/09/2040977.html 前几篇篇文章介绍了介绍了JVM的参数设置并给出了一些生产环境的 ...
- HttpClient忽略SSL证书
今天公司项目请求一个接口地址是ip格式的,如:https://120.20.xx.xxx/xx/xx,报一个SSL的错: 由于之前请求的接口地址都是域名地址,如:https://www.xxx.com ...
- c语言的全排列
在c语言中实现全排列,对于刚接触c语言,还没学习算法的人来说,比较困难了吧.估计大佬也不会看这种基础的东西,全排列实现的办法很多,在c++中有一个专门的函数可以使用,但是在c中实现就有点困难了.如果你 ...
- metasploit篇
第一部分:基本使用 1.在kali中metasploit默认使用postgresql作为它的数据库: /etc/init.d/postgresql start 开机自启:update-rc.d pos ...
- golang数据结构和算法之CircularBuffer环形缓冲队列
慢慢练语法和思路, 想说的都在代码及注释里. CircularBuffer package CircularBuffer const arraySize = 10 type CircularBuffe ...
- xampp配置虚拟域名
首先使用notpad++(我用的notpad++,记事本也可以)打开(安装xampp目录下的)apach-->conf-->extra-->httpd-vhosts.conf 在文件 ...
- Tensorflow之MNIST手写数字识别:分类问题(2)
整体代码: #数据读取 import tensorflow as tf import matplotlib.pyplot as plt import numpy as np from tensorfl ...
- 4. jenkins 构建任务
这边说一下 ,服务器的分布. 因为我这边 测试环境的项目比较多,不能修改主机名 1号机器 节点机器(node) 最终项目发布到这台机器 2号机器 jenkins jenkins的部署,发布 3号机 ...