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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JVM Class详解之一

發布時間:2025/3/21 编程问答 58 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JVM Class详解之一 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

首先看Class中包含哪些信息簡單的說所有java文件中有的信息class文件都有,編譯器幫我們將java文件轉化成了JVM能看懂的class格式而已

Class 概述

Class文件是一組以8位字節為基礎的二進制流,各個數據項目按照嚴格順序緊湊排列在Class文件中。
所有的16位,32位,64位長度的數據將被構造成2個,4個,8個字節單位來標示。

ClassFile結構

類型 名稱 數量
u4 magic 1
u2 minor_version 1
u2 major_version 1
u2 constant_pool_count 1
cp_info constant_pool constant_pool_count-1
u2 access_flags 1
u2 this_class 1
u2 super_class 1
u2 interfaces_count 1
u2 interfaces interfaces_count
u2 fields_count 1
field_info fields fields_count
u2 methods_count 1
method_info methods methods_count
u2 attributes_count 1
attribute_info attributes attributes_count

class格式說明

  • magic:魔數,魔數的唯一作用是確定這個文件是否為一個能被虛擬機所接受的Class文件。魔數值固定為0xCAFEBABE
  • minor_version、major_version: 分別為Class文件的副版本和主版本
  • constant_pool_count: 常量池計數器,constant_pool_count的值等于constant_pool表中的成員數加1
  • constant_pool[]: 常量池,constant_pool是一種表結構,它包含Class文件結構及其子結構中引用的所有字符串常量、類或接口名、字段名和其它常量。常量池不同于其他,索引從1開始到constant_pool_count?-1
  • access_flags: 訪問標志,access_flags是一種掩碼標志,用于表示某個類或者接口的訪問權限及基礎屬性
  • this_class: 類索引,this_class的值必須是對constant_pool表中項目的一個有效索引值
  • super_class: 父類索引
  • interfaces_count: 接口計數器,interfaces_count的值表示當前類或接口的直接父接口數量
  • interfaces[]: 接口表,interfaces[]數組中的每個成員的值必須是一個對constant_pool表中項目的一個有效索引值,它的長度為interfaces_count
  • fields_count: 字段計數器
  • fields[]: 字段表,fields[]數組中的每個成員都必須是一個fields_info結構的數據項
  • methods_count: 方法計數器
  • methods[]: 方法表,methods[]數組中的每個成員都必須是一個method_info結構的數據項
  • attributes_count: 屬性計數器
  • attributes[]: 屬性表,attributes表的每個項的值必須是attribute_info結構

廢話不多說HelloWorld搞起

public class HelloWorld { String str = "";public String getStr() { return str; }public void setStr(String str) { this.str = str; } }

編譯成class文件以后,只用javap -verbose HelloWorld.class 指令可以查看當前class的內容

同時使用UE打開class文件

我們來一起看下ClassFile結構

前4個字節為魔數,也就是0xCAFEBABE,這里都是十六進制

魔數后2個字節為副版本號,這里副版本號是0

主版本號0x0033,轉為十進制,主版本號是51 標示當前class是通過jdk 1.7編譯的,0x32是jdk1.6 0x31是jdk1.5

這兩個字節是常量池計數器,常量池的數量為0x001A,轉為十進制是26,也就是說常量池索引為1~26

從常量池開始

常量池計數器后面緊跟著就是常量池的內容
所有的常量池項都具有如下通用格式:

cp_info { u1 tag; u1 info[]; } CONSTANT_Class_info { u1 tag; u2 name_index; } CONSTANT_Fieldref_info { u1 tag; u2 class_index; u2 name_and_type_index; } CONSTANT_Methodref_info { u1 tag; u2 class_index; u2 name_and_type_index; } CONSTANT_InterfaceMethodref_info { u1 tag; u2 class_index; u2 name_and_type_index; } CONSTANT_NameAndType_info { u1 tag; u2 name_index; u2 descriptor_index; } CONSTANT_Utf8_info { u1 tag; u2 length; u1 bytes[length]; } CONSTANT_MethodHandle_info { u1 tag; u1 reference_kind; u2 reference_index; }


后面的0x07對應tag找到是CONSTANT_Class,標示接下來的是一個class的信息。后面的 00 02 是class的name_index 標示指向常量池的第二個常量。我們再看第二個常量

第二個常量是01開頭,我們查看常量類型表中對應是Utf-8,再按照utf-8的結構,后面的00 0A代表了這個utf-8的長度這里長度轉換為10進制是11,后面緊跟著utf-8的實際內容


再后面0x 07,是常量池的下一個產量,也是一個class信息,后面跟00 04,name_index執行常量池的
第4個常量。

第4個常量又是utf-8,后面長度為 0x10 十進制為16,接下來的為實際內容

接下來都可以按照此方法分析。
直觀結果可以通過javap指令查看


