JVM(6):クラスファイルの構造

概要:JVMコードをバイトコード(.classファイル)を理解することができる、それがいかなる特定のプロセッサが仮想マシンのみです直面していません。バイトコードは、特定のマシンに向け異なるオペレーティングシステム(クロスプラットフォーム)上で実行できるJavaプログラムを再コンパイルする必要はありませんので、されていません

A、クラスのクラスファイルの構造

JVM仕様で、単一のクラスファイルのクラスファイル構造:

ClassFile {
    u4             magic; //Class 文件的标志
    u2             minor_version;//Class 的小版本号
    u2             major_version;//Class 的大版本号
    u2             constant_pool_count;//常量池的数量
    cp_info        constant_pool[constant_pool_count-1];//常量池
    u2             access_flags;//Class 的访问标记
    u2             this_class;//当前类
    u2             super_class;//父类
    u2             interfaces_count;//接口
    u2             interfaces[interfaces_count];//一个类可以实现多个接口
    u2             fields_count;//Class 文件的字段属性
    field_info     fields[fields_count];//一个类会可以有个字段
    u2             methods_count;//Class 文件的方法数量
    method_info    methods[methods_count];//一个类可以有个多个方法
    u2             attributes_count;//此类的属性表中的属性数
    attribute_info attributes[attributes_count];//属性表集合
}

 クラスファイルのバイトコード概略構成団体

バイトコードのクラスは、概略的な構造組織をファイル

 

1.1、マジッククラスファイルのバージョン番号(最初の4バイト)

u4             magic; //Class 文件的标志

各クラスファイルの最初の4バイトのマジックナンバー(マジックナンバー)と呼ばれる:マジックナンバーが何であるか(1)

(2)の役割:ファイルは仮想マシンのクラスファイルとして受信することができるかどうかを決定します

1.2、クラスファイルのバージョン(4-8バイト)

  u2             minor_version;//Class 的小版本号
  u2             major_version;//Class 的大版本号

第五及び第六である:次いで、4バイトのマジックナンバーは、クラスファイルのバージョン番号であるマイナーバージョン番号、第7及び第8のメジャーバージョン番号

仮想マシンの低バージョンは、コンパイラ生成されたクラスファイルではなく、その逆の低いバージョンを実行することができます。

1.3、定数プール

 u2             constant_pool_count;//常量池的数量
 cp_info        constant_pool[constant_pool_count-1];//常量池

主な定数プールは、2つの定数を保存します:

(1)リテラル:、人生は、最終的に一定値文字列です。

(2)シンボル定数:クラスおよびインタフェースの完全修飾名、フィールド名と記述子、メソッド名と記述

定数プール・カウンター:カウンターがカウントを開始し、0がアイドル状態です。

定数プールテーブルが:各々が定数プールテーブル内の定数である(14種類)、最初の表を開始すると、この定電流定部品の種類を表す定数の種類を識別するためにU1 -tagフラグの種類であります

1.4、アクセスフラグ(2バイト)

役割:など、クラスやインターフェイスレベルのアクセス情報の一部を識別するために、このクラスは、それが最終的などとして宣言するかどうかの事のようなものであれば、それは、パブリックまたは抽象型であるかどうか、クラスまたはインタフェースです。

1.5、現在のクラスのインデックス、親インデックス、インデックスセットインタフェース

    u2             this_class;//当前类
    u2             super_class;//父类
    u2             interfaces_count;//接口
    u2             interfaces[interfaces_count];//一个雷可以实现多个接口
  • 効果指標のカテゴリ:クラスの完全修飾名を決定するための手段;
  • インデックスの親の役割:このクラスの親クラスの完全修飾名を決定するためには、Javaの単一継承するので、そのインデックスは、唯一の親クラスです。APART  java.lang.Object さらに、すべてのJavaクラスは、親クラスを持っています。
  • 接口索引集合作用:  用来描述这个类实现了哪些接口,这些被实现的接口将按implents后的接口顺序从左到右排列在接口索引集合中。

1.6、字段表集合

    u2             fields_count;//Class 文件的字段的个数
    field_info     fields[fields_count];//一个类会可以有个字段

作用:用于描述接口或者类中声明的变量(字段包括林级变量以及实例变量,不包括方法内部声明的局部变量)

字段表的结构

1.7、方法表集合

    u2             methods_count;//Class 文件的方法的数量
    method_info    methods[methods_count];//一个类可以有个多个方法

(methods_count 表示方法的数量,而 method_info 表示的方法表)

方法表的结构

方发表结构:包括了访问标志、名称索引、描述符索引、属性表集合

1.8、属性表集合

   u2             attributes_count;//此类的属性表中的属性数
   attribute_info attributes[attributes_count];//属性表集合

作用:在Class文件,字段表,方法表中都可以携带自己的属性表集合,用于描述某些场景的专有信息

二、字节码技术

掌握字节码技术可以自研框架,我有看过我们公司自研的框架源码(据说是几个华为跳槽来养老的人写的),他们主要是封装最近流行的SpringBoot框架,以及集成了很多流行技术。框架里边大量用到了字节码技术,还有各种设计模式,所以感觉掌握字节码技术是架构师必备技能!

2.1、字节码技术简介

字节码技术应用场景:AOP技术、Lombok去除重复代码插件、动态修改Class文件等。

