JVM---数据存储和访问(类文件结构)
一、类文件结构概述
计算机只识0和1
代码编译的结果从本地机器码到字节码是一个很重大意义的转变。
文件的数据项
把上面的文件数据项转化成图如下:
主次版本号
常量池:
包含两大类常量:字面量(Literal)和符号引用(Symbolic References)
字面量包括:文本字符串,声明为final的常量值等
符号引用(编译原理方面概念):
类和接口的全限定名(Fully Qualified Name)
字段的名称和描述符(Descriptor)
方法的名称和描述符
常量在存储的时候常量表
二、获取class文件示例一下
这里是在windows环境下打开CMD,到JDK安装目录下执行命令
使用javap -verbose Test(备注.class文件) 看不到所有内容
用法: javap <options> <classes>
其中, 可能的选项包括:-help --help -? 输出此用法消息-version 版本信息-v -verbose 输出附加信息-l 输出行号和本地变量表-public 仅显示公共类和成员-protected 显示受保护的/公共类和成员-package 显示程序包/受保护的/公共类和成员 (默认)-p -private 显示所有类和成员-c 对代码进行反汇编-s 输出内部类型签名-sysinfo 显示正在处理的类的系统信息 (路径, 大小, 日期, MD5 散列)-constants 显示最终常量-classpath <path> 指定查找用户类文件的位置-cp <path> 指定查找用户类文件的位置-bootclasspath <path> 覆盖引导类文件的位置
改下命令输出到文件中
我们现在可以打开其中一个看下内容如下,想要看懂的话还需要参照常量池中的14种常量项的结构总表
常量池中的14种常量项的结构总表
三、开始进入学习
先看下我们打开的demo文件整体结构图(常量池和内容信息也在字节码文件信息中由于特殊内容比较多,所以单独拉出来)
原始文件打开如下解析:
Classfile /D:/JD_SoftInstaller/RD_softInstaller/JDK/bin/Test.classLast modified 2019-1-18; size 2889 bytesMD5 checksum 6242eda79aea8128ea49a2dd0652454eCompiled from "Test.java"
public class test.Testminor version: 0major version: 52flags: ACC_PUBLIC, ACC_SUPER
Constant pool:#1 = Methodref #46.#93 // java/lang/Object."<init>":()V#2 = Class #94 // java/io/File#3 = String #95 // C:\Users\XXXXXX\Desktop\dbData\goodsExtListUpdate.txt#4 = Methodref #2.#96 // java/io/File."<init>":(Ljava/lang/String;)V#5 = Methodref #2.#97 // java/io/File.createNewFile:()Z#6 = Class #98 // java/io/BufferedWriter#7 = Class #99 // java/io/FileWriter#8 = Methodref #7.#100 // java/io/FileWriter."<init>":(Ljava/io/File;)V#9 = Methodref #6.#101 // java/io/BufferedWriter."<init>":(Ljava/io/Writer;)V#10 = Methodref #45.#102 // test/Test.readAndWrite:(ILjava/io/BufferedWriter;)V#11 = Class #103 // java/lang/Exception#12 = Methodref #6.#104 // java/io/BufferedWriter.flush:()V#13 = Methodref #6.#105 // java/io/BufferedWriter.close:()V#14 = String #106 // C:\Users\XXXXXX\Desktop\dbData\goodsExtList.txt#15 = Class #107 // java/io/InputStreamReader#16 = Class #108 // java/io/FileInputStream#17 = Methodref #16.#100 // java/io/FileInputStream."<init>":(Ljava/io/File;)V#18 = String #109 // GBK#19 = Methodref #15.#110 // java/io/InputStreamReader."<init>":(Ljava/io/InputStream;Ljava/lang/String;)V#20 = Class #111 // java/io/BufferedReader#21 = Methodref #20.#112 // java/io/BufferedReader."<init>":(Ljava/io/Reader;)V#22 = String #113 //#23 = Methodref #20.#114 // java/io/BufferedReader.readLine:()Ljava/lang/String;#24 = Class #115 // java/lang/String#25 = Methodref #24.#116 // java/lang/String.getBytes:(Ljava/lang/String;)[B#26 = Methodref #24.#117 // java/lang/String."<init>":([BLjava/lang/String;)V#27 = String #118 // hash#28 = Methodref #24.#119 // java/lang/String.contains:(Ljava/lang/CharSequence;)Z#29 = String #120 // CREATE TABLE `gold_pocket_goods_ext0` (#30 = Class #121 // java/lang/StringBuilder#31 = Methodref #30.#93 // java/lang/StringBuilder."<init>":()V#32 = Methodref #30.#122 // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;#33 = String #123 // \n#34 = Methodref #30.#124 // java/lang/StringBuilder.toString:()Ljava/lang/String;#35 = Methodref #6.#125 // java/io/BufferedWriter.write:(Ljava/lang/String;)V#36 = String #126 // set @sharding = 'gold_pocket_goods_ext#37 = Methodref #30.#127 // java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;#38 = String #128 // ID hash ' ;#39 = Fieldref #129.#130 // java/lang/System.out:Ljava/io/PrintStream;#40 = Methodref #131.#132 // java/io/PrintStream.println:(Ljava/lang/String;)V#41 = String #133 // CREATE TABLE `gold_pocket_goods_ext#42 = String #134 // ` (#43 = Class #135 // java/lang/NullPointerException#44 = Methodref #43.#93 // java/lang/NullPointerException."<init>":()V#45 = Class #136 // test/Test#46 = Class #137 // java/lang/Object#47 = Utf8 <init>#48 = Utf8 ()V#49 = Utf8 Code#50 = Utf8 LineNumberTable#51 = Utf8 LocalVariableTable#52 = Utf8 this#53 = Utf8 Ltest/Test;#54 = Utf8 main#55 = Utf8 ([Ljava/lang/String;)V#56 = Utf8 e#57 = Utf8 Ljava/lang/Exception;#58 = Utf8 args#59 = Utf8 [Ljava/lang/String;#60 = Utf8 writename#61 = Utf8 Ljava/io/File;#62 = Utf8 out#63 = Utf8 Ljava/io/BufferedWriter;#64 = Utf8 StackMapTable#65 = Class #59 // "[Ljava/lang/String;"#66 = Class #94 // java/io/File#67 = Class #98 // java/io/BufferedWriter#68 = Class #103 // java/lang/Exception#69 = Utf8 Exceptions#70 = Class #138 // java/io/IOException#71 = Utf8 readAndWrite#72 = Utf8 (ILjava/io/BufferedWriter;)V#73 = Utf8 pathname#74 = Utf8 Ljava/lang/String;#75 = Utf8 filename#76 = Utf8 reader#77 = Utf8 Ljava/io/InputStreamReader;#78 = Utf8 br#79 = Utf8 Ljava/io/BufferedReader;#80 = Utf8 line#81 = Utf8 nullPoint#82 = Utf8 Ljava/lang/NullPointerException;#83 = Utf8 i#84 = Utf8 I#85 = Class #115 // java/lang/String#86 = Class #107 // java/io/InputStreamReader#87 = Class #111 // java/io/BufferedReader#88 = Class #135 // java/lang/NullPointerException#89 = Class #139 // java/io/FileNotFoundException#90 = Class #140 // java/io/UnsupportedEncodingException#91 = Utf8 SourceFile#92 = Utf8 Test.java#93 = NameAndType #47:#48 // "<init>":()V#94 = Utf8 java/io/File#95 = Utf8 C:\Users\XXXXXX\Desktop\dbData\goodsExtListUpdate.txt#96 = NameAndType #47:#141 // "<init>":(Ljava/lang/String;)V#97 = NameAndType #142:#143 // createNewFile:()Z#98 = Utf8 java/io/BufferedWriter#99 = Utf8 java/io/FileWriter#100 = NameAndType #47:#144 // "<init>":(Ljava/io/File;)V#101 = NameAndType #47:#145 // "<init>":(Ljava/io/Writer;)V#102 = NameAndType #71:#72 // readAndWrite:(ILjava/io/BufferedWriter;)V#103 = Utf8 java/lang/Exception#104 = NameAndType #146:#48 // flush:()V#105 = NameAndType #147:#48 // close:()V#106 = Utf8 C:\Users\XXXX\Desktop\dbData\goodsExtList.txt#107 = Utf8 java/io/InputStreamReader#108 = Utf8 java/io/FileInputStream#109 = Utf8 GBK#110 = NameAndType #47:#148 // "<init>":(Ljava/io/InputStream;Ljava/lang/String;)V#111 = Utf8 java/io/BufferedReader#112 = NameAndType #47:#149 // "<init>":(Ljava/io/Reader;)V#113 = Utf8#114 = NameAndType #150:#151 // readLine:()Ljava/lang/String;#115 = Utf8 java/lang/String#116 = NameAndType #152:#153 // getBytes:(Ljava/lang/String;)[B#117 = NameAndType #47:#154 // "<init>":([BLjava/lang/String;)V#118 = Utf8 hash#119 = NameAndType #155:#156 // contains:(Ljava/lang/CharSequence;)Z#120 = Utf8 CREATE TABLE `gold_pocket_goods_ext0` (#121 = Utf8 java/lang/StringBuilder#122 = NameAndType #157:#158 // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;#123 = Utf8 \n#124 = NameAndType #159:#151 // toString:()Ljava/lang/String;#125 = NameAndType #160:#141 // write:(Ljava/lang/String;)V#126 = Utf8 set @sharding = 'gold_pocket_goods_ext#127 = NameAndType #157:#161 // append:(I)Ljava/lang/StringBuilder;#128 = Utf8 ID hash ' ;#129 = Class #162 // java/lang/System#130 = NameAndType #62:#163 // out:Ljava/io/PrintStream;#131 = Class #164 // java/io/PrintStream#132 = NameAndType #165:#141 // println:(Ljava/lang/String;)V#133 = Utf8 CREATE TABLE `gold_pocket_goods_ext#134 = Utf8 ` (#135 = Utf8 java/lang/NullPointerException#136 = Utf8 test/Test#137 = Utf8 java/lang/Object#138 = Utf8 java/io/IOException#139 = Utf8 java/io/FileNotFoundException#140 = Utf8 java/io/UnsupportedEncodingException#141 = Utf8 (Ljava/lang/String;)V#142 = Utf8 createNewFile#143 = Utf8 ()Z#144 = Utf8 (Ljava/io/File;)V#145 = Utf8 (Ljava/io/Writer;)V#146 = Utf8 flush#147 = Utf8 close#148 = Utf8 (Ljava/io/InputStream;Ljava/lang/String;)V#149 = Utf8 (Ljava/io/Reader;)V#150 = Utf8 readLine#151 = Utf8 ()Ljava/lang/String;#152 = Utf8 getBytes#153 = Utf8 (Ljava/lang/String;)[B#154 = Utf8 ([BLjava/lang/String;)V#155 = Utf8 contains#156 = Utf8 (Ljava/lang/CharSequence;)Z#157 = Utf8 append#158 = Utf8 (Ljava/lang/String;)Ljava/lang/StringBuilder;#159 = Utf8 toString#160 = Utf8 write#161 = Utf8 (I)Ljava/lang/StringBuilder;#162 = Utf8 java/lang/System#163 = Utf8 Ljava/io/PrintStream;#164 = Utf8 java/io/PrintStream#165 = Utf8 println
{public test.Test();descriptor: ()Vflags: ACC_PUBLICCode:stack=1, locals=1, args_size=10: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: returnLineNumberTable:line 9: 0LocalVariableTable:Start Length Slot Name Signature0 5 0 this Ltest/Test;public static void main(java.lang.String[]) throws java.io.IOException;descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=5, locals=4, args_size=10: new #2 // class java/io/File3: dup4: ldc #3 // String C:\Users\XXXXXXX\Desktop\dbData\goodsExtListUpdate.txt6: invokespecial #4 // Method java/io/File."<init>":(Ljava/lang/String;)V9: astore_110: aload_111: invokevirtual #5 // Method java/io/File.createNewFile:()Z14: pop15: new #6 // class java/io/BufferedWriter18: dup19: new #7 // class java/io/FileWriter22: dup23: aload_124: invokespecial #8 // Method java/io/FileWriter."<init>":(Ljava/io/File;)V27: invokespecial #9 // Method java/io/BufferedWriter."<init>":(Ljava/io/Writer;)V30: astore_231: iconst_032: aload_233: invokestatic #10 // Method readAndWrite:(ILjava/io/BufferedWriter;)V36: goto 4839: astore_340: aload_241: invokevirtual #12 // Method java/io/BufferedWriter.flush:()V44: aload_245: invokevirtual #13 // Method java/io/BufferedWriter.close:()V48: returnException table:from to target type31 36 39 Class java/lang/ExceptionLineNumberTable:line 15: 0line 16: 10line 17: 15line 20: 31line 25: 36line 22: 39line 23: 40line 24: 44line 26: 48LocalVariableTable:Start Length Slot Name Signature40 8 3 e Ljava/lang/Exception;0 49 0 args [Ljava/lang/String;10 39 1 writename Ljava/io/File;31 18 2 out Ljava/io/BufferedWriter;StackMapTable: number_of_entries = 2frame_type = 255 /* full_frame */offset_delta = 39locals = [ class "[Ljava/lang/String;", class java/io/File, class java/io/BufferedWriter ]stack = [ class java/lang/Exception ]frame_type = 8 /* same */Exceptions:throws java.io.IOExceptionpublic static void readAndWrite(int, java.io.BufferedWriter) throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException, java.io.IOException;descriptor: (ILjava/io/BufferedWriter;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=5, locals=7, args_size=20: ldc #14 // String C:\Users\XXXXX\Desktop\dbData\goodsExtList.txt2: astore_23: new #2 // class java/io/File6: dup7: aload_28: invokespecial #4 // Method java/io/File."<init>":(Ljava/lang/String;)V11: astore_312: new #15 // class java/io/InputStreamReader15: dup16: new #16 // class java/io/FileInputStream19: dup20: aload_321: invokespecial #17 // Method java/io/FileInputStream."<init>":(Ljava/io/File;)V24: ldc #18 // String GBK26: invokespecial #19 // Method java/io/InputStreamReader."<init>":(Ljava/io/InputStream;Ljava/lang/String;)V29: astore 431: new #20 // class java/io/BufferedReader34: dup35: aload 437: invokespecial #21 // Method java/io/BufferedReader."<init>":(Ljava/io/Reader;)V40: astore 542: ldc #22 // String44: astore 646: aload 548: invokevirtual #23 // Method java/io/BufferedReader.readLine:()Ljava/lang/String;51: astore 653: aload 655: ifnull 27058: new #24 // class java/lang/String61: dup62: aload 564: invokevirtual #23 // Method java/io/BufferedReader.readLine:()Ljava/lang/String;67: ldc #18 // String GBK69: invokevirtual #25 // Method java/lang/String.getBytes:(Ljava/lang/String;)[B72: ldc #18 // String GBK74: invokespecial #26 // Method java/lang/String."<init>":([BLjava/lang/String;)V77: astore 679: aload 681: ldc #27 // String hash83: invokevirtual #28 // Method java/lang/String.contains:(Ljava/lang/CharSequence;)Z86: ifne 12389: aload 691: ldc #29 // String CREATE TABLE `gold_pocket_goods_ext0` (93: invokevirtual #28 // Method java/lang/String.contains:(Ljava/lang/CharSequence;)Z96: ifne 12399: aload_1100: new #30 // class java/lang/StringBuilder103: dup104: invokespecial #31 // Method java/lang/StringBuilder."<init>":()V107: aload 6109: invokevirtual #32 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;112: ldc #33 // String \n114: invokevirtual #32 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;117: invokevirtual #34 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;120: invokevirtual #35 // Method java/io/BufferedWriter.write:(Ljava/lang/String;)V123: aload 6125: ldc #27 // String hash127: invokevirtual #28 // Method java/lang/String.contains:(Ljava/lang/CharSequence;)Z130: ifeq 195133: iload_0134: ifeq 163137: new #30 // class java/lang/StringBuilder140: dup141: invokespecial #31 // Method java/lang/StringBuilder."<init>":()V144: ldc #36 // String set @sharding = 'gold_pocket_goods_ext146: invokevirtual #32 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;149: iload_0150: invokevirtual #37 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;153: ldc #38 // String ID hash ' ;155: invokevirtual #32 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;158: invokevirtual #34 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;161: astore 6163: getstatic #39 // Field java/lang/System.out:Ljava/io/PrintStream;166: aload 6168: invokevirtual #40 // Method java/io/PrintStream.println:(Ljava/lang/String;)V171: aload_1172: new #30 // class java/lang/StringBuilder175: dup176: invokespecial #31 // Method java/lang/StringBuilder."<init>":()V179: aload 6181: invokevirtual #32 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;184: ldc #33 // String \n186: invokevirtual #32 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;189: invokevirtual #34 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;192: invokevirtual #35 // Method java/io/BufferedWriter.write:(Ljava/lang/String;)V195: aload 6197: ldc #29 // String CREATE TABLE `gold_pocket_goods_ext0` (199: invokevirtual #28 // Method java/lang/String.contains:(Ljava/lang/CharSequence;)Z202: ifeq 53205: iload_0206: ifeq 235209: new #30 // class java/lang/StringBuilder212: dup213: invokespecial #31 // Method java/lang/StringBuilder."<init>":()V216: ldc #41 // String CREATE TABLE `gold_pocket_goods_ext218: invokevirtual #32 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;221: iload_0222: invokevirtual #37 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;225: ldc #42 // String ` (227: invokevirtual #32 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;230: invokevirtual #34 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;233: astore 6235: getstatic #39 // Field java/lang/System.out:Ljava/io/PrintStream;238: aload 6240: invokevirtual #40 // Method java/io/PrintStream.println:(Ljava/lang/String;)V243: aload_1244: new #30 // class java/lang/StringBuilder247: dup248: invokespecial #31 // Method java/lang/StringBuilder."<init>":()V251: aload 6253: invokevirtual #32 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;256: ldc #33 // String \n258: invokevirtual #32 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;261: invokevirtual #34 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;264: invokevirtual #35 // Method java/io/BufferedWriter.write:(Ljava/lang/String;)V267: goto 53270: goto 300273: astore_2274: iinc 0, 1277: iload_0278: sipush 512281: if_icmpge 292284: iload_0285: aload_1286: invokestatic #10 // Method readAndWrite:(ILjava/io/BufferedWriter;)V289: goto 300292: new #43 // class java/lang/NullPointerException295: dup296: invokespecial #44 // Method java/lang/NullPointerException."<init>":()V299: athrow300: returnException table:from to target type0 270 273 Class java/lang/NullPointerExceptionLineNumberTable:line 30: 0line 31: 3line 32: 12line 34: 31line 36: 42line 37: 46line 38: 53line 40: 58line 41: 79line 42: 99line 45: 123line 46: 133line 47: 137line 49: 163line 50: 171line 52: 195line 53: 205line 54: 209line 56: 235line 57: 243line 69: 270line 62: 273line 63: 274line 64: 277line 65: 284line 67: 292line 71: 300LocalVariableTable:Start Length Slot Name Signature3 267 2 pathname Ljava/lang/String;12 258 3 filename Ljava/io/File;31 239 4 reader Ljava/io/InputStreamReader;42 228 5 br Ljava/io/BufferedReader;46 224 6 line Ljava/lang/String;274 26 2 nullPoint Ljava/lang/NullPointerException;0 301 0 i I0 301 1 out Ljava/io/BufferedWriter;StackMapTable: number_of_entries = 9frame_type = 255 /* full_frame */offset_delta = 53locals = [ int, class java/io/BufferedWriter, class java/lang/String, class java/io/File, class java/io/InputStreamReader, class java/io/BufferedReader, class java/lang/String ]stack = []frame_type = 251 /* same_frame_extended */offset_delta = 69frame_type = 39 /* same */frame_type = 31 /* same */frame_type = 39 /* same */frame_type = 255 /* full_frame */offset_delta = 34locals = [ int, class java/io/BufferedWriter ]stack = []frame_type = 66 /* same_locals_1_stack_item */stack = [ class java/lang/NullPointerException ]frame_type = 252 /* append */offset_delta = 18locals = [ class java/lang/NullPointerException ]frame_type = 250 /* chop */offset_delta = 7Exceptions:throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException, java.io.IOException
}
SourceFile: "Test.java"
四、解析内容讲解
1、字节码文件信息
开头的7行信息包括:Class文件当前所在位置,最后修改时间,文件大小,MD5值,编译自哪个文件,类的全限定名,jdk次版本号,主版本号。 然后紧接着的是该类的访问标志:ACC_PUBLIC, ACC_SUPER,访问标志的含义如下:
2、常量池信息
截取部分内容对比原代码红色框内容
在常量池中,该段代码分布情况。
Constant pool:#1 = Methodref #46.#93 // java/lang/Object."<init>":()V#2 = Class #94 // java/io/File#3 = String #95 // C:\Users\XXXXXX\Desktop\dbData\goodsExtListUpdate.txt
第一个常量是一个方法定义,指向了第46和第93个常量。以此类推查看第46和第93个常量。
最后可以拼接成第一个常量右侧的注释内容:
java/lang/Object."<init>":()V
这段可以理解为该类的实例构造器的声明,由于Main类没有重写构造方法,所以调用的是父类的构造方法。此处也说明了Main类的直接父类是Object。 该方法默认返回值是V, 也就是void,无返回值。
对于后面的V
对于数组类型,每一位使用一个前置的"[“字符来描述,如定义一个java.lang.String[][]类型的维数组,将被记录为”[[Ljava/lang/String;"
3、内容的拆分先提下字段的含义:
对于类的字段access_flags标识有如下几个含义
对于方法access_flags标识有如下几个含义
属性预定义的标识有如下定义:
4、对于本文demo中属性结构如下:
descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:Exception table:LineNumberTable:LocalVariableTable:StackMapTable: number_of_entries = 2Exceptions:
5、那么code的内容结构是什么样的?
这里重点说明一点code_length,同事一个u4类型的长度值,理论上最大值可以达到2^32-1,但是虚拟机中限制了一个方法长度不允许超过65535条字节码指令。如果不是刻意的话,或者复杂的Jsp文件的话,那么应该不会导致编译失败。
LineNumberTable
该属性的作用是描述源码行号与字节码行号(字节码偏移量)之间的对应关系。可以使用 -g:none 或-g:lines选项来取消或要求生成这项信息,如果选择不生成LineNumberTable,当程序运行异常时将无法获取到发生异常的源码行号,也无法按照源码的行数来调试程序。LocalVariableTable
该属性的作用是描述帧栈中局部变量与源码中定义的变量之间的关系。可以使用 -g:none 或 -g:vars来取消或生成这项信息,如果没有生成这项信息,那么当别人引用这个方法时,将无法获取到参数名称,取而代之的是arg0, arg1这样的占位符。
在这里需要引入的另外一个LocalVariableTypeTable。仅仅是把记录的字段描述符的descriptior_index替换成了字段的特征签名
(Signature)由于描述附中泛型的参数化类型被擦除掉,描述符就不能准确描述泛型类型了,所以才需要这个变量属性LocalVariableTypeTable。对于非泛型类型来说,描述符合特征签名描述的信息基本一致。
5.1异常表的属性结构:
引入深入理解Java虚拟机中的案例如下
我们这里的代码demo示例如下
public static void main(java.lang.String[]) throws java.io.IOException;descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=5, locals=4, args_size=10: new #2 // class java/io/File3: dup4: ldc #3 // String C:\Users\liuxiaocheng\Desktop\dbData\goodsExtListUpdate.txt6: invokespecial #4 // Method java/io/File."<init>":(Ljava/lang/String;)V9: astore_110: aload_111: invokevirtual #5 // Method java/io/File.createNewFile:()Z14: pop15: new #6 // class java/io/BufferedWriter18: dup19: new #7 // class java/io/FileWriter22: dup23: aload_124: invokespecial #8 // Method java/io/FileWriter."<init>":(Ljava/io/File;)V27: invokespecial #9 // Method java/io/BufferedWriter."<init>":(Ljava/io/Writer;)V30: astore_231: iconst_032: aload_233: invokestatic #10 // Method readAndWrite:(ILjava/io/BufferedWriter;)V36: goto 4839: astore_340: aload_241: invokevirtual #12 // Method java/io/BufferedWriter.flush:()V44: aload_245: invokevirtual #13 // Method java/io/BufferedWriter.close:()V48: returnException table:from to target type31 36 39 Class java/lang/ExceptionLineNumberTable:line 15: 0line 16: 10line 17: 15line 20: 31line 25: 36line 22: 39line 23: 40line 24: 44line 26: 48LocalVariableTable:Start Length Slot Name Signature40 8 3 e Ljava/lang/Exception;0 49 0 args [Ljava/lang/String;10 39 1 writename Ljava/io/File;31 18 2 out Ljava/io/BufferedWriter;StackMapTable: number_of_entries = 2frame_type = 255 /* full_frame */offset_delta = 39locals = [ class "[Ljava/lang/String;", class java/io/File, class java/io/BufferedWriter ]stack = [ class java/lang/Exception ]frame_type = 8 /* same */Exceptions:throws java.io.IOException
stack
最大操作数栈,JVM运行时会根据这个值来分配栈帧(Frame)中的操作栈深度,此处为1locals:
局部变量所需的存储空间,单位为Slot, Slot是虚拟机为局部变量分配内存时所使用的最小单位,为4个字节大小。方法参数(包括实例方法中的隐藏参数this),显示异常处理器的参数(try catch中的catch块所定义的异常),方法体中定义的局部变量都需要使用局部变量表来存放。值得一提的是,locals的大小并不一定等于所有局部变量所占的Slot之和,因为局部变量中的Slot是可以重用的。args_size:
方法参数的个数,这里是1,因为每个实例方法都会有一个隐藏参数this,如果方法声明为static 那么这里就会显示为0
start 表示该局部变量在哪一行开始可见,length表示可见行数,Slot(虚拟机为局部变量分配内存所使用的最小单位,对于byte,char,float,int ,short,boolean,和returnAddress等长度不超过32位的数据类型,每个局部变量占用1个Slot,而double和long这两种64位的数据类型则需要两个Slot来存放),Name是变量名称,然后是类型签名。
StackMapTable:
这个属性在虚拟机类加载的字节码验证阶段被新类型检查验证器(Type Checker)使用,目的在于代替以前比较消耗性能的基于数据流分析的类型推导验证器。一个方法的code属性最多只能有一个StackMapTable属性,否则抛出ClassFormatError异常。Exception table:异常表实际上是Java代码的一部分,编译器使用异常表而不是简单的跳转命令来实现Java异常及finally处理机制Exceptions:与异常表不一样,这里是在方法throws抛出的时候列举的异常Signature:
在任何类,接口,初始化方法或成员的泛型签名如果包含了类型变量(Type Variables)或参数化类型(Parameterized Types),则Signature属性为他记录泛型签名信息,之所以专门使用这样的一个属性去记录泛型类型,是因为Java语言的泛型采用的是擦除法实现的伪泛型。
Signature结构如下:
signature_index项的值必须是一个对常量池的有效索引。常量池在该索引处的项必须是CONSTANT_Utf8_info结构,标识类签名,表示类签名、方法类型签名或字段类型签名。
StackMapTable结构如下:
SourceFile: "Test.java"
用于记录生成这个Class文件的源码文件名称,可选。
可以使用 -g:none 或-g:sources选项来取消或要求生成这项信息,
我们这里没有提到的还有常量和内部类属性
常量ConstantValue属性结构
InnerClasses内部类属性结构
number_of_classes
inner_class_access_flags
Deprecated和Synthetic属性
BootstrapMethods属性
bootstrap_method
bootstrap_methods[]数组中每个成员都需要包含的内容如下
JVM---数据存储和访问(类文件结构)相关推荐
- JVM学习笔记(Ⅰ):Class类文件结构解析(带你读懂Java字节码,这一篇就够了)
JVM学习笔记(Ⅰ):Class类文件结构解析,带你读懂Java字节码 前言:本文属于博主个人的学习笔记,博主也是小白.如果有不对的地方希望各位帮忙指出.本文主要还是我的学习总结,因为网上的一些知识分 ...
- 数据存储与访问之——初见SQLite数据库
本节引言: 本节我们继续来学习Android数据存储与访问的第三种方式:SQLite数据库,和其他的SQL数据库不同, 我们并不需要在手机上另外安装一个数据库软件,Android系统已经集成了这个数据 ...
- Android基础入门教程——6.2 数据存储与访问之——SharedPreferences保存用户偏好参数
Android基础入门教程--6.2 数据存储与访问之--SharedPreferences保存用户偏好参数 标签(空格分隔): Android基础入门教程 本节引言: 本节给大家介绍的是第二种存储用 ...
- Android数据存储与访问(10级学员张晓丛)
一. 数据存储与访问 Android为数据存数提供了多种方式: 1> 文件 2> SharedPreferences 3> SQLite数据库 4> 内容提供者 ...
- android中资源文件的两种访问方式,在android开发中进行数据存储与访问的多种方式介绍...
在android开发中进行数据存储与访问的多种方式介绍 更新时间:2013年06月07日 16:24:23 作者: 很多时候我们的软件需要对处理后的数据进行存储或再次访问,Android为数据存储 ...
- Android学习笔记---android数据存储与访问
数据存储与访问 --------------------------------------- 一个在手机和sd卡上存储文件的例子 1.a.文件名称:lable b.一个text框 c.文件内 ...
- 深入理解JVM虚拟机(四):Class类文件结构(一)
我们都知道Java中的class文件是经过Java编译器对Java类文件进行编译后的产物.我想有不在少数的C程序员在学习Java之后在认知上会粗略的认为C程序在经过编译后产生的.out文件与.clas ...
- JVM(五):类文件结构
平台无关性 Class类文件的结构 Class的数据类型 无符号数 表 魔数与Class文件的版本 常量池 CONSTANT_Class_info CONSTANT_Utf8_info CONSTAN ...
- 【转】 [Unity3D]手机3D游戏开发:场景切换与数据存储(PlayerPrefs 类的介绍与使用)...
http://blog.csdn.net/pleasecallmewhy/article/details/8543181 在Unity中的数据存储和iOS中字典的存储基本相同,是通过关键字实现数据存储 ...
- Android数据存储与访问
很多时候我们的软件需要对处理后的数据进行存储或再次访问.Android为数据存储提供了如下几种方式: 文件 SharedPreferences(参数) SQLite数据库 内容提供者(Content ...
最新文章
- Java 9推迟6个月发布?
- Python3搭建Django框架浅析
- 使用Codeception进行Yii2的单元测试(一)安装以及简介篇
- 应用调试(四)系统调用SWI
- Envoy为什么能战胜Ngnix——线程模型分析篇
- jenkins-系统管理-节点管理进去报错
- 【LeetCode】【HOT 100】2. 两数相加
- ASP.NET 3.5中客户端回发及回调
- 《强化学习》中的第10章:基于函数逼近的同轨策略控制
- Security+ 学习笔记14 对称密码学
- 9.2. service
- 论文-公式对齐和右侧自动编号
- LearnOpenGL 模型加载—Assimp
- 微信开放平台 公众号第三方平台开发 教程二 创建公众号第三方平台
- [Matlab科学计算] 四阶Runge-Kutta法解常微分方程
- php完全开发手册下载,thinkphp5完全开发手册
- 使用ipv6内网穿透,实现私有云盘搭建,实现远程控制等功能
- Python 基础:04 容器类型
- 2023寒假模拟赛1题解
- 超级电视与海信电视争第一,这是一场胜负已定的战争
热门文章
- wincc逻辑运算符_工控随笔_11_西门子_WinCC的VBS脚本_02_运算符
- 2020CCPC绵阳站 D-Defuse the Bombs (二分答案)
- 干货!容忍数据缺失的临床超声报告知识图谱乳腺癌诊断
- ViewFlipper和ViewPager
- iOS之TabbarController和NavigationController框架
- [初学Spring Boot](1):打不开localhost:8080/hello
- 华为开源数据库openGauss
- 学java难不难?java应该怎么学?
- Vue.js 实战总结
- 你有花生我有酒,一本学道看一天(二)