目录
一、javac编译
1. 编译过程
2. 语法糖
二、Class文件
1. 文件格式
2. 常量池项目
3. 属性类型
三、Class文件实例
1. 源代码
2. javap分析Class文件
四、字节码指令
五、参考资料
javac命令由Java语言编写,目的将Java源码转变成字节码(只完成源码到抽象语法树或字节码的生成),JDK12源码其运行入口是com.sun.tools.javac.Main#main。javac主体代码如下图所示。com.sun.tools.javac.main.JavaCompiler#compile核心方法。
javac编译过程:一个准备(初始化插入式注解处理器);三个处理(解析与填充符号表、处理注解处理器、语义分析与字节码生成),如下图所示。
需要注意的是:生成
Class文件是字节为单位的二进制流,有两种数据类型:无符号数、表,如下图所示。Class文件不保存方法、字段最终的内存布局信息,JVM运行期才能找到内存入口地址。
Class文件格式如下表所示,主要有:常量池、字段表、方法表、属性表等。Class文件可以使用十六进制编辑器WinHex打开。注意:常量池(constant_pool)的数量是constant_pool_count减1,若为0说明“不引用任何常量池项目”;而其他表从0开始计数。
数据类型 |
名称 |
数量 |
作用及特点 |
u4 |
magic |
1 |
1.魔数:确定文件是否是Class文件; 2.固定值:0xCAFEBABE。 |
u2 |
minnor_version |
1 |
次版本号 |
u2 |
major_version |
1 |
1.主版本号; 2.JDK向前兼容老版本,则不能向后兼容新版本。 |
u2 |
constant_pool_count |
1 |
1.常量池容量计数数量; 2.索引从1开始,其他表从0开始; 3.若为0,则说明“不引用任何常量池项目”。 |
cp_info |
constant_pool |
constant_pool_count - 1 |
1.常量池,有两大类常量:字面量、符号引用; 2.有17种不同类型常量,如: CONSTANT_Utf8_info、 CONSTANT_Class_info、 CONSTANT_Fieldref_info、 CONSTANT_Methodref_info、...... |
u2 |
access_flags |
1 |
1.类或接口的访问修饰符; 2.如:ACC_PUBLIC(是否为public修饰)。 |
u2 |
this_class |
1 |
类索引:当前类的全限定名 |
u2 |
super_class |
1 |
1.父类索引:当前类的父类的全限定名; 2.除java.lang.Object外,所有类的父类值都不为0。 |
u2 |
interfaces_count |
1 |
1.接口索引的数量; 2.没有实现任何接口时,该值为0。 |
u2 |
interfaces |
interfaces_count |
1.接口索引:当前类的所有接口的全限定名; 2.接口从左往右的顺序在该表中。 |
u2 |
fields_count |
1 |
类或接口的字段数量 |
field_info |
fields |
fields_count |
1.类或接口的字段(实例变量,类变量); 2.不包括:方法内局部变量; 3.内容有:修饰符、在常量池中索引、简单名称、描述符、属性表(attribute_info); 4.“描述符”:字段的数据类型、方法的参数列表及返回值; 5.不会列出父类或接口的字段; 6.可能含有JVM自动生成的字段,如:this字段。 |
u2 |
methods_count |
1 |
类或接口的方法数量 |
method_info |
methods |
methods_count |
1.类或接口的方法(实例方法,类方法); 2.内容有:修饰符、在常量池中索引、简单名称、描述符、属性表(attribute_info的Code); 3.“描述符”:字段的数据类型、方法的参数列表及返回值; 4.不会列出父类或接口的方法(重写除外); 5.可能含有JVM自动生成的方法,如: |
u2 |
attributes_count |
1 |
属性表数量 |
attribute_info |
attributes |
attributes_count |
1.Class文件、字段、方法都有自己的属性; 2.属性只要不重名,任何编译器都可以添加自己的属性信息。 |
常量池有两大类常量:字面量、符号引用。当类加载时,从常量池获得对应的符号引用,再在类创建或运行解析时,翻译到具体的内存地址中。如下表所示是17种不同类型的常量。
“描述符”作用是描述字段的数据类型、方法的参数列表(包括:数量、类型、顺序)、返回值。数组类型,每一个维度用前置的“[”标识,如:void inc(int[ ] ints)其描述符为([I)V。下表所示是描述符标识字符含义。
Class文件、字段、方法都有自己的属性,这些属性存储到属性表(attribute_info),《Java虚拟机规范》允许属性只要不重名,任何编译器都可以添加自己的属性信息。
如下表所示是常用属性介绍,其中整个Class文件中,只有Code属性描述方法体的代码,其他所有数据项目都是描述元数据。
常用属性 |
使用位置 |
含义 |
Code |
方法表 |
1.作用:描述方法体代码,注意:不是所有方法都有Code属性,如:接口、抽象类的方法等; 2.Code属性表中常用参数: max_stack:操作数栈的最大深度; max_locals:局部变量表的最大slot数量(不是空间大小); args_size:方法的参数数量,注意:若实例方法,则有this参数; code:方法体的字节码指令流; ..... |
LineNumberTable |
Code属性 |
1.源码行号与字节码指令行的对应关系; 2.字节码指令的“行”:是相对于方法体开始的偏移量。 |
LocalVariableTable |
Code属性 |
1.方法的局部变量描述; 2.注意:若实例方法,则有this参数; 3.结构中:start_pc(变量开始的字节码偏移量) + length(长度)决定变量的作用域。 |
StackMapTable |
Code属性 |
1.目的:类加载时字节码验证阶段进行类型检查(新类型检查器); 2.含义:0或多个栈映射帧(代表字节码偏移量),即:执行到该字节码时局部变量表和操作数栈的验证类型。 |
ConstantValue |
字段表 |
1.常量值:为static修饰的变量赋值的值; 2.常量值只能是:基本数据类型、String。 |
Exceptions |
方法表 |
方法抛出的异常列表 |
InnerClasses |
类文件 |
内部类列表 |
Signature |
类、方法表、 字段表 |
1.记录泛型签名信息,如:类型变量、类型参数等; 2.反射API就是根据这个属性来获取泛型信息。 |
MethodParameters |
方法表 |
记录方法的各个形参和信息 |
Synthetic |
类、方法表、 字段表 |
1.标识方法或字段是编译器自动生成,至少有Synthetic或ACC_SYNTHETIC一个; 2.如:实例构造器 |
其他:Deprecated(含有@Deprecated)、EnclosingMethod(含有局部类或匿名类)、 RuntimeVisibleAnnotations(运行时可见的注解,反射可调用)、SourceFile(记录源文件名称)、 RuntimeInvisibleAnnotations(运行时不可见的注解,反射不可调用)、 AnnotationDefault(含有注解类元素默认值)、Modlue(记录模块信息)、 BootstrapMethods(保存invokedynamic指令引用的引导方法限定符)、 ...... |
如下代码,用javac编译成Class文件。
package com.common.instance.demo.core.serviceLevel;
import com.alibaba.fastjson.JSON;
import com.log.util.LogUtil;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.*;
/**
* @description 一级业务线程池处理业务
* @author tcm
* @version 1.0.0
* @date 2021/9/29 16:01
**/
@Component
public class OneLevelAsyncContext implements InitializingBean {
private final String URI = "uri";
private final String PARAMS = "params";
private AsyncListener asyncListener;
private LinkedBlockingDeque queue;
private ThreadPoolExecutor executor;
public Object submitFuture(final HttpServletRequest request, final Callable
javap命令分析Class文件,如:javap -verbose OneLevelAsyncContext.class,代码所示。
Classfile /E:/Idea Project/instance-demo/target/classes/com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext.class
Last modified 2023-7-22; size 4120 bytes
MD5 checksum ab1d73e3259040031896505e9ed1e1bb
Compiled from "OneLevelAsyncContext.java"
public class com.common.instance.demo.core.serviceLevel.OneLevelAsyncContext implements org.springframework.beans.factory.InitializingBean
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #42.#99 // java/lang/Object."":()V
#2 = String #70 // uri
#3 = Fieldref #10.#100 // com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext.URI:Ljava/lang/String;
#4 = String #71 // params
#5 = Fieldref #10.#101 // com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext.PARAMS:Ljava/lang/String;
#6 = InterfaceMethodref #102.#103 // javax/servlet/http/HttpServletRequest.getRequestURI:()Ljava/lang/String;
#7 = InterfaceMethodref #102.#104 // javax/servlet/http/HttpServletRequest.getParameterMap:()Ljava/util/Map;
#8 = InterfaceMethodref #102.#105 // javax/servlet/http/HttpServletRequest.startAsync:()Ljavax/servlet/AsyncContext;
#9 = InterfaceMethodref #106.#107 // javax/servlet/AsyncContext.getRequest:()Ljavax/servlet/ServletRequest;
#10 = Class #108 // com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext
#11 = InterfaceMethodref #109.#110 // javax/servlet/ServletRequest.setAttribute:(Ljava/lang/String;Ljava/lang/Object;)V
#12 = Long 2000l
#14 = InterfaceMethodref #106.#111 // javax/servlet/AsyncContext.setTimeout:(J)V
#15 = Fieldref #10.#112 // com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext.asyncListener:Ljavax/servlet/AsyncListener;
#16 = Methodref #113.#114 // java/util/Objects.nonNull:(Ljava/lang/Object;)Z
#17 = InterfaceMethodref #106.#115 // javax/servlet/AsyncContext.addListener:(Ljavax/servlet/AsyncListener;)V
#18 = Fieldref #10.#116 // com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext.executor:Ljava/util/concurrent/ThreadPoolExecutor;
#19 = Class #117 // com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext$1
#20 = Methodref #19.#118 // com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext$1."":(Lcom/common/instance/demo/core/serviceLevel/OneLevelAsyncContext;Ljava/util/concurrent/Callable;)V
#21 = Methodref #30.#119 // java/util/concurrent/ThreadPoolExecutor.submit:(Ljava/util/concurrent/Callable;)Ljava/util/concurrent/Future;
#22 = InterfaceMethodref #106.#120 // javax/servlet/AsyncContext.complete:()V
#23 = InterfaceMethodref #121.#122 // java/util/concurrent/Future.get:()Ljava/lang/Object;
#24 = String #123 // 100
#25 = Methodref #124.#125 // java/lang/Integer.parseInt:(Ljava/lang/String;)I
#26 = String #126 // 200
#27 = Class #127 // java/util/concurrent/LinkedBlockingDeque
#28 = Methodref #27.#99 // java/util/concurrent/LinkedBlockingDeque."":()V
#29 = Fieldref #10.#128 // com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext.queue:Ljava/util/concurrent/LinkedBlockingDeque;
#30 = Class #129 // java/util/concurrent/ThreadPoolExecutor
#31 = Long 100l
#33 = Fieldref #130.#131 // java/util/concurrent/TimeUnit.MILLISECONDS:Ljava/util/concurrent/TimeUnit;
#34 = Methodref #30.#132 // java/util/concurrent/ThreadPoolExecutor."":(IIJLjava/util/concurrent/TimeUnit;Ljava/util/concurrent/BlockingQueue;)V
#35 = Methodref #30.#133 // java/util/concurrent/ThreadPoolExecutor.allowCoreThreadTimeOut:(Z)V
#36 = Class #134 // com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext$2
#37 = Methodref #36.#135 // com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext$2."":(Lcom/common/instance/demo/core/serviceLevel/OneLevelAsyncContext;)V
#38 = Methodref #30.#136 // java/util/concurrent/ThreadPoolExecutor.setRejectedExecutionHandler:(Ljava/util/concurrent/RejectedExecutionHandler;)V
#39 = Methodref #113.#137 // java/util/Objects.isNull:(Ljava/lang/Object;)Z
#40 = Class #138 // com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext$3
#41 = Methodref #40.#135 // com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext$3."":(Lcom/common/instance/demo/core/serviceLevel/OneLevelAsyncContext;)V
#42 = Class #139 // java/lang/Object
#43 = Class #140 // org/springframework/beans/factory/InitializingBean
#44 = Utf8 InnerClasses
#45 = Utf8 URI
#46 = Utf8 Ljava/lang/String;
#47 = Utf8 ConstantValue
#48 = Utf8 PARAMS
#49 = Utf8 asyncListener
#50 = Utf8 Ljavax/servlet/AsyncListener;
#51 = Utf8 queue
#52 = Utf8 Ljava/util/concurrent/LinkedBlockingDeque;
#53 = Utf8 Signature
#54 = Utf8 Ljava/util/concurrent/LinkedBlockingDeque;
#55 = Utf8 executor
#56 = Utf8 Ljava/util/concurrent/ThreadPoolExecutor;
#57 = Utf8
#58 = Utf8 ()V
#59 = Utf8 Code
#60 = Utf8 LineNumberTable
#61 = Utf8 LocalVariableTable
#62 = Utf8 this
#63 = Utf8 Lcom/common/instance/demo/core/serviceLevel/OneLevelAsyncContext;
#64 = Utf8 submitFuture
#65 = Utf8 (Ljavax/servlet/http/HttpServletRequest;Ljava/util/concurrent/Callable;)Ljava/lang/Object;
#66 = Utf8 request
#67 = Utf8 Ljavax/servlet/http/HttpServletRequest;
#68 = Utf8 task
#69 = Utf8 Ljava/util/concurrent/Callable;
#70 = Utf8 uri
#71 = Utf8 params
#72 = Utf8 Ljava/util/Map;
#73 = Utf8 asyncContext
#74 = Utf8 Ljavax/servlet/AsyncContext;
#75 = Utf8 future
#76 = Utf8 Ljava/util/concurrent/Future;
#77 = Utf8 LocalVariableTypeTable
#78 = Utf8 Ljava/util/concurrent/Callable;
#79 = Utf8 Ljava/util/Map;
#80 = Utf8 Ljava/util/concurrent/Future;
#81 = Utf8 StackMapTable
#82 = Class #141 // java/lang/String
#83 = Class #142 // java/util/Map
#84 = Class #143 // javax/servlet/AsyncContext
#85 = Utf8 Exceptions
#86 = Class #144 // java/util/concurrent/ExecutionException
#87 = Class #145 // java/lang/InterruptedException
#88 = Utf8 MethodParameters
#89 = Utf8 (Ljavax/servlet/http/HttpServletRequest;Ljava/util/concurrent/Callable;)Ljava/lang/Object;
#90 = Utf8 afterPropertiesSet
#91 = Utf8 corePoolSize
#92 = Utf8 I
#93 = Utf8 maxNumPoolSize
#94 = Class #146 // java/lang/Exception
#95 = Utf8 SourceFile
#96 = Utf8 OneLevelAsyncContext.java
#97 = Utf8 RuntimeVisibleAnnotations
#98 = Utf8 Lorg/springframework/stereotype/Component;
#99 = NameAndType #57:#58 // "":()V
#100 = NameAndType #45:#46 // URI:Ljava/lang/String;
#101 = NameAndType #48:#46 // PARAMS:Ljava/lang/String;
#102 = Class #147 // javax/servlet/http/HttpServletRequest
#103 = NameAndType #148:#149 // getRequestURI:()Ljava/lang/String;
#104 = NameAndType #150:#151 // getParameterMap:()Ljava/util/Map;
#105 = NameAndType #152:#153 // startAsync:()Ljavax/servlet/AsyncContext;
#106 = Class #143 // javax/servlet/AsyncContext
#107 = NameAndType #154:#155 // getRequest:()Ljavax/servlet/ServletRequest;
#108 = Utf8 com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext
#109 = Class #156 // javax/servlet/ServletRequest
#110 = NameAndType #157:#158 // setAttribute:(Ljava/lang/String;Ljava/lang/Object;)V
#111 = NameAndType #159:#160 // setTimeout:(J)V
#112 = NameAndType #49:#50 // asyncListener:Ljavax/servlet/AsyncListener;
#113 = Class #161 // java/util/Objects
#114 = NameAndType #162:#163 // nonNull:(Ljava/lang/Object;)Z
#115 = NameAndType #164:#165 // addListener:(Ljavax/servlet/AsyncListener;)V
#116 = NameAndType #55:#56 // executor:Ljava/util/concurrent/ThreadPoolExecutor;
#117 = Utf8 com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext$1
#118 = NameAndType #57:#166 // "":(Lcom/common/instance/demo/core/serviceLevel/OneLevelAsyncContext;Ljava/util/concurrent/Callable;)V
#119 = NameAndType #167:#168 // submit:(Ljava/util/concurrent/Callable;)Ljava/util/concurrent/Future;
#120 = NameAndType #169:#58 // complete:()V
#121 = Class #170 // java/util/concurrent/Future
#122 = NameAndType #171:#172 // get:()Ljava/lang/Object;
#123 = Utf8 100
#124 = Class #173 // java/lang/Integer
#125 = NameAndType #174:#175 // parseInt:(Ljava/lang/String;)I
#126 = Utf8 200
#127 = Utf8 java/util/concurrent/LinkedBlockingDeque
#128 = NameAndType #51:#52 // queue:Ljava/util/concurrent/LinkedBlockingDeque;
#129 = Utf8 java/util/concurrent/ThreadPoolExecutor
#130 = Class #176 // java/util/concurrent/TimeUnit
#131 = NameAndType #177:#178 // MILLISECONDS:Ljava/util/concurrent/TimeUnit;
#132 = NameAndType #57:#179 // "":(IIJLjava/util/concurrent/TimeUnit;Ljava/util/concurrent/BlockingQueue;)V
#133 = NameAndType #180:#181 // allowCoreThreadTimeOut:(Z)V
#134 = Utf8 com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext$2
#135 = NameAndType #57:#182 // "":(Lcom/common/instance/demo/core/serviceLevel/OneLevelAsyncContext;)V
#136 = NameAndType #183:#184 // setRejectedExecutionHandler:(Ljava/util/concurrent/RejectedExecutionHandler;)V
#137 = NameAndType #185:#163 // isNull:(Ljava/lang/Object;)Z
#138 = Utf8 com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext$3
#139 = Utf8 java/lang/Object
#140 = Utf8 org/springframework/beans/factory/InitializingBean
#141 = Utf8 java/lang/String
#142 = Utf8 java/util/Map
#143 = Utf8 javax/servlet/AsyncContext
#144 = Utf8 java/util/concurrent/ExecutionException
#145 = Utf8 java/lang/InterruptedException
#146 = Utf8 java/lang/Exception
#147 = Utf8 javax/servlet/http/HttpServletRequest
#148 = Utf8 getRequestURI
#149 = Utf8 ()Ljava/lang/String;
#150 = Utf8 getParameterMap
#151 = Utf8 ()Ljava/util/Map;
#152 = Utf8 startAsync
#153 = Utf8 ()Ljavax/servlet/AsyncContext;
#154 = Utf8 getRequest
#155 = Utf8 ()Ljavax/servlet/ServletRequest;
#156 = Utf8 javax/servlet/ServletRequest
#157 = Utf8 setAttribute
#158 = Utf8 (Ljava/lang/String;Ljava/lang/Object;)V
#159 = Utf8 setTimeout
#160 = Utf8 (J)V
#161 = Utf8 java/util/Objects
#162 = Utf8 nonNull
#163 = Utf8 (Ljava/lang/Object;)Z
#164 = Utf8 addListener
#165 = Utf8 (Ljavax/servlet/AsyncListener;)V
#166 = Utf8 (Lcom/common/instance/demo/core/serviceLevel/OneLevelAsyncContext;Ljava/util/concurrent/Callable;)V
#167 = Utf8 submit
#168 = Utf8 (Ljava/util/concurrent/Callable;)Ljava/util/concurrent/Future;
#169 = Utf8 complete
#170 = Utf8 java/util/concurrent/Future
#171 = Utf8 get
#172 = Utf8 ()Ljava/lang/Object;
#173 = Utf8 java/lang/Integer
#174 = Utf8 parseInt
#175 = Utf8 (Ljava/lang/String;)I
#176 = Utf8 java/util/concurrent/TimeUnit
#177 = Utf8 MILLISECONDS
#178 = Utf8 Ljava/util/concurrent/TimeUnit;
#179 = Utf8 (IIJLjava/util/concurrent/TimeUnit;Ljava/util/concurrent/BlockingQueue;)V
#180 = Utf8 allowCoreThreadTimeOut
#181 = Utf8 (Z)V
#182 = Utf8 (Lcom/common/instance/demo/core/serviceLevel/OneLevelAsyncContext;)V
#183 = Utf8 setRejectedExecutionHandler
#184 = Utf8 (Ljava/util/concurrent/RejectedExecutionHandler;)V
#185 = Utf8 isNull
{
public com.common.instance.demo.core.serviceLevel.OneLevelAsyncContext();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."":()V
4: aload_0
5: ldc #2 // String uri
7: putfield #3 // Field URI:Ljava/lang/String;
10: aload_0
11: ldc #4 // String params
13: putfield #5 // Field PARAMS:Ljava/lang/String;
16: return
LineNumberTable:
line 23: 0
line 25: 4
line 26: 10
LocalVariableTable:
Start Length Slot Name Signature
0 17 0 this Lcom/common/instance/demo/core/serviceLevel/OneLevelAsyncContext;
public java.lang.Object submitFuture(javax.servlet.http.HttpServletRequest, java.util.concurrent.Callable) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
descriptor: (Ljavax/servlet/http/HttpServletRequest;Ljava/util/concurrent/Callable;)Ljava/lang/Object;
flags: ACC_PUBLIC
Code:
stack=5, locals=7, args_size=3
0: aload_1
1: invokeinterface #6, 1 // InterfaceMethod javax/servlet/http/HttpServletRequest.getRequestURI:()Ljava/lang/String;
6: astore_3
7: aload_1
8: invokeinterface #7, 1 // InterfaceMethod javax/servlet/http/HttpServletRequest.getParameterMap:()Ljava/util/Map;
13: astore 4
15: aload_1
16: invokeinterface #8, 1 // InterfaceMethod javax/servlet/http/HttpServletRequest.startAsync:()Ljavax/servlet/AsyncContext;
21: astore 5
23: aload 5
25: invokeinterface #9, 1 // InterfaceMethod javax/servlet/AsyncContext.getRequest:()Ljavax/servlet/ServletRequest;
30: ldc #2 // String uri
32: aload_3
33: invokeinterface #11, 3 // InterfaceMethod javax/servlet/ServletRequest.setAttribute:(Ljava/lang/String;Ljava/lang/Object;)V
38: aload 5
40: invokeinterface #9, 1 // InterfaceMethod javax/servlet/AsyncContext.getRequest:()Ljavax/servlet/ServletRequest;
45: ldc #4 // String params
47: aload 4
49: invokeinterface #11, 3 // InterfaceMethod javax/servlet/ServletRequest.setAttribute:(Ljava/lang/String;Ljava/lang/Object;)V
54: aload 5
56: ldc2_w #12 // long 2000l
59: invokeinterface #14, 3 // InterfaceMethod javax/servlet/AsyncContext.setTimeout:(J)V
64: aload_0
65: getfield #15 // Field asyncListener:Ljavax/servlet/AsyncListener;
68: invokestatic #16 // Method java/util/Objects.nonNull:(Ljava/lang/Object;)Z
71: ifeq 85
74: aload 5
76: aload_0
77: getfield #15 // Field asyncListener:Ljavax/servlet/AsyncListener;
80: invokeinterface #17, 2 // InterfaceMethod javax/servlet/AsyncContext.addListener:(Ljavax/servlet/AsyncListener;)V
85: aload_0
86: getfield #18 // Field executor:Ljava/util/concurrent/ThreadPoolExecutor;
89: new #19 // class com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext$1
92: dup
93: aload_0
94: aload_2
95: invokespecial #20 // Method com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext$1."":(Lcom/common/instance/demo/core/serviceLevel/OneLevelAsyncContext;Ljava/util/concurrent/Callable;)V
98: invokevirtual #21 // Method java/util/concurrent/ThreadPoolExecutor.submit:(Ljava/util/concurrent/Callable;)Ljava/util/concurrent/Future;
101: astore 6
103: aload 5
105: invokeinterface #22, 1 // InterfaceMethod javax/servlet/AsyncContext.complete:()V
110: aload 6
112: invokeinterface #23, 1 // InterfaceMethod java/util/concurrent/Future.get:()Ljava/lang/Object;
117: areturn
LineNumberTable:
line 34: 0
line 36: 7
line 39: 15
line 40: 23
line 41: 38
line 43: 54
line 44: 64
line 45: 74
line 49: 85
line 58: 103
line 59: 110
LocalVariableTable:
Start Length Slot Name Signature
0 118 0 this Lcom/common/instance/demo/core/serviceLevel/OneLevelAsyncContext;
0 118 1 request Ljavax/servlet/http/HttpServletRequest;
0 118 2 task Ljava/util/concurrent/Callable;
7 111 3 uri Ljava/lang/String;
15 103 4 params Ljava/util/Map;
23 95 5 asyncContext Ljavax/servlet/AsyncContext;
103 15 6 future Ljava/util/concurrent/Future;
LocalVariableTypeTable:
Start Length Slot Name Signature
0 118 2 task Ljava/util/concurrent/Callable;
15 103 4 params Ljava/util/Map;
103 15 6 future Ljava/util/concurrent/Future;
StackMapTable: number_of_entries = 1
frame_type = 254 /* append */
offset_delta = 85
locals = [ class java/lang/String, class java/util/Map, class javax/servlet/AsyncContext ]
Exceptions:
throws java.util.concurrent.ExecutionException, java.lang.InterruptedException
MethodParameters:
Name Flags
request final
task final
Signature: #89 // (Ljavax/servlet/http/HttpServletRequest;Ljava/util/concurrent/Callable;)Ljava/lang/Object;
public void afterPropertiesSet() throws java.lang.Exception;
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=9, locals=3, args_size=1
0: ldc #24 // String 100
2: invokestatic #25 // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
5: istore_1
6: ldc #26 // String 200
8: invokestatic #25 // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
11: istore_2
12: aload_0
13: new #27 // class java/util/concurrent/LinkedBlockingDeque
16: dup
17: invokespecial #28 // Method java/util/concurrent/LinkedBlockingDeque."":()V
20: putfield #29 // Field queue:Ljava/util/concurrent/LinkedBlockingDeque;
23: aload_0
24: new #30 // class java/util/concurrent/ThreadPoolExecutor
27: dup
28: iload_1
29: iload_2
30: ldc2_w #31 // long 100l
33: getstatic #33 // Field java/util/concurrent/TimeUnit.MILLISECONDS:Ljava/util/concurrent/TimeUnit;
36: aload_0
37: getfield #29 // Field queue:Ljava/util/concurrent/LinkedBlockingDeque;
40: invokespecial #34 // Method java/util/concurrent/ThreadPoolExecutor."":(IIJLjava/util/concurrent/TimeUnit;Ljava/util/concurrent/BlockingQueue;)V
43: putfield #18 // Field executor:Ljava/util/concurrent/ThreadPoolExecutor;
46: aload_0
47: getfield #18 // Field executor:Ljava/util/concurrent/ThreadPoolExecutor;
50: iconst_1
51: invokevirtual #35 // Method java/util/concurrent/ThreadPoolExecutor.allowCoreThreadTimeOut:(Z)V
54: aload_0
55: getfield #18 // Field executor:Ljava/util/concurrent/ThreadPoolExecutor;
58: new #36 // class com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext$2
61: dup
62: aload_0
63: invokespecial #37 // Method com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext$2."":(Lcom/common/instance/demo/core/serviceLevel/OneLevelAsyncContext;)V
66: invokevirtual #38 // Method java/util/concurrent/ThreadPoolExecutor.setRejectedExecutionHandler:(Ljava/util/concurrent/RejectedExecutionHandler;)V
69: aload_0
70: getfield #15 // Field asyncListener:Ljavax/servlet/AsyncListener;
73: invokestatic #39 // Method java/util/Objects.isNull:(Ljava/lang/Object;)Z
76: ifeq 91
79: aload_0
80: new #40 // class com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext$3
83: dup
84: aload_0
85: invokespecial #41 // Method com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext$3."":(Lcom/common/instance/demo/core/serviceLevel/OneLevelAsyncContext;)V
88: putfield #15 // Field asyncListener:Ljavax/servlet/AsyncListener;
91: return
LineNumberTable:
line 68: 0
line 70: 6
line 72: 12
line 74: 23
line 76: 46
line 78: 54
line 105: 69
line 106: 79
line 155: 91
LocalVariableTable:
Start Length Slot Name Signature
0 92 0 this Lcom/common/instance/demo/core/serviceLevel/OneLevelAsyncContext;
6 86 1 corePoolSize I
12 80 2 maxNumPoolSize I
StackMapTable: number_of_entries = 1
frame_type = 253 /* append */
offset_delta = 91
locals = [ int, int ]
Exceptions:
throws java.lang.Exception
}
SourceFile: "OneLevelAsyncContext.java"
RuntimeVisibleAnnotations:
0: #98()
InnerClasses:
#40; //class com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext$3
#36; //class com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext$2
#19; //class com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext$1
Java各种语法、关键字、常量变量、符号运算的语义最终都会由多个字节码指令组合来表达。Java虚拟机字节码指令组成如下所示:操作码(Opcode)、操作数(Operand)。
Java虚拟机面向操作数栈而不是面向寄存器的架构,其总数不超过256条(单字节),指令分类如下表所示。
指令类型 |
指令作用 |
指令 |
加载和存储 |
局部表加载到操作数栈 |
1.iload、iload_ 2._ |
操作数栈存储到局部表 |
1.istore、istore_ 2._ |
|
常量加载到操作数栈 |
1.iconst_、aconst_null、bipush、sipush、ldc、......; 2.iconst_表示:int型的常量加载到操作数栈。 |
|
扩充局部变量表的访问索引 |
wide |
|
运算指令 |
加法指令 |
iadd、ladd、fadd、dadd |
减法指令 |
isub、lsub、fsub、dsub |
|
局部变量自增指令 |
iinc |
|
比较指令 |
dcmpg、dcmpl、fcmpg、fcmpl、cmp |
|
...... |
imul、idev、irem、ineg、ishl、ior、iadd、ixor、...... |
|
对象创建和访问 |
类实例创建 |
new |
数组创建 |
newarray、anewarray、multianewarray |
|
访问实例字段或类字段 |
getfield、putfield、getstatic、putstatic |
|
数组元素加载到操作数栈 |
iaload、aaload、...... |
|
操作数栈存储到数组元素 |
iastore、aastore、...... |
|
获取数组长度 |
arraylength |
|
检查类实例类型 |
instanceof、checkcast |
|
操作数栈管理 |
栈顶一个或两个元素出栈 |
pop、pop2 |
栈顶一个或两个元素复制或双份复制重新压入栈顶 |
dup、dup2、dup_x1、dup2_x1、dup_x2、dup2_x2 |
|
最顶端两个元素互换 |
swap |
|
控制转移 |
条件分支 |
ifeq、iflt、ifnull、ificmplt、ifacmpeq、...... |
复合条件分支 |
tableswitch、lookupswitch |
|
无条件分支 |
goto、goto_w、...... |
|
方法调用和返回 |
调用对象实例方法 |
invokevirtual(运行时实际类型进行动态分派 _ 重写) |
调用接口方法 |
invokeinterface(运行时实现该接口的对象,找到合适则调用) |
|
调用实例初始化、私有、父类方法 |
invokespecial(实例初始化、私有、父类方法) |
|
调用类静态方法 |
invokestatic(static方法) |
|
动态调用用户设定的方法 |
invokedunamic(运行时动态解析调用点限定符所引用的方法) |
|
方法返回 |
1.return(void、实例初始化、类或接口初始化方法); 2.ireturn、lreturn、freturn、dreturn、areturn (byte、short、char、boolean、int型返回使用ireturn) |
|
异常处理 |
显示抛出异常 |
athrow(throw语句 + 检测到异常状况自动抛出) |
同步处理 |
synchronized加锁 (都是使用管程Monitor) |
1.方法的隐式加锁,即:方法访问标志ACC_SYNCHRONIZED; 2.语句块的显示加锁,即:monitorenter + monitorexit |
类型转换 |
宽化类型转换(安全转换) |
JVM直接支持:i转l/f/d、l转f/d、f转d |
窄化类型转换(强制转换) |
i2b、i2c、i2s、l2i、f2l、d2f、...... |
|
注意: a.i代表int、l代表long、s代表short、b代表byte、c代表char、f代表float、d代表double、a代表reference型; b.JVM不直接支持byte、short、char、boolean类型的算术运算,转换为int型运算; c.算术指令对操作数栈顶的两个元素运算,运算后先移除这两个元素,后计算结果存入栈顶; d.invokevirtual、invokeinterface、invokespecial、invokestatic调用都固化在JVM内部;而invokedunamic是由用户所设定的引导方法决定的; e.方法无论正常结果还是异常结束,则每条monitorenter都必须对应monitorexit; f.算术运算时,使用NaN(Not a Number)运算,其结果都是NaN。 |
jdk/jdk12: log
Java 进阶之字节码剖析_aload_0_C陈三岁的博客-CSDN博客
Class文件解析_class 详解_Aur_ora的博客-CSDN博客