首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

java 内存错误

2014-01-22 
java 内存异常转载?http://blog.csdn.net/cutesource/article/details/8244250?最近在看《深入理解Java虚拟

java 内存异常

转载?http://blog.csdn.net/cutesource/article/details/8244250

?

最近在看《深入理解Java虚拟机》,书中给了几个例子,比较好的说明了几种OOM(OutOfMemory)产生的过程,大部分的程序员在写程序时不会太关注Java运行时数据区域的结构:

java 内存错误

感觉有必要通过几个实在的例子来加深对这几个区域的了解

1)Java堆

所有对象的实例分配都在Java堆上分配内存,堆大小由-Xmx和-Xms来调节,sample如下所示:

?

[java]?view plaincopy?
  1. public?class?HeapOOM?{??
  2. ??????
  3. ????static?class?OOMObject{}??
  4. ??
  5. ????/**?
  6. ?????*?@param?args?
  7. ?????*/??
  8. ????public?static?void?main(String[]?args)?{??
  9. ????????List<OOMObject>?list?=?new?ArrayList<OOMObject>();??
  10. ??????????
  11. ????????while(true){??
  12. ????????????list.add(new?OOMObject());??
  13. ????????}??
  14. ????}??
  15. ??
  16. }??


加上JVM参数-verbose:gc -Xms10M -Xmx10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+HeapDumpOnOutOfMemoryError,就能很快报出OOM:

?

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

并且能自动生成Dump。

2)方法区

方法区是存放虚拟机加载类的相关信息,如类、静态变量和常量,大小由-XX:PermSize和-XX:MaxPermSize来调节,类太多有可能撑爆永久带:

?

[java]?view plaincopy?
  1. public?class?MethodAreaOOM?{??
  2. ??????
  3. ????static?class?OOMOjbect{}??
  4. ??
  5. ????/**?
  6. ?????*?@param?args?
  7. ?????*/??
  8. ????public?static?void?main(String[]?args)?{??
  9. ????????//?TODO?Auto-generated?method?stub??
  10. ????????while(true){??
  11. ????????????Enhancer?eh?=?new?Enhancer();??
  12. ????????????eh.setSuperclass(OOMOjbect.class);??
  13. ????????????eh.setUseCache(false);??
  14. ????????????eh.setCallback(new?MethodInterceptor(){??
  15. ??
  16. ????????????????@Override??
  17. ????????????????public?Object?intercept(Object?arg0,?Method?arg1,??
  18. ????????????????????????Object[]?arg2,?MethodProxy?arg3)?throws?Throwable?{??
  19. ????????????????????//?TODO?Auto-generated?method?stub??
  20. ????????????????????return?arg3.invokeSuper(arg0,?arg2);??
  21. ????????????????}??
  22. ??????????????????
  23. ????????????});??
  24. ????????????eh.create();??
  25. ????????}??
  26. ????}??
  27. ??
  28. }??


加上永久带的JVM参数:-XX:PermSize=10M -XX:MaxPermSize=10M,运行后会报如下异常:

?

Exception in thread "main" java.lang.OutOfMemoryError: PermGen space

静态变量或常量也会有可能撑爆方法区:

?

[java]?view plaincopy?
  1. public?class?ConstantOOM?{??
  2. ??
  3. ????/**?
  4. ?????*?@param?args?
  5. ?????*/??
  6. ????public?static?void?main(String[]?args)?{??
  7. ????????//?TODO?Auto-generated?method?stub??
  8. ????????List<String>?list?=?new?ArrayList<String>();??
  9. ????????int?i=0;??
  10. ????????while(true){??
  11. ????????????list.add(String.valueOf(i++).intern());??
  12. ????????}??
  13. ????}??
  14. ??
  15. }??


同样加上JVM参数:-XX:PermSize=10M -XX:MaxPermSize=10M,运行后报如下异常:

?

Exception in thread "main" java.lang.OutOfMemoryError: PermGen space

3)Java栈和本地方法栈

栈是存放线程调用方法时存储局部变量表,操作,方法出口等与方法执行相关的信息,栈大小由Xss来调节,方法调用层次太多会撑爆这个区域,samples如下所示:

?

[java]?view plaincopy?
  1. package?com.cutesource;??
  2. ??
  3. public?class?StackOOM?{??
  4. ??
  5. ????/**?
  6. ?????*?@param?args?
  7. ?????*/??
  8. ??????
  9. ????private?int?stackLength?=?1;??
  10. ??????
  11. ????public?void?stackLeak(){??
  12. ????????stackLength++;??
  13. ????????stackLeak();??
  14. ????}??
  15. ??????
  16. ????public?static?void?main(String[]?args)?throws?Throwable{??
  17. ????????//?TODO?Auto-generated?method?stub??
  18. ????????StackOOM?oom?=?new?StackOOM();??
  19. ????????try{??
  20. ????????????oom.stackLeak();??
  21. ????????}catch(Throwable?err){??
  22. ????????????System.out.println("Stack?length:"?+?oom.stackLength);??
  23. ????????????throw?err;??
  24. ????????}??
  25. ??????????
  26. ????}??
  27. ??
  28. }??


设置JVM参数:-Xss128k,报出异常:

?

Exception in thread "main" java.lang.StackOverflowError

打印出Stack length:1007,这里可以看出,在我的机器上128k的栈容量能承载深度为1007的方法调用。当然报这样的错很少见,一般只会出现无限循环的递归中,另外,线程太多也会占满栈区域:

?

[java]?view plaincopy?
  1. package?com.cutesource;??
  2. ??
  3. public?class?StackOOM?{??
  4. ??
  5. ????/**?
  6. ?????*?@param?args?
  7. ?????*/??
  8. ??????
  9. ????private?int?stackLength?=?1;??
  10. ??????
  11. ????private?void?dontStop(){??
  12. ????????while(true){??
  13. ????????????try{Thread.sleep(1000);}catch(Exception?err){}??
  14. ????????}??
  15. ????}??
  16. ??????
  17. ????public?void?stackLeakByThread(){??
  18. ????????while(true){??
  19. ????????????Thread?t?=?new?Thread(new?Runnable(){??
  20. ??
  21. ????????????????@Override??
  22. ????????????????public?void?run()?{??
  23. ????????????????????//?TODO?Auto-generated?method?stub??
  24. ????????????????????dontStop();??
  25. ????????????????}??
  26. ??????????????????
  27. ????????????});??
  28. ????????????t.start();??
  29. ????????????stackLength++;??
  30. ????????}??
  31. ????}??
  32. ??????
  33. ????public?static?void?main(String[]?args)?throws?Throwable{??
  34. ????????//?TODO?Auto-generated?method?stub??
  35. ????????StackOOM?oom?=?new?StackOOM();??
  36. ????????try{??
  37. ????????????oom.stackLeakByThread();??
  38. ????????}catch(Throwable?err){??
  39. ????????????System.out.println("Stack?length:"?+?oom.stackLength);??
  40. ????????????throw?err;??
  41. ????????}??
  42. ??????????
  43. ????}??
  44. ??
  45. }??


报出异常:Exception in thread "main" java.lang.OutOfMemoryError:unable to create new native thread

?

不过在windows上运行这个例子要小心,会出现系统假死的情况,有可能需要重启机器才行。

以上几个例子虽然比较简单,但能很好帮助普通的程序员更加直观的了解Java堆方法区Java栈和本地方法

热点排行