JVM
jvm是什么
是一种规范,是虚构出来的计算机,有自己的指令集、汇编语言
java执行过程
.java文件经过javac编译为.class文件
调用的时候.class和java相关类库被ClassLoader装载到内存
之后通过java解释器和JIT即时编译器(经常执行的在JIT中走,反之走解释器),
之后通过执行引擎执行,再到硬件
![](https://i-blog.csdnimg.cn/blog_migrate/0bdee267d0305ac17e968afd6e8ad9dc.png)
jvm跨平台
jvm是跨语言的平台,只要能编译或生成或形成的.class文件的语言,都可以使用JVM
![](https://i-blog.csdnimg.cn/blog_migrate/60a0ef228c2b0fbea556fda181652df3.png)
jvm文档规范查询
JDK JRE JVM关系
![](https://i-blog.csdnimg.cn/blog_migrate/06b66b0a1688a4a65a877d818e57926a.png)
什么是class文件
class文件是二进制字节流
编译前
![](https://i-blog.csdnimg.cn/blog_migrate/aae6503ee7b8a0933ecb4a280c69c423.png)
编译后
![](https://i-blog.csdnimg.cn/blog_migrate/6e046f1da53a29bec75ae94accc16ddd.png)
字节码
![](https://i-blog.csdnimg.cn/blog_migrate/6ab3ab88134bcfaf4d1a4e899a909899.png)
*u1 u2 u4(u后面跟几,就是几个字节)
class文件解析
ca fe ba be是表示这个文件是一个class文件
00 00 小版本号(这是16进制的,转成10进制,就是版本号0)
00 34 大版本号(这是16进制的,转成10进制,就是版本号52)
00 10 是常量池里面的常量数量,因为是两个字节表示的,所以最多存放65535个字节(2的16次方减1),常量池编号从1开始
*大小版本号放在一起,就是52.0,就是当前版本号
什么是垃圾:
当对象没有引用指向的时候就是垃圾
C/C++回收方法:
手动回收
定位垃圾:
-
引用计数器:
-
对象被引用一次就计数+1,引用完就-1,到0就回收
-
-
根查找器(根可达):
-
从根部开始找起,能找到的都不是垃圾,反之就是垃圾,就回收
-
java虚拟机最好的书
java虚拟机规范
垃圾回收机制
Mark-Sweep(标记清除):将垃圾找到并清除,缺点是碎片化
![](https://i-blog.csdnimg.cn/blog_migrate/d05ad04b0c51c86b14349c7823b6d542.png)
Coppying
(标记清除):不管内存多大,分成两半,只使用一半.回收时将正在使用的拷贝到其中一半,另一半集中清除,坏处是浪费空间
![](https://i-blog.csdnimg.cn/blog_migrate/92f947ac40ee516af753e8ded1428e81.png)
Mark-Compact(标记整理):边使用边整理,使用中的放前面,没使用放后面.缺点是效率低
![](https://i-blog.csdnimg.cn/blog_migrate/a591a1e25b93c9b56d09280b52a16d0c.png)
十种垃圾回收器
![](https://i-blog.csdnimg.cn/blog_migrate/6c3f7fde927063999371c50c26bec121.png)
分代模型:将内存区域分为新生代和老年代
新生代:新new出来的对象,一次就能回收掉的
使用拷贝算法回收
老年代:长时间未被回收掉的
使用标记清除和标记整理
![](https://i-blog.csdnimg.cn/blog_migrate/b351f984d3d7d3171295330e7e19a63c.png)
eden:对象诞生
survivor:eden中GC介入后,剩余的对象.拷贝到survivor并清除eden,GC再次介入后,剩余的对象.拷贝到另一个survivor,反复拷贝清除,直到年龄达到tenured默认年龄阈值
tenured:多次GC没有清除掉的对象达到年龄阈值,拷贝到tenured
![](https://i-blog.csdnimg.cn/blog_migrate/c76a71f5b7ed89d73812f1adfb722980.png)
逃逸:不能有方法引用这个对象,野指针
标量替换:将对象转换成基础数据类型替换掉
放在栈上的对象:没有被引用的被创建的对象
放在堆上的对象:
对象大的话直接放入老年代,FullGC
对象小的话
判断Tlab(线程本地分配缓冲区:JVM给每个线程分配的区域),如果线程的区域够了就直接被回收,如果线程区域不够,则进入eden
分代模型通常成对出现:
ParNew-CMS
ParNew:暂停正在运行的业务线程,多线程回收,约等于Parallel Scavenge,专门配合CMS使用
![](https://i-blog.csdnimg.cn/blog_migrate/dc33691873dcc6d16a514ba8390b19df.png)
CMS:垃圾回收线程和工作线程同时运行(并发),好处是不会卡
初始标记:找出根对象(耗时几百毫秒),
并发标记:运行时监控工作线程并标记
问题1:
浮动垃圾:标记的时候变成垃圾
问题2:
错标:标记为垃圾之后,又被调用
重新标记:修正错标
并发清理:清理垃圾
![](https://i-blog.csdnimg.cn/blog_migrate/f3af864602605f2098262f7d898c6650.png)
Serial-Serial Old:
Serial:暂停正在运行的业务线程,执行回收(存在于理论中,早期版本jdk使用,单线程处理,新生代回收)
![](https://i-blog.csdnimg.cn/blog_migrate/95840192d2d929a21f9edb49c96e1416.png)
Serial Old:暂停正在运行的业务线程,执行回收(存在于理论中,早期版本jdk使用,单线程处理,老年代回收)
![](https://i-blog.csdnimg.cn/blog_migrate/ae39d3346f757d4213c6e32b4b57eb28.png)
Parallel Scavenge - Parallel Old
Parallel Scavenge:暂停正在运行的业务线程,多线程回收(java1.8默认,新生代)
![](https://i-blog.csdnimg.cn/blog_migrate/f3af864602605f2098262f7d898c6650.png)
Parallel Old:暂停正在运行的业务线程,多线程回收(java1.8默认,老年代)
![](https://i-blog.csdnimg.cn/blog_migrate/b5741c94abc15dac99a3e901ce19a628.png)
PS:并不是线程越多回收效率越高,因为N核CPU执行N+M个线程的时候,因为需要轮流执行线程,计算机会将资源浪费在线程调度上