垃圾回收
垃圾回收的具体策略
新生代——复制算法
在新生代采用的垃圾回收属于复制算法,主要原因是新生代区域中的对象数量较少,存活时间短,在对象复制过程中的耗时较少。
老生代——标记-整理算法
主要原因是老生代区域中的对象生命周期较长,采用复制算法将会产生频繁的复制操作,对应的开销较大。
而标记整理算法可以很好的避免这个问题,提升垃圾回收的效率。
参考资料:
https://segmentfault.com/a/1190000010421285#articleHeader2
JVM调优
jps:
虚拟机进程状况工具
用于列出正在运行的虚拟机进程、并显示虚拟执行主类(Main Class,main() 函数所在的类)的名称以及这些进程的本地虚拟机唯一ID
jstat:
虚拟机统计信息监视工具
用于监视虚拟机各种运行状态信息,可以显示本地或者远程虚拟机进程中类装载、内存、垃圾收集、JIT编译等运行数据。
比如虚拟机GC的情况(GC的结果、时间等信息)
jinfo:
Java配置信息工具
用来实时地查看和调整虚拟各项参数。
使用 jsp
命令的 -v 参数可以查看虚拟机启动时显式指定的参数列表,但如果想知道未被显式指定的参数的系统默认值,除了查找资料以外,就只能使用 jinfo
的 -flag 选项进行查询。
jmap
Java内存印像工具
jmap
用于生成堆转储快照(一般为 heapdump 或 dump文件)
其他可生成 heapdump
的方式:使用参数-XX:+HeapDumpOnOutOfMemoryError
使用参数-XX:+HeapDumpOnCtrlBreak
然后使用 Ctrl+Break 生成;Linux系统使用kill -3生成
另外它还可以查询 finalize 执行队列、Java堆和永久代的详细信息
jhat:
虚拟机堆转储快照分析工具
功能:用于分析jmap生成的heapdump。其内置了一个微型的HTTP服务器,可以在浏览器查看分析结果;
实际很少用jhat,主要有两个原因:一是分析工程会耗用服务器资源;功能相对BisualVM、IBM HeapAnalyzer较为简陋;
jstack:
Java堆栈跟踪工具
用于生成虚拟机当前时刻的线程快照(一般称为 threaddump
或者 javacore
文件)
线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合
生成线程快照的主要目的是定位线程出现长时间停顿的原因
JDK1.5 中,java.lang.Thread
类新增了一个 getAllStackTraces()
方法,用于获取虚拟机中所有线程的 StackTraceElement
对象。使用这个方法一样可以完成 jstack
的大部分功能
HSDIS:
JIT生成代码反编译
是一个官方推荐的 HotSpot 虚拟机 JIT 编译代码的反汇编软件。
它的作用是让 HotSpot 的 -XX:+PrintAssembly
指令调用它来把动态生成的本地代码还原为汇编代码输出,同时还生成了大量非常有价值的注释
两个可视化工具:
JConsole:Java监视与管理控制台
VisualVM:多合一故障处理工具
参考资料
https://segmentfault.com/a/1190000010437810#articleHeader8
类加载机制
类加载的过程
类加载的过程包括了加载、验证、准备、解析、初始化五个阶段
在这五个阶段中,加载、验证、准备和初始化这四个阶段发生的顺序是确定的,而解析阶段则不一定,它在某些情况下可以在初始化阶段之后开始,这是为了支持Java语言的运行时绑定(也成为动态绑定或晚期绑定)。
另外注意这里的几个阶段是按顺序开始,而不是按顺序进行或完成,因为这些阶段通常都是互相交叉地混合进行的,通常在一个阶段执行的过程中调用或激活另一个阶段。
加载
加载时类加载过程的第一个阶段,在加载阶段,虚拟机需要完成以下三件事情:
1、通过一个类的全限定名来获取其定义的二进制字节流。
2、将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
3、在Java堆中生成一个代表这个类的java.lang.Class对象,作为对方法区中这些数据的访问入口。
双亲委派模型:
双亲委派模型的工作流程:
如果一个类加载器接受到了类加载的请求,它首先不会自己尝试去加载这个类,而是把请求委托给父加载器去完成,依次向上。
因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器当中,当父类加载器在它的搜索范围中没有找到所需要的类,即无法完成加载时,子类加载器才会去尝试加载该类。
双亲委派模型的好处:
明显的好处是:Java类随着它的类加载器一起具备了一种带优先级的层次关系,有利于保证Java程序的稳定性。
比如:类java.lang.Object类存放在JDK\jre\lib下的rt.jar之中,因此无论是哪个类加载器要加载此类,最终都会委派给启动类加载器进行加载,这边保证了Object类在程序中的各种类加载器中都是同一个类。
参考资料:
类加载机制
类初始化
ClassLoader详解
https://blog.csdn.net/briblue/article/details/54973413