Class类文件结构

引用了

Class文件结构

前言

1.最近在学习关于虚拟机的知识,整理一份比较详细的class文件结构。
2.翻译class文件就可以称为解释器
3.你可以使用javap -v Hello.class 命令去查看class类文件结构
4.可以从你的目标目录和安装目录的rt.jar中读取基本够用的class文件

读取字节码

private fun getClassBit(goal: String): ByteArrayBean {
    var result = getFromJar("/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/rt.jar", goal)
    if (result == null) {
        result = getFromFile("/Users/haha/Downloads/", goal)
    }
    return ByteArrayBean(result, 0)
}

private fun getFromJar(path: String, goal: String): ByteArray? {
    val zipInputStream = ZipInputStream(FileInputStream(path))
    val zipFile = ZipFile(path)
    var zipEntry: ZipEntry?
    while (true) {
        zipEntry = zipInputStream.nextEntry
        if (zipEntry == null) {
            break
        }
        if (zipEntry.name == goal.plus(".class")) {
            return zipFile?.getInputStream(zipEntry).readBytes()
        }
    }
    return null
}

private fun getFromFile(path: String, goal: String): ByteArray {
    val file = File("$path$goal.class")
    return file.readBytes()
}

Class类文件结构

名称 变量 长度/Byte
魔数 magic 4
次版本号 minor_version 2
主版本号 major version 2
常量数 constant_num 2
常量池 constant_pool 常量*(constant_num - 1)
访问标志 access_flags 2
类索引 this_class 2
父类索引 super_class 2
接口数量 interface_num 2
接口池 interface_pool 接口*(interface_num)
变量数量 field_num 2
变量池 field_pool 变量*(field_num)
方法数量 method_num 2
方法池 method_pool 方法*(method_num)
附加属性数量 attribute_num 2
附加属性池 attribute_pool 附加属性*(attribute_num)

常量结构

名称 变量 长度/byte
类型 type 1
内容 content 不固定,由下表决定
类型值 名称 格式 长度/bytes 说明
1 UTF8 length 2 长度
Text length 内容
3 Int 4
4 Float 4
5 Long 8
6 Double 8
7 Class index 2 指向index位置的utf8常量
8 String index 2 指向index位置的utf8常量
9 Fieldref class index 2 指向index位置的class常量
nameAndType index 2 指向index位置的nameAndType常量
10 Methodref class index 2 指向index位置的class常量
nameAndType index 2 指向index位置的nameAndType常量
11 Interface Methodref class index 2 指向index位置的class常量
nameAndType index 2 指向index位置的nameAndType常量
12 NameAndType name index 2 指向index位置的utf8常量
type index 2 指向index位置的utf8常量

备注:当常量池出现long时,constant_pool应该跳过一位,例如constant_pool[16]=1280977330748,下一位应该给constant_pool[18]赋值,原因未知,double未测试,测试class文件为String.class

接口结构

名称 长度
Interface Classref Index 2

备注:接口池存的很简单,只是指向常量池中接口类的索引

变量结构

名称 变量 长度/bytes
访问标志 access_flags 2
变量名索引 name_index 2
变量类型索引 descriptor_index 2
附加属性数量 attribute_num 2
附加属性池 attribute_pool 附加属性*(attribute_num)

方法结构

名称 变量 长度/bytes
访问标志 access_flags 2
方法名索引 name_index 2
方法类型索引 descriptor_index 2
附加属性数量 attribute_num 2
附加属性池 attribute_pool 附加属性*(attribute_num)

附加属性结构

名称 变量 长度/bytes
属性名索引 name_index 2
长度 length 4
内容 attribute_pool length

根据name_index指向的属性决定,属性bean可能为不同格式,不同长度

方法结构-附加属性-Code属性(属于附加属性,包含附加属性)

名称 变量 长度/bytes
最大栈深度 stack_length 2
局部变量表大小 localproperty_num 2
指令长度 order_length 4
指令集 order_array order_length
异常数量 exception_num 2
异常池 exception_pool 异常属性*exception_num
附加属性数量 attribute_num 2
附加属性池 attribute_pool 附加属性*(attribute_num)

方法结构-附加属性-Code属性-异常属性

名称 变量 长度/bytes
起始指令位置 from 2
结束指令位置 to 2
目标指令位置 target 2
异常类型 type 2

已知附加属性

属性名 class field method method-code
Signature * * *
Code *
LineNumberTable *
LocalVariableTable *
StackMapTable *
Deprecated *
RuntimeVisibleAnnotations *
Exceptions *
SourceFile *
InnerClasses *

类访问标志符

类访问标志符

方法访问标志符

方法访问标志符

你可能感兴趣的:(Class类文件结构)