11.JDK8内存模型、本地方法栈、虚拟机栈、栈帧结构(局部变量表、操作数栈、方法出口、虚拟机栈与本地方法栈的关系、寄存器、方法区、堆(Heap)、jvm中的常量池、Metaspace(元空间))

11.JDK8内存模型
11.1.本地方法栈(Native Method Stacks)
11.2.虚拟机栈(Java Virtual Machine Stacks)
11.3.栈帧结构
11.3.1.局部变量表
11.3.2.操作数栈
11.3.3.方法出口
11.4.虚拟机栈与本地方法栈的关系
11.5.寄存器(The pc Register)
11.6.方法区(Method Area)
11.7.堆(Heap)
11.8.jvm中的常量池
11.9.Metaspace(元空间)
11.10.堆内存划分

11.JDK8内存模型

本文转自:https://www.jianshu.com/p/44df41ebdbf6

通常谈到JVM的内存模型,一般人会想到堆和栈等,那么堆和栈如何理解呢?
是运行时的单位
是存储的单位
通俗来说解决的是程序如何和运行,数据如何处理的问题;而堆解决的是数据如何存储,存储在哪儿的问题。
在这里插入图片描述
如上图所示,java虚拟机内存模型主要分为以上五个部分,这里以jdk8为学习对象。

11.1.本地方法栈(Native Method Stacks)

本地方法栈(Native Method Stacks)与虚拟机栈所发挥的作用是非常相似的。其区别在于虚拟机栈为虚拟机执行Java方法所服务,而本地方法栈则是为虚拟机使用到的native方法所服务。

本地方法栈也是一个私有(线程私有)的内存区域,也是后进先出。

虚拟机可以自由实现它,有的虚拟机(如HotSpot虚拟机)直接就把本地方法栈和虚拟机栈合二为一。

本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常

11.2.虚拟机栈(Java Virtual Machine Stacks)

每个Java线程都有一个私有Java虚拟机栈,与该线程同时创建。

在虚拟机栈内,每个方法会生成一个栈帧。每个栈帧代表一次次的方法调用,一个方法的执行到执行完成的过程,代表栈帧从入栈到出栈的过程。

虚拟机栈会抛出StackOverflowError和OutOfMemoryError。
在这里插入图片描述

11.3.栈帧结构

下图表示了栈帧的组成结构:

11.3.1.局部变量表

局部变量表是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量

11.3.2.操作数栈

操作数栈是一个后入先出的栈。

一个方法刚开始执行时操作数栈是空的,方法执行过程中会有各种字节码指令往操作数栈中写入和提取内容,也就是出栈 / 入栈操作。

例如执行iadd指令时,就会将最接近栈顶的两个int元素取出并相加,然后将相加的结果再入栈。

操作数栈中元素的数据类型必须与字节码指令的序列严格匹配,在编译程序代码的时候,编译器要严格保证这一点。比如刚才的iadd指令,它取出的元素必须是int的,不能出现诸如long和float类型的变量。

虽然概念模型中不同栈帧之间是完全相互独立的,但大多虚拟机实现中会有一些优化处理:令两个栈帧出现一部分重叠,让下面的栈帧的部分操作数栈与上面栈帧的部分局部变量表重叠在一起重叠在一起,这样在进行方法调用时就可以公用一部分数据,无须进行额外的参数复制传递,如图所示:
在这里插入图片描述
每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接。

静态解析:我们知道Class文件的常量池中存有大量的符号引用,字节码中的方法调用指令就以常量池中指向方法的符号引用作为参数,这些符号引用一部分会在类加载阶段或者第一次使用的时候就转化为直接引用,这种转化称为静态解析。

动态链接:除去静态解析的另外一部分将在每一次运行期间转化为直接引用,这部分称为动态链接。

所以要执行某个方法时,某个指令(例如invokevirtual)将常量池中的引用作为参数,而根据这个引用就可以找到真正的栈帧。

关于方法的解析与调用,参考:https://blog.csdn.net/reachwang/article/details/103058653

11.3.3.方法出口

方法出口也可以通俗的理解为方法返回方式:在jvm中,方法返回方式有两种:正常和异常

正常出口:当程序执行遇到方法返回的字节码指令,就完成此次方法执行,并根据调用方指定的返回值返回(可以无返回值)。

异常出口:方法在执行中遇到了异常,并且在方法体内没有得到处理,会导致方法退出,这时候不会有任何返回值给调用方。

