JAVA系列之JVM内存调优

一、前提JVM性能调优牵扯到各方面的取舍与平衡 , 往往是牵一发而动全身 , 需要全盘考虑各方面的影响 。在优化时候 , 切勿凭感觉或经验主义进行调整 , 而是需要通过系统运行的客观数据指标 , 不断找到最优解 。同时 , 在进行性能调优前 , 您需要理解并掌握以下的相关基础理论知识:

1、JVM垃圾收集器和垃圾回收算法2、JVM性能监控常用工具和命令3、JVM运行时数据区域4、能够读懂gc日志5、内存分配与回收策略
二、JVM内存结构
JAVA系列之JVM内存调优

文章插图
从上图可以看出 , 整个JVM内存是由栈内存、堆内存和永久代构成 。
年轻代(New generation) = eden + s0 + s1堆内存 = 年轻代 + 老年代(Old generation)JDK1.8以前: JVM内存 = 栈内存 + 堆内存 + 永久代JDK1.8以后: 由元空间取代了永久代 , 元空间并不在JVM中 , 而是使用本地内存 。因此JVM内存 = 栈内存 + 堆内存
1、栈内存栈内存归属于单个线程 , 也就是每创建一个线程都会分配一块栈内存 , 而栈中存储的东西只有本线程可见 , 属于线程私有 。栈的生命周期与线程一致 , 一旦线程结束 , 栈内存也就被回收 。栈中存放的内容主要包括:8大基本类型 + 对象的引用 + 实例的方法
JAVA系列之JVM内存调优

文章插图
2、堆内存堆内存是由年轻代和老年代构成 , JDK1.8以后 , 永久代被元空间取代 , 使用直接内存 , 不占用堆内存 。堆内存是Jvm中空间最大的区域 , 所有线程共享堆 , 所有的数组以及内存对象的实例都在此区域分配 。我们常说的垃圾回收就是作用于堆内存 。
JAVA系列之JVM内存调优

文章插图
Eden区占大容量 , Survivor两个区占小容量 , 默认比例是8:1:1
3、永久代(元空间)这个区域是常驻内存的 。用来存放JDK自身携带的Class对象 。Interface元数据 , 存储的是Java运行时的一些环境 。这个区域不存在垃圾回收!关闭虚拟机就会释放这个区域的内存 。当发现系统中元空间占用内存比较大时 , 排查方向是否加载了大量的第三方jar包 , Tomcat部署了太多应用 , 大量动态生成的反射类等 。
三、JVM常用参数首先JVM内存限制于实际的最大物理内存 , 假设物理内存无限大的话 , JVM内存的最大值跟操作系统有很大的关系 。简单的说就32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制 , 这个限制一般是2GB-3GB(一般来说Windows系统下为1.5G-2G , Linux系统下为2G-3G) , 而64bit以上的处理器就不会有限制 。
1、堆大小设置java -server -Xmx4g -Xms4g -Xmn2g –Xss128k
-Xmx4g:设置JVM最大可用内存为4g 。-Xms4g:设置JVM最小可用内存为4g 。一般配置为与-Xmx相同 , 避免每次垃圾回收完成后JVM重新分配内存 。-Xmn2g:设置年轻代大小为2G 。整个堆大小=年轻代大小 + 年老代大小 , 所以增大年轻代后 , 将会减小年老代大小 。-Xss128k:设置每个线程的堆栈大小 。JDK5.0以后每个线程默认大小为1M , 以前每个线程大小为256K 。根据应用的线程所需内存大小进行调整 。在相同物理内存下 , 减小这个值能生成更多的线程 。

经验总结扩展阅读