Qouson's blog Qouson's blog
首页
  • Java 基础

    • 基础
    • String
  • Java 中级

    • 网络编程
  • Java 高级

    • JVM
    • 多线程
  • Spring
  • SpringMVC
  • SpringBoot
  • MySQL
  • Redis
  • MQ
  • ZooKeeper
  • git
  • linux
  • 设计模式
  • 数据结构与算法
  • 计算机基础
  • Java相关框架
  • 分布式
  • DDD领域驱动设计
  • 系统设计
  • 杂乱无章
Java知识图谱
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

qouson

Java界的小学生
首页
  • Java 基础

    • 基础
    • String
  • Java 中级

    • 网络编程
  • Java 高级

    • JVM
    • 多线程
  • Spring
  • SpringMVC
  • SpringBoot
  • MySQL
  • Redis
  • MQ
  • ZooKeeper
  • git
  • linux
  • 设计模式
  • 数据结构与算法
  • 计算机基础
  • Java相关框架
  • 分布式
  • DDD领域驱动设计
  • 系统设计
  • 杂乱无章
Java知识图谱
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 基础

  • String

  • 网络编程

  • JVM

    • JVM-ERROR
      • SOFE(StackOverFlowError)
      • OOM(OutOfMemoryError)
    • JVM-GC
    • JVM-体系结构
    • JVM-参数和调优
    • JVM-类运行机制
    • JVM
  • 多线程

  • JavaSE
  • JVM
qouson
2024-05-23
目录

JVM-ERROR

# JVM-ERROR(SOFE,OOM,UNKNOW)

  • 架构 20210315170043
  • 常见Error
    • java.lang.StackOverFlowError
    • java.lang.OutOfMemoryEorror:Java heap space
    • java.lang.OutOfMemoryEorror:GC overhead limit exceeded
    • java.lang.OutOfMemoryEorror:Direct buffer memory
    • java.lang.OutOfMemoryEorror:unable to create new native thread
    • java.lang.OutOfMemoryEorror:Metaspace

# SOFE(StackOverFlowError)

  • Demo
public class StackOverFlowErrorDemo {
    public static void main(String[] args) {
        stackOverFlowErrorDemo();
    }
    public static void stackOverFlowErrorDemo(){
        stackOverFlowErrorDemo();
    }
}
//Exception in thread "main" java.lang.StackOverflowError
//    at com.jjc.mypratice.javase.jvm.error.stackoverflowerror.StackOverFlowErrorDemo.stackOverFlowErrorDemo(StackOverFlowErrorDemo.java:15)
1
2
3
4
5
6
7
8
9
10

