什么是JVM
JVM,java虚拟机,java二进制字节码运行环境
好处:
一次编译,到处执行;
自动内存管理,垃圾回收功能;
数组下标越界检查;
多态
内存结构
程序计数器
作用
记住下一条jvm指令的执行地址
特点
程序计数器是线程私有的,每一个线程有一个;
不会出现内存溢出
栈
线程运行需要的内存空间,每个栈由多个栈帧组成,每个线程只能有一个活动栈帧。
栈内存设置 -Xss256k
栈帧
每一个方法运行需要的内存
垃圾回收不涉及栈内存
方法内的局部变量是否线程安全?
如果方法内的局部变量没有逃离方法的作用范围,则线程安全
堆
参数 -Xmx
控制台输入:
4.jvirsualvm
方法区
常量池
串池StringTable(也会垃圾回收)
jdk1.8 串池用堆空间
x2入池,x1从池中获取,x1和x2相等
jdk1.6 串池用永久代
x2拷贝一份入池,x1从池中获取,x2在堆中,不相等
字符串多 可以加大桶个数,减少哈希冲突,提高性能
直接内存
非gc回收,需调用一个unsafe对象释放
垃圾回收
引用计数法
在对象中添加一个计数器,每当有一个地方引用这个对象时,计数器就加一。
缺点:如果有两个对象,都有一个字段,且互相引用着对方,会导致他们的计数都不为0,无法被回收。
可达性分析
通过一系列被称为gc root的根节点集,从这些节点开始,根据引用关系向下搜索,搜索所走过的过程称为引用链,如果某个对象到gc root之间没有引用链,说明这个对象不可达,既不再被使用,可以回收。
四种引用
强引用
当一个对象被强引用时,不可能会垃圾回收机制回收
软引用
当一个对象只有软引用时,垃圾回收时,如果内存不足可能会被回收
弱引用
垃圾回收时,无论内存是否足够都会被回收
虚引用
类似于完全没有引用,需要和引用对列联合使用
终结器引用
垃圾回收算法
标记清除
优点:清除快
缺点:会产生很多内存碎片
标记整理
复制
分代回收
新生代
回收频率高,采用复制算法
老年代
对象价值高
垃圾回收器
串行
吞吐量优先
多个线程回收
响应时间优先
G1 garbge first
新生代回收
会stw
新生代回收+CM(并发标记)
混合回收
老年代也用复制算法,为了满足时间要求,只从老年代中回收那些回收价值较高的老年代对象
full gc概念辨析
G1老年代内存不足时,会触发并发标记和混合回收,在这两个阶段中,如果回收垃圾的速度慢于新产生垃圾的速度,并发收集会失败,触发串行收集,才是full GC,CMS同理。
GC调优
新生代调优
这个容量可以较少进行垃圾回收,减少stw
幸存区
幸存区如果太小,存活时间短的对象可能会被晋升老老年代,这样的对象只有等到full gc才会被回收,显然不合适。
老年代
案例1-新生代空间太小
案例2-时间长是因为并发过程中,重新标记的时间长,可以在重新标记之前先进行一次清理
案例3-1.8以前方法实现是永久代,之后是元空间,使用的是系统空间;
类文件结构
javap 反编译class文件
字节码指令
a11 b34 a++先load再+
cinit
init
多态
语法糖
泛型擦除-原代码编译为字节码后,泛型信息就丢失了。
类加载
加载
连接
连接-验证
连接-准备
静态变量存于堆中
连接-解析
将常量池的符号解析为直接引用
初始化
类加载器
启动类加载器,扩展加载器,应用程序加载器,自定义加载器
双亲委派机制
运行期优化
逃逸分析,会分析代码中的对象是否会被外部用到,如果未被用到,则不会创建对象
方法内联,字段优化
JMM
原子性,可见性,有序性 volatile
CAS