JVM 入门
一、谈谈对java的理解
语言层面 方向如下:
- 平台无关性 Wirte once, run anywhere
- GC 内存模型
- 语言特性(泛型、反射、Lambda表达式)
- 面向对象特点
- 类库(集合、并发、IO库...)
- 异常处理
1).JER,JDK,JVM之间的区别与联系
比如 编译器 javac ,就需要jdk环境
jvm_jre_jdk.png
jvm_jre_jdk的关系.png
2).java的平台无关性是如何实现的
平台无关性.png
3).谈谈ClassLoader 双亲委派机制
内存模型.png
ClassLoader的种类.png
双亲委派机制.png
双亲委派机制是一个锤石的坑爹过程,每需要加载一个类的时候,都会问问他父亲 (非继承的父子关系,而是组合关系),看父亲加载没有,一致询问到顶级的父亲,如果过程中,有谁加载了,就不会重复加载当前的类,如果都没有加载,会从顶级开始尝试加载,没个级别加载的访问路径是有严格区分的;这样做的好处是安全性高,防止核心类库的代码被篡改覆盖,同时也避免了重复加载的冗余!
静态代码块在类被初始化时执行,而不是笼统的在被加载时执行
二、内存模型
1). Java内存模型
内存模型图解.png
2). 程序计数器
程序计数器.png
3). 虚拟机栈
虚拟机栈详细结构.png
4). 本地方法栈
调用其他语言方法的模板
Native.png
5). 元空间|永久代
元空间与永久代.png
6). 堆内存
Java内存中的分部.png
调优.png
堆和栈的区别.png
7). 转储文件分析
转储文件:JVM启动参数;
转储文件.png
使用
Memory Analyze
工具分析dump下是转储文件分析当时内存情况
三、GC
1). 引用计数算法
解决的问题:标记垃圾
- 对象应用的次数 == 0时被清理
- 高效快捷
- 无法清理 循环应用
- 比如两个对象,外部没有任何执行他们的应用,但是连个引用相互为组合关系!
2). 可达性算法
解决的问题:标记垃圾 -> 循环引用
可达性算法.png
那些可以作为GCRoots?
- 静态成员变量
- 虚拟机栈重点局部变量表
- 常量池
- ...
3). 标记清除算法
解决的问题:清除垃圾
标记清除算法.png
遗留的问题:空间碎片太多
3). 复制算法
解决的问题:空间碎片化
复制算法.png
事先预留一份空间,用于复制生存下来的对象;对于大部分的对象,生命周期很短;
- 效率高
- 空间利用率低
4). 标记整理算法
解决的问题,垃圾标记并整理:效率略低
标记整理算法.png
5). 分代收集算法
将复制算法和标记整理算法糅杂与一身
分代收集算法.png
Eden中放置新出生的对象,第一次回收(Eden/from/to/(或者含有老年))之后,将生存的放入From Survivor 中,并将该年龄加一;第二次回收后,生存下来的对象与From Survivor中存活的 一起复制到 To Survivor;第三次 Eden /To Survivor 到 From Survivor ....;如果年龄超过15此就放到老年代(老年代也指接放置一些大的对象);如果从平均添加到老年代的对象大于老年代剩余空间,将会触发一次FullGC;
新生代向老年代过度的条件
- 默认经历了15次MinorGC依然存活(-XX:MaxTenuringThreshold)
- Survivor存放不下
- 新生的大对象
MinorGC与FullGC
- MinorGC: 收集新生代的内存空间;效率是 FullGC的 10倍
- FullGC: 收集整个堆内存
- 触发条件:
- 老年代空间不足
- 从MinorGG晋升到老年代的平均大小大于老年代的剩余空间
- 调用System.gc(); 还不一定执行
- 触发条件:
Finalize() 方法
- 对象存在几种状态
- 存活
- 可恢复:可以被抢救
- 回收
复写Finalize()方法,可以在里面临时抢救这个对象;处于可恢复状态的对象如果被抢救成功,能够存活;
Finalize()方法只能被执行一次;JVM会有一个低优先级的队列去执行这些方法!所以这个方法也不可靠!
网友评论