# OOM(OutOfMemoryError)

  • Java heap space

    • Demo
    public class JavaHeapSpaceDemo {
        public static void main(String[] args) {
            //-Xms10m -Xmx10m
            //byte[] bytes = new byte[30 * 1024 * 1024];
            String str = "demo";
            while(true){
                str = str + new Random().nextInt(11111111) + new Random().nextInt(22222222);
                str.intern();
            }
        }
    }
    //Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    //at com.jjc.mypratice.javase.jvm.error.outofmemeoryerror.javaheapspace.JavaHeapSpaceDemo.main(JavaHeapSpaceDemo.java:14)
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
  • GC overhead limit exceeded

    • GC回收时间过长时会地出OutofMemroyError。过长的定义是,超过98%的时间用来做GC并且回收了不到2%的堆内存,连续多GC都只回收了不到2%的极端情况下才会地出。
    • 假如不地出 GC overhead Limit 错误会发生什么情况呢? 那就是GC清理的这么点内存很快会再次填满,迫使GC再次执行,这样就形成恶性循环CPU使用率一直是100%,而GC却没有在何成果.
    • Demo
    public class GCOverheadLimitExceededDemo {
      //-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=3m
      public static void main(String[] args) {
          int i = 0;
          List<String> list = new ArrayList<>();
          try{
              while(true){
                  list.add(String.valueOf(++i).intern());
              }
          }catch(Throwable e){
              System.out.println("***************" + i);
              e.printStackTrace();
              throw e;
          }
      }
    }
    //java.lang.OutOfMemoryError: GC overhead limit exceeded
    //at java.lang.Integer.toString(Integer.java:401)
    //at java.lang.String.valueOf(String.java:3099)
    //at com.jjc.mypratice.javase.jvm.error.outofmemeoryerror.gcoverheadlimitexceeded.GCOverheadLimitExceededDemo.main(GCOverheadLimitExceededDemo.java:20)
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
  • Direct buffer memory

    • 写NIO程序经常使用ByteBuffer来读取或写入数据,这是一种基于通道(Channel)和缓冲区(buffer)的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过Java堆里面的一个DirectByteBuffer对象作为这块内存的引用操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。
    • ByteBuffer.allocate(capatility)第一种方式是分配JVM堆内存,属于GC的管辖范围,由于需要拷贝所以速度较慢。
    • ByteBuffer.allocateDirect(capatility)第二种方式是分配OS本地内存,即Native,不属于GC管辖范围,由于不需要内存拷贝所以速度较快。
    • 如果不断分配本地内存,堆内存很少使用,那么JVM就不需要执行GC,DirectByteBuffer对象们就不会被回收,这时候堆内存充足,本地内存可能已经被使用光了,再次尝试分配本地内存就会出现OutOfMemory,程序直接崩溃。
    • Demo
    public class DirectBufferMemoryDemo {
      public static void main(String[] args) {
          System.out.println("maxDirectMemory:" + sun.misc.VM.maxDirectMemory() / (double)1024 / 1024 + "MB");
          try{ TimeUnit.SECONDS.sleep(3); }catch(Exception e){e.printStackTrace();}
          //-XX:MaxDirectMemorySize=5m ,配置为5m,实际使用为6m,撑爆MaxDirectMemory
          ByteBuffer byteBuffer = ByteBuffer.allocateDirect(6 * 1024 *1024);
      }
    }
    //Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
  • unable to create native thread

    • 高并发请求服务器时,经常出现如下异常:java.lang.OutOfMemoryEorror:unable to create new native thread。
    • 准确的讲,native thread和对应的操作系统平台有关。
    • 导致原因:
      • 1.应用创建了太多线程了,一个应用进程创建多个线程,超过系统承载极限。
      • 2.服务器不允许应用程序创建这么多线程,linux系统默认允许单个进程可以创建的线程数是1024个,应用创建的线程超过这个数量,就会报错。
    • 解决办法:
      • 1.降低应用程序创建的线程数量,分析应用是否需要创建这么多线程,如果不是,将线程数降至最低。
      • 2.有的应用确实需要这么多线程,修改linux系统的默认1024个线程的限制,扩大默认限制。
    • linux服务器调优
      • linux普通用户上限1024,root无上限。
      • vim /etc/security/limits.d/90-nproc.conf
    • Demo
      public class UnableToCreateNewThreadDemo {
          public static void main(String[] args) {
              int i = 0;
              while(true){
                  new Thread(() -> {
                      System.out.println(Thread.currentThread().getName());
                      try{ TimeUnit.SECONDS.sleep(Integer.MAX_VALUE); }catch(Exception e){e.printStackTrace();}
                  },"" + ++i).start();
              }
          }
      }
    //Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
  • Metaspace

    • Java8之后使用Metaspace替代永久代
    • Metaspace是方法区在HotSpot中的实现,它与持久代最大的区别是:Metaspace并不在虚拟机中而是使用本地内存,也即在Java8中,class metadata(the virtual machines internal presentation of Java class),被存储在叫做Metaspace的native memory
    • 永久代(Java8之后被元空间Metaspace取代)存放了以下信息
      • 虚拟机加载的类信息
      • 常量池
      • 静态变量
      • 即时编译后的代码
    • Demo
    //-XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m
    public class MetaspaceDemo {
      static class MetaspaceError{};
      public static void main(String[] args) {
          int i = 0;
          try{
              while(true){
                  ++i;
                  Enhancer enhancer = new Enhancer();
                  enhancer.setSuperclass(MetaspaceError.class);
                  enhancer.setUseCache(false);
                  enhancer.setCallback(new MethodInterceptor() {
                      @Override
                      public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                          return methodProxy.invokeSuper(o,args);
                      }
                  });
                  enhancer.create();
              }
          }catch(Throwable e){
              System.out.println("执行" + i + "次后Error");
              e.printStackTrace();
          }
      }
    }
    //org.springframework.cglib.core.CodeGenerationException: java.lang.OutOfMemoryError-->Metaspace
    //Caused by: java.lang.OutOfMemoryError: Metaspace
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
编辑 (opens new window)
上次更新: 2024/05/24, 11:36:46
网络编程
JVM-GC

← 网络编程 JVM-GC→

最近更新
01
杂乱无章
12-25
02
基础-大彬
11-14
03
集合-大彬
11-14
更多文章>
Theme by Vdoing | Copyright © 2023-2025 qouson
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式