通过VisualVM,我观察到JBoss服务器上的以下堆使用情况:
服务器使用以下(相关)JVM选项启动:
-Xrs -Xms3072m -Xmx3072m -XX:MaxPermSize=512m -XX:+UseParallelOldGC -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000
我们目前还启用了GC日志记录:
-XX:+PrintGC -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:log\gc.log
基本上,我对观察到的模式感到满意,因为看起来我们没有任何内存泄漏(模式会在几天内重复)。
然而,我想知道是否有优化的空间?
首先,我不明白为什么垃圾回收机制在堆使用量达到2GB时就已经启动了?在我看来,它可能会在以后启动,因为堆将有3GB可用?
此外,我还对观察到的堆使用模式和使用的JVM选项的提示感兴趣:
>
观察到的模式是否允许我对使用的GC策略(UseParallelOldGC)得出结论?这个策略是正确的,还是应该在观察到的堆使用情况下尝试使用另一个?
我可以优化GC进程,以便使用完整的堆大小(3GB)吗?
现在看起来完整的3GB从未使用过,我应该将Xms/Xmx减少到2.5GB吗?
有没有我遗漏的任何明显的GC优化?比如调整-XX:NewSize或-XX:NewRatio?
还有其他的建议吗?
谢谢
我要说的是,你屏幕截图中的GC行为看起来“正常”。
您通常希望在堆空间太满之前触发主要集合,或者根据多种情况,很容易遇到OutOfMemoryError。
此外,您是否知道Java的堆空间分为新(eden)、当前(幸存者)和旧(终身)对象的不同区域?
这个答案提供了一些关于这个主题的极好信息,所以我不会在这里重复:
java内存池是如何划分的?
基本上,堆的每个区域都会触发自己的集合。伊甸园空间通常是经常收集的,而且“很快”幸存者和终身空间通常更大,收集时间更长。
你能根据上图减小堆大小吗?
是的。但是,您当前的配置允许您的应用程序有一些喘息的空间,如果它可能遇到更繁忙的时期或负载高峰的话。
你能优化GC吗?
是的,但没有魔法设置。第一个问题是你真的需要吗?如果你的应用程序只是一个非交互式的“处理器”,我真的不会费心。如果您确实需要低暂停应用程序,那么可以进行一些调整。取舍通常是你需要更多的资源来实现同样的结果。
我的经验是,当负载增加时,低暂停JVM配置会有一个非常明显的下降点。如果您的应用程序通常相当空闲,但您希望在调用它时得到“快速”响应,那么低暂停可能是合适的。在流量/负载达到峰值的繁忙系统上,您可能更喜欢更传统的方法。
总结
在任何情况下,不要试图进行任意更改以“改进”您的配置。对你的方法要科学和专业。
如果没有可用的生产指标,请考虑使用Apache JMeter等工具构建负载测试场景,以模拟应用程序上的典型活负载、增加的负载(例如10%、20%或50%等)和间歇性峰值负载。
为GC和应用程序使用指标,至少测量:
一旦您对使用当前配置记录了应用程序性能的准确基准感到满意,您就应该开始进行任何更改。
显然,记录您的配置及其指标。记录所有更改,然后执行相同的基准测试。然后,您将能够看到任何性能增益(或损失)和任何可能适用的权衡。
以下是Oracle关于该主题的进一步阅读,以帮助您开始学习:
Java SE 6虚拟机垃圾收集调优
主要内容:垃圾回收算法,1、垃圾回收器的分类,2、串行垃圾回收器,3、吞吐量优先,4、响应时间优先,5、G1(Garbage First,jdk9默认),6、Full GC垃圾回收算法 1.标记清除 2.标记复制 3.标记整理 内存效率:复制算法>标记清除算法>标记压缩算法(时间复杂度) 内存整齐度:复制算法=标记清除算法>标记压缩算法 内存利用率:复制算法<标记清除算法=标记压缩算法 年轻代: 存活率低 复制算法 老年代: 区域大,存活率高 标记清除(内存碎片不是太多)+标记压缩共同实现 1、
主要内容:垃圾回收算法,1、垃圾回收器的分类,2、串行垃圾回收器,3、吞吐量优先,4、响应时间优先,5、G1(Garbage First,jdk9默认),6、Full GC垃圾回收算法 1.标记清除 2.标记复制 3.标记整理 内存效率:复制算法>标记清除算法>标记压缩算法(时间复杂度) 内存整齐度:复制算法=标记清除算法>标记压缩算法 内存利用率:复制算法<标记清除算法=标记压缩算法 年轻代: 存活率低 复制算法 老年代: 区域大,存活率高 标记清除(内存碎片不是太多)+标记压缩共同实现 1、
一、垃圾收集算法 1.标记-清除算法 最基础的收集算法是“标记-清除”(Mark-Sweep)算法,如同它的名字一样,算法分为“标记”和“清除”两个阶段。 ①首先标记出所有需要回收的对象 ②在标记完成后统一回收所有被标记的对象。 不足: 效率问题:标记和清除两个过程的效率都不高 空间问题:标记清除之后产生大量不连续的内存碎片,空间碎片太多可能会导致以后程序运行过程中需要分配较大对象时,无法找到足够
我正在做一个与JVM GC相关的项目,我计划用我的手动GC取代JVM自动GC。 我知道JAVA有一个自动垃圾收集器。如果我们集成一个新的手动垃圾收集器,其中开发人员需要显式地调用new并删除对象(如在C中)。 让我们假设程序员在没有内存泄漏的情况下写入空闲。 使用手动垃圾回收机制代替自动垃圾回收机制是否有效? 在工业中使用手动GC是否常见?还是程序员到处使用自动垃圾回收器?
由于ElasticSearch是基于Java语言的应用,所以它必须运行在Java虚拟机上。任何Java程序都被编译成字节码,然后才能运行在JVM上。用最常规的方式思考,可以想象JVM只是执行其它的程序,并且控制程序的行为。但是除非你是在为ElasticSearch开发新的插件(这部分的内容将在第9章 开发ElasticSearch插件中论述),否则这不是你关注的重点。你需要关注的重点是垃圾收集器,
为了理解可用的JVM垃圾收集算法,我在查看java-available垃圾收集算法链接时感到困惑。 根据我的理解,将会有一些标准的GC算法,不同的JVM供应商实现这些算法来创建垃圾收集器。 现在请帮助我理解下面是算法还是算法的实现: 序列, 平行, CMS, G1, 我认为这些是实现某些特定算法的垃圾收集器类型(我不知道算法的名称)。 此外,我还浏览了在http://www.oracle.com/