深入理解JVM-02----java的内存区域与内存溢出异常

1. JVM的内存结构?

运行时数据区通常包括这几个部分:程序计数器(Program Counter Register)、Java栈(VM Stack)、本地方法栈(Native Method Stack)、方法区(Method Area)、堆(Heap)。

1. 程序计数器:也有称作为PC寄存器。

       虽然JVM中的程序计数器并不像汇编语言中的程序计数器一样是物理概念上的CPU寄存器,但是JVM中的程序计数器的功能跟汇编语言中的程序计数器的功能在逻辑上是等同的,也就是说是用来指示 执行哪条指令的。

2. java栈

     栈也叫栈内存,主管Java程序的运行,是在线程创建时创建,它的生命期是跟随线程的生命期,线程结束栈内存也就释放,对于栈来说不存在垃圾回收问题,只要线程一结束该栈就Over,生命周期和线程一致,是线程私有的。基本类型的变量、实例方法、引用类型变量都是在函数的栈内存中分配。

3. 方法区

(1)方法区是线程共享的,通常用来保存装载的类的元结构信息

比如:运行时常量池+静态变量+常量+字段+方法字节码+在类/实例/接口初始化用到的特殊方法等。

(2):通常和永久代关联在一起(Java7之前),但具体的跟JVM的实现和版本有关

4.  本地方法接口

Java语言本身不能对操作系统底层进行访问和操作,但是可以通过JNI接口调用其他语言来实现对底层的访问。 
 
本地接口的作用是融合不同的编程语言为Java所用,它的初衷是融合 C/C++程序,Java诞生的时候是C/C++横行的时候,要想立足,必须有调用C/C++程序,于是就在内存中专门开辟了一块区域处理标记为Native的代码,它的具体做法是Native Method Stack中登记Native方法,在Execution Engine 执行时加载Native libraries

  目前该方法使用的越来越少了,除非是与硬件有关的应用,比如通过Java程序驱动打印机或者Java系统管理生产设备,在企业级应用中已经比较少见。因为现在的异构领域间的通信很发达,比如可以使用Socket通信,也可以使用WebService等等,不多做介绍。

5. 堆

new Person() 是在 堆内存的新生区  的Eden space

 

新生区是类的诞生、成长、消亡的区域,一个类在这里产生,应用,最后被垃圾回收器收集,结束生命。

新生区又分为两部分: 伊甸区(Eden space)和幸存者区(Survivor pace) ,所有的类都是在伊甸区被new出来的。幸存区有两个: 0区(Survivor 0 space)和1区(Survivor 1 spacefrom Survivor  To Survivor

当伊甸园的空间用完时,程序又需要创建对象,JVM的垃圾回收器将对伊甸园区进行垃圾回收(Minor GC),将伊甸园区中的不再被其他对象所引用的对象进行销毁。然后将伊甸园中的剩余对象移动到幸存0.若幸存0区也满了,再对该区进行垃圾回收,然后移动到1区。那如果1区也满了呢?再移动到养老区。若养老区也满了,那么这个时候将产生MajorGCFullGC,进行养老区的内存清理。若养老区执行了Full GC之后发现依然无法进行对象的保存,就会产生OOM异常“OutOfMemoryError

如果出现java.lang.OutOfMemoryError: Java heap space异常,说明Java虚拟机的堆内存不够。原因有二:

1Java虚拟机的堆内存设置不够,可以通过参数-Xms-Xmx来调整。

2)代码中创建了大量大对象,并且长时间不能被垃圾收集器收集(存在被引用)。

 

public class Demo05 {

    // idea VM-option   -Xms1024m -Xmx1024m -XX:+PrintGCDetails  运行
    public static void main(String[] args) {
        long maxMemory=Runtime.getRuntime().maxMemory();
        long totalMemory=Runtime.getRuntime().totalMemory();
        System.out.println("maxMemory:"+maxMemory/1024/1024+"MB");
        System.out.println("totalMemory:"+totalMemory/1024/1024+"MB");
    }
}
maxMemory:982MB
totalMemory:982MB
Heap
 PSYoungGen      total 306176K, used 21012K [0x00000000eaa80000, 0x0000000100000000, 0x0000000100000000)
  eden space 262656K, 8% used [0x00000000eaa80000,0x00000000ebf05358,0x00000000fab00000)
  from space 43520K, 0% used [0x00000000fd580000,0x00000000fd580000,0x0000000100000000)
  to   space 43520K, 0% used [0x00000000fab00000,0x00000000fab00000,0x00000000fd580000)
 ParOldGen       total 699392K, used 0K [0x00000000bff80000, 0x00000000eaa80000, 0x00000000eaa80000)
  object space 699392K, 0% used [0x00000000bff80000,0x00000000bff80000,0x00000000eaa80000)
 PSPermGen       total 21504K, used 2941K [0x00000000bad80000, 0x00000000bc280000, 0x00000000bff80000)
  object space 21504K, 13% used [0x00000000bad80000,0x00000000bb05f758,0x00000000bc280000)

