Java虚拟机学习总结

Jvm分为两大块,第一部分是是Jvm内存区域的管理,第二部分垃圾收集器。目前Jvm默认的是sun公司(已被oracle公司收购)的HotSpot虚拟机;此前还有BEA公司的JRockit(原来研发weblogic的公司,之后也被oracle公司收购,之后java8中虚拟机是两者的标准);还有IBM公司的J9 VM,最终还是HotSpot获得最后的胜利。

一、Jvm示意图简介

jvm示意图

  1. Class Loader类加载器
    负责加载class文件,class文件在文件开头有特定标示,并且ClassLoader只负责class文件的加载,至于他是否运行,则由Exeution Engine(执行引擎)决定。

  2. Native Interface本地库接口
    本地接口的作用是为了融合C/C++语言,为了调用C/C++程序,在内存中开辟了一块区域处理标记为native的代码,它的具体做法是在Native Method Stack(本地方法栈)登记native方法,在Exeution Engine(执行引擎)执行时加载native libraries,native关键字,指的是java 本地库接口(java可以直接调用c语言)JNI指的是Java native interface

  3. Method Area方法区
    方法区是被所有线程共享,所有字段和方法字节码,以及一些特殊方法如构造函数,接口代码也在此定义。简单说,所有定义的方法信息都保存在该区域,此区属于共享区间
    静态变量+常量+类信息+运行时常量池 存在方法区中

  4. PC register 程序计数器
    每个线程都有一个程序计数器,就是一个指针,指向方法区中的方法字节码(下一个将要执行的指令代码),由执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不计。

  5. Native Method Stack 本地方法栈
    它的具体做法是在Native Method Stack登记native方法,在Exeution Engine(执行引擎)执行时加载native libraries。

自问自答:什么是栈?什么是堆?
栈管运行,堆管存储。

  1. Stack栈是什么
    栈也叫栈内存,主管java程序运行,是在线程创建时创建,它的生命周期跟随线程的生命周期,线程结束栈内存就释放,对于栈来说不存在垃圾回收问题,生命周期和线程一致,是线程私有的(私有的内存不需要优化)。基本类型的变量和对象的引用变量都是在函数的栈内存中分配。
    方法存放在栈中,并且称之为“栈帧”(可以用子弹夹的例子作为理解),栈帧主要保存的数据有:本地变量(输入参数、输出参数以及方法内的变量)、栈操作、栈帧数据(包括类文件、方法等)
    栈内存放的数据有:八种基本类型的变量,引用变量,方法
    可能出现的异常:java.lang.StackOverflowError(栈内存溢出异常)

  2. 堆是什么?
    堆分为新生区(伊甸区Eden space、幸存0区Survivor 0 space、幸存1区Survivor 1 space)、养老区(Tenure Generation space)、永久存储区。
    新生区:是类的诞生、成长、消亡的区域,当伊甸园区的空间快被使用完时(占用空间的七成),程序又需要创建对象,Jvm的垃圾收集器将对伊甸园区进行垃圾回收(Minor GC,轻量级),直到养老区也满,将进行Major GC,又称FullGC,全局回收。FullGC后仍无法进行对象的保存,就会产生OOM异常,java.lang.OutOfMemoryError:java heap space,导致java虚拟机堆内存空间不够的原因:
    1、设置的堆内存不够用,可以通过设置参数 -Xms、-Xmx来调整
    2、代码中创建来大量大对象,长时间不能被回收(存在被引用)。
    养老区:用于保存从新生区筛选出来的Java对象,一般池对象都在这个区活跃。
    永久区:永久存储区是一个常驻内存区域,用于存放JDK自身携带的class、interface的元数据。永久区也会出现OOM异常,不过打印出来的异常是 PermGen space,说明java虚拟机对永久代内存设置不够,一般情况下,都是程序启动需要加载大量的第三方jar包。

二、GC垃圾收集器以及优化

**jvm优化,百分之99优化堆,百分之1优化方法区,优化的都是共享空间**
下面简介一下java6、7、8常量池的情况
jdk1.6    有永久代,常量池在方法区
jdk1.7    有永久代,准备去永久代,常量池在堆内存中
jdk1.8    去永久代,常量池在元空间
永久代/元空间只是堆的逻辑组成部分,实际在内存中并不占用堆的组成内存,堆只由新生区和养老区组成。

堆内存调优介绍:
铭记三个参数:
-Xms(start):设置最初分配的大小,默认为物理内存的1/64
-Xmx(max):设置最大分配内存,默认物理内存的1/4
-XX:+PrintGCDetails:输出详细的GC处理日志

GC是什么?
频繁收集Young区(较小收集)
较少收集Old区(较大收集)
基本不动Perm区

新生区GC

新生区GC一般都是较小频繁收集的情况,使用的是复制算法copying,也是MinorGC,或者叫 普通GC。复制算法的规则,新生区可以划分为8:1:1,其中8是指新建对象存放的比例,1:1则是from区域、to区域,当经过垃圾回收之后,剩余存活下来的对象会放到to区域,作为下次复制算法的from区域,以此不断循环,可以提一下的是,一般是满15(有参数可以控制)由新生区进养老区,to区域放满后也可以进养老区。
优点:完整性高,不会产生内存碎片
缺点:1⃣️浪费了一半的内存空间(对于from、to区域而言是1:1)
2⃣️如果对象的存活率过高,java虚拟机将会复制所有的对象,以及对象引用的变量地址,严重影响到性能。

养老区GC

养老区一般使用的是标记清除或者标记清除与标记整理的混合实现,是FullGC,又叫全局GC
标记清除Mark-Sweep缺点:
1⃣️效率低下,需要双重扫描
2⃣️产品内存碎片,内存回收空间不连续(延伸出下面另一算法)
标记整理Mark-Compact缺点:
效率低下,标记整理算法要低于复制算法

三者的特点与区别

内存效率:复制算法>标记清除算法>标记整理算法(此处只是简单的从时间复杂度进行比对)
内存整齐度:复制=标整>标清(内存碎片角度考虑)
内存利用率:标清=标整>复制(复制消耗大量内存)

没有最好的算法,只有最合适的算法,分代收集算法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值