环境
JDK 1.6.0_10-rc2
源代码
/**
* 验证java class文件格式格式
* 以下代码不要修改:
* @author: zhanglixin
* @version: 1.0 2013-1-10
*/
public class ClassFormat1 implements Serializable{
final int C=8;
final String S="Hello!";
private double instaneDouble=1.01;
static double staticDouble = 2.02;
public static void main(String[] args)
{
boolean localBln = true;
}
}
编译后字节码
通过javap -version 查看
E:\testspace\jvm>javap -verbose ClassFormat1
Compiled from "ClassFormat1.java"
public class ClassFormat1 extends java.lang.Object implements java.io.Serializable
SourceFile: "ClassFormat1.java"
minor version: 0
major version: 50
Constant pool:
const #1 = Method #12.#32; // java/lang/Object."<init>":()V
const #2 = Field #11.#33; // ClassFormat1.C:I
const #3 = String #34; // Hello!
const #4 = Field #11.#35; // ClassFormat1.S:Ljava/lang/String;
const #5 = double 1.01d;
const #7 = Field #11.#36; // ClassFormat1.instaneDouble:D
const #8 = double 2.02d;
const #10 = Field #11.#37; // ClassFormat1.staticDouble:D
const #11 = class #38; // ClassFormat1
const #12 = class #39; // java/lang/Object
const #13 = class #40; // java/io/Serializable
const #14 = Asciz C;
const #15 = Asciz I;
const #16 = Asciz ConstantValue;
const #17 = int 8;
const #18 = Asciz S;
const #19 = Asciz Ljava/lang/String;;
const #20 = Asciz instaneDouble;
const #21 = Asciz D;
const #22 = Asciz staticDouble;
const #23 = Asciz <init>;
const #24 = Asciz ()V;
const #25 = Asciz Code;
const #26 = Asciz LineNumberTable;
const #27 = Asciz main;
const #28 = Asciz ([Ljava/lang/String;)V;
const #29 = Asciz <clinit>;
const #30 = Asciz SourceFile;
const #31 = Asciz ClassFormat1.java;
const #32 = NameAndType #23:#24;// "<init>":()V
const #33 = NameAndType #14:#15;// C:I
const #34 = Asciz Hello!;
const #35 = NameAndType #18:#19;// S:Ljava/lang/String;
const #36 = NameAndType #20:#21;// instaneDouble:D
const #37 = NameAndType #22:#21;// staticDouble:D
const #38 = Asciz ClassFormat1;
const #39 = Asciz java/lang/Object;
const #40 = Asciz java/io/Serializable;
{
final int C;
Constant value: int 8
final java.lang.String S;
Constant value: String Hello!
static double staticDouble;
public ClassFormat1();
Code:
Stack=3, Locals=1, Args_size=1
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: aload_0
5: bipush 8
7: putfield #2; //Field C:I
10: aload_0
11: ldc #3; //String Hello!
13: putfield #4; //Field S:Ljava/lang/String;
16: aload_0
17: ldc2_w #5; //double 1.01d
20: putfield #7; //Field instaneDouble:D
23: return
LineNumberTable:
line 37: 0
line 38: 4
line 39: 10
line 40: 16
public static void main(java.lang.String[]);
Code:
Stack=1, Locals=2, Args_size=1
0: iconst_1
1: istore_1
2: return
LineNumberTable:
line 44: 0
line 45: 2
static {};
Code:
Stack=2, Locals=0, Args_size=0
0: ldc2_w #8; //double 2.02d
3: putstatic #10; //Field staticDouble:D
6: return
LineNumberTable:
line 41: 0
}
class文件分析
0X00000000h 偏移0-3:魔法数字。
0X00000000h 偏移4-5:次版本号。
0X00000000h 偏移5-6:主版本号。
0X00000000h 偏移8-9:常量池个数。算法:当前16进制转换为10进制-1。
0X00000000h 偏移A 至 0X00000160h 偏移8:常量池。
0X00000160h 偏移9-A:Access flag类访问修饰符
0X00000160h 偏移B-C:当前类名字索引
0X00000160h 偏移D-E:父类名字索引
0X00000160h 偏移F- 0X00000170h 偏移 0 :该类实现的接口数量。值00 001,1个。
0X00000170h 偏移1-2:接口名字索引。值00 0D,索引值13.即对应常量池索引号13的项,即该接口名字。
0X00000170h 偏移3- 至 0X00000200 偏移4:为域Field的信息
0X00000170h 偏移3-4 :域的数量。值00 04,即4个域。
0X00000170h 偏移5-6 :第一个域的访问修饰(Access Flag),值:00 10,即ACC_FINAL,final方法,不可覆盖。
0X00000170h 偏移7-8 :域名字索引。值00 0E,即对应常量池第14项,即“C”,域的名字为C 。
0X00000170h 偏移9-a :域名字的描述符。值00 0F,即对应常量池第15项,即“I”,域的类型为Integter 整型。
0X00000170h 偏移b-c :该域所含属性的数量。值00 01,含有一个属性。
0X00000170h 偏移d-e :该属性的名字索引。值00 10,即对应常量池16项,即:ConstantValue.该属性值为常量值。
0X00000170h 偏移f- 0X00000180h 偏移2 :属性的长度,值 00 00 00 02,即4个字节长。
0X00000180h 偏移3-4:属性值 00 11,即对应常量池的索引是17,为:“int 8”。
以下各个域相同。
0X00000180h 偏移5 至 0X00000190 偏移4 :第二个域 final String S="Hello!"的域。
0X00000190h 偏移5 至 0X00000190 偏移c :第三个域 private double instaneDouble=1.01 的域。注意该域没有属性集合。
0X00000190h 偏移d 至 0X000001a0 偏移4 :第四个域 static double staticDouble = 2.02 的域。注意该域没有属性集合。
0X000001a0 偏移5 - 0X00000240h 偏移0 :为方法method的信息。
0X000001a0h 偏移5-6 :方法的数量。值00 03,即3个方法。
0X000001a0h 偏移7-8 :第一个方法的访问修饰(Access Flag),值:00 01,即ACC_PUBLIC,public方法。
0X000001a0h 偏移9-a :方法名字索引。值00 17,即对应常量池第23项,即“<init>”,对象实例初始化方法 。
0X000001a0h 偏移b-c :方法名字的描述符。值00 18,即对应常量池第24项,即“()V",方法的参数为空,返回值void。
0X000001a0h 偏移d-e :该方法所含属性的数量。值00 01,含有一个属性。
0X000001a0h 偏移f- 0X000001b0h 偏移 0:该属性的名字索引。值00 19,即对应常量池25项,即:"Code".该属性值为代码。
0X000001b0h 偏移1-4 :属性的长度,值 00 00 00 3c,4个字节长,该属性的长度,3c,即60字节(单位u1),后续60个字节为属性值。
0X000001b0h 偏移3- 0X000001f0h 偏移0:为属性值,即该方法的字节码指令。
以下各个方法相同。
0X000001f0h 偏移1- 0X00000210h偏移d 第二个方法,main方法
0X00000210h 偏移e- 0X00000240h偏移a 第三个方法,<cinit>方法,类初始化方法。
0X00000240h偏移b-0X00000250h 偏移4(文件结尾) :为属性的信息
0X00000240h 偏移b-c :属性的数量。值00 01,即1个属性。
0X00000240h 偏移d-e :第一个属性的索引值,值:00 1e,对应常量池第30项,值为:"SourceFile"。
0X00000240h 偏移f- 0X00000250h 偏移2:属性值长度 00 00 00 02,长度为2个u1。
0X00000250h 偏移3-4: 属性值为 00 1F ,值为31,对应常量值第31项,为:“ClassFormat1.java”
分享到:
相关推荐
Java程序的运行依赖于类加载器将`.class`文件加载到JVM中,并对其进行验证、准备和解析等步骤,最终使类能够在JVM中执行。 #### 三、Class文件的加载过程 Java类的加载过程主要可以分为以下几个阶段: 1. **加载...
验证过程包括文件格式验证、元数据验证、字节码验证和符号引用验证。 - **准备**:在这个阶段,为类变量分配内存并设置它们的默认初始值,如零值或null。不过,final修饰的static变量在编译阶段就已经分配好。此时...
Java的`.class`文件格式具有一定的版本兼容性,使得新的Java版本可以运行旧版本编译的`.class`文件,但可能无法利用新版本的特性。 9. **模块系统与ClassPath**: 自Java 9引入模块系统后,`.class`文件的查找和...
Java字节码是Java程序编译后的产物,它以`.class`文件的形式存在,是Java虚拟机(JVM)能够理解和执行的二进制代码。本文将深入解析Java字节码的格式,帮助你理解其背后的运行机制。 1. **Java字节码结构** Java...
综上所述,通过这个实验,我们可以深入学习Java Class文件格式,了解其内部构造,为后续的Java编程和JVM相关的研究打下坚实的基础。而`笔记.docx`可能包含了实验过程的详细记录,便于回顾和总结。
本篇将围绕"jvm-jit-examples"项目,探讨JVM JIT编译器的工作原理以及CHA(Class Hierarchy Analysis)的作用,并通过实际代码示例来加深理解。 1. JVM JIT编译器 JIT编译器是JVM的一项重要技术,它的主要任务是在...
.class文件遵循特定的二进制格式,包括魔数、版本号、常量池、类和父类信息、接口、字段、方法、属性等部分。了解这些结构对于解析和编辑class文件至关重要。 3. 类编辑器的功能: - 查看字节码:类编辑器可以...
每个部分紧密相连,不存在任何无意义的填充字节,这使得Class文件格式既紧凑又高效。 #### 二、Class文件主要内容解析 1. **Magic Number (魔数)** - 魔数是Class文件的前四个字节,值为`0xCAFEBABE`。它的主要...
1. `String.class.getClassLoader()` 返回的是启动类加载器,因为它是JVM自带的核心类。 2. `com.sun.crypto.provider.DESKeyFactory.class.getClassLoader().getClass().getName()` 返回的是扩展类加载器,因为这类...
1. 类装载器(ClassLoader):负责加载类文件,将字节码转化为内存中的Class对象。类装载器分为引导类装载器、扩展类装载器和应用程序类装载器,以及用户自定义的类装载器。 2. 运行时数据区(Runtime Data Area)...
通过上面的示例,我们可以了解Java JVM程序指令码实例解析的过程,包括编译Java源代码、生成.class文件和反编译.class文件为JVM指令码。 在Java编程中,理解Java JVM程序指令码实例解析的过程非常重要,可以帮助...
- `PersistentServiceExample.class`:持久化服务的示例类文件。 - `PersistentServiceExampleMBean.class`:示例类对应的MBean实现。 #### jboss 目录 - **jboss**:JBoss的核心组件目录。 - `jmx`:Java ...
Java 动态加载 jar 和 class 文件实例解析 Java 动态加载 jar 和 class 文件实例解析是 Java 语言中的一种重要机制,用于加载和实例化类文件。在 Java 中,类文件加载是动态的,也就是说只有当我们需要使用某个类时...
本文将深入探讨字节码的概念,通过具体的示例和常量池的解析来阐述其工作原理。 首先,我们需要理解什么是字节码。字节码是一种中间表示形式,它是Java源代码编译后的产物,存储在.class文件中。每个字节码指令都是...
Class 文件是 Java 虚拟机能够识别并执行的一种文件格式,它由编译器生成,并供 JVM 使用。Class 文件具有以下特点: 1. **二进制流**:Class 文件是一组以 8 个字节为基础单位的二进制流。 2. **紧凑排列**:文件...
这篇博客“Java类动态加载(一)——java源文件动态编译为class文件”可能主要探讨了如何在运行时将Java源代码(.java)编译成对应的字节码文件(.class),并将其加载到Java虚拟机(JVM)中。以下是对这个主题的详细解析...
在每个`.class`文件的开头都有一个魔数(Magic Number),其值为`0xCAFEBABE`,用来识别文件格式。紧接着是`minor_version`和`major_version`字段,它们分别表示次版本号和主版本号,用于标识字节码对应的Java版本。...
- **问题解析**:如果遇到“无法读取 xxx.java”这样的错误提示,通常意味着文件路径不正确、文件不存在或者没有权限访问该文件。 - **解决方法**: - 检查文件路径是否正确; - 确保文件名为 `.java` 而不是 `....
**Java虚拟机(JVM)学习测试代码** 在Java编程领域,Java虚拟机(JVM)是核心组件之一,它负责执行编译后的Java字节码。本项目"jvm-test-demo"是一个专为深入理解JVM工作原理而设计的学习实践平台。通过此项目,...
在Java编程环境中,.class文件是Java源代码经过编译后的二进制文件,它包含了程序的字节码,是Java虚拟机(JVM)执行的基石。本教程将详细介绍如何使用工具jclasslib和编写Java程序来修改.class文件的内容。 首先,...