vm调试配置实验

分析工具:   Eclipse Memory Analyzer

图解jvm内存结构:


Java堆溢出:

package jvm;

import java.util.ArrayList;
import java.util.List;

/**
 * -verbose:gc -Xms20M -Xmx20M -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDetails
 * 
 * @author xlj
 */
public class HeapOOM {

	public static void main(String[] args) {
		List<OOMObject> list = new ArrayList<OOMObject>();
		while (true) {
			list.add(new OOMObject());
		}
	}
}

class OOMObject {
}

-verbose:gc  -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDetails表示打印信息,产生hprof分析文件(项目根目录)

1、-Xms :表示java虚拟机堆区内存初始内存分配的大小

2、-Xmx: 表示java虚拟机堆区内存可被分配的最大上限

1、-XX:newSize:表示新生代初始内存的大小,应该小于 -Xms的值;
2、-XX:MaxnewSize:表示新生代可被分配的内存的最大上限;当然这个值应该小于 -Xmx的值;

1、 -XX:PermSize:表示非堆区初始内存分配大小,其缩写为permanent size(持久化内存)方法区
2、 -XX:MaxPermSize:表示对非堆区分配的内存的最大上限。
    

[GC [PSYoungGen: 5416K->504K(6656K)] 5416K->3681K(20480K), 0.0066120 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 

[GC [PSYoungGen: 6043K->504K(6656K)] 9220K->8232K(20480K), 0.0060092 secs] [Times: user=0.05 sys=0.02, real=0.01 secs] 
[Full GC [PSYoungGen: 6648K->0K(6656K)] [ParOldGen: 10893K->13330K(13824K)] 17541K->13330K(20480K) [PSPermGen: 2614K->2614K(21504K)], 0.1963102 secs] [Times: user=0.41 sys=0.00, real=0.20 secs] 
[Full GC [PSYoungGen: 3031K->3001K(6656K)] [ParOldGen: 13330K->13330K(13824K)] 16361K->16331K(20480K) [PSPermGen: 2614K->2614K(21504K)], 0.1339469 secs] [Times: user=0.38 sys=0.00, real=0.13 secs] 
[Full GC [PSYoungGen: 3001K->3001K(6656K)] [ParOldGen: 13330K->13318K(13824K)] 16331K->16320K(20480K) [PSPermGen: 2614K->2614K(21504K)], 0.1357866 secs] [Times: user=0.42 sys=0.00, real=0.13 secs] 
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid17220.hprof ...
Heap dump file created [27972051 bytes in 0.106 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2245)
at java.util.Arrays.copyOf(Arrays.java:2219)
at java.util.ArrayList.grow(ArrayList.java:242)
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:216)
at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:208)
at java.util.ArrayList.add(ArrayList.java:440)
at jvm.HeapOOM.main(HeapOOM.java:16)
Heap
 PSYoungGen      total 6656K, used 3208K [0x00000000ff900000, 0x0000000100000000, 0x0000000100000000)
  eden space 6144K, 52% used [0x00000000ff900000,0x00000000ffc220e8,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
  to   space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
 ParOldGen       total 13824K, used 13318K [0x00000000feb80000, 0x00000000ff900000, 0x00000000ff900000)
  object space 13824K, 96% used [0x00000000feb80000,0x00000000ff881bd8,0x00000000ff900000)
 PSPermGen       total 21504K, used 2645K [0x00000000f9980000, 0x00000000fae80000, 0x00000000feb80000)

  object space 21504K, 12% used [0x00000000f9980000,0x00000000f9c156f8,0x00000000fae80000)


虚拟机栈和本地方法栈溢出:

由于在HotSpot虚拟机中并不区分虚拟机栈和本地方法栈,因此,对于HotSpot来说,虽然-Xoss参数(设置本地方法栈大小)存在,但实际上是无效的,栈容量只由-Xss参数设定。关于虚拟机栈和本地方法栈,在Java虚拟机规范中描述了两种异常:如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常。如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常。

package jvm;
/**
 * VM Args:-Xss128k
 * @author xlj
 */
public class JavaVMStackSOF {

	private int stackLength = 1;

	public void stackLeak() {
		stackLength++;
		stackLeak();
	}

	public static void main(String[] args) throws Throwable {
		JavaVMStackSOF oom = new JavaVMStackSOF();
		try {
			oom.stackLeak();
		} catch (Throwable e) {
			System.out.println("stack length:" + oom.stackLength);
			throw e;
		}
	}
}


stack length:988
Exception in thread "main" java.lang.StackOverflowError
at jvm.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:11)
at jvm.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:12)

………………

package jvm;


/**
 * VM Args:-Xss128k
 * 
 * @author xlj 虚拟机栈和本地方法栈溢出
 */
public class JavaVMStackSOF {


	private int stackLength = 1;


	public void stackLeak() {
		stackLength++;
		stackLeak();
	}


	public static void main(String[] args) throws Throwable {
		JavaVMStackSOF oom = new JavaVMStackSOF();
		try {
			oom.stackLeak();
		} catch (Throwable e) {
			System.out.println("stack length:" + oom.stackLength);
			throw e;
		}
	}
}

Exception in thread"main"java.lang.OutOfMemoryError:PermGen spaceat java.lang.String.intern(Native Method)at org.fenixsoft.oom.RuntimeConstantPoolOOM.main(RuntimeConstantPoolOOM.java:18)

2.4.3 方法区和运行时常量池溢出


package jvm;

import java.util.ArrayList;
import java.util.List;

/**
 * VM Args:-XX:PermSize=10M -XX:MaxPermSize=10M
 * @author xlj  运行时常量池导致的内存溢出异常
 */
public class RuntimeConstantPoolOOM {

	public static void main(String[] args) {
		// 使用List保持着常量池引用,避免Full GC回收常量池行为
		List<String> list = new ArrayList<String>();
		// 10MB的PermSize在integer范围内足够产生OOM了
		int i = 0; 
		while (true) {
			list.add(String.valueOf(i++).intern());
		}
	}
}



Error occurred during initialization of VM
java.lang.OutOfMemoryError: PermGen space
at sun.misc.Launcher.<init>(Launcher.java:71)
at sun.misc.Launcher.<clinit>(Launcher.java:57)
at java.lang.ClassLoader.initSystemClassLoader(ClassLoader.java:1489)
at java.lang.ClassLoader.getSystemClassLoader(ClassLoader.java:1474)

package jvm;
/**
 * jdk6 都是false
 * jdk7 true  false
 * @author xlj
 *这段代码在JDK 1.6中运行,会得到两个false,而在JDK 1.7中运行,会得到一个true和一
个false。产生差异的原因是:在JDK 1.6中,intern()方法会把首次遇到的字符串实例复制
到永久代中,返回的也是永久代中这个字符串实例的引用,而由StringBuilder创建的字符串
实例在Java堆上,所以必然不是同一个引用,将返回false。而JDK 1.7(以及部分其他虚拟
机,例如JRockit)的intern()实现不会再复制实例,只是在常量池中记录首次出现的实例
引用,因此intern()返回的引用和由StringBuilder创建的那个字符串实例是同一个。对str2比
较返回false是因为“java”这个字符串在执行StringBuilder.toString()之前已经出现过,字符串
常量池中已经有它的引用了,不符合“首次出现”的原则,而“计算机软件”这个字符串则是首
次出现的,因此返回true。
 */
public class RuntimeConstantPoolOOM1 {

	public static void main(String[] args) {
 		String str1 = new StringBuilder("中国").append("钓鱼岛").toString();
		System.out.println(str1.intern() == str1);
		
		String str2 = new StringBuilder("ja").append("va").toString();
		System.out.println(str2.intern() == str2);
	}	
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值