日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

java类索引_《Java虚拟机原理图解》1.3、class文件中的访问标志、类索引、父类索引、接口索引集合...

發(fā)布時(shí)間:2024/4/19 java 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java类索引_《Java虚拟机原理图解》1.3、class文件中的访问标志、类索引、父类索引、接口索引集合... 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

講完了class文件中的常量池,我們就相當(dāng)于克服了class文件中最麻煩的模塊了。現(xiàn)在,我們來(lái)看一下class文件中緊接著常量池后面的幾個(gè)東西:訪問(wèn)標(biāo)志、類索引、父類索引、接口索引集合。

1. 訪問(wèn)標(biāo)志、類索引、父類索引、接口索引集合 在class文件中的位置

好,讓我們來(lái)一一擊破它們,看看它們到底是什么東西。

2. 訪問(wèn)標(biāo)志(access_flags)能夠表示什么?

訪問(wèn)標(biāo)志(access_flags)緊接著常量池后,占有兩個(gè)字節(jié),總共16位,如下圖所示:

當(dāng)JVM在編譯某個(gè)類或者接口的源代碼時(shí),JVM會(huì)解析出這個(gè)類或者接口的訪問(wèn)標(biāo)志信息,然后,將這些標(biāo)志設(shè)置到訪問(wèn)標(biāo)志(access_flags)這16個(gè)位上。JVM會(huì)考慮如下設(shè)置如下訪問(wèn)表示信息:

a. 我們知道,每個(gè)定義的類或者接口都會(huì)生成class文件(這里也包括內(nèi)部類,在某個(gè)類中定義的靜態(tài)內(nèi)部類也會(huì)單獨(dú)生成一個(gè)class文件)。

對(duì)于定義的類,JVM在將其編譯成class文件時(shí),會(huì)將class文件的訪問(wèn)標(biāo)志的第11位設(shè)置為1。第11位叫做ACC_SUPER標(biāo)志位;

對(duì)于定義的接口,JVM在將其編譯成class文件時(shí),會(huì)將class文件的訪問(wèn)標(biāo)志的第8位 設(shè)置為?1。第8位叫做ACC_INTERFACE標(biāo)志位;

b.?class文件表示的類或者接口的訪問(wèn)權(quán)限有public類型的和包package類型的。

如果類或者接口被聲明為public類型的,那么,JVM將其編譯成class文件時(shí),會(huì)將class文件的訪問(wèn)標(biāo)志的第16位設(shè)置為1。第16位叫做ACC_PUBLIC標(biāo)志符;

c. 類是否為抽象類型的,即我們定義的類有沒(méi)有被abstract關(guān)鍵字修飾,即我們定義的類是否為抽象類。

如果我們形如:

public??abstract??class?MyClass{......}

定義某個(gè)類時(shí),JVM將它編譯成class文件的時(shí)候,會(huì)將class文件的訪問(wèn)標(biāo)志的第7位設(shè)置為1。第7位叫做ACC_ABSTRACT標(biāo)志位。 另外值得注意的是,對(duì)于定義的接口,JVM在編譯接口的時(shí)候也會(huì)對(duì)class文件的訪問(wèn)標(biāo)志上的ACC_ABSTRACT標(biāo)志位設(shè)置為1;

d.?該類是否被聲明了final類型,即表示該類不能被繼承。

此時(shí)JVM會(huì)在編譯class文件的過(guò)程中,會(huì)將class文件的訪問(wèn)標(biāo)志的第12位設(shè)置為1。第12位叫做ACC_FINAL標(biāo)志位;

e.如果我們這個(gè)class文件不是JVM通過(guò)Java源代碼文件編譯而成的,而是用戶自己通過(guò)class文件的組織規(guī)則生成的,那么,一般會(huì)對(duì)class文件的訪問(wèn)標(biāo)志第4位設(shè)置為1。通過(guò)JVM編譯源代碼產(chǎn)生的class文件此標(biāo)志位為0,第4位叫做ACC_SYNTHETIC標(biāo)志位;

f.枚舉類,對(duì)于定義的枚舉類如:public enum EnumTest{....},JVM也會(huì)對(duì)此枚舉類編譯成class文件,這時(shí),對(duì)于這樣的class文件,JVM會(huì)對(duì)訪問(wèn)標(biāo)志第2位設(shè)置為1,以表示它是枚舉類。第2位叫做ACC_ENUM標(biāo)志位;

g.?注解類,對(duì)于定義的注解類如:public @interface{.....},JVM會(huì)對(duì)此注解類編譯成class文件,對(duì)于這樣的class文件,JVM會(huì)將訪問(wèn)標(biāo)志第3位設(shè)置為1,以表示這是個(gè)注解類,第3位叫做ACC_ANNOTATION標(biāo)志位。

當(dāng)JVM確定了上述標(biāo)志位的值后,就可以確定訪問(wèn)標(biāo)志(access_flags)的值了。實(shí)際上JVM上述標(biāo)志會(huì)根據(jù)上述確定的標(biāo)志位的值,對(duì)這些標(biāo)志位的值取或,便得到了訪問(wèn)標(biāo)志(access_flags)。如下圖所示:

