第一章: Java虚拟机介绍
1.1 jvm分类
Sun Classic VM : 世界上第一款商用的Java虚拟机Extract VM:准确试内存管理 编译器和解释器混合工作以及两级及时编译器HotSpot VM:KVM: kilobyte 简单,轻量, 高度可移植。 在手机平台运行JRockit: BEA. 世界最快的Java虚拟机 优势 1.垃圾收集器。2. MissionControl 服务套件J9:Dalvik:Microsoft JVM:Azul VM Liquidj VM: 高性能的Java虚拟机TaobaoVM:
1.2 Java虚拟机内存管理
线程共享区:方法区,Java堆
线程独占区:程序计数器, 虚拟机栈,本地方法栈
1.2.1 程序计数器
当前程序执行的字节码行号程序计数器处于线程独占区执行Java方法,计数器记录当前程序地址,native方法,记录undefined此区域没有任何内存溢出
1.2.2 Java虚拟机栈
栈帧:每个方法执行,都会创建一个栈帧局部变量表:存放编译期可知的各种基本数据类型,引用类型,returnAddress大小:递归的调用出现栈溢出:stackoverflowError:栈溢出OutOfMemery
1.2.3 Java虚拟机的本地方法栈
为虚拟机执行native方法的
1.2.4 Java虚拟机内存区域—堆区域
存放对象实例垃圾收集器管理的主要区域新生代。老年代
1.2.5 Java内存区域-方法区
1.存储虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据2.方法区和永久代3.垃圾回收在方法区的行为4.异常的定义OutOfMemeryError
1.2.6 Java内存区域-直接内存和运行时常量池
1.String s1 = "abc";String s3 = new String("abc");s3.internal() 运行时常量2.直接内存能够分配堆外内存
1.2.7 对象在内存中的布局—对象的创建

第二章 垃圾回收机制-概述
2.1 如何判定对象为垃圾对象
1.引用计数法2.可达性分析法
2.2 如何回收
1.回收的策略标记-清除法复制算法标记-整理算法分代收集算法2.垃圾收集器SerialParnewCmsG1
2.3 何时回收
2.3.1 引用计数法
垃圾回收-判断对象是否存活算法--引用计数法在对象中添加引用计数器,当有地方引用这个对象的时候,引用计数器的值就+1,当引用失效的时候,计数器的值就是-1打印详细的GC信息-verbose:gc-xx:PrintGCDetails代码:Main m1 = new Main()Main m2 = new Main()m1.instance = m2;m2.instance = m1;m1 = null;m2 = null;
2.3.2 可达性分析法
垃圾回收-判断对象是否存活算法--可达性分析法(主流)作为GC Roots的对象虚拟机栈方法区的类属性所引用的对象方法区中常量所引用的对象本地方法栈中引用的对象
2.3.4 垃圾回收算法-标记清除算法
效率问题空间问题回收内存时导致内存不连续
2.3.5 垃圾回收算法-复制算法
内存资源极大浪费(内存空间只用一半)堆:新生代Eden:伊甸园Survivor:存活区Tenured Gen:老年代方法区栈
2.3.6 垃圾回收算法-标记整理清楚算法。分代收集算法
垃圾回收算法-标记整理清楚算法。分代收集算法标记整理--回收老年代分代收集算法--根据不同的分代采用不同的算法
2.3.7 垃圾收集器—Serial收集器(针对新生代)
最基本-发展最悠久单线程垃圾收集器
2.3.8 垃圾收集器—parnew收集器
多线程垃圾收集器
2.3.9 垃圾收集器—Parallel收集器
复制算法(新生代收集器)多线程收集器可达到吞吐量:CPU用与运行用户代码的时间与CPU消耗的总时间的比值吞吐量 = (执行用户代码时间)/ (执行用户代码的时间 + 垃圾回收所占用的时间)-XX:MaxGCPauseMillis: 垃圾收集器最大停顿的时间-XX:GCTimeRatio : 吞吐量大小(0,100)
2.3.10 垃圾收集器—CMS收集器
Concurrent Mark Sweep(并发标记清楚算法)工作过程:初始标记并发标记重新标记并发清理优点:并发收集低停顿缺点:占用大量的CPU资源无法收集浮动垃圾出现Concurrent Mode Failure时间碎片
2.3.11 垃圾收集器—G1收集器
优势:并行 并发分代收集空间整合可预测的停顿步骤:初始标记并发标记最终标记筛选回收
第三章 内存分配—概述
3.1 内存分配策略
内存分配策略优先分配到Eden大对象直接分配到老年代长期存活的对象分配到老年代空间分配担保动态对象年龄判断
3.1.1 内存分配-Eden区域
打印详细的GC信息-verbose:gc-xx:PrintGCDetails使用Serial算法-XX:+UserSerialGC指定堆内存大小(20M)-Xms20M-Xmx20M新生代内存大小-Xmn10M限制Eden区的大小-XX:SurvivorRation=8
3.1.2 内存分配-大对象直接进入老年代
指定对象的大小(如果大小这个值,则直接进入老年代)--XX:PretenureSizeThreshold=6M(指定大对象为6M)
3.1.3 内存分配-长期存活的对象进入老年代
--XX:MaxTenuringThreshold 15(默认值为)
3.1.4 内存分配-空间分配担保
-XX:+HandlePromotionFailure
3.1.5 内存分配-逃逸分析与栈上分配
逃逸分析:分析对象的作用域引用的作用域仅在当前方法中有效,没有发生逃逸引用成员变量的值,发生逃逸代码:
3.2 虚拟机工具介绍
jpsjstatjinfojmapjhatjstackjconsole
3.2.1 虚拟机工具-jps
Java Process status本地虚拟机唯一ID local virtual machine IDjps -l 类的全名jps -m 接收命令行参数jps -v 接收虚拟机参数
3.2.2 虚拟机工具-jstat
类加载。内存。垃圾收集 git编译信息jstat -gcutil 6692jstat -gcutil 6692 1000 10S0:Survivor0S1:Survivor1E:EdenO:OldM:MetaCCS:压缩类空间YGC:年轻代发生的GC次数YGCT:年轻代发生的GC次数的时间FGC:FGCT:GCT:
元空间本质和永久代本质类似
元空间不在虚拟机,在直接内存中
**
3.2.3 虚拟机工具-jinfo
实时查看和调整虚拟机的各项参数jinfo -flag UseSerialGC-XX:
3.2.4 虚拟机工具-jmap
导出进程的快照信息 显示堆中的信息jmap -dump:format=b,file=~/a.bin pidjmap histo-XX:+HeapDumpOnOutOfMemoryError
3.2.5 虚拟机工具-jhat (Jvm heap Analysis Tool)
将dump的heap信息拷贝本地分析jmap -dump:format=b,file=d:\a.bin pidjhat d:\a.binOQL的使用
3.2.6 虚拟机工具-jstack
生成线程栈快照目的:导致线程长时间停留原因jstack -l pidMap<Thread,StackTraceElemnt[]> m = Thread.getAllStackTraces();for( Map.Entry<Thread,StackTraceElemnt[]> en : m.entry.set) {}
3.2.7 可视化虚拟机工具-jconsole内存监控
3.2.8 可视化虚拟机工具-jconsole线程监控
3.2.9 可视化虚拟机工具-jconsole线程死锁监控
第四章 性能调优
知识工具数据经验性能调优--案例1性能调优--案例2Class文件简介和发展历史Helle.javajavac Helle.java生成Helle.class运行Java程序java Helle
第五章 class文件结构


第六章 类加载过程
6.1 类加载的过程—加载
通过一个类的全限定名来获取定义此类的二进制流将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构在内存中生成一个代表这个类的Class对象,作为这个类的各种数据的访问入口加载源:文件class文件jar文件网络计算生成一个二进制流由其他文件生成数据库
6.2 类加载的过程—验证
为了确保class文件的字节流中包含的信息复合当前虚拟机的要求并不回危害虚拟机自身的安全文件格式验证元数据验证字节码验证符号引用验证
6.3 类加载的过程—准备
为类变量分配内存并设置变量的初始值(给变量初始化为默认的值)这些变量使用的内存都将在方法区中进行分配
6.4 类加载的过程—解析
虚拟机将常量池中的符号引用替换为直接引用的过程类或者接口的解析字段解析类方法解析接口解析
6.5 类加载的过程—初始化
类加载的最后一步执行<clinit>方法的过程4.如果多个线程同时初始化一个类,只有一个线程执行这个类的init方法问题:多线程执行static 代码块时,容易阻塞
6.6 类加载器
1.通过一个类的全限定名来获取描述2.只有被同一个类加载器加载才相等
6.6.1 载器分类
启动类加载器由C+实现,时虚拟机的一部分。lib扩展类加载器lib/ext应用程序加载器加载用户类路径自定义类加载器优势:高度的灵活通过自定义类加载器可以实现热部署代码加密
6.6.2 自定义类加载器
1.定一个类,继承classloader2.重写loadClass方法3.实例ClassLoader mycl = new ClassLoader(){public Class<?> loadClass(String name) throws {String filename = name.substring(name.lastIndexOf(".") + 1) + ".class";InputStream ins = getClass().getResouceAsStream(fileName);if ( ins == null ) {return super.loadClass(name);}byte [] buff = new byte[ins.available()];ins.read(buff);return defineClass(name, buff, 0, buff.length);}}Class c = mycl.loadClass("com.root.Test").newInstance();


