写点什么

JVM 读书笔记

用户头像
hasWhere
关注
发布于: 5 小时前

第 1 章 Hostspot 介绍

1.1HotSpot 历史

SUN 的 JDK 版本从 1.3.1 开始运用 HotSpot 虚拟机, 2006 年底开源。

主要使用 C++实现,JNI 接口部分用 C 实现。

HotSpot 是较新的 Java 虚拟机,用来代替 JIT(Just in Time),可以大大提高 Java 运行的性能。

Java 原先是把源代码编译为字节码在虚拟机执行,这样执行速度较慢。

HotSpot 将常用的部分代码编译为本地(原生,native)代码,这样显着提高了性能。

HotSpot JVM 参数可以分为规则参数(standard options)和非规则参数(non-standard options)。

规则参数相对稳定,在 JDK 未来的版本里不会有太大的改动。非规则参数则有因升级 JDK 而改动的可能。

1.2 HotSpot 基础知识

HotSpot 包括一个解释器和两个编译器(client 和 server,二选一的),解释与编译混合执行模式,默认启动解释执行。


编译器java 源代码被编译器编译成 class 文件(字节码),java 字节码在运行时可以被动态编译(JIT)成本地代码(前提是解释与编译混合执行模式且虚拟机不是刚启动时)。

解释器: 解释器用来解释 class 文件(字节码),java 是解释语言(书上这么说的)。


server 启动慢,占用内存多,执行效率高,适用于服务器端应用;

client 启动快,占用内存小,执行效率没有 server 快,默认情况下不进行动态编译,适用于桌面应用程序。

由-XX:+RewriteFrequentPairs 参数控制 client 模式默认关闭,server 模式默认开启


在 jre 安装目录下的 lib/i386/jvm.cfg 文件下。


java -version

Java HotSpot(TM) Client VM (build 14.3-b01, mixed mode, sharing)

mixed mode 解释与编译 混合的执行模式 默认使用这种模式


java -Xint -version

Java HotSpot(TM) Client VM (build 14.3-b01, interpreted mode, sharing)

interpreted 纯解释模式 禁用 JIT 编译


java -Xcomp -version

Java HotSpot(TM) Client VM (build 14.3-b01, compiled mode, sharing)

compiled 纯编译模式(如果方法无法编译,则回退到解释模式执行无法编译的方法)

1.3 动态编译

动态编译(compile during run-time),英文称 Dynamic compilation;Just In Time 也是这个意思。

HotSpot 对 bytecode 的编译不是在程序运行前编译的,而是在程序运行过程中编译的。HotSpot 里运行着一个监视器(Profile Monitor),用来监视程序的运行状况。java 字节码(class 文件)是以解释的方式被加载到虚拟机中(默认启动时解释执行)。

程序运行过程中,那一部分运用频率大,那些对程序的性能影响重要。对程序运行效率影响大的代码,称为热点(hotspot),HotSpot 会把这些热点动态地编译成机器码(native code),同时对机器码进行优化,从而提高运行效率。对那些较少运行的代码,HotSpot 就不会把他们编译。


HotSpot 对字节码有三层处理:

  1. 不编译(字节码加载到虚拟机中时的状态。也就是当虚拟机执行的时候再编译),

  2. 编译(把字节码编译成本地代码。虚拟机执行的时候已经编译好了,不要再编译了),

  3. 编译并优化(不但把字节码编译成本地代码,而且还进行了优化)。

至于那些程序那些不编译,那些编译,那些优化,则是由监视器(Profile Monitor)决定。

1.4 为什么不静态编译那?

为什么字节码在装载到虚拟机之前就编译成本地代码?

动态编译器也在许多方面比静态编译器优越。

静态编译器通常很难准确预知程序运行过程中究竟什么部分最需要优化。

函数调用都是很浪费系统时间的,因为有许多进栈出栈操作。因此有一种优化办法,就是把原来的函数调用,通过编译器的编译,改成非函数调用,把函数代码直接嵌到调用出,变成顺序执行。

面向对象的语言支持多态,静态编译无效确定程序调用哪个方法,因为多态是在程序运行中确定调用哪个方法。

第 2 章 Java 内存区域与虚拟对象

2.2  java 虚拟机运行时数据区:

  1. 程序计数器:当前线程所执行的字节码的行号指示器(线程私有)

  2. java 虚拟机栈(局部变量表)

  3. 本地方法栈

  4. java(所有线程共享):所有的实例对象以及数组都要在堆上分配、垃圾收集器现在基本都采用分代收集算法:新生代和老生代、Eden 空间、From Survivor 空间、To Survivor 空间等。

  5. 方法区:用于存储虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据

  6. 运行时常量池:用于存放编译器生成的各种字面量和符号引用、是方法区的一部分

  7. 直接内存:


2.3 hotspot 虚拟对象探秘

  • 指针碰撞和空闲列表(java 堆内存是不是规整的)

  • 对象内存布局:对象头(Header)、实例数据(Instance Data)、和对齐填充(Padding)


  • 对象访问方式取决于虚拟机的实现、主流访问方式:句柄和直接指针(访问速度快)

第 3 章  垃圾收集与内存分配策略

  • 对象已死吗(引用计数算法、可达性分析算法)

  • 垃圾收集算法(标记-清楚算法、复制算法、标记整理算法、分代收集算法)

  • hotspot 的算法实现(枚举根节点、安全点、安全区域)

  • 垃圾收集器(G1 收集器、CMS 收集器)

  • 垃圾收集器参数总结

  • 内存分配和回收策略(对象优先在 eden 分配、大对象直接进入老年代、长期存活的对象进入老年代、空间对象年龄分配、空间分配担保)

第 4 章  性能监控和故障处理工具

  • jdk 命令行工具(jps、jstat、jinfo、jmap、jhat、jstack、hsdis)

  • jdk 可视化工具(jconsole、visualvm)

第 5 章 调优案例与分析

  • Direct Memory 内存不足   抛出 OutOfMemoryError 异常

  • 线程堆栈 内存不足   抛出 StackOverflowError 异常

  • socket 缓冲区 没个 socket 连接都有 Receive 和 Send 俩个缓冲区、分别占有 37KB 和 25KB

  • eclipse 运行速度调优(JDK 版本问题、调整内存设置控制垃圾收集频率、选择收集器降低延迟)

代码编译的结果从本地机器码转化为字节码。


第 6 章   类文件结构

  • java 虚拟机上运行的其他语言:Clojure、Groovy、JRuby、Jython、Scala 等。语言无关性和平台无关性


  • Class 文件是一组以 8 位字节为基础单位的二进制流、采用类 C 语言结构体的伪结构来存储数据(无符号数和表)。魔数(头四个字节),版本号(紧跟魔数的四个字节)、常量池、访问标志、类索引、父类索引与接口索引集合、字段表集合、方法表集合、属性表集合。

  • 字节码指令:字节码与数据类型、加载和存储指令、运算指令、类型转换指令、对象创建和访问指令、操作数栈管理指令、控制转移指令、方法调用和返回值指令、异常处理指令、同步指令。

  • 公有设计和私有实现。虚拟机实现方式:(1)将输入的 java 虚拟机代码在加载和执行翻译成另外一种虚拟机的指令集,(2)将输入的 java 虚拟机代码在加载和执行时翻译成宿主机 CPU 的本地指令集。

第 7 章 虚拟机类加载机制

  • 类加载时机:加载(loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)、卸载(Unloading)。

            加载:    1)通过一个类的全限定名来获取定义此类的二进制字节流

                           2)将这个字节流所代表的静态存储结构结构化为方法区的运行时数据结构

                           3)在内存中生成一个代表这个类的 java.lang.Class 对象,作为方法区这个类的各种数据的访问接口

             特殊:   数组类本身不通过类加载器创建、它是由 java 虚拟机直接创建的。

             

第 8 章 虚拟机字节码执行引擎

第 9 章 类加载及执行子系统的案例和实战

  • tomcat:正统的类加载器结构


  • osgi:灵活的类加载器结构(学习 javaEE 规范、去看 JBoss 源码;学习类加载器、就去看 OSGi 源码)、Equinox、Felix。

  • 字节码生成技术与动态代理实现

  • Retrotranslator:跨域 JDK 版本(java 逆向移植工具)

第 10 章  编译器优化

  • 前端编译器:sun 的 javac、Eclipse JDT 中的增量式编译器(ECJ);JIT 编译器(即时编译器): Hotspot VM 的 C1 C2 编译器;AOT 编译器

  • Javac 编译过程:

                 1)解析与填充符号表过程

                 2)插入式注解处理器的注解处理过程

                 3)分析与字节码生成过程

  • 插入式注解处理器

第 11 章  运行期优化(Hotspot)

  • 为何 Hotspot 虚拟机要使用解释器和编译器并存的架构?    (即时编译和逆优化)

  • 为何 Hotspot 虚拟机要实现俩个不同的即时编译器?             (Clinent 编译器和 Server 编译器)

  • 程序何时使用解释器执行?何时使用编译器执行?                (基于采样的热点探测、基于计数器的热点探测)    

  • 哪些程序代码会被编译为本地代码?如何编译为本地代码?()

  • 如何从外部观察即时编译器的编译过程和编译结果?

  • 编译优化技术(公共子表达式消除、数组边界检查消除、方法内联、逃逸分析)

第 12 章  java 内存模型与线程


第 13 章  线程安全与锁优化

  • java 语言中的线程安全

  • 线程安全的实现方法

  • 锁优化(自旋锁与自适应锁、锁消除、锁粗化、轻量级锁、偏向锁)


关键截图

类的生命周期


JavaEE 版本


基本类型的零值

Class 文件版本号


常量池的项目类型


计算机并行执行


回边计数器阈值


发布于: 5 小时前阅读数: 6
用户头像

hasWhere

关注

间歇性努力的学习渣 2018.04.20 加入

通过博客来提高下对自己的要求

评论

发布
暂无评论
JVM读书笔记