一、前言
我们在tomcat配置文件中会指定JVM参数:JAVA_HOME=/opt/jdk1.8.0_152
JAVA_OPTS="-server -Xms1024m -Xmx1024m -XX:PermSize=256M -XX:MaxPermSize=512M"
说明:
-server:表示以服务模式启动,启动速度会稍微慢一点,但性能会高很多。不加这个参数,默认是以客户端模式启动
-Xms:初始堆内存大小,Server端JVM最好将-Xms和-Xmx设为相同值
-Xmx:堆内存最大值,建议不要超过物理内存的一半
-XX:PermSize=n:设定内存永久保存区域的最小值
-XX:MaxPermSize=n:设定内存永久保存区域的最大值
二、JVM的内存
1、那么看下JVM内存是如何分配的?JVM的内存 = 年轻代(Young) + 年老代(Tenured) + 持久代
1)新生代(Young Generation):用于存放新创建的对象,采用复制回收方法,如果在s0和s1之间复制一定次数后,转移到年老代中。这里的垃圾回收叫做minor GC。
2)年老代(Old Generation):这些对象垃圾回收的频率较低,采用的标记整理方法,这里的垃圾回收叫做 major GC。
3)永久代(Permanent Generation):存放Java本身的一些数据,当类不再使用时,也会被回收。
2、这里可以详细的说一下新生代复制回收的算法流程:
在新生代中,分为三个区:Eden, from survivor, to survior。
1)当触发minor GC时,会先把Eden中存活的对象复制到to Survivor中;
2)然后再看from survivor,如果次数达到年老代的标准,就复制到年老代中;如果没有达到则复制到to survivor中,如果to survivor满了,则复制到年老代中。
3)然后调换from survivor 和 to survivor的名字,保证每次to survivor都是空的等待对象复制到那里的。
PS:新生代到年老代有一个过度过程
三、堆(Heap)和非堆(Non-heap)内存
按照官方的说法:“Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配。堆是在 Java 虚拟机启动时创建的。”“在JVM中堆之外的内存称为非堆内存(Non-heap memory)”。可以看出JVM主要管理两种类型的内存:堆和非堆。简单来说堆就是Java代码可及的内存,是留给开发人员使用的;非堆就是JVM留给自己用的。
四、JDK8新增
1、从JDK8开始,永久代(PermGen)的概念被废弃掉了,取而代之的是一个称为Metaspace的存储空间。区别:
PermSize有默认值,可以设置初始大小和最大大小
Metaspace使用的是本地内存,可以设置初始大小和最大大小
Metaspace不进行任何设置的情况下,最大限制就是系统内存大小,内存足够的情况下,不会出现OOM,但是如果占用太多会不会被系统进程kill掉?
参考资料:
https://www.cnblogs.com/xing901022/p/7725961.html
https://blog.csdn.net/KilluaZoldyck/article/details/75094855
https://www.cnblogs.com/tomcatandjerry/p/4218589.html