文章目录
深入理解java虚拟机
什么是java虚拟机
jvm通俗来说是一个程序,操作系统角度来看,当它运行起来就是一个进程。是执行字节码文件(.class)的虚拟进程。
自动内存管理机制
运行时数据区域
线程共享:
堆:内存大,存放对象实例。垃圾收集器管理的主要区域,也称gc堆。
方法区:存储已经被虚拟机加载的类信息、常量(运行时常量池)、静态变量、即时编译器编译后的代码等数据。
线程私有:
虚拟机栈:方法执行的内存模型,存储方法中的局部变量、方法出口等信息。
本地方法栈:本地native方法执行的内存模型。
程序计数器:内存较小,当前线程所执行的字节码的行号指示器。通过改变这个计数器的值,选取下一条需要执行的指令,实现分支、循环、跳转等功能。
OutOfMemoryError
除了程序计数器外,其他的运行时区域都有可能发生OOM内存溢出异常,
垃圾回收机制
如何判断对象是否存活
1.引用计数算法:给对象添加一个引用计数器,每当有一个地方引用它时,计数器的值+1,引用时效则-1,当值为0时代表对象已死。(不能解决对象之间相互循环引用)
2.可达性分析算法:通过一系列GC Roots对象做为起始点,从这些节点开始向下搜索,走过的路径成为引用链。若一个对象到GC Roots之间没有任何引用链相连,则说明对象已死。
java对象引用
jdk1.2之后,引用被分为强引用,软引用,弱引用,虚引用,引用强度依次减弱。
垃圾收集算法
1.标记-清除算法
2.复制算法:每次使用一半内存,用完时将存活对象复制到另一块中,再清除这一半内存空间。(新生代)
3.标记-整理算法(老年代)
4.分代收集算法:新生代、老年代
垃圾收集器
1.Serial收集器:单线程收集器,执行时必须暂停其他所有的工作线程,简单而高效。
2.ParNew收集器:Serial收集器的多线程版本。单cpu环境中,性能没有Serial收集器好。
3.Parallel Scavenge收集器:多线程,吞吐量优先,有自适应调节策略。主要适合在后台运算多不需要太多与用户交互的任务。
4.Serial Old收集器:老年代收集器。
5.Parallel Old收集器:多线程老年代收集器。
6.CMS收集器:并发收集,最短回收停顿时间优先。
7.G1收集器:并发与并行,分代收集,空间整合,可预测的停顿。
GC日志
Full GC代表此次垃圾收集出现了工作线程停顿。
内存分配
年龄计数器:经过一次GC年龄+1,默认15岁晋升老年代。
1.对象优先在Eden分配
2.大对象直接进入老年代
3.长期存活的对象将进入老年代
4.动态对象年龄判定:相同年龄的对象大小总和大于survivor空间的一半,年龄大于或等于该年龄的对象直接进入老年代。
虚拟机性能监控
jdk命令行工具
jps
jps 虚拟机进程状况
jsp -v 显示进程启动时jvm参数
jstat
虚拟机统计信息监控
jdk的可视化工具
JConsole
VisualVM
类加载机制
加载时机
加载:无约束
初始化:
1.遇到new、getstatic、putstatic、invokestatic字节码指令时。
2.对类反射调用时。
3.先初始化父类,后子类。
4.虚拟机启动时,先初始化指定的main方法类。
加载过程
加载-验证-准备-解析-初始化-使用-卸载
类加载器
启动加载器(Bootstrap ClassLoader):C++实现,加载lib目录中的类。
扩展类加载器(Extension ClassLoader):java实现,加载lib\ext目录中的类。
应用程序类加载器(Application ClassLoader):java实现,加载用户目录下的类。程序中默认类加载器。
自定义类加载器(User Classloader)
双亲委派模型
启动加载器《–扩展类加载器《–应用程序类加载器《–自定义类加载器
类加载器之间的关系,成为双亲委派模型。
工作过程:类加载器收到了类加载请求,会先将请求委派给父类加载器,当父类搜索范围中没找到相应的类,才会交给子类加载器加载。
作用:java类随着类加载器一起具备带优先级的层级关系。