通过简单的小例子程序,演示java虚拟机各部分内存溢出情况:

(1).java堆溢出:

Java堆用于存储实例对象,只要不断创建对象,并且保证GC Roots到对象之间有引用的可达,避免垃圾收集器回收实例对象,就会在对象数量达到堆最大容量时产生OutOfMemoryError异常。

想要方便快速地产生堆溢出,要使用如下java虚拟机参数:-Xms10m(最小堆内存为10MB),-Xmx10m(最大堆内存为10MB,最小堆内存和最大堆内存相同是为了避免堆动态扩展),-XX:+HeapDumpOnOutOfMemoryError可以让java虚拟机在出现内存溢出时产生当前堆内存快照以便进行异常分析。

例子代码如下:

  1. public class HeapOOM{
  2. static class OOMObject{
  3. }
  4. public static void main(String[] args){
  5. List<OOMObject> list = new ArrayList<OOMObject>();
  6. while(true){
  7. list.add(new OOMObject());
  8. }
  9. }
  10. }

运行一段时间就会发现产生OutOfMemoryError异常,并且产生了堆内存异常dump文件。

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

由于Sun的HotSpot虚拟机不区分java虚拟机栈和本地方法栈,因此对于HotSpot虚拟机来说-Xoss参数(设置本地方法栈大小)虽然存在,但是实际上是无效的,栈容量只能由-Xss参数设定。

由于Java虚拟机栈会出现StackOverflowError和OutOfMemoryError两种异常,所以分别使用两个例子演示这两种情况:

a.java虚拟机栈深度溢出:

单线程的环境下,无论是由于栈帧太大,还是虚拟机栈容量太小,当内存无法再分配的时候,虚拟机总抛出StackOverflowError异常。使用-Xss128k将java虚拟机栈大小设置为128kb,例子代码如下:

  1. public class JavaVMStackOF{
  2. private int stackLength = 1;
  3. public void stackLeak(){
  4. statckLength++;
  5. stackLeak();
  6. }
  7. public static void main(String[] args){
  8. JavaVMStackOF oom = new JavaVMStackOF();
  9. oom.stackLeak();
  10. }
  11. }

运行一段时间后,产生StackOverflowError异常。Java虚拟机栈溢出一般会产生在方法递归调用过多而java虚拟机栈内存不够的情况下。

b.java虚拟机栈内存溢出:

多线程环境下,能够创建的线程最大内存=物理内存-最大堆内存-最大方法区内存,在java虚拟机栈内存一定的情况下,单个线程占用的内存越大,所能创建的线程数目越小,所以在多线程条件下很容易产生java虚拟机栈内存溢出的异常。

使用-Xss2m参数设置java虚拟机栈内存大小为2MB,例子代码如下:

  1. public class JavaVMStackOOM{
  2. private void dontStop(){
  3. while(true){
  4. }
  5. }
  6. public void stackLeakByThread(){
  7. while(true){
  8. Thread t = new Thread(new Runnable(){
  9. public void run(){
  10. dontStop();
  11. }
  12. });
  13. t.start();
  14. }
  15. }
  16. public static void main(String[] args){
  17. JavaVMStackOOM oom = new JavaVMStackOOM();
  18. oom. stackLeakByThread();.
  19. }
  20. }

运行一段时间之后,java虚拟机栈就会因为内存太小无法创建线程而产生OutOfMemoryError。

(3).运行时常量池溢出:

运行时常量池属于方法区的一部分,可以使用-XX:PermSize=10m和-XX:MaxPermSize=10m将永久代最大内存和最小内存设置为10MB大小,并且由于永久代最大内存和最小内存大小相同,因此无法扩展。

String的intern()方法用于检查常量池中如果有等于此String对象的字符串存在,则直接返回常量池中的字符串对象,否则,将此String对象所包含的字符串添加到运行时常量池中,并返回此String对象的引用。因此String的intern()方法特别适合演示运行时常量池溢出,例子代码如下:

  1. public class RuntimeConstantPoolOOM{
  2. public static void main(String[] args){
  3. List<String> list = new ArrayList<String>();
  4. int i = 0;
  5. while(true){
  6. list.add(String.valueOf(i++).intern());
  7. }
  8. }
  9. }

运行一段时间,永久代内存不够,运行时常量池因无法再添加常量而产生OutOfMemoryError。

(4).方法区溢出:

运行时常量池是方法区的一部分,他们都属于HotSpot虚拟机中的永久代内存区域。方法区用于存放Class的相关信息,Java的反射和动态代理可以动态产生Class,另外第三方的CGLIB可以直接操作字节码,也可以动态产生Class,实验通过CGLIB来演示,同样使用-XX:PermSize=10m和-XX:MaxPermSize=10m将永久代最大内存和最小内存设置为10MB大小,并且由于永久代最大内存和最小内存大小相同,因此无法扩展。例子代码如下:

  1. public class JavaMethodAreaOOM{
  2. public static void main(String[] args){
  3. while(true){
  4. Enhancer enhancer = new Enhancer();
  5. enhancer.setSuperClass(OOMObject.class);
  6. enhancer.setUseCache(false);
  7. enhancer.setCallback(new MethodInterceptor(){
  8. public Object intercept(Object obj, Method method, Object[] args,
  9. MethodProxy proxy)throws Throwable{
  10. return proxy.invokeSuper(obj, args);
  11. }
  12. });
  13. enhancer.create();
  14. }
  15. }
  16. class OOMObject{
  17. }
  18. }

运行一段时间之后,永久代内存不够,方法区无法再存放CGLIB创建处理的Class信息,产生方法区OutOfMemoryError。

(5).本机直接内存溢出:

