java虚拟机学习(三) 内存溢出异常

  1. java 堆溢出:

    在eclipse中测试时,可以在Debug/Run中设置虚拟机参数,比如-xmx 20M 代表虚拟机堆内存大小最大值是20M,-xms是最小堆内存。然后写个死循环测试类不断在List集合中添加对象, 当堆内存超出20M ,会报OutOfMemory异常。

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

    一个线程中如果,方法的深度超过了虚拟机允许的深度 ,会报StackOverFlow异常,比如递归调用方法。这个异常容易去实现,另一种是java虚拟机栈在扩展时如果无法申请到内存,则会报OutOfMemory异常。

public class Main {

	private static int count=0;

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try{
			deap();
		}catch(Exception ex){
			ex.printStackTrace();

		}

	}

	private static void deap(){
		count++;
		System.out.println(count);
		deap();
	}
}

在设置-Xss为1M 和 10M时, 输出的计数变量会差10倍左右,我的理解是虚拟机栈运行时其实就是java方法执行时内存模型,在无止境的递归时会向虚拟机栈中压入栈帧用于存储执行时的操作数,局部变量方法出口等信息。当这块内存满时,就会报栈溢出。

操作系统中系统限制了每一个进程的内存上限, 如果规定每个进程的内存大小上限为1GB, 那么在虚拟机中,方法区内存和堆内存可以通过虚拟机参数设置(xmx和 maxPerSize),虚拟机进程内存减去 堆内存和方法区的总内存,如果忽略计数器和虚拟机本身执行所消耗的内存(这两部分占的内存很小),基本上剩下的内存会被虚拟机栈和本地方法栈瓜分。 每一个线程分配到的虚拟机栈内存越大,那么可以创建的线程数量就越少。

3.方法区和运行时常量池溢出:

方法区内存大小设置可以通过虚拟机参数 -XX:PermSize 和 -XX:MaxPermSize来设置,java 1.6环境中以下代码可以实现方法区常量池内存溢出:

public static void main(String[] args) {
		// TODO Auto-generated method stub
		int i=0;
		ArrayList<String> list=new ArrayList<String>();

		while(true){
			list.add(String.valueOf(i++).intern());
		}

	}

这里String.intern()方法的作用是字符串常量池中如果存在一个等于这个String对象的字符串,则返回引用,否则会将此字符串存入常量池,java 1.6中常量池是分配在永久代内存中,gc几乎不会去回收,所以常量池内存会溢出(1.7 虚拟机中已将字符串常量池从永久代移除), 填充方法区内存可以使用gclib来创建大量的类,因为方法区用于存放类Class的相关信息用的,比如类名,访问修饰符,常量池等, Spring,OSGI等主流框架会遇到这样的问题,这类框架都需要加载大量的类,而回收一个类判定条件比较苛刻,在方法区内存分配小时会报OutOfMemoryError:PerGen space异常,即方法区溢出。

4.本机内存溢出:

DirectMemory 容量可以通过设置虚拟机参数 -XX:MaxDirectMemorySize来设定,实验方法: 设置了直接内存上限后,不断地通过unsafe类的allocateMemory()方法去申请内存,当达到上限时会报:OutOfMemory异常.

参考连接:

http://lavasoft.blog.51cto.com/62575/25492/

时间: 2024-08-05 20:50:11

java虚拟机学习(三) 内存溢出异常的相关文章

Java虚拟机4:内存溢出

http://www.cnblogs.com/xrq730/p/4833713.html 堆溢出 Java堆唯一的作用就是存储对象实例,只要保证不断创建对象并且对象不被回收,那么对象数量达到最大堆容量限制后就会产生内存溢出异常了.所以测试的时候把堆的大小固定住并且让堆不可扩展即可.测试代码如下 package com.xrq.test; import java.util.ArrayList; import java.util.List; /** * 测试内容:堆溢出 * * 虚拟机参数:-Xms

java虚拟机学习-JVM内存管理:深入Java内存区域与OOM(3)

概述 Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 对于从事C.C++程序开发的开发人员来说,在内存管理领域,他们即是拥有最高权力的皇帝又是执行最基础工作的劳动人民——拥有每一个对象的“所有权”,又担负着每一个对象生命开始到终结的维护责任. 对于Java程序员来说,不需要在为每一个new操作去写配对的delete/free,不容易出现内容泄漏和内存溢出错误,看起来由JVM管理内存一切都很美好.不过,也正是因为Java程序员把内存控制的

Java虚拟机6:内存溢出和内存泄露、并行和并发、Minor GC和Full GC、Client模式和Server模式的区别