程序正常退出时,相当于把当前栈帧出栈,调用pc计数器的值作为返回地址,即调用该方法的指令的下一条指令的地址。

程序异常退出时:当程序发生异常时,返回地址需要通过异常表来确定,在栈帧中没有保存异常表。

11.4.虚拟机栈与本地方法栈的关系

为了更好地理解虚拟机栈和本地方法栈的结构模型以及关系,我们以网上的例子简单描述下,如下图:
在这里插入图片描述

11.5.寄存器(The pc Register)

Java虚拟机可以支持多个线程同时执行,每个Java线程都有其自己的 pc(程序计数器)寄存器。在任何时候,每个Java虚拟机线程都在执行单个方法的代码,即该线程的当前方法。(如果不是native,则该pc寄存器包含当前正在执行的Java虚拟机指令的地址。如果线程当前正在执行的方法是native,则Java虚拟机的pc寄存器值未定义。

pc寄存器中的值就是当前指令所在的内存地址,即returnAddress类型的数据,当线程执行native方法时,pc中的值为undefined。

11.6.方法区(Method Area)

Java虚拟机具有一个在所有Java虚拟机线程之间共享的方法区域。该方法区域类似于常规语言的编译代码的存储区域,或者类似于操作系统过程中的“文本”段。它存储每个类的结构,例如运行时常量池,字段和方法数据,以及方法和构造函数的代码,包括用于类和实例初始化以及接口初始化的特殊方法。

方法区是在虚拟机启动时创建的。尽管方法区在逻辑上是堆的一部分,但是可以选择不进行垃圾回收或压缩。该规范没有规定方法区域的位置或用于管理已编译代码的策略。方法区域可以是固定大小的,或者可以根据计算的需要进行扩展,如果不需要更大的方法区域,则可以缩小。方法区域的内存不必是连续的。

可能抛出OutOfMemoryError异常。

11.7.五、堆(Heap)

Java虚拟机具有一个在所有Java虚拟机线程之间共享的堆。堆是运行时数据区,从中分配所有类实例和数组的内存。

堆是在虚拟机启动时创建的。对象的堆存储由GC(垃圾收集器)回收;对象永远不会显式释放。Java虚拟机可以根据实现者的系统要求选择GC。堆的大小可以是固定的,也可以根据计算要求进行扩展,如果不需要更大的堆,则可以将其收缩。堆的内存不必是连续的。

可能抛出OutOfMemoryError异常。

在jdk1.8之前的版本对内存空间是不同的,主要区别在于:1.8中删除了永久代,新增了元空间。

元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制,但可以通过参数来指定元空间的大小。
在这里插入图片描述

11.8.jvm中的常量池

参考文章:https://blog.csdn.net/weixin_40999907/article/details/87907083
方法区:运行时常量池
Class文件:常量池
堆:String常量池

11.9.Metaspace(元空间)

本部分转自:https://blog.csdn.net/universe_ant/article/details/58585854

其实,移除永久代的工作从JDK 1.7就开始了。JDK 1.7中,存储在永久代的部分数据就已经转移到Java Heap或者Native Heap。但永久代仍存在于JDK 1.7中,并没有完全移除,譬如符号引用(Symbols)转移到了native heap;字面量(interned strings)转移到了Java heap;类的静态变量(class statics)转移到了Java heap。我们可以通过一段程序来比较JDK 1.6、JDK 1.7与JDK 1.8的区别,以字符串常量为例:

package com.paddx.test.memory;

import java.util.ArrayList;
import java.util.List;

public class StringOomMock {

	static String base = "string";
	
	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();
		for(int i = 0; i < Integer.MAX_VALUE; i++) {
			String str = base + base;
			base = str;
			list.add(str.intern());
		}
	}
	
}

JDK1.6的运行结果:
在这里插入图片描述
JDK1.7的运行结果:
在这里插入图片描述
JDK 1.8的运行结果:
在这里插入图片描述
从上述结果可以看出,JDK 1.6下,会出现“PermGen space”的内存溢出,而在JDK 1.7和JDK 1.8中,会出现堆内存溢出,并且JDK 1.8中参数PermSize和MaxPermSize已经失效。因此,可以大致验证JDK 1.7和JDK 1.8中将字符串常量由永久代转移到堆中,并且JDK 1.8中已经不存在永久代的结论。现在我们来看一看元空间到底是一个什么东西?

