JVM (6): Class File Structure

Overview: JVM code can be appreciated bytecode (.class files), it does not face any particular processor is only for virtual machines. Bytecode is not directed to a particular machine, so no need to recompile the Java program can run on different operating systems (cross-platform)

A, Class class file structure

The JVM specification, a single class file ClassFile structures:

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];//属性表集合
}

 Class file byte code schematic structural organization :

Byte code class files schematic structural organization

 

1.1, the version number of the Magic Class file (first 4 bytes)

u4             magic; //Class 文件的标志

(1) What is the magic number: the first four bytes of each Class file called magic number (Magic Number)

(2) the role of: determining whether the file can be received as a virtual machine Class file

1.2, Class file version (4-8 bytes)

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

Then the magic number of four bytes is the version number of Class file: The fifth and sixth are minor version number , the seventh and the eighth major version number .

Low version of the virtual machine can perform low version of the compiler generated Class file, not vice versa.

1.3, constant pool

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

The main constant pool storing two constants:

(1) literal: string, life is a constant value final.

(2) Symbol constants: classes and interfaces fully qualified name, field name and descriptor, method name and descriptor

Constant pool counters: counter starts counting, 0 is idle.

Constant pool table: each is a constant in the constant pool table (14 kinds), beginning the first table is a type of u1 -tag flag to identify the type of constants, which represents the type of constant current constant part of this

1.4, access flag (2 bytes)

Role: to identify some of the class or interface level access information, such as: This Class is a class or an interface, whether it is public or abstract type, if it is the kind of thing whether declared as final and so on.

1.5, the index of the current class, parent index, the index set Interface

    u2             this_class;//当前类
    u2             super_class;//父类
    u2             interfaces_count;//接口
    u2             interfaces[interfaces_count];//一个雷可以实现多个接口
  • Effect index categories: means for determining the fully qualified name of the class;
  • Index parent role: to determine the fully qualified name of the parent class of this class, because the Java single inheritance, so the index is only one parent class. Apart  java.lang.Object addition, all the java class has a parent class;
  • 接口索引集合作用:  用来描述这个类实现了哪些接口,这些被实现的接口将按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 is a framework for Java classworking widely used, it can give you insight into the details of assembly language jvm library operations. BCEL javassist with different bytecode method, in an actual BCEL jvm instruction layers operating on times (BCEL has extensive instruction set supports jvm) is emphasized and javassist source level other work.

(2) ASM

It is a lightweight Java bytecode manipulation frame, directly related to the operations and instructions of the underlying JVM. High-performance, high-quality.

(3)CGLB

Class library, based on ASM to achieve

(4) Javassist

Open-source analysis, edit, create class libraries Java bytecode. ASM poor performance compared with similar CGLB, simple to use and more popular

2.3, Javassist library using

(1) Javassist advantages:

  • Smaller than the reflective overhead, high performance;
  • Bytecode operation allows us to achieve the following functions Runtime: dynamically generate a new class dynamically change the structure of a class (add / delete / modify new properties / methods).

(2) create a class using Javassist code implementation

	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) modify the class file information 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, bytecode instructions Introduction

 

pending upgrade.................

 

### If you have help, welcome thumbs up! comment! Forwarding! Thank you!

Previous: The compiler and runtime code optimization

Next: VM class loading mechanism

  Reference: in-depth understanding of the Java Virtual Machine (Version 2): JVM advanced features and best practices

Published 52 original articles · won praise 116 · views 50000 +

Guess you like

Origin blog.csdn.net/RuiKe1400360107/article/details/103525058