Process finished with exit code 0

1. 各个参数是什么意思

-Xmx  我的内存是16G    最大分配的内存时3614MB  大概是1/4

-Xms   也就是totalMemory的值   大概是243MB    243x16=3888    是Xmx的1/16

YoungGen + OldGen = Xms 对应的内存

元空间是非堆内存, 不是Heap space里面的

新生代:eden from to(这里主要触发的是minor GC 轻量级gc)         老年代:(主要是major GC  也就是full gc)

2. 两个重要的异常StackOverFlow  和OutOfMemory

public class StackOver {
    public static void sayHi(){
        sayHi();
    }

    public static void main(String[] args) {
        sayHi();

    }
       
}

3. OOM

-Xms8m -Xmx8m -XX:+PrintGCDetails  来运行会报OOM
public class Demo06 {
    byte[] arr=new byte[1024*1024];//1MB

    public static void main(String[] args) {
        List<Demo06> list=new ArrayList<Demo06>();
        try {
            for (int i = 0; i <40 ; i++) {
                list.add(new Demo06());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
"C:\Program Files\Java\jdk1.7.0_80\bin\java" -Xms8m -Xmx8m -XX:+PrintGCDetails "-javaagent:E:\Idea\IntelliJ IDEA 2017.3.5\lib\idea_rt.jar=20091:E:\Idea\IntelliJ IDEA 2017.3.5\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.7.0_80\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\jce.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\jfxrt.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\resources.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\rt.jar;H:\workspace_idea\JAVAIO\out\production\JAVAIO;E:\Idea\IntelliJ IDEA 2017.3.5\lib\junit-4.12.jar;E:\Idea\IntelliJ IDEA 2017.3.5\lib\hamcrest-core-1.3.jar" com.jvm.chap7.Demo06
[GC [PSYoungGen: 1352K->504K(2560K)] 6472K->5736K(8192K), 0.0010429 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC-- [PSYoungGen: 1571K->1571K(2560K)] 6803K->6811K(8192K), 0.0008861 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC [PSYoungGen: 1571K->1451K(2560K)] [ParOldGen: 5240K->5224K(5632K)] 6811K->6676K(8192K) [PSPermGen: 2934K->2933K(21504K)], 0.0088053 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[GC-- [PSYoungGen: 1451K->1451K(2560K)] 6676K->6684K(8192K), 0.0011673 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GCException in thread "main" java.lang.OutOfMemoryError: Java heap space
 [PSYoungGen: 1451K->1441K(2560K)] [ParOldGen: 5232K->5221K(5632K)] 6684K->6662K(8192K) [PSPermGen: 2933K->2933K(21504K)], 0.0059655 secs] [Times: user=0.09 sys=0.00, real=0.01 secs] 
	at com.jvm.chap7.Demo06.<init>(Demo06.java:7)
Heap
	at com.jvm.chap7.Demo06.main(Demo06.java:13)
 PSYoungGen      total 2560K, used 1526K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
  eden space 2048K, 74% used [0x00000000ffd00000,0x00000000ffe7db08,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
  to   space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
 ParOldGen       total 5632K, used 5221K [0x00000000ff780000, 0x00000000ffd00000, 0x00000000ffd00000)
  object space 5632K, 92% used [0x00000000ff780000,0x00000000ffc99610,0x00000000ffd00000)
 PSPermGen       total 21504K, used 2998K [0x00000000fa580000, 0x00000000fba80000, 0x00000000ff780000)
  object space 21504K, 13% used [0x00000000fa580000,0x00000000fa86d910,0x00000000fba80000)

Process finished with exit code 1

一般是使用MAT 分析工具来去看内存的问题 会生成hprof文件   堆转储快照文件,通过下面的命令

-Xms8m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError

如果是内存泄漏  去查看GC roots引用链

如果不存在泄漏 就是内存溢出  内存对象还存活  就应该检查-Xmx -Xms参数 去调大或调小来看

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值