JDK1.8对JVM架构的改造将类元数据放到本地内存中,另外,将常量池和静态变量放到Java堆里。HotSpot VM将会为类的元数据明确分配和释放本地内存。在这种架构下,类元信息就突破了原来-XX:MaxPermSize的限制,现在可以使用更多的本地内存。这样就从一定程度上解决了原来在运行时生成大量类造成经常Full GC问题,如运行时使用反射、代理等。所以升级以后Java堆空间可能会增加。

元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间的最大区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制,但可以通过以下参数指定元空间的大小:

-XX:MetaspaceSize,初始空间大小,达到该值就会触发垃圾收集进行类型卸载,同时GC会对改值进行调整:

-XX:MetaspaceSize,初始空间大小,达到该值就会触发垃圾收集进行类型卸载,同时GC会对改值进行调整:如果释放了大量的空间,就适当降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize时,适当提高该值。

-XX:MaxMetaspaceSize,最大空间,默认是没有限制的。

除了上面的两个指定大小的选项外,还有两个与GC相关的属性:

-XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间导致的垃圾收集器。

-XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空间容量的百分比,减少为释放空间所导致的垃圾收集。

现在我们在JDK 1.8重新运行一下上面第二部分(PermGen(永久代))的代码,不过这次不再指定PermSize和MaxPermSize。而是制定MetaspaceSize和MaxMetaspaceSize的大小。输出结果如下:
在这里插入图片描述

11.10.堆内存划分

以下转自:https://www.cnblogs.com/cjsblog/p/9850300.html

