您的位置:首页 > 编程语言 > Java开发

【JVM.1】java内存区域与内存溢出

2018-04-19 11:23 453 查看

鲁迅曾说过:Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的“高墙”,墙外面的人想进来,墙里面的人想出去。

 

一.虚拟机内存分布

Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。

stackInt length:1581
Exception in thread "main" java.lang.StackOverflowError
at jvm.StackSOF.stackLeak(StackSOF.java:11)
at jvm.StackSOF.stackLeak(StackSOF.java:11)
View Code 实验结果表明:在单线程下,无论是由于栈帧太大还是虚拟机栈容量太小,当内存无法分配时,虚拟机都是抛出StackOverflowError异常。

  如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常。

/**
* 这时候不妨设置的大些  特别提示:如果你想尝试运行这段代码,记得保存当前工作,很可能电脑会卡死机
* -Xss4M
*/
public class StackOOM {
private void notStop() {
while (true) {
}
}
public void stackLeakByThread() {
while (true) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
notStop();
}
});
thread.start();
}
}
public static void main(String[] args) {
StackOOM oom = new StackOOM();
oom.stackLeakByThread();
}
}

运行结果:

我在windows环境下,出现内存使用爆满,电脑卡死,只能被迫重启电脑。

 

3.  方法区和运行时常量池溢出

  方法区用于存放Class相关信息,基本思路就是运行时产生大量的类去填满方法区,直到溢出。

/**
* 方法区内存10M 方法区最大内存10M
* -XX:PermSize=10M -XX:MaxPermSize=10M
*/
public class MethodAreaOOM {

static class OOMObject {
}

public static void main(String[] args) {
while (true) {
//使用了CFLIB这类字节码技术,有兴趣可以另外了解一下
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OOMObject.class);
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
return methodProxy.invokeSuper(o, objects);
}
});
enhancer.create();
}
}
}

运行结果:

书中介绍会抛出异常
caused by: java.OutOfMemoryError: PermGen space
.....
.....
我自己执行时出现内存使用率迅速增长,
我顾及电脑会再次卡死就手动关闭了程序

 

4.  本机直接内存溢出

  使用Unsage类的allocateMemory()方法来真正申请分配内存。

/**
* 设置最大堆内存20M  最大直接内存10M
* -Xmx20M -XX:MaxDirectMemorySize=10M
*/
public class DirectMemoryOOM {
private static final int _1MB = 1024*1024;

public static void main(String[] args) throws Exception{
Field field = Unsafe.class.getDeclaredFields()[0];
field.setAccessible(true);
Unsafe unsafe = (Unsafe)field.get(null);
while (true) {
unsafe.allocateMemory(_1MB);//分配内存
}
//执行后 360提示电脑虚拟内存不足
}
}

运行结果:

Exception in thread "main" java.lang.OutOfMemoryError
at sun.misc.Unsafe.allocateMemory(Native Method)
at jvm.DirectMemoryOOM.main(DirectMemoryOOM.java:20)

 

本章小结

  通过这一章的学习,我们明白了虚拟机中的内存是怎么划分的,哪部分区域、什么样的代码和操作可能导致内存溢出异常。虽然Java有垃圾收集机制,但内存溢出异常离我们仍然并不遥远,

  本章只讲解了各个区域出现异常的原因,下一章会详细讲解Java垃圾收集机制的底层实现。

  

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: