Exception、Error 报错整理
作者:互联网
报错整理
- 一、堆内存溢出异常 java.lang.OutOfMemoryError: PermGen space
- 二、并发修改异常 java.util.ConcurrentModificationException
- 三、栈溢出 java.lang.StackOverflowError
- 四、堆内存溢出异常 java.lang.OutOfMemoryError: Java heap space
- 五、GC回收时间过长异常 java.lang.OutOfMemoryError: GC overhead limit exceeded
- 六、直接内存溢出 java.lang.OutOfMemoryError: Direct buffer memory
- 七、java.lang.OutOfMemoryError: Direct buffer memory
- 八、元空间异常 java.lang.OutOfMemoryError: Metaspace
一、堆内存溢出异常 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