Java虚拟机可以通过参数-XX:MaxDirectMemorySize设定本机直接内存可用大小,如果不指定,则默认与java堆内存大小相同。JDK中可以通过反射获取Unsafe类(Unsafe的getUnsafe()方法只有启动类加载器Bootstrap才能返回实例)直接操作本机直接内存。通过使用-XX:MaxDirectMemorySize=10M,限制最大可使用的本机直接内存大小为10MB,例子代码如下:

  1. public class DirectMemoryOOM{
  2. private static final int _1MB = 1024* 1024 * 1024;
  3. publc static void main(String[] args) throws Exception{
  4. Field unsafeField = Unsafe.class.getDeclaredFields()[0];
  5. unsafeField.setAccessible(true);
  6. Unsafe unsafe = (Unsafe) unsafeField.get(null);
  7. while(true){
  8. //unsafe直接想操作系统申请内存
  9. unsafe.allocateMemory(_1MB);
  10. }
  11. }
  12. }

当运行一段时间之后,10MB的本机直接内存被分配光,无法在进行直接内存分配时,产生OutOfMemoryError。

(转)《深入理解java虚拟机》学习笔记2——Java内存溢出实例的更多相关文章

  1. 《深入Java虚拟机学习笔记》- 第19章 方法的调用与返回

    <深入Java虚拟机学习笔记>- 第19章 方法的调用与返回

  2. 《深入Java虚拟机学习笔记》- 第16章 控制流

    <深入Java虚拟机学习笔记>- 第16章 控制流

  3. 《深入Java虚拟机学习笔记》- 第17章 异常

    <深入Java虚拟机学习笔记>- 第17章 异常

  4. 《深入Java虚拟机学习笔记》- 第13章 逻辑运算

    <深入Java虚拟机学习笔记>- 第13章 浮点运算

  5. 《深入Java虚拟机学习笔记》- 第14章 浮点运算

    <深入Java虚拟机学习笔记>- 第13章 浮点运算

  6. 《深入Java虚拟机学习笔记》- 第8章 连接模型

    Java虚拟机学习笔记(八)连接模型

  7. 《深入Java虚拟机学习笔记》- 第4章 网络移动性

    Java虚拟机学习笔记(四)网络移动性

  8. 《深入Java虚拟机学习笔记》- 第2章 平台无关

    Java虚拟机学习笔记(二)平台无关

  9. Java虚拟机学习笔记——JVM垃圾回收机制

    Java虚拟机学习笔记——JVM垃圾回收机制 Java垃圾回收基于虚拟机的自动内存管理机制,我们不需要为每一个对象进行释放内存,不容易发生内存泄漏和内存溢出问题. 但是自动内存管理机制不是万能药,我们 ...

  10. Java虚拟机系列(三)---内存溢出情况及解决方法

    因为Java虚拟机内存有堆内存.方法区.虚拟机栈.本地方法栈和程序计数器五部分组成,其中程序计数器是唯一一块不会发生内存溢出异常的内存区,所以只有四类内存区可能发生内存溢出异常,其中虚拟机栈和本地方法 ...

随机推荐

  1. 手把手教你使用Size Class

    在 iOS8 中,我们不用再像以前那样,一个页面新建多个 xib 文件来适配不同类型的屏幕,现在我们可以把各种尺寸屏幕的适配工作放在一个文件中完成,然后可以通过不同类别的 Size 来定制各种尺寸的界 ...

  2. Inaccurate values for “Currently allocated space” and “Available free space” in the Shrink File dialog for TEMPDB only

    转载自:http://blogs.msdn.com/b/ialonso/archive/2012/10/08/inaccurate-values-for-currently-allocated-spa ...

  3. Adobe Edge Animate –弹性的方块-使用tweenmax缓动效果

    Adobe Edge Animate –弹性的方块-使用tweenmax缓动效果 版权声明: 本文版权属于 北京联友天下科技发展有限公司. 转载的时候请注明版权和原文地址. 此前有Edge爱好者提出一 ...

  4. 关于64位Linux编译hadoop2

    Apache官方提供hadoop2的安装包是在32位机器下编译的,生产环境一般使用64的Linux,那么需要在64位机器下重新编译可以查看hadoop-2.2.0-src下的BUILDING.txtB ...

  5. Sublime Text3 包管理器、插件安装

    安装插件之前先要安装包管理器,包管理器的安装也很简单,复制粘贴对应版本命令代码回车即可 一.包管理器安装 1.打开Sublime3控制台,按ctrl+~ 2.输入安装包管理器命令行代码 3.注意需要联 ...

  6. 实现类似 QQ音乐网页版 的单页面总结

    最近需要对创业团队的网站进行改版,而我负责前端设计和实现. 下面是一些总结与体会: 当设计完成之前,我就跟和我配合的Java 后台说用iframe实现,结果说麻烦不肯,到最后突然对我说还是用ifram ...

  7. 小议jQuery中的事件

    学了jQuery这么长时间,到这里真的有一种柳暗花明又一村的感觉,在这里先表达一下自己学这一章节的happy心情吧(在严厉的金工实习老师眼皮底下偷偷学习,当然还有各种nerves~). 1加载DOM ...

  8. Category

    Category 首先我们来谈谈Category. Objective-C提供了一种与众不同的方式——Catagory,可以动态的为已经存在的类添加新的行为.这样可以保证类的原始设计规模较小,功能增加 ...

  9. StrictMode模式介绍

    最新的Android平台中(Android 2.3起),新增加了一个新的类,叫StrictMode(android.os.StrictMode).这个类可以用来帮助开发者改进他们编写的应用,并且提供了 ...

  10. 验证hashmap非线程安全

    http://www.blogjava.net/lukangping/articles/331089.html final HashMap<String, String> firstHas ...