Java虚拟机读书笔记
文章平均质量分 58
shengzhu1
scala语言编程,java语言编程
展开
-
Java虚拟机的即时编译与C/C++的静态优化编译器比较
Java虚拟机的即时编译与C/C++的静态优化编译器相比,可能会由于下列这些原因导致输出的本地代码有一些劣势(也包括一些虚拟机执行子系统的性能劣势):原创 2017-06-16 00:43:59 · 678 阅读 · 0 评论 -
Java的符号引用和直接引用
类加载过程的解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程(参考深入理解Java虚拟机第七章),那么,什么是符号引用和直接引用呢?符号引用(Symbolic References)符号引用以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义的定位到目标即可。符号引用与虚拟机实现的内存布局无关,引用的目标并不一定已经加载到内存中。各种虚拟机实现的内存布局可以各不相同,原创 2017-06-09 17:30:12 · 4483 阅读 · 1 评论 -
类加载的过程
Java虚拟机中类加载的全过程,分为加载、验证、准备、解析和初始化这5个阶段。加载在加载阶段,虚拟机需要完成3件事:通过一个类的全限定名来获取定义此类的二进制字节流将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。数组类的加载本身不通过类加载器(系统的引导类加载器)创建,它是由J原创 2017-06-14 15:33:50 · 393 阅读 · 0 评论 -
Java的特殊类——数组对象的类
Java数组对象的类是一种特殊的类,在Java内部是没有这个类的,数组对象的类是在运行时确立的,没有生命任何成员变量、成员方法、构造函数、Annotation甚至连length成员变量这都没有,它就是一个彻彻底底的空类。对数组对象取长度的时候,需用到.length,而不是一般对象的.length(),是因为JVM在处理时对数组的长度做了特殊的处理,它是通过arraylength这条指令来实现的。参考原创 2017-06-26 14:57:40 · 1530 阅读 · 0 评论 -
类与类加载器
类加载器虽然只用于实现类的加载动作,但对于任意一个类,都需要由加载它的类和这个类本身一起确认其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间。也就是说,要比较两个类是否“相等”,只有二者是同一个类加载器加载出来的前提下才有意义,否则,即使两个类来源于同一个Class文件,被同一个虚拟机加载,只要加载它们的类加载器(loadClass方法)不同,两个类就必定不相等。双亲委派模型原创 2017-06-14 16:08:01 · 349 阅读 · 0 评论 -
虚拟机的字节码执行引擎
在Java虚拟机规范中制定了虚拟机字节码执行引擎的概念模型,这个概念模型成为各种虚拟机执行引擎的统一外观(Facade)。不同的虚拟机中,执行引擎可能有解释执行(通过解释器)和编译执行(通过即时编译器产生本地机器码)两种选择,也可能是二者兼备,甚至还可能包含几个不同级别的编译器执行引擎。但是从外观上来看,所有的Java虚拟机的执行引擎都是一致的:输入的是字节码文件,处理过程是字节码解析的等效过程,输原创 2017-06-14 19:20:12 · 278 阅读 · 0 评论 -
方法的调用
方法调用不同于方法的执行,其唯一任务是确定被调用方法的版本(即调用哪一个方法),不涉及方法内部的具体运行过程 。Class文件的编译过程不包括传统编译中的连接步骤,一切方法调用在Class文件里面存储的只是符号引用,而不是方法在实际运行时内存布局的入口地址(直接引用)。这种特性使得Java方法需要在类加载期间,甚至到运行期间才能确定目标方法的直接引用。解析所有方法的调用的目标方法在Class文件中都原创 2017-06-14 20:40:23 · 490 阅读 · 0 评论 -
JAVA的解释执行
Java一开始被定位为“解释执行”的语言,但是现在主流的虚拟机中都包含了即时编译器,Class文件中的代码到底会被解释执行还是编译执行,只有虚拟机自己才能判断。 Java语言中,Javac编译器完成了程序代码经过词性分析、语法分析到抽象语法树,再遍历语法树生成线性的字节码指令流的过程。因为这一部分动作是在Java虚拟机之外进行的,而解释器在虚拟机的内部,所以Java程序的编译就是半独立的实现。Ja原创 2017-06-14 20:55:41 · 4106 阅读 · 0 评论 -
早期(编译期)优化
解析与填充符号表词法、语法分析词法分析是将源代码的字符流转变为标记(Token)集合,单个字符是程序编写过程的最小元素,而标记是编译过程中的最小元素,关键字(int等)、变量名、字面量、运算符(四则运算等)都可以作为标记。语法分析是指根据Token序列构造抽象语法树的过程,抽象语法树(Abstract Syntax Tree,AST)是一种用来描述程序代码语法结构的树形表示方法,语法树的每一个节点都原创 2017-06-14 22:11:01 · 404 阅读 · 0 评论 -
Java的语法糖
泛型与类型擦除本质是参数化类型(Parametersized Type)的应用,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别为泛型类、泛型接口和泛型方法。泛型在C#中是真实存在的,例如List<int>和List<String>就是两个不同的类型,在系统运行期生成,有自己的虚方法表和类型数据,这种实现称为类型膨胀,基于这种方法实现的泛型为真实泛型。但是在原创 2017-06-15 10:43:35 · 426 阅读 · 0 评论 -
Java的即时编译(Just In Time, JIT)及其优化
Java程序最初是通过解释器进行解释执行的,当虚拟机发现某个方法或代码块运行的特别频繁时,会把这些代码认定为“热点代码”(Hot Spot Code)。为了提高热点代码的执行效率,在运行时,虚拟机会把这些代码编译成本地平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器称为即时编译器(JIT编译器,不是Java虚拟机内必须的部分)。要了解HotSpot虚拟机内的即时编译器的运作过程,要解决几原创 2017-06-15 13:57:01 · 8408 阅读 · 0 评论 -
Class类文件的结构与语言无关
无关性的基石**与平台无关的实现:**Sun公司以及其他的虚拟机提供商发布了许多可以运行在各种不同平台上的虚拟机,这些虚拟机都可以载入和执行同一种平台无关的字节码,从而实现了程序的“一次编写,到处运行”。实现语言无关性的基础是虚拟机和字节码存储格式。Java虚拟机不和包括Java在内的任何语言绑定,它只与Class文件这种特定的二进制文件格式所关联,Class文件中包含了Java虚拟机指令集和符号表原创 2017-06-14 00:59:29 · 389 阅读 · 0 评论 -
虚拟机的类加载的时机
之前讲过,在Class文件中描述的各种信息,最终都需要加载到虚拟机中之后才能运行和使用。而虚拟机如何加载这些Class文件?虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。类加载的时机类从被加载到虚拟机内存开始,到卸载出内存为止,整个生命周期包括:加载(Loading)、验证(Verificat原创 2017-06-14 11:19:50 · 419 阅读 · 0 评论 -
内存分配与回收策略
对象优先分配在Eden上大多数情况下,对象在新生代的Eden上分配。当Eden区没有足够空间进行分配时,虚拟机将发起一次Minor GC(新生代垃圾收集)。大对象分配大对象一般直接进入老年代,所谓大对象是指,需要大量连续内存空间的Java对象,最典型的就是很长的字符串和数组,大对象对内存分配来说是一个坏消息,应尽量避免。长期存活的对象既然虚拟机采用了分代收集的思想,那么内存回收时必须能识别哪些对象应原创 2017-06-13 20:22:10 · 350 阅读 · 0 评论 -
Java与线程
线程的实现线程是比进程更轻量级的调度执行单位,线程的引入,可以把一个进程的资源分配和执行调度分开,各个进程既可以进行共享进程资源(内存地址、文件I/O等),又可以独立调度(线程是CPU调度的基本单位)。主流的操作系统都提供了线程实现,Java语言则提供了在不同硬件和操作系统下对线程操作的统一操作,每个已经执行start()且还未结束的java.lang.Thread类的实例就代表一个线程。Tread原创 2017-06-16 01:12:53 · 313 阅读 · 0 评论 -
Java中的线程安全与实现
线程安全的定义:当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象是线程安全的。Java语言中的线程安全按照线程安全的“安全程度”由强至弱来排序,可以将Java中各种操作共享的数据分为5类:不可变、绝对线程安全、相对线程安全、线程兼容和线程对立。不可变不可变(Im原创 2017-06-16 01:15:44 · 551 阅读 · 0 评论 -
Java的锁优化
锁优化的目的是为了在线程之间更高效的共享数据,以及解决竞争问题,从而提高程序的执行效率。自旋锁与自适应自旋锁 锁消除 & 锁粗化 轻量级锁偏向锁原创 2017-06-16 01:18:33 · 296 阅读 · 0 评论 -
Java的JIT编译优化技术
具体参考《深入理解JVM虚拟机》第十一章原创 2017-06-16 16:04:18 · 412 阅读 · 0 评论 -
JVM的自动内存管理机制
程序计数器程序计数器(Program Counter Register)是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里(仅是概念模型,各种虚拟机会通过更高效的方式去实现),字节码解释器工作时就是通过改变这个计数器的值来取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。由于java虚拟机的多线程通过线程轮流原创 2017-06-12 11:18:27 · 331 阅读 · 0 评论 -
JVM对象的创建与内存管理
对象的创建在语言层面上,创建对象(例如克隆、反序列化)通常只是一个new关键字而已,而在虚拟机中,是怎么创建的?虚拟机遇到一条new指令时1、首先去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载、解析和初始化过。如果没有,就执行相应的类加载过程。2、在类加载检查通过后,虚拟机为新生对象分配内存,对象所需内存的大小在类加载完成后便可以完全确定,等同原创 2017-06-12 22:09:46 · 281 阅读 · 0 评论 -
垃圾回收器与内存分配机制
GC(Garbage Collection)需要完成的三件事:哪些内存需要回收?什么时候回收?如何回收?编译期可知的回收程序计数器、虚拟机栈和本地方法栈3个区域随线程而生,随线程而灭,栈中的栈帧(方法执行的基础数据结构,第八章内容)随着方法的进入和推出而进行着出栈和进栈操作。每一个栈帧中分配多少内存基本上是在类结构确定下来就已知的,因此这几个区域的内存分配和回收都具有确定性,在方法结束或线程原创 2017-06-13 14:20:01 · 332 阅读 · 0 评论 -
垃圾收集算法
标记-清除(Mark-Sweep)算法最基础的算法,分为标记和清除两部分:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象,之所以说最基础,是因为后续的收集算法都是基于这种思路对其不足进行改进。不足有两个:一个是效率问题,标记和清除两个过程的效率都不高;另一个是空间问题,标记清除后会产生大量的不连续的内存碎片,碎片太多可能会导致以后分配较大的对象时,无法找到足够的连续内存而不得不提原创 2017-06-13 15:08:32 · 316 阅读 · 0 评论 -
HotSpot的垃圾收集算法实现
GC Roots的确定(枚举根结点)可达性分析的GC Roots的节点主要在全局性的引用(例如常量或类静态属性即静态变量)与执行上下文(栈帧中的本地变量表)中,但是,方法去往往数百兆,逐个检查里面的引用太过消耗时间。另一个原因是GC(垃圾收集)停顿的问题,因为枚举根结点时必须停顿所有的Java执行线程(Stop The World),否则对象引用如果不断变动,那么结果将没有意义。解决方案是在停顿时使原创 2017-06-13 15:43:36 · 566 阅读 · 0 评论 -
垃圾收集器简介
上面的三个属于用于新生代的收集器,下面是老年代,有连线代表可以互相配合使用。Serial收集器Serial收集器是最基本、发展历史最悠久的收集器,是一个单线程的收集器,其并不仅仅代表只会使用一个CPU或一条收集线程去完成垃圾收集工作,更重要的是它在进行垃圾收集的时候,必须暂停其他所有的工作线程,直至它收集结束。优点:简单而高效,对于限定单个CPU环境来说,由于没有线程交互的开销,专心做垃圾收集自然可原创 2017-06-13 19:28:41 · 321 阅读 · 0 评论 -
Java虚拟机的JIT编译过程
在默认情况下,虚拟机在代码编译器还未完成之前,都仍然按照解释方式继续执行,而编译动作则在后台的编译栈中执行。在后台执行编译的过程中,编译器做了什么?Server Compiler和Client Compiler两个编译器的编译过程是不一样的。对于Client Compiler来说,它是一个简单快速的三段式编译器,主要的关注点在局部性的优化,而放弃了许多耗时较多的全局优化手段。原创 2017-06-15 14:19:13 · 546 阅读 · 0 评论