jvm
讲的好的链接(https://www.zhihu.com/question/20097631)
jvm三个主要的子系统:
(1)类加载子系统
(2)运行时数据区(内存结构)
(3)执行引擎
运行时数据区(内存结构)
java native关键字
简单地讲,一个Native Method就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:该方法的实现由非java语言实现,比如C。
程序计数器
java栈(8种基本类型的变量+对象的引用变量+实例方法)
把栈撑爆,出现错误
栈帧中存放(局部变量表,操作数栈,执行运行时常量池的引用,方法返回地址,动态链接)
黄色部分是线程共享的,蓝色部分是线程私有的
堆中存放对象(1.7之前是永久代,1.7之后是元空间)
方法区中存放全局变量(静态变量),常量,类信息等(运行时常量池)【存储了每一个类的结构信息】
私有的:像局部变量等属于线程私有的
https://www.cnblogs.com/alsf/p/9017447.html
堆中分为:新生儿(Eden),from(s0区域),to(s1区域),当Eden放满之后,会发生轻gc(没用的对象进行垃圾回收),没有回收的对象转移到from(s0)区域,from区域放满之后也会触发轻gc,存活下来的对象会转移到to区域,然后to区域变成from区域,from区域变成to区域,来回变换一定的次数后,最终存活下来的对象放入到老年代,老年代放满之后会发生中gc(fullgc).老年代中存放的是存活时间成或者比较大的对象。
jvm类加载机制
生命周期:加载-》连接(验证,准备,解析)-》初始化-》使用-》卸载
加载:将字节文件(.class文件)从磁盘读到内存
类加载器的种类:
(1)启动类加载器:负责加载JRE的核心类库,如JRE目标下的rt,jar,charsets.jar等
(2)扩展类加载器:加载JRE扩展目录ext中的jar包
(3)系统类加载器:加载classpath路径下的类包(如:加载用户写的类)
(4)用户自定义类加载器:加载用户自定义路径下的类包
类加载机制:
(1)全盘负责委托机制:是指当一个ClassLoader装载一个类时,除非显示地使用另一个ClassLoader,则该类所依赖及引用的类也由这个CladdLoader载入。
(2)双亲委派机制:指先委托父类加载器寻找目标,在找不到的情况下在自己的路径中查找并载入目标类(防止用户自定义类捣乱)
(上边是父类)
启动类加载器(boot classload) |
扩展类加载器(ext cl) |
系统类加载器(app cl) |
双亲委派模式的优势
沙箱安全机制:比如自己写的String.class类不会被加载,这样防止核心库被随意篡改
避免类的重复加载:当父加载器已经加载了该类的时候,就不需要子加载器再加载一次。
GC算法和收集器
(1)如何判断对象可以被回收
java堆内存中存放着几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象之中哪些还“存活”着,哪些已经“死去”。那么GC具体通过什么手段来判断一个对象已经”死去”的?
【1】引用计数法
给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1,当引用失效时,计数器减1,任何时刻计数器为0的对象就是不可能再被使用的。
缺点:目前主流的java虚拟机都摒弃掉了这种算法,最主要的原因是它很难解决对象之间相互循环引用的问题。尽管该算法执行效率很高。
【2】可达性分析算法
目前主流的编程语言(java,C#等)的主流实现中,都是称通过可达性分析(Reachability Analysis)来判定对象是否存活的。这个算法的基本思路就是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连(用图论的话来说,就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的。如下图所示,对象object 5、object 6、object 7虽然互相有关联,但是它们到GC Roots是不可达的,所以它们将会被判定为是可回收的对象。
在Java语言中,可作为GC Roots的对象包括下面几种:
- 虚拟机栈(栈帧中的本地变量表)中引用的对象。
- 方法区中类静态属性引用的对象。
- 方法区中常量引用的对象。
- 本地方法栈中JNI(即一般说的Native方法)引用的对象。
(2)垃圾回收算法
https://blog.csdn.net/yrwan95/article/details/82829186
(1)标记-清除算法
(2)复制算法
(3)标记-整理算法
(4)分代回收
Eden(标记-清除算法)【标记-清除算法:节约空间,有内存碎片】,from to(复制算法)【复制算法:好处,没有内存碎片,坏处,费内存】,老年代(标记-整理算法),分代回收(jvm采用的就是这种算法)
(3)垃圾收集器
Serial收集器(串行):单线程收集器,垃圾收集的时候必须暂停其他的工作线程,即STW(stop the world)(新生代采用复制算法,老年代采用标记-整理算法)
ParNew收集器:多线程收集器(多条垃圾收集线程),垃圾收集的时候必须暂停其他的工作线程,即STW(stop the world)(新生代采用复制算法,老年代采用标记-整理算法)
Parallel Scavenge收集器(jdk8默认的):吞吐量优先收集器
CMS收集器
优点:并发收集(垃圾收集与用户线程一起“并发”执行的。),低停顿
缺点:(1)对CPU资源敏感(2)无法处理浮动垃圾(垃圾收集过程中新产生的垃圾)(3)使用的是标记-清除算法,会导致收集结束时有大量的空间碎片。
G1收集器
调优
JVM调优主要是调整下面两个指标
(1)停顿时间:垃圾收集器做垃圾回收中断应用执行的时间。-XX:MaxGCPauseMillis
(2)吞吐量:垃圾收集的时间和总时间的占比:1/(1+n),吞吐量为1-1/(1+n)。-XX:GCTimeRatio=n
GC调优步骤:(https://www.cnblogs.com/baizhanshi/p/6140925.html?utm_source=itdadao&utm_medium=referral)
(1)打印GC日志
-信息:+PrintGCDetails -xx:+PrintGCTimeStamps -xx:+PrintGCDateStamps -xloggc:./gc.log
(2)分析日志得到关键性指标
(3)分析GC原因,调节JVM参数
JMM(java内存模型)(线程安全性获得保证)
(1)可见性
(2)原子性
(3)有序性
加载顺序:静态代码块-》构造块-》构造方法