java 虚拟机(jvm)-16-Java GC Ergonomics 人体工程学

人机工程学(Ergonomics)

人机工程学是Java虚拟机(JVM)和垃圾收集启发式(例如基于行为的启发式)提高应用程序性能的过程。

JVM为垃圾收集器,堆大小和运行时编译器提供与平台相关的默认选择。

这些选择符合不同类型应用程序的需求,同时需要较少的命令行调整。

此外,基于行为的调优动态地优化堆的大小以满足应用程序的指定行为。

本节介绍这些默认选择和基于行为的调整。

在使用后续部分中描述的更详细控件之前,请使用这些默认值。

垃圾收集器,堆和运行时编译器默认选择

以下是有关垃圾收集器,堆大小和运行时编译器默认选择的信息。

  • 被称为服务器级机器的一类机器被定义为具有以下内容的机器:

两个或更多物理处理器

两个或更多GB的物理内存

  • 在服务器级计算机上,默认情况下选择以下内容:

Garbage-First(G1)收集器

初始堆大小为物理内存的1/64

最大堆大小为物理内存的1/4

分层编译器,使用C1和C2

实战

查看机器基础信息

linux 系统为例

  • jdk 版本
java -version

本机为 1.8

  • 查看核数
cat /proc/cpuinfo | grep "physical id" | uniq | wc -l

结果为 4 核

  • 查看内存
free -h

如下,内存为 8G

             total       used       free     shared    buffers     cached
Mem:          7.7G       6.1G       1.6G       192K       194M       1.5G
-/+ buffers/cache:       4.4G       3.3G
Swap:           9G       584K         9G
  • 查看是 32/64 位
getconf LONG_BIT

本机为 64 位

XXFox 推荐参数

-Xmx5440M -Xms5440M -XX:MaxMetaspaceSize=512M -XX:MetaspaceSize=512M -XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:+ParallelRefProcEnabled

基于行为的调整

可以将Java HotSpot VM垃圾收集器配置为优先满足两个目标之一:最大暂停时间和应用程序吞吐量。

如果满足首选目标,收藏家将尝试最大化另一个目标。当然,这些目标并不总能得到满足:应用程序需要最少的堆来保存至少所有实时数据,而其他配置可能会妨碍达到部分或全部目标。

最大暂停时间目标

暂停时间是垃圾收集器停止应用程序并恢复不再使用的空间的持续时间。最大暂停时间目标的意图是限制这些暂停的最长时间。

垃圾收集器维持平均停顿时间和平均时差。

平均值是从执行开始时开始的,但是它的加权使得最近的暂停计数更加严重。如果平均加上暂停时间的方差大于最大暂停时间目标,则垃圾收集器认为目标未得到满足。

使用命令行选项 -XX:MaxGCPauseMillis=<nnn> 指定最大暂停时间目标。

这被解释为对垃圾收集器的暗示,希望暂停时间<nnn>毫秒或更少。

垃圾收集器调整Java堆大小和与垃圾收集相关的其他参数,以试图使垃圾收集暂停时间小于<nnn>毫秒。

最大暂停时间目标的默认值因收集器而异。这些调整可能导致垃圾收集更频繁地发生,从而降低了应用程序的整体吞吐量。

但是,在某些情况下,无法满足所需的暂停时间目标。

吞吐量目标

吞吐量目标是根据收集垃圾所花费的时间来衡量的,而在垃圾收集之外花费的时间是应用时间。

目标由命令行选项 XX:GCTimeRatio=nnn 指定。

垃圾收集时间与应用时间的比率为 1/(1 + nnn)。

例如,XX:GCTimeRatio=19 设置目标为垃圾收集总时间的1/20或5%。

垃圾收集所花费的时间是所有垃圾收集引起的暂停的总时间。如果未满足吞吐量目标,则垃圾收集器的一个可能操作是增加堆的大小,以便在收集暂停之间在应用程序中花费的时间可以更长。

脚印(Footprint)

如果已满足吞吐量和最大暂停时间目标,则垃圾收集器会减小堆的大小,直到无法满足其中一个目标(总是吞吐量目标)。

可以使用 -Xms=<nnn>-Xmx=<mmm> 分别设置垃圾收集器可以使用的最小和最大堆大小,以获得最小和最大堆大小。

