名词解释:
堆内内存:on-heap memory
对外内存:off-heap memory
堆内与堆外的关系
其实堆内堆外是两个相对的关系,堆内内存是我们常用到的。Java分配的非空对象都是由java虚拟机的垃圾收集器管理的,这一部分称为堆内内存,虚拟机会定期对垃圾内存进行回收,在某些特定的时间点,它会进行一次彻底的回收(full gc)。彻底回收时,垃圾收集器会对所有分配的堆内内存进行完整的扫描,这意味着一个重要的事实——这样一次垃圾收集对Java应用造成的影响,跟堆的大小是成正比的。过大的堆会影响Java应用的性能。所以说给应用分配的内存越大,系统性能就越好,因为对应的垃圾回收的代价也就越大,具体如下图:
堆内内存 = 新生代+老年代+持久代
对于JVM,在jvm参数中只要使用-Xms,-Xmx等参数就可以设置堆的大小和最大值
目前常用的垃圾回收算法有很多种:
引用计数器法(Reference Counting)
标记清除法(Mark-Sweep)
复制算法(Coping)
标记压缩法(Mark-Compact)
分代算法(Generational Collecting)
分区算法(Region)
其中 cms是常用的算法。
为了解决堆内内存问题,一种解决方案就是使用堆外内存(off-heap memory)。堆外内存意味着把内存对象分配在Java虚拟机的堆以外的内存,这些内存直接受操作系统管理(而不是虚拟机)。这样做的结果就是能保持一个较小的堆,以减少垃圾收集对应用的影响。
使用堆外内存的优势:
1、减少了垃圾回收
因为垃圾回收会暂停其他的工作。
2、加快了复制的速度
堆内在flush到远程时,会先复制到直接内存(非堆内存),然后在发送;而堆外内存相当于省略掉了这个工作。
同样任何一个事物使用起来有优点就会有缺点,堆外内存的缺点就是内存难以控制,使用了堆外内存就间接失去了JVM管理内存的可行性,改由自己来管理,当发生内存溢出时排查起来非常困难。
目前很流行spark技术,经常导致OOM,就是因为堆内内存管理出现问题,但是也提出改进
转载:https://blog.csdn.net/qq_38905818/article/details/100989020