通过以上两篇的文章我们可以发现每一个区域都有一个可变的伸缩区,当我们的内存空间不足的时候,会在可变的范围内扩大内存空间,当我们的内存空间变得不紧张的时候我们再释放可变空间。
class GCDemo { public static void main(String[] args) { Runtime run =Runtime.getRuntime(); long maxMemory =run.maxMemory(); long totalMemory =run.totalMemory(); System.out.println("总内存"+(maxMemory/(double)1024/1024)+"M"); System.out.println("可用内存"+(totalMemory/(double)1024/1024)+"M"); } }
输出GC的处理日志:
那么现在的可调整内存空间(伸缩区)就在123M-1810M之间,这样可能造成程序的性能下降,所以我们将初始内存空间和最大的内存空间设置为相等。就避免了伸缩区的可调策略。从而提升程序的性能。
输出GC的处理日志:
可以看出调整后的堆内存的每个区域都比以前大了,此时没有可伸缩的区域,而且也解释了前面的问题,老年代的内存空间是最大的,而两个存活的内存一定是相等的。
所有使用关键字new新实例化的对象一定会在伊甸园区进行保存,而对于存活区保存的一定是已经在伊甸园区中存在好久,并且经过了好几次的Minor
GC还保存下来的活跃对象。那么这个对象将晋升到存活区之中,存活区一定会有两块空间,这两块空间的大小一定是相等的,目的:一块存活区为了晋升、另外一块存活区为了对象回收。这两块内存空间一定有一块是空的。在年轻代中使用的是Minor
GC,这种GC算法采用的是复制算法。
老年代主要是接收由年轻代发送来的对象,一般情况下经过了好几次的Minor GC之后还会保存下来的对象才会进入到老年代。如果你要保存的对象超过了伊甸园区的大小,那么此对象也将直接保存到老年代之中。当老年代内存不足时将引发“Full GC在老年代里面会采用两种算法结合的模式实现GC的处理:整理-压缩。
标记-清除
在活跃对象较多时比较高效,但是由于该算法直接回收内存对象会造成内存的碎片化这也是最头疼的问题。
标记-压缩
在标记-清除的基础上进行对象的移动,成本较高,但是不产生碎片。类似于电脑的磁盘管理。
虽然jdk1.8中没有永久代但是javaEE目前依然是1.7
1、JDK 1.8中的内存分为:年轻代、老年代、元空间;
2、年轻代有两个组成部分:伊甸园区、两个存活区,GC回收策略为“复制”;
3、老年代的保存空间一般较大,使用的是“整理-压缩”GC回收策略。
4、JDK 1.8之前存在有永久代;
面试题:
一般什么时候会发生GC?如何处理?
Java中的GC会有两种回收:年轻代的Minor GC,另外一个就是老年代的Full
GC;新对象创建时如果伊甸园空间不足会触发
MinorGC,如果此时老年代的内存空间不足会触发Full
GC,如果空间都不足抛出OutOfM emoryError
。
面试题:
如果整个Java项目运行缓慢,你该如何解决?
避免堆内存的伸缩空间进行操作,将初始化内存空间与整体堆内存空间大小设置为一一样,使用“-Xms”、“-Xmx”
面试题:
当一个对象非常大的时候,请问是如何保存的?
该对象将直接保存在老年代。