Java

学习JVM原理-13.类加载时的Preparation阶段

摘自《深入理解Java虚拟机》周志明著 Preparation阶段为static变量并设置初始值. 这里要区别变量是不是final.   1. public static final int abc = 123; 实际上对应两步:        a. 编译时即在constant pool里生成123这个字面量        b. 在prepration阶段再赋值为123   2. public static int abc = 123; 也可以分做两步:        a. preparation阶段先把abc赋值为0;        b. 在initialize阶段才赋值为123

学习JVM原理-14.类装载时的Initialization并不总会执行

摘自《深入理解Java虚拟机》周志明著 代码里出现类名,未必就会初始化这个类. 不太严谨地说,只有你"用到"这个类时,类才会Initialize. 如果你只是点它的名,或者用的是它的父类,是不会Initialize的 直接看例子: class Bean { public static int beanValue = 123; static{ System.out.println("Bean inited"); } } main(){ new Bean(); // 会打印"Bean inited" } main(){ int i = Bean.beanValue;; // 会打印"Bean inited" } main(){ Class b = Bean.class; // 不会打印"Bean inited" } 再看下继承的情况 class SubBean extends Bean{ static { System.out.println("SubBean inited"); } public …

学习JVM原理-14.类装载时的Initialization并不总会执行 Read More »

学习JVM原理-15.类initialization与继承关系

摘自《深入理解Java虚拟机》周志明著 class Bean { static { System.out.println("Bean inited"); } } class SubBean extends Bean{ static { System.out.println("SubBean inited"); } } main(){ int i = SubBean.subBeanValue; /*会先打印"Bean inited",再打印"SubBean inited" */ /*JVM会保证在子类的<clinit>方法执行之前,父类的<clint>()方法已经执行完毕*/ }

学习JVM原理-同一个ClassLoader加载的类,才是同一个类

摘自《深入理解Java虚拟机》周志明著 Object bean = anotherClassLoader.loadClass("Bean").newInstance(); //用自写的Class Loader装载Bean类并生成一个实例 System.out.println(bean instanceof Bean) // 答案将是false! 因为这里的Bean类是用系统默认的Classloader 装载的

两个Integer对象是否 ==

其机制与String是类似的 Integer a = 5; Integer b = 5; System.out.println(a == b); // true. Integer c = new Integer(5); Integer d = new Integer(5); System.out.println(c == d); // false.

学习JVM原理-四种Class Loader

摘自《深入理解Java虚拟机》周志明著 按ClassLoader的父子关系(概念上的父子关系,未必有类继承)排列 1.  Bootstrap ClassLoader 加载$JRE/lib下的类,如rt.jar里面的类 2.      Extension ClassLoader 加载$JRE/lib/ext下的类,如”sunjce_provider.jar”里面的类 3.          Application/System ClassLoader 加载ClassPath上指定的类库,它就是程序中默认的类加载器 4.              User ClassLoader

学习JVM原理-如果constant literal变了,用到它的其它类都要重新编译

假定Foo里定义了一个constant literal(literal 指String, int之类的字面量),而Bar里又用到了这个常量 一旦Foo里的常量值变了, 而Bar没有重新编译,则Bar里的值仍是Foo变之前的那个值 为什么会这样?  因为编译Bar时会把Foo里的常量值直接写到Bar.class这个字节码文件里; 运行Bar的代码时,JVM并不会动态地去Foo里取这个值,而是直接从Bar.class字节码文件中把值找出来,所以Foo的改动不会影响到Bar的运行 所以,如果Foo里的常量值变了,则Bar应该重新编译,把Foo中的新值更新到字节码文件中

学习JVM原理-ClassLoader的Parents Delegation Model

摘自《深入理解Java虚拟机》周志明著 考虑到Class Loader之间的父子关系,JAVA建议采用 Parents Delegation Model来实现一个Class Loader: 装载一个类时,先把这件事委托给Parent Class Loader,Parent再委托给GrandParent,如此传递,直到根 Loader; 如果根Loader能够装载,则返回装载出的类,否则一级一级往下传,一旦载出来就返回 然而这个模式并不是硬性的约束,有两种情况违反了这个模式:   1. Bootstrap Loader需要装载一个SPI如JAXB的实现,但这些实现不在rt.jar里,因此需要调用System ClassLoader或者User Class Loader. (Thread.currentThred().getContextClassLoader() 就是干这个的)   2. 热替换如OSGi

学习JVM原理-9.ByteCode文件结构概述

摘自《深入理解Java虚拟机》周志明著 ByteCode类文件   1. 二进制文件   2. 以字节为单位存放有意义的数据,不以0/1为单位(怪不得叫字节码?)   3. 某段数据的意义由它所处的位置来定,并不像XML或JSON一样有元数据,如<name>abc</name>,ByteCode文件里只有"abc" 数据结构的范式(把一个类文件看作一栋楼)      1. 砖头: 无符号数     2. 房间: Table, 由无符号数搭建而成     3. Table下可以有Table     4. 整个类文件就是一个Table 主要数据成员:   1.Magic Number,表明当前文件是Class文件(固定为0xCAFEBABE)   2.minor_version 和 major_version,这决定了本class可以被什么版本的JRE运行   3.constant pool   4.access_flags, this_class,super_class, interfaces等   5.fields, methods   6.attributes,如字节码指令,exceptions,line number等

学习JVM原理-10. 用javap分析bytecode文件中的Constant Pool

受教于《深入理解Java虚拟机》周志明著 直接看ByteCode文件会累死的,我们可以用JDK附带的javap -verbose A.class 来生成可读的信息. 下面就举个例子,看下这类信息中的Constant Pool部分 package pool; public class PlayConstant { private static final int DEFAULT_PLAYER_COUNT = 55; private String gameName; public Long getMoney(int playerCount) { long money = 10 * playerCount; return money; } } 一起来分析一下它的Constant Pool:    const #1 = class #2; // pool/PlayConstant –#2意思是它的值在Pool中的第#2个位置 const #2 = Asciz pool/PlayConstant; const …

学习JVM原理-10. 用javap分析bytecode文件中的Constant Pool Read More »