浅析JVM 第三篇(堆内存参数调整)

来源:互联网 发布:北京市java招聘 编辑:程序博客网 时间:2024/05/18 01:32

堆内存调整参数(调优的关键)

这里写图片描述

通过以上两篇的文章我们可以发现每一个区域都有一个可变的伸缩区,当我们的内存空间不足的时候,会在可变的范围内扩大内存空间,当我们的内存空间变得不紧张的时候我们再释放可变空间。

  • 在堆内存的调优之中我们要特别注意两个参数-Xms初始化内存分配大小,默认为物理内存的1/64,-Xmx 最大的分配内存默认为物理内存的1/4。

    以本人8G电脑来说:
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 实现算法
    1. 首先扫面伊甸园区中的存活对象,其中有活跃对象和不活跃对象。此时会将活跃的对象晋升到其两个存活区中的那个空的存活去中而另一个存活区中的活跃对象也会复制到这个存活区,如果该存活区还有不活跃对象会晋升到老年代中。以保证必须有一个空的存活区这时伊甸园会产生新的空间,保存新的对象。
    2. 通过以上分析会发现伊甸园区中保存的对象大部分可能是临时对象,那么这就会频繁的发生Minor GC,所以HotSpot为了加快此空间的分配操作,采用了两种技术。
      Bump-The-Pointer
      该技术采用栈的形式,每一个最后保存的对象一般都会保存在伊甸园区的顶部,这样的话只要每创建一个新的对象我们就只需要检查保存对象后面是否有新的空间即可。
      TLAB
      Bump-The-Pointer虽然提高了内存的分配速度但是如果是多个线程同时保存一个对象那?显然是不适合的所以TLAB算法又将伊甸园区分为多个数据块,每个数据块使用Bump-The-Pointer进行对象的保存和分配。

老年代参数调整

老年代主要是接收由年轻代发送来的对象,一般情况下经过了好几次的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”
面试题:
当一个对象非常大的时候,请问是如何保存的?
该对象将直接保存在老年代。

2 0
原创粉丝点击