JVM进阶了解原理

1 篇文章 0 订阅

最近学习了钟洪发老师的JVM课程后,总结得出以下经验,做个记录

 

一:JVM的内部结构


    1、虚拟机栈
        一个线程会创建一个栈
        调用一个方法就会创建一个栈帧(简称入栈),直到方法返回一个结果(简称出栈)
        虚拟机栈是一个后入先出的数据结构,例如(调用方A,A方法调用B方法,B方法又调用C方法,那么出栈时,肯定是C方法先执行完出栈,再到B,再到A)
        栈里存放的是在调用方法时,产生的局部变量以及变量存储的数据
    
    2、方法区
        存储(类结构信息、常量池(基本类型的值),静态变量,构造函数),在类加载时,使用类加载器(Class Loader)中载入时,初始化的。
        方法区会回收没有被使用过的变量
        方法区里的数据是线程共享的
        
    3、堆
        存放对象的地方。所有用new关键字实例出来的对象都存放在堆。这个区会被垃圾回收频繁回收
        
        写个例子:
            static Integer i1 = new Integer(1);  
            static Integer i2 = new Integer(1);
            
            static Integer a = 1;
            static Integer a = 2;
            
            public static void main(String[] args){
                System.out.println(i1 == i2);//返回false  new出来的对象内存地址指向堆
                System.out.println(a == b);//返回true      int类型的值1 是存放在方法区的,a,b都指向方法区常量池的内存地址,是同一个
            }
        
        
            
    
    
二、堆的内部结构
    
    
        1、堆分为新生代,老年代
        新生代又分为:Eden(伊甸园)、Survivor(幸存者):分为大小对称的两个区域 S0 S1
        
        
        2、新new出来的对象会进入到新生代的Eden中,当Eden内存被放满之后,会执行普通的垃圾回收minor gc
        minor gc执行之后,幸存下来的对象,会被放入到s0或s1当中,s0与s1必然会有一个空间是空的。
        例如:
            minor gc 执行之后,剩下 A,B,C三个对象 A,B,C三个对象的年龄分别初始化为1放入到s0空间,则s1的空间是空的
            当下一次执行Eden满了执行minor gc后,A,B,C三个对象会被复制到s1空间,并且三个对象的年龄加1,则为2,并且清空s0
            之后会反复以上操作。
            
            对象的年龄达到设定的一个值之后,会进入到老年代。
            例如:当A,B,C对象的年龄都达到10之后,会进入到老年代当中。
            
        3、Eden与Survivor的空间比例是8:1
        也就是说  Eden占新生代的80%,s0与s1都占10%。因为年轻代的对象都是刚创建出来就会死的。也就是说新生代会一直由10%的空间的空着的
            
        4、如果老年代空间满了之后会出发,全局垃圾回收  major gc 或 full gc
        major gc:只回收老年代垃圾
        full gc:回收老年代与新生代的垃圾
        
        5、触发full gc时,就会触发STW(stop the world)现象,就是所有的进程都挂起,只等待full GC完成。所以要配置参数减少full gc的出现,否则程序会卡顿。
            
        
            
            
            
三、有关内存的常用配置参数

    1、Heap Space 堆内存:使用 -Xms 、 -Xmx
        -Xms:是在JVM启动时初始的Heap值,默认是系统物理内存的1/64但小于1G。默认当空余堆内存大于70%的时候,会减少到-Xms的值。
              可通过-XX:MaxHeapFreeRation=来指定这个比例。但是我们一般不使用这个配置,我们一般会把-Xms与-Xmx设置为一样。这样可以避免JVM要重新分配内存,不会发生
              内存抖动,也可以减少垃圾回收的次数。
        -Xmx:JVM可申请的最大Heap值,默认是物理内存的1/4,但是小于1G,默认空余内存小于40%时,JVM会增大到-Xmx指定的值。
        
        可在idea中加入JVM参数-Xms4g -Xmx4g -XX:+PrintGCDetails来查看GC的变化,可设置一样或者不一样的值查看结果。
        
        -Xmn:设置新生代大小,Sun公司推荐是堆内存的3/8 例如:-Xmn2g
            因为整个堆内存=新生代+老年代+永久代,也就是说新生代如果占用内存越大,老年大也就相应的缩小,会导致程序崩溃,所以这个值很重要。
        
        
        说明:不是所有new出来的对象都会进入到新生代,也有可能直接进入到老年代。
            例如:大对象:可通过设置-XX:PretenureSizeThreshold=1024单位为字节,也就是说当对象的大小超过1024字节的时候,会直接进入到老年代分配。
                  大的数组对象:但是数组中不可引用外部对象。如果老年代不够存放,会报错:OutOfMemoryError异常。
                  OutOfMemoryError异常:要么堆内存不够,要么存在内存泄漏
        
        
        -XX:+MaxTenuringThreshold=10:代表新生代年龄到10后进入老年代,设置为0不会计算对象年龄,直接进入老年代。
        
    2、Method Area 方法区:-XX:MaxPermSize或-XX:PermSize
        -XX:PermSize:持久代初始化大小
        -XX:MaxPermSize或:持久代初始化大小
        设置成同样的值。一般设置为512m
        
    3、Native Area 栈:-Xss
            -Xss:每个线程的栈的大小,上面说过,一个线程建立一个栈,小系统推荐:128K 大系统:256K。
            
            
四、内存泄漏与内存溢出

    1、内存泄漏 memory leak:指的是申请了一个内存空间后,无法释放,则称为内存泄漏,占着茅坑不拉屎
    1、内存溢出 memory of memory 简称OOM:指的是堆内的剩余空间已经无法容纳新创建的数据时,会报出OOM异常。
        例如:创建一个4M的数组,但是堆内剩余空间只剩3M,那么则会报错OOM
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
            
            
            
            
        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

紫川琴秀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值