字节码技术优势Java字节码增强指的是在Java字节码生成之后,对其进行修改,增强其功能。这种方式相当于对应用程序的二进制文件进行修改,可以减少代码冗余、提高性能。

实现字节码增强主要步骤

(1)修改字节码:

在内存中获取到原来的字节码,然后通过一些工具(如:ASM、Javaasist)来修改它的byte[]数组,得到一个新的byte数组;

(2)使修改后的字节码生效(2种方法):

  1. 自定义ClassLoader来加载修改后的字节码;
  2. 替换掉原来的字节码:在JVM加载用户的Class时,拦截,返回修改后的字节码;或者在运行时,使用Instrumentation.redefineClasses方法来替换掉原来的字节码

2.2、常见的字节码操作类库

(1)BCEL

BCELは広く使われているのclassworking Javaのためのフレームワークである、それはあなたのアセンブリ言語、JVMライブラリー操作の詳細への洞察を与えることができます。実際BCELの中の異なるバイトコード方式とBCELのJavassistのJVMの命令層倍で動作するが(BCELがサポートは、JVM広範な命令セットを持つ)強調しJavassistのれるソースレベル他の作品。

(2)ASM

これは、直接基礎となるJVMの操作や指示に関連した、軽量のJavaバイトコード操作フレームです。高性能、高品質。

(3)CGLB

ASMに基づくクラスライブラリは、達成するために

(4)Javassistの

オープンソースの分析、編集、クラスライブラリのJavaバイトコードを作成します。同様のCGLB、使用する簡単な多くの人気と比較ASMパフォーマンスの低下

2.3、Javassistのライブラリ使用

(1)Javassistの利点:

  • 反射オーバーヘッド、高性能よりも小さいです。
  • バイトコード操作は、私たちは実行時、以下の機能を実現することができます:動的にクラスの構造を変更する動的に新しいクラスを生成する(新しいプロパティ/メソッドを変更/追加/削除)。

(2)Javassistのコード実装を使用してクラスを作成します

	public static void main(String[] args)
			throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException,
			SecurityException, IllegalArgumentException, InvocationTargetException {
		Class<?> clazz = Class.forName("com.itmayiedu.Test0005");
		Object newInstance = clazz.newInstance();
		Method method = clazz.getDeclaredMethod("sum", int.class, int.class);
		Object invoke = method.invoke(newInstance, 1, 1);
	}

	public void sum(int a, int b) {
		System.out.println("sum:" + a + b);
	}

	public static void main(String[] args) throws CannotCompileException, NotFoundException, IOException {
		ClassPool pool = ClassPool.getDefault();
		// 创建class文件
		CtClass userClass = pool.makeClass("com.itmayiedu.entity.User");
		// 创建id属性
		CtField idField = CtField.make("private Integer id;", userClass);
		// 创建name属性
		CtField nameField = CtField.make("private Integer name;", userClass);
		// 添加属性
		userClass.addField(idField);
		// 添加属性
		userClass.addField(nameField);
		// 创建方法
		CtMethod getIdMethod = CtMethod.make("public Integer getId() {return id;}", userClass);
		// 创建方法
		CtMethod setIdMethod = CtMethod.make("public void setId(Integer id) { this.id = id; }", userClass);
		// 添加方法
		userClass.addMethod(getIdMethod);
		// 添加方法
		userClass.addMethod(setIdMethod);
		// 添加构造器
		CtConstructor ctConstructor = new CtConstructor(new CtClass[] { CtClass.intType, pool.get("java.lang.String") },
				userClass);
		// 创建Body
		ctConstructor.setBody("	{this.id = id;this.name = name;}");
		userClass.addConstructor(ctConstructor);
		userClass.writeFile("F:/test");// 将构造好的类写入到F:\test 目录下
	}

(2)クラスファイル情報Javassistのを修正

public static void main(String[] args)
			throws NotFoundException, CannotCompileException, InstantiationException, IllegalAccessException,
			NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException, IOException {
		ClassPool pool = ClassPool.getDefault();
		// 需要加载类信息
		CtClass userClass = pool.get("com.itmayiedu.User");
		// 需要添加的方法
		CtMethod m = new CtMethod(CtClass.intType, "add", new CtClass[] { CtClass.intType, CtClass.intType },
				userClass);
		// 方法权限
		m.setModifiers(Modifier.PUBLIC);
		// 方法体内容
		m.setBody("{System.out.println(\"Test003\"); return $1+$2;}");
		userClass.addMethod(m);
		userClass.writeFile("F:/test");// 将构造好的类写入到F:\test 目录下
		// 使用反射技术执行方法
		Class clazz = userClass.toClass();
		Object obj = clazz.newInstance(); // 通过调用User 无参构造函数
		Method method = clazz.getDeclaredMethod("add", int.class, int.class);
		Object result = method.invoke(obj, 200, 300);
		System.out.println(result);
	}

 

 2.4、バイトコード命令の紹介

 

更新する.................

 

あなたが助けを持っている場合は###、親指を歓迎します!コメント!転送!ありがとうございます!

前:コンパイラとランタイムコードの最適化

次へ:VMクラスローディング機構

  参考:Java仮想マシン(バージョン2)の深い理解:JVMは機能やベストプラクティスを進めました

公開された52元の記事 ウォンの賞賛116 ・は 50000 +を見て

おすすめ

転載: blog.csdn.net/RuiKe1400360107/article/details/103525058