其他分享
首页 > 其他分享> > Exception、Error 报错整理

Exception、Error 报错整理

作者:互联网

报错整理

一、堆内存溢出异常 java.lang.OutOfMemoryError: PermGen space

发生原因及问题复现

使用Tomcat 6 启动项目,控制台报错
在这里插入图片描述
在这里插入图片描述

问题分析

Tomcat 6 经过查询,此问题是堆内存不足,调整JVM参数即可解决。

PermGen(永久代)的默认尺寸比较小,64M,进行大量操作变量时,会经常发生

解决原因

项目启动时设置合适JVM参数
-Xms1024m -Xmx1024m -XX:PermSize=512m -XX:MaxPermSize=512m

避免发生

根据项目及自己的判断进行设置合适的JVM参数在进行启动。
-Xms1024m 初始
-Xmx1024m
-XX:PermSize=512m
-XX:MaxPermSize=512m

二、并发修改异常 java.util.ConcurrentModificationException

发生原因及问题复现

在这里插入图片描述

问题分析

使用ArrayList 在多线程环境下,大量进行add 操作,会造成并发修改异常

解决原因

List<String> list = new ArrayList<>();

可替换为

List<String> list2 = new Vector<>(); 
List<String> list3 = Collections.synchronizedList(new ArrayList<>());
List<String> list4 = new CopyOnWriteArrayList();

避免发生

当项目中使用大量线程List时,考虑其他几种List

三、栈溢出 java.lang.StackOverflowError

设置 VM参数
-Xms1m -Xmx1m

故障现象
java.lang.StackOverflowError
在这里插入图片描述

导致原因
深度方法调用

package com.xin;

/**
 * @author :小心仔
 * @date :Created in 2021/11/6 21:33
 * @description:
 */
public class StackOverFlowError {
    public static void main(String[] args) {
        StackOverFlowErrors();
    }

    public static void StackOverFlowErrors(){
        StackOverFlowErrors();
    }
}

四、堆内存溢出异常 java.lang.OutOfMemoryError: Java heap space

设置 VM参数
-Xms1m -Xmx1m

故障现象
java.lang.OutOfMemoryError: Java heap space
在这里插入图片描述

导致原因
Java 8,对象太多了,太大

public class JavaHeapSpaceDemo {
    public static void main(String[] args) {
        String str = "1111";
        while (true){
            str += str + new Random().nextInt(1111111) + new Random().nextInt(1111111222);
            str.intern();
        }
    }
}

五、GC回收时间过长异常 java.lang.OutOfMemoryError: GC overhead limit exceeded

配置参数
-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m

故障现象
java.lang.OutOfMemoryError: GC overhead limit exceeded
在这里插入图片描述

导致原因
GC 回收时间过长会抛出 java.lang.OutOfMemoryError: GC overhead limit exceeded,超过98%的时间用于GC且回收不到2%的堆内存,加入不抛出异常,会导致内存每次快速填满,导致CPU 一直100%,而GC没有任何成果

public class GCOverHeadDemo {
    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: Direct buffer memory

配置参数
-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m

故障现象
Exception in thread “main” java.lang.OutOfMemoryError: Direct buffer memory
在这里插入图片描述

导致原因
写NIO程序 ,通过Buffe读取和写入数据,这是一种基于 通道(Chanel)与缓冲区(Buffer)的 I / O方式
它可以使用native函数直接分配堆外内存,通过一个存储在 Java堆里面的DirectByteBuffer 对象作为这块内存的引用进行操作,
这样能在一些场景中提高性能,因此避免Java堆和Native堆中来回复制数据。
ByteBuffer.allocate(capability) 第一种方式分配JVM堆内存,属于GC管辖范围,由于需要拷贝比较慢
ByteBuffer.allocateDirect(capability) 第一种方式分配OS本地内存,不属于GC管辖范围,由于不需要内存拷贝相对较快
但如果不断分配本地内存,堆内存很少使用,那么JVM不需要执行GC,DirectByteBuffer对象就不会回收
这时候堆内存充足,但本地内存已经用光,再次尝试分配本地内存就会出现OutOfMemoryError,程序崩溃。

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 (InterruptedException e) { e.printStackTrace();}
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(6 * 1024 * 1024);
    }
}

七、java.lang.OutOfMemoryError: Direct buffer memory

配置参数

故障现象
java.lang.OutOfMemoryError: Direct buffer memory

导致原因
高并发请求服务器时,经常出现与服务器有关
1 你的应用创建太多线程了,一个应用创建多个线程,超过系统承载极限
2 你的服务器不允许应用程序创建折磨多线程,Linux系统默认单个线程可创建线程
你的应用创建超过这个数量,就会报

解决办法
1 想办法降低应用程序创建线程的数量,分析应用是否需要创建折磨多线程,不是,修改代码
2 对于有的应用,确实需要创建很多线程,远超过Linux 默认1024个线程的限制,可修改Linux配置

Linux

 vim /etc/security/limits.d/90-nproc.conf

可以根据实际情况配置

在这里插入图片描述

package com.xin;

import java.util.concurrent.TimeUnit;

/**
 * @author :小心仔
 * @date :Created in 2021/11/7 9:55
 * @description:
 */
public class UnableCreateNewThreadDemo {

    public static void main(String[] args) {
        for (int i = 0; ; i++) {
            System.out.println("****************" + i);
            new Thread(() -> {
                try {
                    TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }, String.valueOf(i)).start();
        }
    }

}

八、元空间异常 java.lang.OutOfMemoryError: Metaspace

配置参数
-XX:MetaspaceSize=8m -XX:MaxMetaspaceSize=8m

故障现象
java.lang.OutOfMemoryError: Metaspace
在这里插入图片描述

导致原因
Java8及之后的版本使用Metaspace来替换永久代
Metaspace是在HotSpot中的实现,与持久代的区别在于:Metaspace并不在虚拟机内存中二是使用本地内存,也即是在java8中,class metadata(the virtual machines internal presentation of java class),被存储在叫做Metaspace 的native memory

永久代(Java8之后被原空间Metaspace取代了)存放以下信息:
虚拟机加载的类信息
常量池
静态变量
即时编译后的代码

package com.xin;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * @author :小心仔
 * @date :Created in 2021/11/7 10:42
 * @description:
 */
public class MetaspaceDemo {

    static class OOMTest{}

    public static void main(String[] args) {
        int i = 0;
        try{
            while (true){
                i++;
                Enhancer enhancer = new Enhancer();
                enhancer.setSuperclass(OOMTest.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 t){
            System.out.println(i+"次发生了异常");
            t.printStackTrace();

        }

    }

}

标签:lang,Exception,java,报错,内存,Error,OutOfMemoryError,GC,public
来源: https://blog.csdn.net/weixin_45395031/article/details/121135021