java类索引_《Java虚拟机原理图解》1.3、class文件中的访问标志、类索引、父类索引、接口索引集合...
講完了class文件中的常量池,我們就相當(dāng)于克服了class文件中最麻煩的模塊了。現(xiàn)在,我們來看一下class文件中緊接著常量池后面的幾個東西:訪問標(biāo)志、類索引、父類索引、接口索引集合。
1. 訪問標(biāo)志、類索引、父類索引、接口索引集合 在class文件中的位置
好,讓我們來一一擊破它們,看看它們到底是什么東西。
2. 訪問標(biāo)志(access_flags)能夠表示什么?
訪問標(biāo)志(access_flags)緊接著常量池后,占有兩個字節(jié),總共16位,如下圖所示:
當(dāng)JVM在編譯某個類或者接口的源代碼時,JVM會解析出這個類或者接口的訪問標(biāo)志信息,然后,將這些標(biāo)志設(shè)置到訪問標(biāo)志(access_flags)這16個位上。JVM會考慮如下設(shè)置如下訪問表示信息:
a. 我們知道,每個定義的類或者接口都會生成class文件(這里也包括內(nèi)部類,在某個類中定義的靜態(tài)內(nèi)部類也會單獨生成一個class文件)。
對于定義的類,JVM在將其編譯成class文件時,會將class文件的訪問標(biāo)志的第11位設(shè)置為1。第11位叫做ACC_SUPER標(biāo)志位;
對于定義的接口,JVM在將其編譯成class文件時,會將class文件的訪問標(biāo)志的第8位 設(shè)置為?1。第8位叫做ACC_INTERFACE標(biāo)志位;
b.?class文件表示的類或者接口的訪問權(quán)限有public類型的和包package類型的。
如果類或者接口被聲明為public類型的,那么,JVM將其編譯成class文件時,會將class文件的訪問標(biāo)志的第16位設(shè)置為1。第16位叫做ACC_PUBLIC標(biāo)志符;
c. 類是否為抽象類型的,即我們定義的類有沒有被abstract關(guān)鍵字修飾,即我們定義的類是否為抽象類。
如果我們形如:
public??abstract??class?MyClass{......}
定義某個類時,JVM將它編譯成class文件的時候,會將class文件的訪問標(biāo)志的第7位設(shè)置為1。第7位叫做ACC_ABSTRACT標(biāo)志位。 另外值得注意的是,對于定義的接口,JVM在編譯接口的時候也會對class文件的訪問標(biāo)志上的ACC_ABSTRACT標(biāo)志位設(shè)置為1;
d.?該類是否被聲明了final類型,即表示該類不能被繼承。
此時JVM會在編譯class文件的過程中,會將class文件的訪問標(biāo)志的第12位設(shè)置為1。第12位叫做ACC_FINAL標(biāo)志位;
e.如果我們這個class文件不是JVM通過Java源代碼文件編譯而成的,而是用戶自己通過class文件的組織規(guī)則生成的,那么,一般會對class文件的訪問標(biāo)志第4位設(shè)置為1。通過JVM編譯源代碼產(chǎn)生的class文件此標(biāo)志位為0,第4位叫做ACC_SYNTHETIC標(biāo)志位;
f.枚舉類,對于定義的枚舉類如:public enum EnumTest{....},JVM也會對此枚舉類編譯成class文件,這時,對于這樣的class文件,JVM會對訪問標(biāo)志第2位設(shè)置為1,以表示它是枚舉類。第2位叫做ACC_ENUM標(biāo)志位;
g.?注解類,對于定義的注解類如:public @interface{.....},JVM會對此注解類編譯成class文件,對于這樣的class文件,JVM會將訪問標(biāo)志第3位設(shè)置為1,以表示這是個注解類,第3位叫做ACC_ANNOTATION標(biāo)志位。
當(dāng)JVM確定了上述標(biāo)志位的值后,就可以確定訪問標(biāo)志(access_flags)的值了。實際上JVM上述標(biāo)志會根據(jù)上述確定的標(biāo)志位的值,對這些標(biāo)志位的值取或,便得到了訪問標(biāo)志(access_flags)。如下圖所示:
舉例:定義一個最簡單的類Simple.java,使用編譯器編譯成class文件,然后觀察class文件中的訪問標(biāo)志的值,以及使用javap -v Simple 查看訪問標(biāo)志。
package?com.louis.jvm;
public?class?Simple?{
}
使用UltraEdit查看編譯成的class文件,如下圖所示:
上述的圖中黃色部分表示的是常量池部分,具體為什么是常量池部分不是本文的重點,有興趣的讀者可以參考我的《Java虛擬機原理圖解》系列關(guān)于常量池的博客,你就可以很輕松地識別常量它們了。
常量池后面緊跟著就是訪問標(biāo)志,它的十六進(jìn)制值為0x0021,二進(jìn)制的值為:00000000 00100001,由二進(jìn)制的1的位數(shù)可以得出第11、16位為1,分別對應(yīng)ACC_SUPER標(biāo)志位和ACC_PUBLIC標(biāo)志位。
也可以通過一下運算:
0x0021 = 0x0001 | 0x0020,? 即:?? 訪問標(biāo)志表示的標(biāo)志是ACC_PUBLIC + ACC_SUPER
為了驗證我們的運算,使用javap -v Simple查看反編譯信息如下:(小技巧:使用javap -v Simple指令的結(jié)果展示在命令提示符下顯示不友好,一般我是使用javap -v Simple > temp.txt,將結(jié)果重定向到文件中,然后查看文件)
3. 類索引(this_class)是什么?
我們知道一般情況下一個Java類源文件經(jīng)過JVM編譯會生成一個class文件,也有可能一個Java類源文件中定義了其他類或者內(nèi)部類,這樣編譯出來的class文件就不止一個,但每一個class文件表示某一個類,至于這個class表示哪一個類,便可以通過 類索引 這個數(shù)據(jù)項來確定。JVM通過類的完全限定名確定是某一個類。
類索引的作用,就是為了指出class文件所描述的這個類叫什么名字。
類索引緊接著訪問標(biāo)志的后面,占有兩個字節(jié),在這兩個字節(jié)中存儲的值是一個指向常量池的一個索引,該索引指向的是CONSTANT_Class_info常量池項,
以上面定義的Simple.class 為例,如下圖所示,查看他的類索引在什么位置和取什么值。
由上可知,它的類索引值為0x0001,那么,它指向了常量池中的第一個常量池項,那我們再看一下常量池中的信息。使用javap -v Simple,常量池中有以下信息:
可以看到常量池中的第一項是CONSTANT_Class_info項,它表示一個"com/louis/jvm/Simple"的類名。即類索引是告訴我們這個class文件所表示的是哪一個類。
3. 父類索引(super_class)是什么?
Java支持單繼承模式,除了java.lang.Object 類除外,每一個類都會有且只有一個父類。class文件中緊接著類索引(this_class)之后的兩個字節(jié)區(qū)域表示父類索引,跟類索引一樣,父類索引這兩個字節(jié)中的值指向了常量池中的某個常量池項CONSTANT_Class_info,表示該class表示的類是繼承自哪一個類。
4. 接口索引集合(interfaces)是什么?
一個類可以不實現(xiàn)任何接口,也可以實現(xiàn)很多個接口,為了表示當(dāng)前類實現(xiàn)的接口信息,class文件使用了如下結(jié)構(gòu)體描述某個類的接口實現(xiàn)信息:
由于類實現(xiàn)的接口數(shù)目不確定,所以接口索引集合的描述的前部分叫做接口計數(shù)器(interfaces_count),接口計數(shù)器占用兩個字節(jié),其中的值表示著這個類實現(xiàn)了多少個接口,緊跟著接口計數(shù)器的部分就是接口索引部分了,每一個接口索引占有兩個字節(jié),接口計數(shù)器的值代表著后面跟著的接口索引的個數(shù)。接口索引和類索引和父類索引一樣,其內(nèi)的值存儲的是指向了常量池中的常量池項的索引,表示著這個接口的完全限定名。
舉例:
定義一個Worker接口,然后類Programmer實現(xiàn)這個Worker接口,然后我們觀察Programmer的接口索引集合是怎樣表示的。
/**
*?Worker?接口類
*?@author?luan?louis
*/
public?interface?Worker{
public?void?work();
}
package?com.louis.jvm;
public?class?Programmer?implements?Worker?{
@Override
public?void?work()?{
System.out.println("I'm?Programmer,Just?coding....");
}
}
總結(jié)
以上是生活随笔為你收集整理的java类索引_《Java虚拟机原理图解》1.3、class文件中的访问标志、类索引、父类索引、接口索引集合...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 获取中位数java_java 计算中位
- 下一篇: java中mvc事务_关于项目中的事务问