java面试-谈谈你对OOM的理解

发布于:2021-06-19 13:57:03

1、java.lang.StackOverflowError


在一个函数中调用自己就会产生这样的错误(栈溢出)发生区域:java虚拟机栈或本地方法栈

public class StackOverFlowErrorDemo {
public static void main(String[] args) {
stackOverFlowError();
}

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


2、java.lang.OutOfMemoryError: Java heap space


new 一个很大对象发生区域:java堆

/**
* -Xms10m -Xmx10m
*/
public class JavaHeapSpaceDemo {

static class OOMObject{
}

public static void main(String[] args) {
List list = new ArrayList<>();
while (true){
list.add(new OOMObject());
}
}
}


3、java.lang.OutOfMemoryError: GC overhead limit exceeded


GC回收时间过长,超过98%的时间用来做GC,并且回收了不到2%的堆内存

/**
* -Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
*/
public class GCoverheadDemo {

public static void main(String[] args) {
int i = 0;
List list = new ArrayList<>();

while (true) {
list.add(String.valueOf(++i).intern());
}
}
}  


4、java.lang.OutOfMemoryError: Direct buffer memory


原因:直接内存不足


写NIO程序经常使用ByteBuffer来读取或写入数据,这是一种基于通道与缓冲区的I/O方式

ByteBuffer.allocate() 分配JVM堆内存,属于GC管辖范围,需要拷贝所以速度相对较慢

ByteBuffer.allocateDirect() 分配操作系统本地内存,不属于GC管辖范围,不需要内存拷贝所以速度相对较快



/**
* -Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
*/
public class DirectBufferMemoryDemo {

public static void main(String[] args) throws InterruptedException {
System.out.println("maxDirectMemory : " + sun.misc.VM.maxDirectMemory() / 1024 / 1024 + "MB");
TimeUnit.SECONDS.sleep(1);
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(6 * 1024 * 1024);
}
}


5、java.lang.OutOfMemoryError : unable to create new native thread


一个应用进程创建了多个线程,超过系统承载极限,Linux默认允许单个进程可以创建的线程数1024

/**
* 一个应用进程创建了多个线程,超过系统承载极限,Linux默认是1024
*/
public class UnableCreateNewThreadDemo {
public static void main(String[] args) {
for (int i = 0; ; i++) {
new Thread(() -> {
try {
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, String.valueOf(i)).start();
}
}
}  


linux系统下:



ulimit -u --查看线程上限
cat /etc/security/limits.d/20-nproc.conf


6、java.lang.OutOfMemoryError: Metaspace


java8使用Metaspace代替永久代,与永久代最大的区别是:元空间并不在虚拟机内存中,而是使用本地内存。  


永久代(java8使用Metaspace)存放的信息:


虚拟机加载的类信息常量池静态变量即时编译后的代码

/**
* 不断生成类往元空间推,类占据的空间总是会超过Metaspace的大小
* -XX:MetaspaceSize=8m -XX:MaxMetaspaceSize=8m
*/
public class MetaspaceOOMDemo {

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 e) {
System.out.println(i + "次后发送了异常");
e.printStackTrace();
}

}
}


  


  


?


?





转载于:https://www.cnblogs.com/wjh123/p/11143379.html






相关资源:2019年最新Java面试题.docx

相关推荐

最新更新

猜你喜欢