JVM
内存结构
程序计数器
如果线程正在执行一个Java方法,则这个计数器记录的正在执行虚拟机字节码指令的地址;如果正在执行的是Native方法,则这个计数器的值为空(Undefined)
线程私有
- 不会存在内存溢出
Java虚拟机栈
- 每个线程运行时所需要的内存,称为虚拟机栈
- 每个栈由多个栈帧组成,对应着每次方法调用时所占用的内存
- 每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法
方法内局部变量是否安全:
- 如果方法内局部变量没有逃离方法的作用范围,它是线程安全的
- 如果是局部变量引用了对象,并逃离方法的作用范围,需要考虑线程安全
本地方法栈
堆
- 通过new创建的对象会使用堆内存
- 线程共享,需要考虑线程安全
- 有垃圾回收机制
- jps
- 查看当前系统中有哪些Java进程
- jmap
- 查看堆内存使用情况jmap -heap id
- jconsole
- 图形界面
- jvisualvm
方法区
线程共享
存储和类相关的信息
1.8前会导致永久代内存溢出,后会导致元空间内存溢出
常量池
- 常量池就是一张表,虚拟机根据这张常量表找到要执行的类名、方法名、类型参数、字面量等信息
- 运行时常量池,常量池是*.class文件中的,当该类被加载时,它的常量池信息就会放入运行时常量池,并发里面的符号地址变为真实地址
垃圾回收
判断对象可以回收
引用计数法
可达性分析算法
四种引用
- 强引用
- 软引用
- 弱引用
- 虚引用
回收算法
- 标记清除
- 会造成内存碎片
- 标记整理
- 整理效率较低
- 复制
- 占用双倍的内存空间
分代的垃圾回收
新生代
- 伊甸园
- 幸存区from
- 幸存区to
老年代
minor gc会触发STW,暂停其它用户的线程,等垃圾回收结束后,用户才恢复运行
当对象寿命超过阈值时,会晋升到老年代,最大寿命是15(4bit)
- 当老年代空间不足会先尝试触发minor gc,如果之后空间仍然不足,那么触发full gc,STW时间更长
VM相关参数
垃圾回收器
串行
- 单线程
- 堆内存较小,适合个人电脑
吞吐量优先
- 多线程
- 堆内存较大,多核CPU
- 让单位时间内STW的时间最短
响应时间优先
- 多线程
- 堆内存大,多核CPU
- 尽可能让STW的时间最短
G1
类加载
类加载的时机
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 划水摸鱼!