在JDK1.7以及其前期的JDK版本中,堆内存通常被分为三块区域:Young Generation、Old Generation、Permanent Generation for VM Matedata。
在这里插入图片描述
在JDK1.8中把存放元数据中的永久内存从堆内存中移到了本地内存中,JDK1.8中JVM堆内存结构就变成了如下:
在这里插入图片描述
推统计信息
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Java 虚拟机面试题全面解析,《深入理解Java虚拟机》干货版,自己总结,希望能够帮助大家,免费下载~什么是类加载机制? 虚拟机和物理机的别是什么? 运行时栈帧结构 Java方法调用 什么是方法调用? Java的方法调用,有什么特殊之处? Java虛拟机调用字节码指令有哪些? 虚拟机是如何执行方法里面的字节码指令的? 解释执行 基于的指令集和基于寄存器的指令集 什么是基于的指令集? 什么是基于寄存器的指令集? 基于的指令集的优缺点? Javac编译过程分为哪些步骤? 什么是即时编译器? 解释器和编译器 为什么要采用分层编译? 分层编译器有哪些层次? 编译对象与触发条件 热点代码有哪些? 如何判断一段代码是不是热点代码? Hotspot虚拟机使用第二种,有两个计数器: 方法调用计数器统计方法 有哪些经典的优化技术(即时编译器)? 公共子达式消除 数组边界检查消除 方法内联 逃逸分析 如果对象不会逃逸到方法或线程外,可以做什么优化? Java与C/C++的编译器对比 物理机如何处理并发问题? Java内存模型 什么是Java内存模型? Java内存模型的目标? 主内存与工作内存 内存间的交互操作 原子性、可见性、有序性 volatile 什么是 volatile? 为什么基于 volatile变量的运算在并发下不一定是安全的? 为什么使用 volatile? 并发与线程 并发与线程的关系? 什么是线程? 实现线程有哪些方式? Java线程的实现 Java线程调度 什么是线程调度? 线程调度有哪些方法? 线程安全的定义? Java语言操作的共享数据,包括哪些? 不可变 如何实现线程安全? 阻塞同步(互斥同步) 非阻塞同步 锁优化是在DK的那个版本? 为什么要提出自旋锁? 自旋锁的原理? 自旋的缺点? 什么是自适应自旋? 锁消除 锁粗化 轻量级锁 偏向锁 JDK是什么? JDK是用于支持Java程序开发的最小环境。 1.Java程序设计语言 2.Java虚拟机 3. Java ap类库 JRE是什么? JRE是支持Java程序运行的标准环境。 1. Java SE aPi子集 2.Java虚拟机 Java历史版本的特性? Java∨ ersion se5.0 引入泛型; 增强循环,可以使用迭代方式; 自动装箱与自动拆箱; 类型安全的枚举 ·可变参数; 静态引入 数据(注解); 引入 Instrumentation Java∨ ersion se6 支持脚本语言 引入JDBC40API; 引入 Java Compiler API; 可插拔注解; 增加对 Native PKi( Public Key Infrastructure)、 Java gss( Generic Security Service) Kerberos和 LDAP(Lightweight Directory Access Protocol的支持; 继承 Web services 做了很多优化。 Java∨ ersion se7 switch语句块允许以字符串作为分支条件; 在创建泛型对象时应用类型推断 ·在一个语句块捕获多种异常; ·支持动态语言; 支持try-with- resources 引入 Java nio.2开发包; ·数值类型可以用2进制字符串示,并且可以在字符串添加下划线; 钻石型语法; nu值的自动处理。 Java 8 函数式接口 Lambda达式 接口的增强 运行时数据域包括哪些? 1.程序计数器 2.Java虚拟机 3.本地方法 4.Java 5.方法 6.运行时常量池 7.直接内存 程序计数器(线程私有) 程序计数器( Program Counter Register)是一块较小的内存空间,可以看作是当前线程所 执行字节码的行号指示器。分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这 个计数器完成。 由于Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式实现的。为了线 程切换后能恢复到正确的执行位置,每条线程都需要一个独立的程序计数器,各线程之间的计 数器互不影响,独立存储。 1.如果线程正在执行的是一个Java方法,计数器记录的是正在执行的虚拟机字节码指令的地 址 2.如果正在执行的是 Native方法,这个计数器的值为空 程序计数器是唯一—个没有规定任何 OutofMemoryError的域 Java虚拟机(线程私有) Java虚拟机( Java virtual machine stacks)是线程私有的,生命周期与线程相同。 虛拟机描述的是Ja阳a方法执行的内存模型:每个方法被执行的时候都会创建一个 帧( Stack frame),存储 1.局部变量 2.操作 3.动态链接 4.方法出口 每—一个方法被调用到执行完成的过程,就对应着一个栈帧在虛拟机从入到出的过程。 这个域有两种异常情况: 1. StackOverflow error:线程请求的深度大于虚拟机所允许的深度 2. OutOfMemoryError:虚拟机扩展到无法申请足够的内存时 本地方法(线程私有 虚拟机虚拟机执行Java方法(字节码)服务。 本地方法( Native method stacks)为虚拟机使用到的 Native方法服务。 Java(线程共享) Java( Java Heap)是Java虚拟机内存最大的一块。Java虚拟机启动时创建,被所 有线程共享。 作用:存放对象实例。垃圾收集器主要管理的就是Java。Java在物理上可以不连续,只 要逻辑上连续即可。 方法(线程共亨) 方法( Method area)被所有线程共享,用于存储已被虛拟机加载的类信息、常量、静态 变量、即时编译器编译后的代码等数据。 和Java一样,不需要连续的内存,可以选择固定的大小,更可以选择不实现垃圾收集。 运行时常量池 运行时常量池( Runtime Constant pool)是方法的一部分。保存 Class文件的符号引 用、翻译岀来的直接引用。运行时常量池可以在运行期间将新的常量放入池 Java对象访问是如何进行的? Object ob j new Object( 对于上述最简单的访问,也会涉及到Java、Java方法这三个最重要内存域。 Object obj 如果出现在方法,则上述代码会反映到Java的本地变量,作为 reference类型数 据出现。 new Object( 反映到Java,形成一块存储了 bject类型所有对象实例数据值的内存。Java还包 含对象类型数据的地址信息,这些类型数据存储在方法, 如何判断对象是否“死去”? 1.引用计数法 2.根搜索算法 什么是引用计数法? 给对象添加一个引用计数器,每当有一个地方引用它,计数器就+1,;当引用失效时,计数器 就-1;任何时刻计数器都为0的对象就是不能再被使用的 引用计数法的缺点? 很难解决对象之间的循环引用问题。 什么是根搜索算法? 通过一系列的名为" GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索所走过 的路径称为引用链( Reference chain),当一个对象到 GC Roots没有任何引用链相连(用 图论的话来说就是从 GC Roots到这个对象不可达)时,则证明此对象是不可用的。 object 5 object 6 object 7 仍然存活的对象 □判定可回收的对象 Java的4种引用方式? 在」DK1.2之后,Java对引用的概念进行了扩充,将引用分为 1.强引用 Strong reference 2.软引用 Soft reference 3.弱引用 Weak Reference 4.虚引用 Phantom reference 强引用
视频目录 第1节说在前面的话 [免费观看] 00:05:07分钟 | 第2节整个部分要讲的内容说明 [免费观看] 00:06:58分钟 | 第3节环境搭建以及jdk,jre,jvm关系 [免费观看] 00:20:48分钟 | 第4节jvm初体验-内存溢出问题的分析与解决 [免费观看] 00:17:59分钟 | 第5节jvm再体验-jvm可视化监控工具 [免费观看] 00:21:17分钟 | 第6节杂谈 [免费观看] 00:12:37分钟 | 第7节Java的发展历史00:27:24分钟 | 第8节Java的发展历史续00:02:27分钟 | 第9节Java技术体系00:08:46分钟 | 第10节jdk8的新特性00:07:31分钟 | 第11节lanmbda达式简介00:07:02分钟 | 第12节Java虚拟机-classic vm00:06:06分钟 | 第13节Java虚拟机-ExactVM00:03:35分钟 | 第14节Java虚拟机-HotSpotVM00:04:23分钟 | 第15节Java虚拟机-kvm00:03:04分钟 | 第16节Java虚拟机-JRockit00:04:12分钟 | 第17节Java虚拟机-j900:04:23分钟 | 第18节Java虚拟机-dalvik00:02:20分钟 | 第19节Java虚拟机-MicrosoftJVM00:03:57分钟 | 第20节Java虚拟机-高性能Java虚拟机00:02:58分钟 | 第21节Java虚拟机-TaobaoVM00:03:06分钟 | 第22节Java内存域-简介00:07:56分钟 | 第23节Java内存域-Java虚拟机00:12:04分钟 | 第24节Java内存域-程序计数器00:12:54分钟 | 第25节Java内存域-本地方法00:02:39分钟 | 第26节Java内存域-内存00:05:08分钟 | 第27节Java内存域-方法00:06:32分钟 | 第28节Java内存域-直接内存和运行时常量池00:15:53分钟 | 第29节对象在内存的布局-对象的创建00:21:19分钟 | 第30节探究对象的结构00:13:47分钟 | 第31节深入理解对象的访问定位00:08:01分钟 | 第32节垃圾回收-概述00:06:20分钟 | 第33节垃圾回收-判断对象是否存活算法-引用计数法详解00:14:08分钟 | 第34节垃圾回收-判断对象是否存活算法-可达性分析法详解00:07:09分钟 | 第35节垃圾回收算法-标记清除算法00:04:36分钟 | 第36节垃圾回收算法-复制算法00:14:35分钟 | 第37节垃圾回收算法-标记整理算法和分代收集算法00:05:24分钟 | 第38节垃圾收集器-serial收集器详解00:09:45分钟 | 第39节垃圾收集器-parnew收集器详解00:04:53分钟 | 第40节垃圾收集器-parallel收集器详解00:11:02分钟 | 第41节垃圾收集器-cms收集器详解00:14:58分钟 | 第42节最牛的垃圾收集器-g1收集器详解00:18:04分钟 | 第43节内存分配-概述00:04:23分钟 | 第44节内存分配-Eden域00:22:51分钟 | 第45节内存分配-大对象直接进老年代00:06:42分钟 | 第46节内存分配-长期存活的对象进入老年代00:03:40分钟 | 第47节内存分配-空间分配担保00:04:54分钟 | 第48节内存分配-逃逸分析与上分配00:10:32分钟 | 第49节虚拟机工具介绍00:10:27分钟 | 第50节虚拟机工具-jps详解00:11:20分钟 | 第51节虚拟机工具-jstat详解00:09:20分钟 | 第52节虚拟机工具-jinfo详解00:05:03分钟 | 第53节虚拟机工具-jmap详解00:08:48分钟 | 第54节虚拟机工具-jhat详解00:08:10分钟 | 第55节虚拟机工具-jstack详解00:10:19分钟 | 第56节可视化虚拟机工具-Jconsole内存监控00:07:09分钟 | 第57节可视化虚拟机工具-Jconsole线程监控00:12:18分钟 | 第58节死锁原理以及可视化虚拟机工具-Jconsole线程死锁监控00:10:38分钟 | 第59节VisualVM使用详解00:08:03分钟 | 第60节性能调优概述00:11:22分钟 | 第61节性能调优-案例100:23:28分钟 | 第62节性能调优-案例200:10:05分钟 | 第63节性能调优-案例300:12:41分钟 | 第64节前半部分内容整体回顾00:15:41分钟 | 第65节Class文件简介和发展历史 [免费观看] 00:11:26分钟 | 第66节Class文件结构概述 [免费观看] 00:16:50分钟 | 第67节Class文件设计理念以及意义 [免费观看] 00:13:41分钟 | 第68节文件结构-魔数 [免费观看] 00:09:49分钟 | 第69节文件结构-常量池 [免费观看] 00:23:44分钟 | 第70节文件结构-访问标志 [免费观看] 00:11:36分钟 | 第71节文件结构-类索引00:11:26分钟 | 第72节文件结构-字段集合00:13:21分钟 | 第73节文件结构-方法集合00:10:06分钟 | 第74节文件结构-属性集合00:18:23分钟 | 第75节字节码指令简介00:09:18分钟 | 第76节字节码与数据类型00:09:34分钟 | 第77节加载指令00:09:33分钟 | 第78节运算指令00:10:24分钟 | 第79节类型转换指令00:13:42分钟 | 第80节对象创建与访问指令00:09:38分钟 | 第81节操作树指令00:03:27分钟 | 第82节控制转移指令00:11:58分钟 | 第83节方法调用和返回指令00:06:37分钟 | 第84节异常处理指令00:09:44分钟 | 第85节同步指令00:07:34分钟 | 第86节类加载机制概述00:07:26分钟 | 第87节类加载时机00:13:15分钟 | 第88节类加载的过程-加载00:15:15分钟 | 第89节类加载的过程-验证00:10:24分钟 | 第90节类加载的过程-准备00:05:40分钟 | 第91节类加载的过程-解析00:14:04分钟 | 第92节类加载的过程-初始化00:19:41分钟 | 第93节类加载器00:22:41分钟 | 第94节双亲委派模型00:17:03分钟 | 第95节运行时栈帧结构00:08:46分钟 | 第96节局部变量00:20:48分钟 | 第97节操作数00:08:36分钟 | 第98节动态连接00:02:56分钟 | 第99节方法返回地址和附加信息00:03:24分钟 | 第100节方法调用-解析调用00:09:49分钟 | 第101节方法调用-静态分派调用00:16:21分钟 | 第102节方法调用-动态分派调用00:09:02分钟 | 第103节动态类型语言支持00:09:27分钟 | 第104节字节码执行引擎小结00:03:38分钟 | 第105节总结与回顾00:10:55分钟
这本书的内容是帮你全面了解java虚拟机,本书第1版两年内印刷近10次,98%以上的评论全部为5星级的好评,是整个Java图书领域公认的经典著作和超级畅销书,繁体版在台湾也十分受欢迎。第2版在第1版的基础上做了很大的改进:根据最新的JDK1.7对全书内容进行了全面的升级和补充;增加了大量处理各种常见JVM问题的技巧和最佳实践;增加了若干与生产环境相结合的实战案例;对第1版的错误和不足之处的修正;等等。 第2版不仅技术更新、内容更丰富,而且实战性更强。全书共分为五大部分,围绕内存管理、执行子系统、程序编译与优化、高效并发等核心主题对JVM进行了全面而深入的分析,深刻揭示了JVM的工作原理。第一部分从宏观的角度介绍了整个Java技术体系、Java和JVM的发展历程、模块化,以及JDK的编译,这对理解本书后面内容有重要帮助。第二部分讲解了JVM的自动内存管理,包括虚拟机内存域的划分原理以及各种内存溢出异常产生的原因;常见的垃圾收集算法以及垃圾收集器的特点和工作原理;常见虚拟机监控与故障处理工具的原理和使用方法。第三部分分析了虚拟机的执行子系统,包括类文件结构虚拟机类加载机制、虚拟机字节码执行引擎。第四部分讲解了程序的编译与代码的优化,阐述了泛型、自动装箱拆箱、条件编译等语法糖的原理;讲解了虚拟机的热点探测方法、HotSpot的即时编译器、编译触发条件,以及如何从虚拟机外部观察和分析JIT编译的数据和结果;第五部分探讨了Java实现高效并发的原理,包括JVM内存模型结构和操作;原子性、可见性和有序性在Java内存模型的体现;先行发生原则的规则和使用;线程在Java语言的实现原理;虚拟机实现高效并发所做的一系列锁优化措施。 前言 第一部分 走近Java 第1章 走近Java 1.1 概述 1.2 Java技术体系 1.3 Java发展史 1.4 Java虚拟机发展史 1.4.1 Sun Classic Exact VM 1.4.2 Sun HotSpot VM 1.4.3 Sun Mobile-Embedded VM Meta-Circular VM 1.4.4 BEA JRockit IBM J9 VM 1.4.5 Azul VM BEA Liquid VM 1.4.6 Apache Harmony Google Android Dalvik VM 1.4.7 Microsoft JVM及其他 1.5 展望Java技术的未来 1.5.1 模块化 1.5.2 混合语言 1.5.3 多核并行 1.5.4 进一步丰富语法 1.5.5 64位虚拟机 1.6 实战:自己编译JDK 1.6.1 获取JDK源码 1.6.2 系统需求 1.6.3 构建编译环境 1.6.4 进行编译 1.6.5 在IDE工具进行源码调试 1.7 本章小结 第二部分 自动内存管理机制 第2章 Java内存域与内存溢出异常 2.1 概述 2.2 运行时数据域 2.2.1 程序计数器 2.2.2 Java虚拟机 2.2.3 本地方法 2.2.4 Java 2.2.5 方法 2.2.6 运行时常量池 2.2.7 直接内存 2.3 HotSpot虚拟机对象探秘 2.3.1 对象的创建 2.3.2 对象的内存布局 2.3.3 对象的访问定位 2.4 实战:OutOfMemoryError异常 2.4.1 Java溢出 2.4.2 虚拟机和本地方法溢出 2.4.3 方法和运行时常量池溢出 2.4.4 本机直接内存溢出 2.5 本章小结 第3章 垃圾收集器与内存分配策略 3.1 概述 3.2 对象已死吗 3.2.1 引用计数算法 3.2.2 可达性分析算法 3.2.3 再谈引用 3.2.4 生存还是死亡 3.2.5 回收方法 3.3 垃圾收集算法 3.3.1 标记-清除算法 3.3.2 复制算法 3.3.3 标记-整理算法 3.3.4 分代收集算法 3.4 HotSpot的算法实现 3.4.1 枚举根节点 3.4.2 安全点 3.4.3 安全域 3.5 垃圾收集器 3.5.1 Serial收集器 3.5.2 ParNew收集器 3.5.3 Parallel Scavenge收集器 3.5.4 Serial Old收集器 3.5.5 Parallel Old收集器 3.5.6 CMS收集器 3.5.7 G1收集器 3.5.8 理解GC日志 3.5.9 垃圾收集器参数总结 3.6 内存分配与回收策略 3.6.1 对象优先在Eden分配 3.6.2 大对象直接进入老年代 3.6.3 长期存活的对象将进入老年代 3.6.4 动态对象年龄判定 3.6.5 空间分配担保 3.7 本章小结 第4章 虚拟机性能监控与故障处理工具 4.1 概述 4.2 JDK的命令行工具 4.2.1 jps:虚拟机进程状况工具 4.2.2 jstat:虚拟机统计信息监视工具 4.2.3 jinfo:Java配置信息工具 4.2.4 jmap:Java内存映像工具 4.2.5 jhat:虚拟机转储快照分析工具 4.2.6 jstack:Java跟踪工具 4.2.7 HSDIS:JIT生成代码反汇编 4.3 JDK的可视化工具 4.3.1 JConsole:Java监视与管理控制台 4.3.2 VisualVM:多合一故障处理工具 4.4 本章小结 第5章 调优案例分析与实战 5.1 概述 5.2 案例分析 5.2.1 高性能硬件上的程序部署策略 5.2.2 集群间同步导致的内存溢出 5.2.3 外内存导致的溢出错误 5.2.4 外部命令导致系统缓慢 5.2.5 服务器JVM进程崩溃 5.2.6 不恰当数据结构导致内存占用过大 5.2.7 由Windows虚拟内存导致的长时间停顿 5.3 实战:Eclipse运行速度调优 5.3.1 调优前的程序运行状态 5.3.2 升级JDK 1.6的性能变化及兼容问题 5.3.3 编译时间和类加载时间的优化 5.3.4 调整内存设置控制垃圾收集频率 5.3.5 选择收集器降低延迟 5.4 本章小结 第三部分 虚拟机执行子系统 第6章 类文件结构 6.1 概述 6.2 无关性的基石 6.3 Class类文件的结构 6.3.1 魔数与Class文件的版本 6.3.2 常量池 6.3.3 访问标志 6.3.4 类索引、父类索引与接口索引集合 6.3.5 字段集合 6.3.6 方法集合 6.3.7 属性集合 6.4 字节码指令简介 6.4.1 字节码与数据类型 6.4.2 加载和存储指令 6.4.3 运算指令 6.4.4 类型转换指令 6.4.5 对象创建与访问指令 6.4.6 操作数管理指令 6.4.7 控制转移指令 6.4.8 方法调用和返回指令 6.4.9 异常处理指令 6.4.10 同步指令 6.5 公有设计和私有实现 6.6 Class文件结构的发展 6.7 本章小结 第7章 虚拟机类加载机制 7.1 概述 7.2 类加载的时机 7.3 类加载的过程 7.3.1 加载 7.3.2 验证 7.3.3 准备 7.3.4 解析 7.3.5 初始化 7.4 类加载器 7.4.1 类与类加载器 7.4.2 双亲委派模型 7.4.3 破坏双亲委派模型 7.5 本章小结 第8章 虚拟机字节码执行引擎 8.1 概述 8.2 运行时栈帧结构 8.2.1 局部变量 8.2.2 操作数 8.2.3 动态连接 8.2.4 方法返回地址 8.2.5 附加信息 8.3 方法调用 8.3.1 解析 8.3.2 分派 8.3.3 动态类型语言支持 8.4 基于的字节码解释执行引擎 8.4.1 解释执行 8.4.2 基于的指令集与基于寄存器的指令集 8.4.3 基于的解释器执行过程 8.5 本章小结 第9章 类加载及执行子系统的案例与实战 9.1 概述 9.2 案例分析 9.2.1 Tomcat:正统的类加载器架构 9.2.2 OSGi:灵活的类加载器架构 9.2.3 字节码生成技术与动态代理的实现 9.2.4 Retrotranslator:跨越JDK版本 9.3 实战:自己动手实现远程执行功能 9.3.1 目标 9.3.2 思路 9.3.3 实现 9.3.4 验证 9.4 本章小结 第四部分 程序编译与代码优化 第10章 早期(编译期)优化 10.1 概述 10.2 Javac编译器 10.2.1 Javac的源码与调试 10.2.2 解析与填充符号 10.2.3 注解处理器 10.2.4 语义分析与字节码生成 10.3 Java语法糖的味道 10.3.1 泛型与类型擦除 10.3.2 自动装箱、拆箱与遍历循环 10.3.3 条件编译 10.4 实战:插入式注解处理器 10.4.1 实战目标 10.4.2 代码实现 10.4.3 运行与测试 10.4.4 其他应用案例 10.5 本章小结 第11章 晚期(运行期)优化 11.1 概述 11.2 HotSpot虚拟机内的即时编译器 11.2.1 解释器与编译器 11.2.2 编译对象与触发条件 11.2.3 编译过程 11.2.4 查看及分析即时编译结果 11.3 编译优化技术 11.3.1 优化技术概览 11.3.2 公共子达式消除 11.3.3 数组边界检查消除 11.3.4 方法内联 11.3.5 逃逸分析 11.4 Java与CC++的编译器对比 11.5 本章小结 第五部分 高效并发 第12章 Java内存模型与线程 12.1 概述 12.2 硬件的效率与一致性 12.3 Java内存模型 12.3.1 主内存与工作内存 12.3.2 内存间交互操作 12.3.3 对于volatile型变量的特殊规则 12.3.4 对于long和double型变量的特殊规则 12.3.5 原子性、可见性与有序性 12.3.6 先行发生原则 12.4 Java与线程 12.4.1 线程的实现 12.4.2 Java线程调度 12.4.3 状态转换 12.5 本章小结 第13章 线程安全与锁优化 13.1 概述 13.2 线程安全 13.2.1 Java语言的线程安全 13.2.2 线程安全的实现方法 13.3 锁优化 13.3.1 自旋锁与自适应自旋 13.3.2 锁消除 13.3.3 锁粗化 13.3.4 轻量级锁 13.3.5 偏向锁 13.4 本章小结 附  录 附录A 编译Windows版的OpenJDK 附录B 虚拟机字节码指令 附录C HotSpot虚拟机主要参数 附录D 对象查询语言(OQL)简介 附录E JDK历史版本轨迹

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

涂作权的博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值