深入理解Java虚拟机读书笔记九

来源:互联网 发布:淘宝女童模特佳佳 编辑:程序博客网 时间:2024/05/21 10:17

第4章 调优案例分析与实战

    从实践经验的角度出发,除了Java堆和永久代之外,我们注意到下面这些区域还会占用较多的内存,这里所有的内存总和会受到操作系统进程最大内存的限制:

    Direct Memory:可通过 -XX:MaxDirectMemorySize调整大小,内存不足时抛出OutO fMemoryError 或 OutOfMemoryError : Direct bufTer memory

    线程堆栈 : 可通过-Xss调整大小, 内存不足时抛出 StackOverflowError (纵向无

发分配,即无法分配新的检帧)OutOfMemoryError: unable to create new native thread (横向无法分配,即无法建立新的线程)

    Socket缓存区: 每个Socket 连接都Receive 和 Send 两个缓存区,分别占大约37 KB 和 25KB 的内存,连接多的话,这块内存占用也比较可观。 如果无法分配,则可能生抛出 IOException : Too many open files 异常

    JNI代码:如果代码中使用JNI调用本地库,那本地库使用的内存也不在堆中

Eclipse运行速度调优

    调整内存设置控制垃圾吸收集频率。

选择收集器降低延迟

参数的一些基本知识

    (1DisableExplicitGC这个配置的作用是什么?

    -XX:+DisableExplicitGC标志自动将System.gc()调用转换成一个空操作,就是应用中调用System.gc()会变成一个空操作。最主要的原因是为了防止开发人员在代码里到处写System.gc()的调用而干扰了程序的正常运行。有些应用程序本来不会出一次fullGC,但因为在代码里调用了System.gc()而不间歇性被暂停。

    (2)应用中调用System.gc()会有什么影响?

    在Oracle/Sun JDK这个具体实现上,System.gc()的默认效果是引发一次stop-the-worldfull GC,对整个GC堆做收集,影响应用的性能。

    (3DisableExplicitGC这个设置了会有什么结果?

    其中一种情况是下述三个条件同时满足时会发生的: 

        1、应用本身在GC堆内的对象行为良好,正常情况下很久都不发生full GC; 

        2、应用大量使用了NIOdirect memory,经常反复的申请DirectByteBuffer 

        3、使用了-XX:+DisableExplicitGC 

        此时有可能会抛出这个异常:java.lang.OutOfMemoryError: Direct buffer memory  

    (4Direct ByteBuffer什么值得注意的地方?

        1DirectByteBuffer没有finalizer,它的native memory的清理工作是通过sun.misc.Cleaner自动完成的。 

        2sun.misc.Cleaner是一种基于PhantomReference的清理工具,比普通的finalizer轻量些。做full GC的话会对old genreference processing,进而能触发Cleaner对已死的DirectByteBuffer对象做清理工作。而如果很长一段时间里没做过GC或者只做了young GC的话则不会在old gen触发Cleaner的工作,那么就可能让本来已经死了的、但已经晋升到old genDirectByteBuffer关联的native memory得不到及时释放。

       3、为DirectByteBuffer分配空间过程中会显式调用System.gc(),以期通过full GC来强迫已经无用的DirectByteBuffer对象释放掉它们关联的native memory: 

     这几个实现特征使得Oracle/Sun JDK 6依赖于System.gc()触发GC来保证DirectByteMemory的清理工作能及时完成。

    如果打开了-XX:+DisableExplicitGC,清理工作就可能得不到及时完成,于是就有机会见到direct memoryOOM

    (5)使用了Direct ByteBuffer如何处理?

     如果在使用Oracle/Sun JDK 6,应用里有任何地方用了direct memory,那么使用-XX:+DisableExplicitGC要小心。

     如果用了该参数而且遇到direct memoryOOM,可以尝试去掉该参数看是否能避开这种OOM

     如果担心System.gc()调用造成full GC频繁,可以尝试下面提到 -XX:+ExplicitGCInvokesConcurrent 参数 (-XX:+ExplicitGCInvokesConcurrent  System.gc()和应用程序并发执行,就是不stop-the-world-XX:+ExplicitGCInvokesConcurrent 或 -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses 这两个参数也是用来改变System.gc()的默认行为用的;不同的是这两个参数只能配合CMS使用(-XX:+UseConcMarkSweepGC),

而且System.gc()还是会触发GC的,只不过不是触发一个完全stop-the-worldfull GC,而是一次并发GC周期。 CMS GC周期中也会做reference processing。所以,如果用这两个参数的其中一个,而不是用-XX:+DisableExplicitGC的话,就避开了由full GC带来的长GC pause,同时NIO direct memoryOOM也不会那么容易发生。

    (6MaxDirectMemorySize 与 NIO direct memory 的默认上限 

     -XX:MaxDirectMemorySize 是用来配置NIO direct memory上限用的VM参数。

     MaxDirectMemorySize没显式配置的时候,NIO direct memory可申请的空间的上限就是-Xmx减去一个survivor space的预留大小。 

    (7HeapDump位置问题

    -XX:+HeapDumpBeforeFullGC-XX:+HeapDumpAfterFullGC-XX:+HeapDumpOnOutOfMemoryError 这几个参数可以在不同条件下做出HPROF格式的heap dump。如果不想了解各种环境被配置成什么样,“working directory”到底在哪里的话,就在VM启动参数里加上 -XX:HeapDumpPath=一个绝对路径,这样自动做出的heap dump就会被存到指定的目录里去。 

0 0
原创粉丝点击