JVM内存模型

JAVA语言的夸平台特性:

 在下载jdk时选择针对不同系统的版本,不同的jdk编译java文件生成适合不同系统的字节码;

查看jvm虚拟机执行代码过程:

       1、在idea中选中要反编译的class文件,右键-->open in terminal,使用javap -c命令,将编译后的文件输出到指定目录:

        2、从编译后的文件中可以看到虚拟机的执行过程,命令的具体含义参考最后附件链接中的《00-JVM指令手册.pdf》

JVM的内存模型:

       1、JVM虚拟机中的 栈、本地方法栈、程序计数器 是每个线程单独所有,堆、方法区是所有线程共有,其中程序计数器记录这个线程执行到代码的哪一行了,堆 存放系统中程序执行过程中线程创建的对象,方法区(元空间)存放代码信息;(jdk1.8之前 静态变量和常量放在方法区中,jdk1.8 开始静态变量和常量放入堆中);

          对象栈上分配我们通过JVM内存分配可以知道JAVA中的对象都是在堆上进行分配,当对象没有被引用的时候,需要依靠GC进行回收内存,如果对象数量较多的时候,会给GC带来较大压力,也间接影响了应用的性能。为了减少临时对象在堆内分配的数量,JVM通过逃逸分析确定该对象不会被外部访问。如果不会逃逸可以将该对象在栈上分配内存,这样该对象所占用的内存空间就可以随栈帧出栈而销毁,就减轻了垃圾回收的压力。

          对象逃逸分析:就是分析对象动态作用域,当一个对象在方法中被 定义后,它可能被外部方法所引用,例如作为调用参数传递到其他地方中。
            

       2、每个线程启动时会创建一个栈(左边的main线程),栈里面包含 线程中创建的局部变量、对当前执行代码的数据操作、代码执行的位置(程序计数器),一个线程每开始执行一个子方法就创建一个栈帧、子方法执行结束对应的栈帧就销毁,栈帧中存储子方法的成员变量;

            本地方法栈是为虚拟机使用到的Native方法服务,具体怎么服务不了解

 GC原理:

       1、堆中的对象分为年轻代和老年代(默认比例是1:2,即年轻代占整个堆空间的1/3),年轻代分为eden、survivor0和survivor1区(内存大小比例通常为8:1:1),当eden区的内存空间不足时触发 minor GC(也叫young GC),将存活下来的对象放入s0中,每minor GC一次就会将存活下来的对象移动一次(s0和s1来回移动),当年轻代的内存空间不足 或 移动次数达到15(可调整,默认15)次则会将年轻代中的对象移动到老年代;

       2、当老年代中的内存空间不足时会触发full GC(也叫major GC),full GC会对年轻代及老年代中的对象进行回收,当老年代中的对象超出了内存则会OOM(内存溢出);

        GC时会触发STW(stop the world)机制,即所有线程都会被暂停,就像系统卡死一样。所以JVM调优的很重要一步就是较少GC次数、尤其是full GC(相对minor GC而言执行时间会长很多)。

判断对象能否被回收的两种方式:

       1、引用计数法给对象中添加一个引用计数器,每当有一个地方引用它,计数器就加1;当引用失效,计数器就减1;计数器为0的对象就是可以被回收的;这个方法实现简单,效率高,但是目前主流的虚拟机中并没有选择这个算法来管理内存,其最主要的原因是它很难解决 对象之间相互循环引用的问题。 所谓对象之间的相互引用问题,如下面代码所示:除了对象objA 和 objB 相互引用着对方之外,这两个对象之间再无任何引用。但是他们因为互相引用对方,导致它们的引用计数器都不为0,于是引用计数算法无法通知 GC 回收器回收他们。

        2、可达性分析算法:将“GC Roots” 对象作为起点,从这些节点开始向下搜索引用的对象,找到的对象都标记为非垃圾对象,其余未标记的对象都是垃圾对象

内存参数设置:

       

 常用的参数设置格式:

        -Xms2048M -Xmx2048M -Xmn1024M -Xss512K -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M

关于元空间的JVM参数有两个:-XX:MetaspaceSize=N和 -XX:MaxMetaspaceSize=N
-XX:MaxMetaspaceSize : 设置元空间最大值, 默认是-1, 即不限制, 或者说只受限于本地内存大小。
-XX:MetaspaceSize: 指定元空间触发Fullgc的初始阈值(元空间无固定初始大小), 以字节为单位,默认是21M,达到该值就会触发 full gc进行类型卸载, 同时收集器会对该值进行调整: 如果释放了大量的空间(实际使用的空间比21M小很多), 就适当降低该值; 如果释放了很少的空间(21M快被使用完了), 那么在不超过-XX:MaxMetaspaceSize(如果设置了的话) 的情况下, 适当提高该值。这个跟早期jdk版本的 -XX:PermSize 参数意思不一样,- XX:PermSize 代表永久代的初始容量。
        由于调整元空间的大小需要Full GC,这是非常昂贵的操作,如果应用在启动的时候发生大量Full GC导致应用启动很慢,通常会调整永久代或元空间的大小,基于这种情况,一般建议在JVM参数中将MetaspaceSize和MaxMetaspaceSize设置成一样的值,并设置得比初始值要大,这样可以较少full GC次数 提高启动速度,对于8G物理内存的机器来说,一般建议将这两个值都设置为256M。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值