调整策略

堆增大或缩小到支持所选吞吐量目标的大小。

了解堆调整策略,例如选择最大堆大小以及选择最大暂停时间目标。

除非您知道需要的堆大于默认的最大堆大小,否则不要为堆选择最大值。选择足以满足您应用的吞吐量目标。

应用程序行为的更改可能导致堆增长或缩小。例如,如果应用程序开始以更高的速率分配,则堆增长以保持相同的吞吐量。

如果堆增长到其最大大小并且未满足吞吐量目标,则最大堆大小对于吞吐量目标而言太小。

将最大堆大小设置为接近平台上的总物理内存的值,但不会导致应用程序的交换。再次执行应用程序。如果仍未满足吞吐量目标,则应用程序时间的目标对于平台上的可用内存来说太高。

如果可以满足吞吐量目标,但暂停时间过长,则选择最大暂停时间目标。选择最大暂停时间目标可能意味着您的吞吐量目标将无法满足,因此请选择对应用程序而言可接受的折衷的值。

当垃圾收集器试图满足竞争目标时,堆的大小通常会振荡。即使应用程序已达到稳定状态,也是如此。实现吞吐量目标(可能需要更大的堆)的压力与最大暂停时间和最小占用空间(两者都可能需要小堆)的目标竞争。

参考资料

https://docs.oracle.com/javase/9/gctuning/ergonomics.htm#JSGCT-GUID-DB4CAE94-2041-4A16-90EC-6AE3D91EC1F1

目录

java 内存模型入门系列教程-00

发布了481 篇原创文章 · 获赞 73 · 访问量 593万+
展开阅读全文

java8下的垃圾收集器(parallel scavenge),内存不足而引发的fullGC如何确定哪些对象进入老年代?

04-16