常量池后面緊跟的2個字節是Access Flag,這個表示用于標示類或接口層次的訪問信息,如這個Class是類還是接口,是否為public類型,是否定義為abstrace類型。
標志名稱 標志值 含義
ACC_PUBLIC 0x0001 是否為public類型
ACC_FINAL 0x0010 是否被聲明為final,只有類可設置
ACC_SUPER 0x0020 是否允許使用invokespecial字節碼指令,JDK1.2以后編譯出來的類這個標志為真
ACC_INTERFACE 0x0200 標識這是一個接口
ACC_ABSTRACT 0x0400 是否為abstract類型,對于接口和抽象類,此標志為真,其它類為假
ACC_SYNTHETIC 0x1000 標識別這個類并非由用戶代碼產生
ACC_ANNOTATION 0x2000 標識這是一個注解
ACC_ENUM 0x4000 標識這是一個枚舉
我們這里0021標示為public Class

接下來的是類索引,父類索引與接口索引集合
this_class,super_class,interfaces_count,interfaces

類索引

為2個字節

這里為00 01,指向常量池中第一個常量,之前我們分析過常量池中第一個常量為Class類型,內容指向第二個常量UTF-8的HelloWorld。
標示當前名為HelloWorld

父類索引

也是2個字節

指向常量中第三個常量,對應內容為java/lang/Object

接口數量


表示接口數量為0

字段表集合

00 01 標示字段數量為1
字段表的格式如下

類型 名稱 數量
u2 access_flags 1
u2 name_index 1
u2 descriptor_index 1
u2 attributes_count 1
attribute_info attributes attributes_coun

accessFlags為 00 00 當時當前字段無修飾符
字段修飾符格式如下

標志名稱 標志值 含義
ACC_PUBLIC 0x0001 字段是否為public
ACC_PRIVATE 0x0002 字段是否為private
ACC_PROTECTED 0x0004 字段是否為protected
ACC_STATIC 0x0008 字段是否為static
ACC_FINAL 0x0010 字段是否為final
ACC_VOLATILE 0x0040 字段是否為volatile
ACC_TRANSIENT 0x0080 字段是否為transient
ACC_SYNTHETIC 0x1000 字段是否為編譯器自動產生
ACC_ENUM 0x4000 字段是否為enum

name_index為 00 05指向常量池中的第五個常量
第5個常量為str,變量名為str

descriptor_index指向常量池第6個變量,為Ljava/lang/String類型
attributes_count(屬性計數器,占2字節,0x0000,所以該字段沒有額外需要描述的信息)

方法集合


method_count: 00 03 有3個方法
methods:方法表集合

類型 名稱 數量
u2 access_flags 1
u2 name_index 1
u2 descriptor_index 1
u2 attributes_count 1
attribute_info attributes attributes_coun

access flags的定義見下表

標志名稱 標志值 含義
ACC_PUBLIC 0x0001 字段是否為public
ACC_PRIVATE 0x0002 字段是否為private
ACC_PROTECTED 0x0004 字段是否為protected
ACC_STATIC 0x0008 字段是否為static
ACC_FINAL 0x0010 字段是否為final
ACC_SYNCHRONIZED 0x0020 字段是否為synchronized
ACC_BRIDGE 0x0040 方法是否是由編譯器產生的橋接方法
ACC_VARARGS 0x0080 方法是否接受不定參數
ACC_NATIVE 0x0100 字段是否為native
ACC_ABSTRACT 0x0400 字段是否為abstract
ACC_STRICTFP 0x0800 字段是否為strictfp
ACC_SYNTHETIC 0x1000 字段是否為編譯器自動產生

這里方法access flags 為 00 01 說明方法為public的
name_index為00 07,方法名指向常量中第7個常量方法名為, descriptor_index為常量池第8個常量()V


attributes_count 為 00 01標示這個方法的屬性表集合中有一個屬性。屬性名稱為接下來2位0x0009,指向常量池中第9個常量:Code
接下來4位為 00 00 00 3D標示Code屬性值的字節長度為3D,接下來為00 02標示該方法的操作數棧的深度最大值為2.
00 01標示該方法的局部變量占用空間為1.

接下來4位00 00 00 0B 為機器編譯生成字節碼指令的長度為11,后面11個字節就是字節碼指令(字節碼指令可查詢虛擬機字節碼指令表),這里字節碼指令長度用4個字節標示,所有字節碼指令超長Class編譯會失敗的。
再接下來為 00 00標示Code屬性異常表結合為空。
再后面為 00 02,,說明Code帶有2個屬性, 00 10即為Code屬性第一個屬性的屬性名成指向常量池中第16個常量
接下來的00 00 00 0E 標示LinueNumberTable屬性值所占字節長度為15.接下來2位 00 03標示該line number table中有3個line number table表,start pc為 00 00 line number第 00 01個為00 04 第 00 02個為 00 0A?
再后面的 00 01又是第二個方法的access flags,接著開始第二個方法。


from:?https://yq.aliyun.com/articles/7241?spm=5176.100239.blogcont37179.10.F6pHuW

總結

以上是生活随笔為你收集整理的JVM Class详解之一的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。