舉例:定義一個(gè)最簡(jiǎn)單的類Simple.java,使用編譯器編譯成class文件,然后觀察class文件中的訪問(wèn)標(biāo)志的值,以及使用javap -v Simple 查看訪問(wèn)標(biāo)志。

package?com.louis.jvm;

public?class?Simple?{

}

使用UltraEdit查看編譯成的class文件,如下圖所示:

上述的圖中黃色部分表示的是常量池部分,具體為什么是常量池部分不是本文的重點(diǎn),有興趣的讀者可以參考我的《Java虛擬機(jī)原理圖解》系列關(guān)于常量池的博客,你就可以很輕松地識(shí)別常量它們了。

常量池后面緊跟著就是訪問(wèn)標(biāo)志,它的十六進(jìn)制值為0x0021,二進(jìn)制的值為:00000000 00100001,由二進(jìn)制的1的位數(shù)可以得出第11、16位為1,分別對(duì)應(yīng)ACC_SUPER標(biāo)志位和ACC_PUBLIC標(biāo)志位。

也可以通過(guò)一下運(yùn)算:

0x0021 = 0x0001 | 0x0020,? 即:?? 訪問(wèn)標(biāo)志表示的標(biāo)志是ACC_PUBLIC + ACC_SUPER

為了驗(yàn)證我們的運(yùn)算,使用javap -v Simple查看反編譯信息如下:(小技巧:使用javap -v Simple指令的結(jié)果展示在命令提示符下顯示不友好,一般我是使用javap -v Simple > temp.txt,將結(jié)果重定向到文件中,然后查看文件)

3. 類索引(this_class)是什么?

我們知道一般情況下一個(gè)Java類源文件經(jīng)過(guò)JVM編譯會(huì)生成一個(gè)class文件,也有可能一個(gè)Java類源文件中定義了其他類或者內(nèi)部類,這樣編譯出來(lái)的class文件就不止一個(gè),但每一個(gè)class文件表示某一個(gè)類,至于這個(gè)class表示哪一個(gè)類,便可以通過(guò) 類索引 這個(gè)數(shù)據(jù)項(xiàng)來(lái)確定。JVM通過(guò)類的完全限定名確定是某一個(gè)類。

類索引的作用,就是為了指出class文件所描述的這個(gè)類叫什么名字。

類索引緊接著訪問(wèn)標(biāo)志的后面,占有兩個(gè)字節(jié),在這兩個(gè)字節(jié)中存儲(chǔ)的值是一個(gè)指向常量池的一個(gè)索引,該索引指向的是CONSTANT_Class_info常量池項(xiàng),

以上面定義的Simple.class 為例,如下圖所示,查看他的類索引在什么位置和取什么值。

由上可知,它的類索引值為0x0001,那么,它指向了常量池中的第一個(gè)常量池項(xiàng),那我們?cè)倏匆幌鲁A砍刂械男畔ⅰJ褂胘avap -v Simple,常量池中有以下信息:

可以看到常量池中的第一項(xiàng)是CONSTANT_Class_info項(xiàng),它表示一個(gè)"com/louis/jvm/Simple"的類名。即類索引是告訴我們這個(gè)class文件所表示的是哪一個(gè)類。

3. 父類索引(super_class)是什么?

Java支持單繼承模式,除了java.lang.Object 類除外,每一個(gè)類都會(huì)有且只有一個(gè)父類。class文件中緊接著類索引(this_class)之后的兩個(gè)字節(jié)區(qū)域表示父類索引,跟類索引一樣,父類索引這兩個(gè)字節(jié)中的值指向了常量池中的某個(gè)常量池項(xiàng)CONSTANT_Class_info,表示該class表示的類是繼承自哪一個(gè)類。

4. 接口索引集合(interfaces)是什么?

一個(gè)類可以不實(shí)現(xiàn)任何接口,也可以實(shí)現(xiàn)很多個(gè)接口,為了表示當(dāng)前類實(shí)現(xiàn)的接口信息,class文件使用了如下結(jié)構(gòu)體描述某個(gè)類的接口實(shí)現(xiàn)信息:

由于類實(shí)現(xiàn)的接口數(shù)目不確定,所以接口索引集合的描述的前部分叫做接口計(jì)數(shù)器(interfaces_count),接口計(jì)數(shù)器占用兩個(gè)字節(jié),其中的值表示著這個(gè)類實(shí)現(xiàn)了多少個(gè)接口,緊跟著接口計(jì)數(shù)器的部分就是接口索引部分了,每一個(gè)接口索引占有兩個(gè)字節(jié),接口計(jì)數(shù)器的值代表著后面跟著的接口索引的個(gè)數(shù)。接口索引和類索引和父類索引一樣,其內(nèi)的值存儲(chǔ)的是指向了常量池中的常量池項(xiàng)的索引,表示著這個(gè)接口的完全限定名。

舉例:

定義一個(gè)Worker接口,然后類Programmer實(shí)現(xiàn)這個(gè)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文件中的访问标志、类索引、父类索引、接口索引集合...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。