``` public static void main(String[] args) { byte[] b1=new byte[2*_10m];//分配20mb内存 byte[] b2=new byte[2*_10m];// 分配20mb内存 byte[] b_2=new byte[2*_10m];//分配20mb内存 byte[] b3=new byte[2*_10m];//分配20mb内存 byte[] b5=new byte[2*_10m];//分配20mb内存 byte[] b4=new byte[3*_10m];//分配30mb内存 System.out.println("------------"); byte[] b_6=new byte[4*_10m - 10000];//分配40mb内存 } ``` ``` -XX:InitialHeapSize=209715200 -XX:MaxHeapSize=209715200 -XX:MaxNewSize=104857600 -XX:NewSize=104857600 -XX:+PrintCommandLineFlags -XX:+PrintGC -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC [GC (Allocation Failure) [PSYoungGen: 68001K->1064K(92160K)] 68001K->62512K(194560K), 0.0429928 secs] [Times: user=0.14 sys=0.03, real=0.04 secs] [Full GC (Ergonomics) [PSYoungGen: 1064K->0K(92160K)] [ParOldGen: 61448K->62335K(102400K)] 62512K->62335K(194560K), [Metaspace: 3459K->3459K(1056768K)], 0.0150700 secs] [Times: user=0.09 sys=0.00, real=0.02 secs] ------------ [Full GC (Ergonomics) [PSYoungGen: 74897K->51200K(92160K)] [ParOldGen: 62335K->82707K(102400K)] 137233K->133907K(194560K), [Metaspace: 3460K->3460K(1056768K)], 0.0200246 secs] [Times: user=0.08 sys=0.02, real=0.02 secs] [Full GC (Allocation Failure) Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at com.learn.mq.MqApplicationTests.main(MqApplicationTests.java:40) [PSYoungGen: 51200K->51200K(92160K)] [ParOldGen: 82707K->82688K(102400K)] 133907K->133889K(194560K), [Metaspace: 3460K->3460K(1056768K)], 0.0101650 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] Heap PSYoungGen total 92160K, used 53438K [0x00000000f9c00000, 0x0000000100000000, 0x0000000100000000) eden space 81920K, 65% used [0x00000000f9c00000,0x00000000fd02f930,0x00000000fec00000) from space 10240K, 0% used [0x00000000fec00000,0x00000000fec00000,0x00000000ff600000) to space 10240K, 0% used [0x00000000ff600000,0x00000000ff600000,0x0000000100000000) ParOldGen total 102400K, used 82688K [0x00000000f3800000, 0x00000000f9c00000, 0x00000000f9c00000) object space 102400K, 80% used [0x00000000f3800000,0x00000000f88c03f0,0x00000000f9c00000) Metaspace used 3491K, capacity 4500K, committed 4864K, reserved 1056768K class space used 381K, capacity 388K, committed 512K, reserved 1048576K ``` 伊甸园内存:80 老年代内存:100 ------------下面的那一次gc日志 : PSYoungGen: 74897K->51200K(92160K)] [ParOldGen: 62335K->82707K(102400K) gc之前,伊甸园已使用内存为20+20+30,老年代为20+20+20 gc之后,伊甸园已使用内存为20+30,老年代为20+20+20+20 剩余内存 伊甸园:30 老年代:20 均不足以放下引起这次gc的40大小的对象,而这次gc如果把30移动到老年代,gc之后内存为: 伊甸园已使用内存为20+20,老年代为20+20+20+30 这样伊甸园剩余内存为40,放得下40的对象,也不用报错,为什么收集器没有这么做呢? 或者说收集器对于哪些对象提前进入老年代行为是怎么确定的呢? 大于eden/2的对象一定要 目前看起来是年龄比较大的进去了,可是最大的年龄也挺小啊~~ ps:为了避免其他因素,我把参数改为:-verbose:gc -XX:+PrintGCDetails -Xmn105M -Xmx205M -Xms205M -XX:SurvivorRatio=8 -XX:+PrintCommandLineFlags后,得到了同样的结果 问答

JVM中奇怪的Full GC, 大家帮忙分析下

02-03

下面的gc log中的full gc是怎么触发的,理解不了,请大神看看~ ``` 2015-02-03T14:40:12.029+0800: 470.095: [GC [PSYoungGen: 1271672K->13218K(3940864K)] 1374109K->115656K(8135168K), 0.0061610 secs] [Times: user=0.05 sys=0.00, real=0.00 secs] 2015-02-03T14:40:12.036+0800: 470.101: [Full GC [PSYoungGen: 13218K->0K(3940864K)] [ParOldGen: 102437K->98542K(4194304K)] 115656K->98542K(8135168K) [PSPermGen: 64633K->64632K(262144K)], 0.3928440 secs] [Times: user=3.18 sys=0.02, real=0.40 secs] 2015-02-03T14:43:12.622+0800: 650.688: [GC [PSYoungGen: 2750752K->24677K(3932160K)] 2849294K->123219K(8126464K), 0.0274110 secs] [Times: user=0.06 sys=0.10, real=0.03 secs] 2015-02-03T14:43:12.650+0800: 650.715: [Full GC [PSYoungGen: 24677K->0K(3932160K)] [ParOldGen: 98542K->108727K(4194304K)] 123219K->108727K(8126464K) [PSPermGen: 65137K->65128K(262144K)], 0.4234160 secs] [Times: user=3.40 sys=0.03, real=0.42 secs] 2015-02-03T14:43:27.212+0800: 665.277: [GC [PSYoungGen: 828133K->12061K(3961344K)] 936860K->120788K(8155648K), 0.0092620 secs] [Times: user=0.05 sys=0.02, real=0.01 secs] 2015-02-03T14:43:27.221+0800: 665.287: [Full GC [PSYoungGen: 12061K->0K(3961344K)] [ParOldGen: 108727K->101742K(4194304K)] 120788K->101742K(8155648K) [PSPermGen: 65191K->65191K(262144K)], 0.2733550 secs] [Times: user=2.09 sys=0.01, real=0.27 secs] ``` 1. 从日志可以看出一些规律来,每次做完一次young gc会立马做一次full gc(时间几乎一致),此时young 区大小会变为0(开始大小和上一次young gc完的大小是一致的) 2. jdk版本为 1.7.0_55 3. JVM参数 -Xmx8192m -Xms8192m -XX:NewSize=4096m -XX:MaxNewSize=4096m -XX:SurvivorRatio=4 -XX:MaxPermSize=256m -XX:PermSize=256m 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览