经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Java » 查看文章
JVM 常见错误汇总
来源:cnblogs  作者:HOsystem  时间:2023/7/28 9:42:11  对本文有异议

栈内存溢出

栈内存错误包括:栈帧过多(StackOverflowError)、栈帧过大(OutOfMemoryError)

  • StackOverflowError:如果线程请求的栈深度大于虚拟机所允许的最大深度;
  • OutOfMemoryError:如果虚拟机的占内存允许动态扩展,当扩展容量无法申请到足够的内存时;

栈帧过多

  1. /**
  2. * 栈帧过多导致内存溢出演示
  3. * java.lang.StackOverflowError
  4. *
  5. * -Xss256k 设置栈内存大小
  6. */
  7. public class StackOverflowDemo {
  8. private static int count;
  9. public static void main(String[] args) {
  10. try {
  11. method1();
  12. }catch (Throwable e){
  13. e.printStackTrace();
  14. System.out.println(count);
  15. }
  16. }
  17. private static void method1() {
  18. count++;
  19. method1();
  20. }
  21. }

栈帧过大

  1. /**
  2. * 栈帧过大导致内存溢出演示
  3. * Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
  4. *
  5. * -Xss256k 设置栈内存大小
  6. *
  7. *《Java虚拟机规范》明确允许Java虚拟机实现自行选择是否支持栈的动态扩展, 而HotSpot虚拟机的选择不支持扩展;
  8. * 结论:无论式由于栈帧太大还是虚拟机容量太小, 当新的栈帧内存无法分配的时候, HotSpot虚拟机抛出的都是StackOverflowError异常;
  9. * 若在允许动态扩展栈容量大小的虚拟机上, 结果就会导致不一样的错误; 如Classic虚拟机, 则会出现java.lang.OutOfMemoryError;
  10. * 若测试不限于单线程, 通过不断建立线程的方式, 在HotSpot也可以产生内存溢出异常;代码如下, 现象不容易出现;
  11. * 注: Java的线程时映射到操作系统的内核线程上的, 因此代码执行时有较大风险, 可能会导致操作系统假死;
  12. */
  13. public class Demo {
  14. private void dontStop() {
  15. while (true) {
  16. }
  17. }
  18. public void stackLeakByThread() {
  19. while (true) {
  20. Thread thread = new Thread(new Runnable() {
  21. @Override
  22. public void run() {
  23. dontStop();
  24. }
  25. });
  26. thread.start();
  27. }
  28. }
  29. public static void main(String[] args) throws Throwable {
  30. Demo oom = new Demo();
  31. oom.stackLeakByThread();
  32. }
  33. }

堆内存溢出

堆内存溢出包括:Java堆(Heap)内存溢出、元空间内存溢出、运行时常量池溢出、本机直接内存溢出;

Java 堆内存溢出

  1. /**
  2. * 演示堆内存溢出
  3. * java.lang.OutOfMemoryError: Java heap space
  4. *
  5. * -Xmx8m
  6. */
  7. public class Demo {
  8. public static void main(String[] args) {
  9. int i = 0;
  10. try {
  11. List<String> list = new ArrayList<>();
  12. String a = "hello";
  13. while (true) {
  14. list.add(a); // hello, hellohello, hellohellohellohello ...
  15. a = a + a; // hellohellohellohello
  16. i++;
  17. }
  18. } catch (Throwable e) {
  19. e.printStackTrace();
  20. System.out.println(i);
  21. }
  22. }
  23. }

方法区溢出:永久代内存溢出、元空间内存溢出

  • 永久代内存溢出(JDK1.6)
  1. 演示永久代内存溢出 java.lang.OutOfMemoryError: PermGen space
  2. -XX:MaxPermSize=8m
  3. import com.sun.xml.internal.ws.org.objectweb.asm.ClassWriter;
  4. import com.sun.xml.internal.ws.org.objectweb.asm.Opcodes;
  • 元空间内存溢出(JDK1.8)
  1. import jdk.internal.org.objectweb.asm.ClassWriter;
  2. import jdk.internal.org.objectweb.asm.Opcodes;
  3. /**
  4. * 演示元空间内存溢出
  5. *
  6. * java.lang.OutOfMemoryError: Metaspace
  7. *
  8. * -XX:MaxMetaspaceSize=8m
  9. */
  10. public class Demo extends ClassLoader { // 可以用来加载类的二进制字节码
  11. public static void main(String[] args) {
  12. int j = 0;
  13. try {
  14. Demo test = new Demo();
  15. for (int i = 0; i < 10000; i++, j++) {
  16. // ClassWriter 作用是生成类的二进制字节码
  17. ClassWriter cw = new ClassWriter(0);
  18. // 版本号, public, 类名, 包名, 父类, 接口
  19. cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, "Class" + i, null, "java/lang/Object", null);
  20. // 返回 byte[]
  21. byte[] code = cw.toByteArray();
  22. // 执行了类的加载
  23. test.defineClass("Class" + i, code, 0, code.length); // Class 对象
  24. }
  25. } finally {
  26. System.out.println(j);
  27. }
  28. }
  29. }

直接内存溢出

  1. import java.nio.ByteBuffer;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. /**
  5. * 演示直接内存溢出
  6. *
  7. * -Xmx6M
  8. */
  9. public class Demo {
  10. static int _100Mb = 1024 * 1024 * 100;
  11. public static void main(String[] args) {
  12. List<ByteBuffer> list = new ArrayList<>();
  13. int i = 0;
  14. try {
  15. while (true) {
  16. ByteBuffer byteBuffer = ByteBuffer.allocateDirect(_100Mb);
  17. list.add(byteBuffer);
  18. i++;
  19. }
  20. } finally {
  21. System.out.println(i);
  22. }
  23. // 方法区是jvm规范
  24. // jdk6 中对方法区的实现称为永久代
  25. // jdk8 对方法区的实现称为元空间
  26. }
  27. }

原文链接:https://www.cnblogs.com/HOsystem/p/17586764.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号