温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Java虚拟机OOM怎么用

发布时间:2022-01-18 10:58:19 来源:亿速云 阅读:187 作者:iii 栏目:编程语言

本文小编为大家详细介绍“Java虚拟机OOM怎么用”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java虚拟机OOM怎么用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

通过代码模拟Java虚拟机规范中描述的各个运行时区域内存溢出的场景。

首先,虚拟机启动参数配置如下:

-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8	1

输出:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space     at java.util.Arrays.copyOf(Arrays.java:2245)     at java.util.Arrays.copyOf(Arrays.java:2219)     at java.util.ArrayList.grow(ArrayList.java:213)     at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:187)     at java.util.ArrayList.add(ArrayList.java:411)     at HeapOOM.main(HeapOOM.java:15) Heap  def new generation   total 9216K, used 8920K [0x32570000, 0x32f70000, 0x32f70000)   eden space 8192K, 100% used [0x32570000, 0x32d70000, 0x32d70000)   from space 1024K, 71% used [0x32d70000, 0x32e26040, 0x32e70000)   to   space 1024K, 0% used [0x32e70000, 0x32e70000, 0x32f70000)  tenured generation   total 10240K, used 5693K [0x32f70000, 0x33970000, 0x33970000)    the space 10240K, 55% used [0x32f70000, 0x334ff7f8, 0x334ff800, 0x33970000)  compacting perm gen  total 12288K, used 135K [0x33970000, 0x34570000, 0x37970000)    the space 12288K, 1% used [0x33970000, 0x33991dd8, 0x33991e00, 0x34570000)     ro space 10240K, 45% used [0x37970000, 0x37df1888, 0x37df1a00, 0x38370000)     rw space 12288K, 54% used [0x38370000, 0x389f04f8, 0x389f0600, 0x38f70000)	1	2	3	4	5	6	7	8	9	10	11	12	13	14	15	16	17	18

2. 虚拟机栈和本地方法栈溢出

  • 2.1 StackOverflowError

  • 虚拟机抛出StackOverflowError异常,输出:

    Exception in thread "main" java.lang.StackOverflowError     at JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:7)     at JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:8) ...	1	2	3	4

    需要注意,为每个线程的栈分配的内存越大,反而越容易产生栈内存溢出异常。 
    这个不难理解,每个线程分配到栈容量越大,可以建立的线程数量自然就越少,建立线程时就越容易把剩下的内存耗尽。 
    因此,可以通过“减少内存”的手段来解决栈内存溢出问题。
    /**  *   *   * 功能描述: 栈OutOfMemoryError   * VM Args:-Xss2M 调大单线程可使用栈空间大小  * @author zhuyiquan90  * @created 2017-9-1 上午11:20:06  * @version 1.0.0  * @date 2017-9-1 上午11:20:06  */ public class JavaVMStackOOM { private void dontStop() { while (true) {         }     } public void stackLeakByThread() { while (true) {             Thread thread = new Thread(new Runnable() { @Override public void run() {                     dontStop();                 }             });             thread.start();         }     } public static void main(String[] args) {         JavaVMStackOOM oom = new JavaVMStackOOM();         oom.stackLeakByThread();     } }	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	28	29	30	31	32	33	34	35	36	37

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

    JDK 1.7开始逐步“去永久代化”。在JDK 1.6及之前的版本,由于常量池分配在永久代,可以通过-XX:PermSize和-XX:MaxPermSize限制方法区大小,从而间接限制常量池容量。


    import java.util.ArrayList; import java.util.List; /**  *   *   * 功能描述: 运行时常量池内存溢出  * VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M  * @author 作者 zhuyiquan90  * @created 2017-9-1 上午11:50:48  * @version 1.0.0  * @date 2017-9-1 上午11:50:48  */ public class RuntimeConstantPoolOOM { public static void main(String[] args) { // 使用List保持常量池引用,避免Full GC回收常量池行为 List<String> list = new ArrayList<String>(); // 10MB的PermSize在integer范围内足够产生OOM int i =0; while(true) {             list.add(String.valueOf(i++).intern());         }     } }	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

    在JDK 1.7及以上,while循环将一直进行下去。

    方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。对于这些区域的测试,基本的思想是运行时产生大量的类去填满方法去,直到溢出。
    package com.suning; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; /**  *   *   * 功能描述: 方法区内存溢出  * VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M  * @author 作者 zhuyiquan90  * @created 2017-9-1 下午3:31:27  * @version 1.0.0  * @date 2017-9-1 下午3:31:27  */ public class JavaMethodAreaOOM { public static void main(String[] args) { while (true) {             Enhancer enhancer = new Enhancer();             enhancer.setSuperclass(OOMObject.class);             enhancer.setUseCache(false);             enhancer.setCallback(new MethodInterceptor() { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { // TODO Auto-generated method stub return proxy.invokeSuper(obj, args);                 }             });             enhancer.create();         }     } static class OOMObject {     } }	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	28	29	30	31	32	33	34	35	36	37	38	39	40	41	42	43

    4. 本机直接内存溢出

    运行结果:

    Exception in thread "main" java.lang.OutOfMemoryError at sun.misc.Unsafe.allocateMemory(Native Method)     at DirectMemoryOOM.main(DirectMemoryOOM.java:14)	1	2	3

读到这里,这篇“Java虚拟机OOM怎么用”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI