《深入理解Java虚拟机 —— 周志明》读书笔记

2016/09/10 blog 共 3437 字,约 10 分钟
Bob.Zhu

第一部分 走进Java

第1章 走近Java

  • 概述
  • java技术体系
  • java发展史
  • java虚拟机发展史
  • 展望java技术的未来
    • 模块化
    • 混合语言
    • 多核并行
    • 进一步丰富语法
    • 64位虚拟机
  • 实战:自己编译JDK

1.1 概述

Java不仅是一门编程语言,还是一个由一系列计算机软件和规范形成的技术体系。

1.2 java技术体系

从广义上讲,Clojure,JRuby,Groovy等运行于JVM上的语言及其相关的程序都属于Java技术体系中的一员。 从传统意义上来讲,Sun官方所定义的Java技术体系包括:

  • Java程序设计语言
  • 各种硬件平台上的Java虚拟机
  • Class文件格式
  • Java API类库
  • 来自商业机构和开源社区的第三方Java类库

JDK包括:Java程序设计语言,Java虚拟机,Java API类库;
JRE包括:Java虚拟机,Java API类库中的Java SE API类库子集。

1.3 java发展史

  • 1995/05/23 Oak to Java
  • 1996/01/23 Java 1.0
  • 1997/02/18 Java 1.1
  • 1998/12/04 J2SE 1.2
  • 2000/05/08 J2SE 1.3
  • 2002/02/13 J2SE 1.4
  • 2004/09/29 Java SE 5
  • 2006/12/11 Java SE 6
  • 2011/07/28 Java SE 7
  • 2014/03/19 Java SE 8

1.4 java虚拟机发展史

  • Sun classic / Exact VM
    Sun classic 是世界上第一款商用虚拟机,这款虚拟机只能使用纯解释器方式来执行代 Java 代码。如果要使用 JIT 编译器,就要进行外挂。 但加入外挂了 JIT 编译器,JIT 编译器就完全接管了虚拟机的执行系统,解释器便不再工作。 基于程序响应时间的压力,这边编译器不敢应用耗时稍高的优化技术,Java 语言很慢的形象也是从这时树立起来的。 Exact VM,是Sun的虚拟机团队为了解决 Sun classic 虚拟机的问题而开发的新的虚拟机, 编译器和解释器混合工作,使用准确式内存管理,更利于GC。

  • Sun HotSpot VM
    HotSpot VM 是目前使用最广的虚拟机,看起来“血统纯正”的 HotSpot 并非Sun公司开发,而是一家名为“longview Technologies”的小公司设计, 甚至这个虚拟机当初并非为了 Java 语言而开发,它来源于 StrongTalk VM,而这款虚拟机中相当多的技术又是来源于一款支持Self语言实现“达到C 语言50%以上的执行效率”的目标而设计的虚拟机。Sun公司注意到这款虚拟机在JIT编译上由许多优秀的理念和实际效果,在1997年收购此公司, 获得了 HotSpot VM。

  • BEA JRockit / IBM J9 VM
    前面介绍的是 Sun 公司研发的虚拟机,除了 Sun 公司之外,其他公司和组织也研发过不少虚拟机,规模最大和最著名的就是 BEA 和 IBM 了。 BEA 公司的 JRockit VM 号称速度最快的虚拟机,专注于服务器端应用,不太关注程序启动速度,因此 JRockit 不包含解析器实现,全部代码都靠即时编译器 编译后执行。 IBM 的 J9 VM,并不是 IBM 开发的唯一的虚拟机,但是当前主力发展的 Java 虚拟机,是由 IBM Ottawa 实验室一个名为 SmallTalk 的虚拟机扩展而来, 扩展出支持Java的虚拟机就被称为 J9 了。 在2008年和2009年,Oracle 分别收购了 BEA 和 Sun 公司,这样 Oracle 就同时拥有了两款优秀的虚拟机:JRockit VM 和 HotSpot VM。

1.5 展望java技术的未来

  • 模块化
  • 混合语言
  • 多核并行
  • 进一步丰富语法
  • 64位虚拟机

1.6 实战:自己编译JDK

第二部分 自动内存管理机制

第2章 Java内存区域与内存溢出异常

2.1 概述

内存泄漏和溢出的时候能够排查到问题原因并解决。

2.2 运行时数据区域

根据《Java 虚拟机规范(Java SE 7版)》的规定,Java虚拟机管理的内存,将会包括以下几个运行时数据区域:

Java虚拟机运行时数据区

方法区和堆:所有线程共享的数据区;
虚拟机栈、本地方法栈和程序计数器:线程隔离的数据区。

2.2.1 程序计数器

程序计数器是较小的一块内存空间,而且没有规定任何OutOfMemoryError的情况,可以看作当前线程所执行的字节码的 行号指示器。字节码解释器就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。Java 虚拟机的多线程 是通过线程轮流切换并分配处理器的执行时间来实现,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核) 都只会执行一条线程中的指令。因此,为了线程切换后能够恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器, 各个计数器之间互不影响,独立存储,称为“线程私有”。

如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址; 如果正在执行的是Native方法,这个计数器值则为空(undefined)。

Q: 1.没有规定OutOfMemoryError,那么是固定大小的吗?
2.如何查看当前内存大小?

2.2.2 Java 虚拟机栈

Java 虚拟机栈也是线程私有,描述的是 Java 方法执行的内存模型:每个方法执行的同时都会创建要给帧栈(stack frame) 用于存储局部变量表、操作数栈、动态连接、方法出口等信息。每个方法从调用直至完成的过程,就是一个帧栈在虚拟机栈中 入栈到出栈的过程。

局部变量表:存放了编译器可知的8中基本数据类型、对象引用(reference类型,可能是指向一个对象起始地址的引用指针, 也可能是指向一个代表对象的句柄或者其它与此对象相关的位置)、returnAddress类型(指向了一条字节码指令的地址)。 局部变量表所需要的内存空间在编译期间完成分配,在方法运行期间不会改变局部变量表的大小。

可能抛出StackOverflowError或者OutOfMemoryError异常。

Q: 1.概念:存储局部变量表、操作数栈、动态连接、方法出口?

2.2.3 本地方法栈

本地方法栈和虚拟机栈作用类似,虚拟机栈为Java执行Java方法(也就是字节码)服务, 而本地方法栈则为虚拟机使用到的Native方法服务。有的虚拟机(比如Sun HotSpot) 直接将本地方法栈和虚拟机栈合二为一。

2.2.4 堆

堆是Java虚拟机所管理的内存中最大的一块,被所有线程共享,在虚拟机启动时创建。 此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。 堆是垃圾回收器管理的主要区域,因此很多时候也被称为“GC堆”,细分为新生代和老生代。

2.2.5 方法区

线程共享,用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。 对于HotSpot虚拟机,很多人更愿意把方法区称为永久代(Permanent generation),本质上 两者并不相等,仅仅是因为HotSpot虚拟机设计团队选择把GC分代收集扩展至方法区,或者说 使用永久代来实现方法区而已,这样能够省去专门为方法区编写内存管理代码的工作。 方法区很少有内存需要回收,但也并不是完全不需要,曾经有未回收导致内存泄漏的BUG。

2.2.6 运行时常量池

运行时常量池是方法区的一部分,

2.3 HotSpot 虚拟机对象探秘

2.4 实战:OutOfMemoryError 异常

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

第4章 虚拟机性能监控与故障处理工具

第5章 调优案例分析与实战

第三部分 虚拟机执行子系统

第6章 类文件结构

第7章 虚拟机类加载机制

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

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

第四部分 程序编译与代码优化

第10章 早期(编译期)优化

第11章 晚期(运行期)优化

第五部分 高效并发

第12章 Java内存模型与线程

第13章 线程安全与锁优化

参考资料

  • 深入理解Java虚拟机:JVM高级特性与最佳实践 —— 周志明
  • test

文档信息

Search

    Table of Contents