后续的JVM参数分析都在这里整理
#-Xss1m 设置每个线程的堆栈大小
#-XX:+UseParNewGC 设置年轻代为并行收集。
#-XX:+UseConcMarkSweepGC 设置并发收集器
#-XX:+CMSParallelRemarkEnabled 表示并行remark
#-XX:+UseCMSCompactAtFullCollection 打开对年老代的压缩。可能会影响性能,但是可以消除碎片
#-XX:+UseFastAccessorMethods 原始类型的快速优化
#-XX:+UseCMSInitiatingOccupancyOnly 使用手动定义初始化定义开始CMS收集
#-XX:+UseCompressedOops
#-XX:-ReduceInitialCardMarks
#-XX:CMSInitiatingOccupancyFraction=75
#-XX:SurvivorRatio=3 survivor和eden的比值为1:3
#-XX:+DisableExplicitGC
#-XX:-UseAdaptiveSizePolicy
1.-Xms100m -Xmx100m
ms:minus即最小内存,jvm启动的时候初始化内存,如果ms和mx不相同则jvm的内存会根据使用情况动态调整,一般设置两个值相同。
ms,mx的内存是指young和tenured两块的内存,有些blog说这个是整个jvm的内存包含permgen的内存,实际是不正确的。可以通过jstat -gc来计算出来的,详情见截图。
S0C+S1C+EC+OC=102400也就是100M
2.-Xmn 指定young内存的大小
指定-Xmn50M 通过计算就可以得出young和old区域分别是50M
3.-XX:PermSize -XX:MaxPermSize
-XX:PermSize jvm初始化永久代的大小,-XX:MaxPermSize jvm最大的永久代大小。
此处设置100M可以看出来永久代的确是100M。young和tunured堆内存不受影响。
4.-XX:NewRatio=4
设置young和tenured的比值1:4 100M的话则tenured的内存为80M。
5.-XX:SurvivorRatio=3
survivor和eden的比值为1:3 所以survivor占用内存的1/5。
6.-XX:MaxTenuringThreshold=n
设置对象在young区域复制的次数,超过这个次数存活的对象拷贝至old区域。
验证这个参数,过程还是挺纠结的,先把纠结的过程记录下吧,测试代码如下。
public class TestOOM { public static void main(String[] args) throws InterruptedException { List list=new ArrayList(); OOM oom=new OOM(); Thread.sleep(20*1000); for(int i=0;i<15;i++){ // System.out.println(i); // list.add(new OOM()); OOM xx=new OOM(); xx=null; Thread.sleep(2*1000); } } } class OOM{ byte[] bytes=new byte[1024*1024*8]; }
第一次尝试,
java -Xms100M -Xmx100M -Xmn30M -XX:SurvivorRatio=1 TestOOM
heap分配100M,young 30M XX:SurvivorRatio=1这样eden,survivor都是10M了。预想第一次分配的8M对象进入Eden,后面再分配对象的时候肯定会出现minor gc,这样不断的分配对象,不断的设置成null,这样就会不断的出现minor gc超过一定的次数就会进入tenured区域。可是发现实际的结果还是与想象的差别很大,因为对象直接就在tenured区域中分配了,而且tenured区域满的时候开始minor gc了。
确实大对象会直接进入tenured区域,这就引出了另外一个参数, -XX:PretenureSizeThreshold,这个参数的值只能是B,字节。
第二次尝试,可以设置超过10M的对象才能进入tenured区域。
java -Xms100M -Xmx100M -Xmn30M -XX:SurvivorRatio=1 -XX:PretenureSizeThreshold=10485760 TestOOM
不过发现这个参数不灵光,这个8M的对象还是直接进入了tenured区域。也是上面的现象tenured区域满的时候开始minor gc了。
哎,这个参数不灵光啊,突然又有个新的想法,为何不把tenured区域的参数设置小于8M,这样用户不就进不去了,这样不就一直在young区域gc了吗,此时小小得意了一下,心想这不就没有问题了。
第三次尝试,
java -Xms35M -Xmx35M -Xmn30M -XX:SurvivorRatio=1 -XX:MaxTenuringThreshold=10 TestOOM
虽然这次按照预想的在young区域进行minor gc但是又有新的问题啦,minor gc 6次之后竟然报oom。
所以怀疑是不是jvm内部机制如果minor gc 6次内存没有减的话就会报错,于是乎猜想如果-XX:MaxTenuringThreshold=3是不是三次之后就会将对象进入tenured区域,但是此时发现tenured区域没有足够的空间此时会抛oom错误呢。
第四次尝试,
java -Xms35M -Xmx35M -Xmn30M -XX:SurvivorRatio=1 -XX:MaxTenuringThreshold=3 TestOOM
还是以失败告终啊,竟然还是minor gc 6次之后才报错啊,是在不明白了,有大神给解读下这是为什么吗?
相关推荐
在Eclipse的安装目录下找到`eclipse.ini`文件,添加或修改`-vm`参数指向新安装的JDK的`bin`目录下的`javaw.exe`或`java.exe`。 通过上述方法,通常可以成功解决Eclipse启动时出现的“Incompatible JVM”问题。在...
方法逃逸是指在一个方法体内,定义一个局部变量,而它可能被外部方法引用,比如作为调用参数传递给方法,或作为对象直接返回。线程逃逸是指这个对象被其他线程访问到,比如赋值给了实例变量,并被其他线程访问到了。...
通过合理设置JVM参数,我们可以优化内存使用,减少垃圾回收带来的性能影响,同时避免依赖不确定的`finalize()`方法来管理资源。在开发Java应用时,应尽量减少对垃圾回收机制的干预,让JVM自行管理内存,以实现更高效...
### Java中main()方法浅析 #### 一、概述 在Java编程语言中,`main()`方法具有特殊的意义,它是所有Java应用程序的起点。当Java虚拟机(JVM)启动并加载了一个包含`main()`方法的类时,它会自动调用这个方法来开始...
这个参数是由JVM负责赋值的,JVM会将命令行参数传递给这个数组。例如,在dos命令行中运行Java程序时,可以在类名后加上一个或者多个字符串(以空格隔开),这时JVM会依次将这些数值赋给args数组。 main()方法的...
### 浅析JAVA异常处理机制 #### 一、Java异常处理机制概述 异常处理是Java语言中的一个重要机制,它能够确保程序在遇到不可预料的情况时仍能维持稳定运行。异常处理主要包括三个方面:捕获异常、控制程序流程以及...
在启动JVM时,添加`-Dfile.encoding=UTF-8`参数,确保整个运行环境使用UTF-8编码。 其次,当涉及文件读写或网络数据传输时,输出流和输入流的编码必须与预期编码一致。例如,当我们写入文件时,应明确指定输出流的...
### Java中堆内存与栈内存分配浅析 #### 一、引言 在Java编程语言中,内存管理是一项至关重要的技术。程序运行时所使用的内存主要分为两类:堆内存(Heap Memory)和栈内存(Stack Memory)。理解这两种内存类型的...
Notes 我的笔记: 知识不总结,就会被大脑当垃圾清理 :horse:求知之路必然不会...Apache的MaxClients参数详解及其在Tomcat执行FullGC时的影响 JavaEE 浅析Web容器 计算机网络 UDP&TCP DB MySQL索引背后的数据结构
这在定义常量时非常有用,例如在数学公式或配置参数中。例如: ```java final double PI = 3.14159; ``` 这里的`PI`变量一旦赋值后,就无法更改。`final`常量在类加载时会被静态初始化,确保了其在整个程序运行...
方法表包含了方法的访问控制标志、返回类型、名称、参数列表和字节码指令等。 6) 属性:属性(Attribute)是Class文件中的元数据,可以提供额外的信息,如方法的异常处理、代码行数、注解等。JVM规范定义了一些标准...
字节码的表示方式通常使用类型签名,这是JVM用来表示方法参数和返回值类型的字符串形式。 类型签名是一种规范,例如`long f (int n, String s, int[] arr)`的类型签名是`f(ILjava/lang/String;[I)J`,它由方法名、...
1. 分配内存:Java虚拟机(JVM)在堆内存中为新对象分配所需的空间。这个过程包括为对象的所有字段分配内存。 2. 初始化:接下来,对对象的成员变量进行默认初始化。例如,基本类型变量会被赋予默认值,引用类型...
2. 具有一个无参数的构造器,以便容器可以实例化Bean。 3. 实现`Serializable`接口,以便支持序列化,实现对象持久化。 4. 属性通常是私有的,通过getter和setter方法进行访问控制。 5. 可能包含事件监听器和属性...
`Class.forName()`方法内部调用了本地方法`forName0`,并传入了一个布尔参数`initialize`,默认值为`true`,表示在加载类之后执行初始化。初始化阶段不仅包括对类变量的赋值,还包括执行静态初始化块,对于父类也是...
这样,你可以将Runnable对象作为参数传递给Thread类的构造函数,创建Thread对象,然后启动线程。 ```java public class MyRunnable implements Runnable { @Override public void run() { // 这里编写线程要执行...
JNI是一个规范,它定义了Java虚拟机(JVM)如何与本地代码(通常为C/C++)交互。通过JNI,Java程序员可以调用本地方法,反之,本地代码也可以调用Java方法。 2. **JNI的用途**: - **性能提升**:对于计算密集型...
<BR>3、常见异常实例包括:数组下标越界,算法溢出(超出数值表达范围),除数为零,无效参数、内存溢出异常处理功能:主要处理一些同步异常(除数为0),不宜处理一些异步事件(Disk I/O End、网络信息到达、点击...