Java Class文件
1、Class文件中的内容结构列表
--magic(魔数) OXCAFEBABE 用于区分JAVA Class文件和非JAVA Class文件
--minor version/major version 用于检测Class文件版本号是否属于JVM可以处理的范围
--constant pool count/constant pool 常量池
--access flags 访问标志
--this class 当前类的一个对常量池的索引
--super class 超类
--interfaces count/interfaces 所实现接口
--fields count/fields 字段信息
--methods count/methods 方法信息
--attributes count/attributes 属性信息
2、Java数组最多有255维
类型的生命周期
3、动态连接阶段:验证(数据是否合法),准备(为类分配内存),解析(符号引用转为直接引用,可选操作)
任何类的初始化都要求他所有它的祖先类(而非祖先接口)预先初始化,而一个接口的初始化并不需要它所有的祖先接口预先初始化。只有在某个接口所声明的非常量字段被使用时,该接口才会被初始化。
4、Java编译器把类变量初始化语句和静态初始化语句的代码都放到class文件的<clinit>()方法中,顺序就按照它们在类或者接口中声明的顺序。
并非所有的类都需要在它们的class文件中拥有一个<clinit>()方法。如果类没有声明类变量也没有静态初始化语句,那么它就不会有<clinit>()方法。如果类声明了类变量,但是没有明确使用类变量初始化语句或者静态初始化语句初始化它们,那么类不会有<clinit>()方法。如果类仅包含静态final变量的类变量初始化语句,而且这些类变量初始化语句采用编译时常量表达式,类也不会有<clinit>()方法。只有那些的确需要执行Java代码来赋予类变量正确初始值的类才会有类初始化方法。
例如:
Example类在被装载的时候,angle和length并没有作为类变量保存在方法区中。因此不需要<clinit>()方法来初始化他们,它们并非类变量,而是常量,被Java编译器特殊处理了。Java虚拟机在使用它们的任何类的常量池或者字节码流中直接存放的是它们表示的常量的int值,而不是一个指向Example类的angle字段的符号引用。
5、所有在接口中声明的隐式公开(public)、静态(static)和最终(final)字段都必须在字段初始化语句中初始化。
6、主动使用和被动使用--Java虚拟机首次使用类型时初始化它们
--6中活动被认为主动使用:创建类的新实例 调用类中声明的静态方法 操作类或者接口中声明的非常量静态字段 调用Java API中特定的反射方法 初始化一个类的子类 指定一个类作为Java虚拟机启动时的初始化类
使用一个非常量的静态字段只有当类或者接口的确声明了这个字段时才是主动使用。比如类中声明的字段可能会被子类引用;接口中声明的字段可能会被子接口或者实现了这个接口的类引用。对于子类、子接口和实现了接口的类来说,这就是被动使用——使用它们并不会触发它们的初始化。只有当字段的确是被类或者接口声明的时候才是主动使用。
例如:
执行Example中的main只会导致Example和NewParent被初始化,NewBornBady没有被初始化,也不需要被装载。
输出:
Example was initialized
NewParent was initialized
2
7、对象的生命周期
--实例化一个类的四种途径:明确的使用new操作符 调用Class或者java.lang.reflect.Constructor对象的newInstance()方法 调用任何现有对象的clone()方法 通过java.io.ObjectInputStream类的getObject()方法反序列化
--如果构造方法没有明确地从this()或者super()调用开始,对应的<init>()方法默认会调用超类的无参数<init>()方法
--<init>()方法不允许捕捉由它们所调用的<init>()方法抛出的任何异常。比如如果子类的<init>()方法调用一个被意外中止的超类的<init>()方法,那么子类的<init>()方法也必须同样被意外中止。
--finalize方法:如果类声明了finalize方法,垃圾收集器会在释放这个实例所占据的内存空间之前执行这个方法一次。终结方法可以被程序直接调用,但不会影响垃圾收集器的自动调用过程。垃圾收集器(最多)只会调用一个对象的终结方法一次——在对象变成不再被引用的之后的某个时候,在占据的对象被重用之前。如果终结方法代码执行后,对象重新被引用了(复活了),随后再次变得不被引用,垃圾收集器不会第二次调用终结方法。
垃圾收集器自动调用终结方法抛出的任何异常都将被忽略。
--对象不再被引用时会被垃圾收集器回收以释放堆空间;类不再被引用时则会被卸载类型,这样类型所占据的方法区内存空间就会被释放。使用启动类装载器装载的类型永远是可触及的,不会被卸载。只有使用用户自定义的类装载器装载的类型才会变成不可触及的,从而被虚拟机回收。如果某个类型的Class实例被发现无法通过正常的垃圾收集堆触及,那么这个类型就是不可触及的。
判断动态装载的类型的Class实例在正常的垃圾收集过程中是否可以触及有两种方式:第一,程序保持对Class实例的明确引用;其次,如果堆中还存在一个可触及的对象,在方法区中它的类型数据指向一个Class实例,那么这个Class实例就是可触及的。
1、Class文件中的内容结构列表
--magic(魔数) OXCAFEBABE 用于区分JAVA Class文件和非JAVA Class文件
--minor version/major version 用于检测Class文件版本号是否属于JVM可以处理的范围
--constant pool count/constant pool 常量池
--access flags 访问标志
--this class 当前类的一个对常量池的索引
--super class 超类
--interfaces count/interfaces 所实现接口
--fields count/fields 字段信息
--methods count/methods 方法信息
--attributes count/attributes 属性信息
2、Java数组最多有255维
类型的生命周期
3、动态连接阶段:验证(数据是否合法),准备(为类分配内存),解析(符号引用转为直接引用,可选操作)
任何类的初始化都要求他所有它的祖先类(而非祖先接口)预先初始化,而一个接口的初始化并不需要它所有的祖先接口预先初始化。只有在某个接口所声明的非常量字段被使用时,该接口才会被初始化。
4、Java编译器把类变量初始化语句和静态初始化语句的代码都放到class文件的<clinit>()方法中,顺序就按照它们在类或者接口中声明的顺序。
并非所有的类都需要在它们的class文件中拥有一个<clinit>()方法。如果类没有声明类变量也没有静态初始化语句,那么它就不会有<clinit>()方法。如果类声明了类变量,但是没有明确使用类变量初始化语句或者静态初始化语句初始化它们,那么类不会有<clinit>()方法。如果类仅包含静态final变量的类变量初始化语句,而且这些类变量初始化语句采用编译时常量表达式,类也不会有<clinit>()方法。只有那些的确需要执行Java代码来赋予类变量正确初始值的类才会有类初始化方法。
例如:
class Example{ static final int angle = 35; static final int length = angle * 2; }
Example类在被装载的时候,angle和length并没有作为类变量保存在方法区中。因此不需要<clinit>()方法来初始化他们,它们并非类变量,而是常量,被Java编译器特殊处理了。Java虚拟机在使用它们的任何类的常量池或者字节码流中直接存放的是它们表示的常量的int值,而不是一个指向Example类的angle字段的符号引用。
5、所有在接口中声明的隐式公开(public)、静态(static)和最终(final)字段都必须在字段初始化语句中初始化。
6、主动使用和被动使用--Java虚拟机首次使用类型时初始化它们
--6中活动被认为主动使用:创建类的新实例 调用类中声明的静态方法 操作类或者接口中声明的非常量静态字段 调用Java API中特定的反射方法 初始化一个类的子类 指定一个类作为Java虚拟机启动时的初始化类
使用一个非常量的静态字段只有当类或者接口的确声明了这个字段时才是主动使用。比如类中声明的字段可能会被子类引用;接口中声明的字段可能会被子接口或者实现了这个接口的类引用。对于子类、子接口和实现了接口的类来说,这就是被动使用——使用它们并不会触发它们的初始化。只有当字段的确是被类或者接口声明的时候才是主动使用。
例如:
class NewParent{ static int hoursOfSleep = (int)(Math.random()*3.0); static{ System.out.println("NewParent was initiaized"); } } NewBornBady extends NewParent{ static int hoursOfCrying = 6 + (int)(Math.random()*2.0); static{ System.out.println("NewBornBady was initialized"); } } class Example{ public static void main(String[] args){ int hours = NewBornBady.hoursOfSleep; System.out.println(hours); } static{ System.out.println("Example was initialized"); } }
执行Example中的main只会导致Example和NewParent被初始化,NewBornBady没有被初始化,也不需要被装载。
输出:
Example was initialized
NewParent was initialized
2
7、对象的生命周期
--实例化一个类的四种途径:明确的使用new操作符 调用Class或者java.lang.reflect.Constructor对象的newInstance()方法 调用任何现有对象的clone()方法 通过java.io.ObjectInputStream类的getObject()方法反序列化
--如果构造方法没有明确地从this()或者super()调用开始,对应的<init>()方法默认会调用超类的无参数<init>()方法
--<init>()方法不允许捕捉由它们所调用的<init>()方法抛出的任何异常。比如如果子类的<init>()方法调用一个被意外中止的超类的<init>()方法,那么子类的<init>()方法也必须同样被意外中止。
--finalize方法:如果类声明了finalize方法,垃圾收集器会在释放这个实例所占据的内存空间之前执行这个方法一次。终结方法可以被程序直接调用,但不会影响垃圾收集器的自动调用过程。垃圾收集器(最多)只会调用一个对象的终结方法一次——在对象变成不再被引用的之后的某个时候,在占据的对象被重用之前。如果终结方法代码执行后,对象重新被引用了(复活了),随后再次变得不被引用,垃圾收集器不会第二次调用终结方法。
垃圾收集器自动调用终结方法抛出的任何异常都将被忽略。
--对象不再被引用时会被垃圾收集器回收以释放堆空间;类不再被引用时则会被卸载类型,这样类型所占据的方法区内存空间就会被释放。使用启动类装载器装载的类型永远是可触及的,不会被卸载。只有使用用户自定义的类装载器装载的类型才会变成不可触及的,从而被虚拟机回收。如果某个类型的Class实例被发现无法通过正常的垃圾收集堆触及,那么这个类型就是不可触及的。
判断动态装载的类型的Class实例在正常的垃圾收集过程中是否可以触及有两种方式:第一,程序保持对Class实例的明确引用;其次,如果堆中还存在一个可触及的对象,在方法区中它的类型数据指向一个Class实例,那么这个Class实例就是可触及的。
发表评论
-
深入JVM学习笔记 JVM指令介绍
2011-11-18 16:22 969JVM指令介绍 栈和局部变量操作 1、常量入栈操作 - ... -
深入JVM学习笔记 垃圾收集
2011-11-16 10:25 804垃圾收集 1、垃圾收集 ... -
深入JVM学习笔记 连接模型
2011-11-15 14:13 970连接模型 1、Class文件 ... -
深入JVM学习笔记 JVM是什么
2011-11-04 10:58 1210JVM是什么 1、守护和非 ... -
深入JVM学习笔记 Java技术体系结构
2011-11-01 14:43 9681、不同Java虚拟机执行 ... -
GridBagLayout的一篇好文章
2011-10-28 16:36 816http://www.cnblogs.com/willmove ... -
JVM书籍保存
2011-10-25 17:05 1680JVM的经典书籍 -
Java继承与上溯 深入理解
2011-10-12 16:21 727Java继承与上溯: Child继承Parent,子类的变量和 ... -
java并发学习 读书笔记二
2011-09-13 10:26 843Executor框架介绍 1、Execu ... -
Andorid教程视频
2011-07-18 13:39 554http://v.youku.com/v_playlist/f ... -
近期面试学习
2011-06-15 21:49 643面试题目Java方面记载: ... -
设计模式 经典书籍
2011-04-30 00:09 980GoF的著作《设计模式——可复用面向对象软件的基础》 有机会 ... -
2011.03.07 Java泛型通配符
2011-03-07 20:36 7091、通配符提供了使用的 ... -
2011.03.07 Java泛型通配符
2011-03-07 20:26 675先看看Collection库中的几个方法。 public i ... -
每日学习:2011.3.4 Java泛型
2011-03-04 12:08 7061、在泛型代码内部,无 ... -
每日学习:2011.3.3 闭包 动态代理 Map的key
2011-03-03 15:05 6621、闭包:是一个可调用的对象,它记录了一些信息,这些信息来自于 ...
相关推荐
本篇JVM学习笔记主要涵盖了以下几个核心知识点: 1. **运行时数据区**: - **程序计数器**:记录当前线程执行的字节码的行号,用于线程恢复执行时跳转到正确位置。 - **Java虚拟机栈**:每个方法执行时创建的栈帧...
Java虚拟机栈同样是线程私有的,其生命周期与线程相同。它用来描述Java方法执行的内存模型,每个方法被执行时都会创建一个栈帧来存储局部变量表、操作数栈、动态链接、方法出口等信息。方法执行过程即为栈帧的入栈和...
这个资料包不仅涵盖了理论知识,还包含个人的学习笔记,对于学习和掌握JVM的各个方面都将大有裨益。无论是初学者还是经验丰富的开发者,都可以从中找到提升自己技能的宝贵资源。通过深入学习和实践,可以更好地理解...
本篇JVM学习笔记主要关注对象声明、相关内存分配方法以及虚拟内存的物理和虚拟寻址概念。 首先,我们来看对象声明。在Java中,对象是在堆上创建的。例如,`CHeapObj` 类展示了如何在C++中模拟Java对象在堆上的分配...
4. **减少内存泄漏**:避免创建过多的短生命周期对象,尤其是大数据量的集合,这可能会导致新生代频繁触发垃圾收集。 5. **代码优化**:良好的编程习惯可以降低GC压力,如及时释放不再使用的对象引用,避免使用静态...
### JVM学习笔记核心知识点整理 #### 一、引言与背景 随着软件开发技术的不断发展,Java作为一种广泛应用的编程语言,其背后的核心技术——Java虚拟机(JVM)的重要性日益凸显。掌握JVM不仅可以帮助开发者更好地理解...
《JVM学习笔记》 Java虚拟机(JVM)是Java平台的核心组成部分,它负责运行所有的Java应用程序。这篇笔记将深入探讨JVM的工作原理、内存管理、类加载机制以及优化策略,帮助读者全面理解JVM并提升Java程序的性能。 ...
这份“JVM的学习笔记PDF版”应该包含了关于JVM的详细信息,帮助学习者深入理解这个复杂的系统。JVM允许Java代码跨平台运行,通过解释器、类加载器、垃圾收集器等组件实现“一次编写,到处运行”的理念。 1. **JVM...
### 深入Java虚拟机JVM类加载学习笔记 #### 一、Classloader机制解析 在Java虚拟机(JVM)中,类加载器(ClassLoader)是负责将类的`.class`文件加载到内存中的重要组件。理解类加载器的工作原理对于深入掌握JVM以及...
- 类的生命周期包括加载、验证、准备、初始化和卸载五个阶段。 - 双亲委派模型:类加载器在加载类时,会将任务委托给父类加载器,直到Bootstrap ClassLoader。 3. **内存区域**: - 程序计数器:记录当前线程...
了解这个过程有助于我们理解和控制类的生命周期。 四、垃圾收集与内存优化 JVM的垃圾收集机制负责自动回收不再使用的对象所占用的内存,主要有标记-清除、复制、标记-整理和分代收集等算法。理解垃圾收集的工作...
栈帧的生命周期与方法同步,线程私有。 - **本地方法栈**:与虚拟机栈相似,但服务于本地(Native)方法。 - **堆**:所有线程共享,存储对象实例和数组。堆被分为新生代和老年代,新生代用于短期对象,老年代用于...
### JVM学习笔记知识点详解 #### 一、JVM的基本结构 **JVM(Java Virtual Machine,Java虚拟机)**是一种可以执行Java字节码的虚拟机。它为Java提供了平台无关性,使得Java代码可以在任何安装了JVM的平台上运行。 ...
《JVM内存管理学习笔记》 在Java世界中,JVM(Java Virtual Machine)是运行所有Java应用程序的核心。深入理解JVM内存管理对于优化程序性能、预防和解决内存泄漏问题至关重要。本文将从JVM内存模型、内存区域划分、...
JVM根据对象生命周期的不同,将堆内存划分为新生代和老年代,分别采用不同的回收策略。 五、性能优化 1. 参数调优:通过调整JVM启动参数,如-Xms、-Xmx设定堆大小,-XX:+UseConcMarkSweepGC选择垃圾收集器等,来...
【描述】"ImagesForJVM——JVM笔记图片" 暗示这些图片可能是教学或学习笔记的一部分,旨在通过视觉化的方式解释JVM的关键概念,如内存模型、类加载机制、垃圾收集以及性能优化等方面。 【标签】"java" 明确了这些...
### Java分布式应用学习笔记02再谈JVM 在深入探讨Java虚拟机(JVM)时,我们再次聚焦于这个核心组件,它不仅是Java运行环境的心脏,也是构建分布式应用的关键技术之一。JVM作为Java语言的核心执行环境,其设计与...
- **分代收集(Generational GC)**:根据对象的生命周期,将堆分为新生代和老年代,不同年代采用不同的垃圾回收策略。 3. **垃圾回收器**: - **Serial GC**:单线程的垃圾回收器,适合轻量级应用。 - **...
新生代又细分为Eden区、Survivor区(From和To),用于进行垃圾收集和对象生命周期管理。 2. **方法区(Method Area)**:在Java 8之前,也被称为永久代,存储了类的信息,如类名、方法信息、常量池等。Java 8之后,...
2. **类与对象**:深入解析类的定义、对象的创建及生命周期,包括封装、继承和多态等面向对象的三大特性,以及构造函数、访问修饰符的使用。 3. **包与接口**:介绍了Java中的包机制,用于组织和管理类,以及接口的...