zoukankan      html  css  js  c++  java
  • java中之内存溢出说明

    java语句是编译型和解释型语言,选通过编译命令javac 把java文件编译为.class字节码文件,然后通过java虚拟机(JVM)加载class文件到内存运行。

    而java虚拟机在运行程序时有自己的内存管理机制,大致可以分为方法区,java虚拟机栈,本地方法栈,堆,程序计数器。

    大致如下图所示:

    下面来单独说说这几个区域是干什么的,以及可能出现的异常实例说明:

    方法区:

    是class字节码文件加载到内存时,会把一些常量数据,类文件信息,静态变量,java即时编译的代码等数据,是线程共享的数据。运行时常量池是方法区的一部分(和jdk的版本有关系,后续会有说明)

    常量池中的内容不一定都是编译的时候产生的,比如String.intern()方法,可以在运行时产生字符串放到常量池中,当常量池无法再申请到内存时,会抛出OutOfMemoryError异常。

    可以通过虚拟机参数设置方法区的大小:  -XX:PermSize  和 -XX:MaxPermSize来限定方法区的大小。

          程序举例如下所示:

    package com.three.fourteen;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class TestMethod {
    
        /**
         * 设置方法区的参数为:
         *    -XX:PermSize=10M -XX:MaxPermSize=10M
         * @param args
         */
        public static void main(String[] args) {
     
            List<String> lists=new ArrayList<String>();
            int i=1;
            while(true) {
                lists.add(String.valueOf(i++).intern());
            }
        }
    }

    上面的代码会产生内存溢出:

    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
     at java.util.Arrays.copyOf(Unknown Source)
     at java.util.Arrays.copyOf(Unknown Source)
     at java.util.ArrayList.grow(Unknown Source)
     at java.util.ArrayList.ensureExplicitCapacity(Unknown Source)
     at java.util.ArrayList.ensureCapacityInternal(Unknown Source)
     at java.util.ArrayList.add(Unknown Source)
     at com.three.fourteen.TestMethod.main(TestMethod.java:18)

    这个和jdk版本有关系,本地是使用jdk 1.8测试,测试结果显示java堆内存溢出,而不是方法区溢出,可以确定jdk1.8版本中的常量池存放到java堆中。

          

    java虚拟机栈:

    此部分是线程私有的区域,为了解决多线程的同步问题,每个线程需要的变量都会主存中复制一份备份放到虚拟机栈中ThreadLocal,此部分是每个线程都会创建并且私有的,

    各线程操作的都是线程备份的副本,彼此间互不干涉。存放的是一些变量名和一些对象的引用。若是栈中无法申请在申请到内存,则会抛出StackOutOfMemoryError异常。

    设置栈的大小的参数是: -Xss=128k

    具体代码如下所示:

    public class TestThreadLocal {
    
        private int i=0;
        
        public void StackOverFlow() {
            i++;
            StackOverFlow();
        }
        
        public static void main(String[] args) {
     
            TestThreadLocal ttl=new TestThreadLocal();
            ttl.StackOverFlow();
        }
    }

    Exception in thread "main" java.lang.StackOverflowError

     at com.three.fourteen.TestThreadLocal.StackOverFlow(TestThreadLocal.java:9)
     at com.three.fourteen.TestThreadLocal.StackOverFlow(TestThreadLocal.java:9)
     at com.three.fourteen.TestThreadLocal.StackOverFlow(TestThreadLocal.java:9)

           ...............

    提示栈溢出

     以上都是出自深入理解Java虚拟机中的部分内容!

  • 相关阅读:
    linux下拼接字符串的代码
    postgresql实现插入数据返回当前的主键ID
    记录一个linux下批处理的代码
    iptables
    mybatis获得执行insert的返回值
    git commit之后撤销
    仿照CIFAR-10数据集格式,制作自己的数据集
    C/C++ 在处理文件所在路径下创建子目录
    C/C++ 图像二进制存储与读取
    C/C++ 文件路径解析
  • 原文地址:https://www.cnblogs.com/guopengxia0719/p/10534321.html
Copyright © 2011-2022 走看看