http://www.cnblogs.com/xrq730/p/4839245.html 前言 之前的文章尤其是讲解GC的时候提到了很多的概念,比如内存溢出和内存泄露.并行与并发.Client模式和Server模式.Minor GC和Full GC,本文详细讲解下这些概念的区别. 内存溢出和内存泄露的区别 1.内存溢出 内存溢出指的是程序在申请内存的时候,没有足够大的空间可以分配了. 2.内存泄露 内存泄露指的是程序在申请内存之后,没有办法释放掉已经申请到内存,它始终占用着内存,即被分配的对象可

Java虚拟机学习 - 体系结构 内存模型(1)

一:Java技术体系模块图 二:JVM内存区域模型 1.方法区 也称"永久代" ."非堆",  它用于存储虚拟机加载的类信息.常量.静态变量.是各个线程共享的内存区域.默认最小值为16MB,最大值为64MB,可以通过-XX:PermSize 和 -XX:MaxPermSize 参数限制方法区的大小. 运行时常量池:是方法区的一部分,Class文件中除了有类的版本.字段.方法.接口等描述信息外,还有一项信息是常量池,用于存放编译器生成的各种符号引用,这部分内容将在类加

java虚拟机学习-JVM内存管理:深入垃圾收集器与内存分配策略(4)

Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 说起垃圾收集(Garbage Collection,下文简称GC),大部分人都把这项技术当做Java语言的伴生产物.事实上GC的历史远远比Java来得久远,在1960年诞生于MIT的Lisp是第一门真正使用内存动态分配和垃圾收集技术的语言.当Lisp还在胚胎时期,人们就在思考GC需要完成的3件事情:哪些内存需要回收?什么时候回收?怎么样回收? 经过半个世纪的发展,目前的内存分配策略

Java虚拟机学习 - 体系结构 内存模型

一:Java技术体系模块图 二:JVM内存区域模型 1.方法区 也称"永久代" ."非堆",  它用于存储虚拟机加载的类信息.常量.静态变量.是各个线程共享的内存区域.默认最小值为16MB,最大值为64MB,可以通过-XX:PermSize 和 -XX:MaxPermSize 参数限制方法区的大小. 运行时常量池:是方法区的一部分,Class文件中除了有类的版本.字段.方法.接口等描述信息外,还有一项信息是常量池,用于存放编译器生成的各种符号引用,这部分内容将在类加

Java虚拟机学习 - 体系结构 内存模型(转载)

一:Java技术体系模块图 二:JVM内存区域模型 1.方法区 也称"永久代” .“非堆”,  它用于存储虚拟机加载的类信息.常量.静态变量.是各个线程共享的内存区域.默认最小值为16MB,最大值为64MB,可以通过-XX:PermSize 和 -XX:MaxPermSize 参数限制方法区的大小. 运行时常量池:是方法区的一部分,Class文件中除了有类的版本.字段.方法.接口等描述信息外,还有一项信息是常量池,用于存放编译器生成的各种符号引用,这部分内容将在类加载后放到方法区的运行时常量池中

如何写出让java虚拟机发生内存溢出异常OutOfMemoryError的代码

程序小白在写代码的过程中,经常会不经意间写出发生内存溢出异常的代码.很多时候这类异常如何产生的都傻傻弄不清楚,如果能故意写出让jvm发生内存溢出的代码,有时候看来也并非一件容易的事.最近通过学习<深入理解java虚拟机-JVM高级特性与最佳实践>这本书,终于初步了解了一下java虚拟机的内存模型.本文通过写出使jvm发生内存溢出异常的代码来对自己的学习结果进行总结,同时也提醒自己以后写代码时候不要再跳进这个坑啦. java的内存管理是由java虚拟机自动进行管理的,并不需要程序员过多的手动干预

深入理解java虚拟机学习 笔记 第二章 java 内存区域和内存溢出异常

2.2 运行时区域 java虚拟机划分成若干个不同的数据区域, 1.程序计数器,字节码解释器工作时就是通过改变计数器的值来取吓一跳需要执行的字节码命令 了解 String.intern()方法 作用: 如果字符串常量池中一个包含了一个等于此String对象的字符串,则返回代表池中的这个字符串的String对象,否则将此对象包含的字符串添加到常量池中,并返回此String对象的引用. 实战 将堆的最小值 -Xms参数与最大值-Xmx参数设置为一样即可避免堆自动扩展  通过参数 -XX:+HeapD

java虚拟机学习-触摸java常量池(13)

java虚拟机学习-深入理解JVM(1) java虚拟机学习-慢慢琢磨JVM(2) java虚拟机学习-慢慢琢磨JVM(2-1)ClassLoader的工作机制 java虚拟机学习-JVM内存管理:深入Java内存区域与OOM(3) java虚拟机学习-JVM内存管理:深入垃圾收集器与内存分配策略(4) java虚拟机学习-JVM调优总结(5) java虚拟机学习-JVM调优总结(6) java虚拟机学习-JVM调优总结-基本垃圾回收算法(7) java虚拟机学习-JVM调优总结-垃圾回收面临的