首先要说Jvm,先来说一说Jvm,Jre,JDK三者的关系吧!如下图:
JDK:作为软件开发工作包,包含有JRE和一些工具类的包。
JRE:为java程序运行提供必要的环境,由JVM和Java的Api组成。
JVM:简单点理解就是,通过一些规定和存储分区以及gc管理使java程序能更好的运行。
---------------------------------------分割线--------------------------------------------------
下面就要来说说JVM了,我按照简版的最好理解的来说。
主要分为堆内存,栈内存,non Heap区。
比较流行的将堆分为新生代和年老代。
新生代分为Eden,survivor1,survovor2,内存空间分配为8:1:1。用的时候只用Eden和其中一个存活区,等到执行MinorGc的时候将未被回收的对象放到另一个存活区中。MinorGc负责新生代的垃圾回收,执行频率高,速度比较快。
年老代,在新生代中经过多次MinorGc未被回收的进入年老代。majorGc负责年老代的垃圾回收。执行频率低,速度是MinorGc的十倍之久。我们可以通过内存配置来优化它。
---------------------------------------分割线--------------------------------------------------
Gc优化的参数:
- -xms:启动时堆内存初始大小。
- -xmx:堆内存最大值。
- -xmn:新生代空间大小,剩下的就是年老代的空间大小。
- --xx:permSize:永久代初始化空间大小。
- --xx:MaxPermSize:永久代最大值。
我们在配置时一般将xms和xmx配置成相等的这样可以减少MajorGc的调用,数值一般配置为可用物理内存的80%。xmn配置为Xmn的30%。配置permSize需要根据我们部署的项目多少,以及jar包的多少来配置。如果jar包比较多,就需要配大一点。---------------------------------------分割线--------------------------------------------------
常见的内存溢出异常:
- outofMemoryError:permGen space——非堆溢出(永久保存区异常),一般项目jar包太多。永久内存不够,把permSize调大点就好了。
- outofMemoryError:java heap space——堆溢出,xms调大点
- outofMemoryError:unable to create new native thread——栈溢出,无法创建新线程,比较少见。
---------------------------------------分割线--------------------------------------------------
垃圾回收算法:
- 标记算法:直接标记清除(效率不高空间会产生大量碎片)
- 复制算法:原始的复制算法是将新生代分为两部分,每次只使用其中一部分,执行minorGc的时候,将未被回收的放到另一部分中。这样每次只能使用一个。内存浪费比较大。优化后的复制算法是将新生代分成3部分一个Eden区(对象出生的地),两个survivor区,内存占比8:1:1。每次只使用Eden和其中一个survivor区,执行minorGc的时候,将存活的对象放到另一个survivor分区中,这样使得内存不被浪费。
- 分代回收:分成新生代和老年代,不同的分区采用不同的方法。
- 标记整理:对应老年代比较适合。
---------------------------------------分割线--------------------------------------------------
常见垃圾回收器
- serial收集器:单线程垃圾回收器,只用一个cpu,一条线程。
- parNew:多线程版本的serial收集器。
- parallel Scavenge:并行的多线程收集器,采用复制算法。以吞吐量优先。
- parallel old 和serial old 是针对老年代的版本。
- CMS:采用标记清除的算法,适合年老代,以最短停顿时间为目标。
- GI收集器:面向服务器端的垃圾收集器。
并发:指用户线程和垃圾回收线程同时执行(不一定是并行,有可能是交叉执行),用户进程在运行,而垃圾回收线程在另一个 CPU 上运行。
纯属个人理解,不喜勿喷。。。
6万+

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



