HotSpot虚拟机之Class文件及字节码指令
目录
一、javac编译
1. 编译过程
2. 语法糖
二、Class文件
1. 文件格式
2. 常量池项目
3. 属性类型
三、Class文件实例
1. 源代码
2. javap分析Class文件
四、字节码指令
五、参考资料
一、javac编译
1. 编译过程
javac命令由Java语言编写,目的将Java源码转变成字节码(只完成源码到抽象语法树或字节码的生成),JDK12源码其运行入口是com.sun.tools.javac.Main#main。javac主体代码如下图所示。com.sun.tools.javac.main.JavaCompiler#compile核心方法。
javac编译过程:一个准备(初始化插入式注解处理器);三个处理(解析与填充符号表、处理注解处理器、语义分析与字节码生成),如下图所示。
需要注意的是:生成<init>()、<clinit>()方法在编译期完成;Lombok操作通过插入式注解处理器完成对字段的getter()和setter()方法。
2. 语法糖
二、Class文件
1. 文件格式
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自动生成的方法,如:<init>()、<cinit>()方法。 |
u2 | attributes_count | 1 | 属性表数量 |
attribute_info | attributes | attributes_count | 1.Class文件、字段、方法都有自己的属性; 2.属性只要不重名,任何编译器都可以添加自己的属性信息。 |
2. 常量池项目
常量池有两大类常量:字面量、符号引用。当类加载时,从常量池获得对应的符号引用,再在类创建或运行解析时,翻译到具体的内存地址中。如下表所示是17种不同类型的常量。
“描述符”作用是描述字段的数据类型、方法的参数列表(包括:数量、类型、顺序)、返回值。数组类型,每一个维度用前置的“[”标识,如:void inc(int[ ] ints)其描述符为([I)V。下表所示是描述符标识字符含义。
3. 属性类型
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.如:实例构造器<init>()、类构造器<cinit>(); |
其他:Deprecated(含有@Deprecated)、EnclosingMethod(含有局部类或匿名类)、 RuntimeVisibleAnnotations(运行时可见的注解,反射可调用)、SourceFile(记录源文件名称)、 RuntimeInvisibleAnnotations(运行时不可见的注解,反射不可调用)、 AnnotationDefault(含有注解类元素默认值)、Modlue(记录模块信息)、 BootstrapMethods(保存invokedynamic指令引用的引导方法限定符)、 ...... |
三、Class文件实例
1. 源代码
如下代码,用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<Runnable> queue;private ThreadPoolExecutor executor;public Object submitFuture(final HttpServletRequest request, final Callable<Object> task) throws ExecutionException, InterruptedException {// 获取请求URIfinal String uri = request.getRequestURI();// 获取请求参数final Map<String, String[]> params = request.getParameterMap();// 开启异步上下文final AsyncContext asyncContext = request.startAsync();asyncContext.getRequest().setAttribute(URI, uri);asyncContext.getRequest().setAttribute(PARAMS, params);// 超时设置asyncContext.setTimeout(2 * 1000);if (Objects.nonNull(asyncListener)) {asyncContext.addListener(this.asyncListener);}// 线程池处理业务Future<Object> future = executor.submit(new Callable<Object>() {@Overridepublic Object call() throws Exception {// 业务处理Object result = task.call();return result;}});// 完成异步上下文,否则报超时等异常asyncContext.complete();return future.get();}// 完成初始化配置@Overridepublic void afterPropertiesSet() throws Exception {// 线程池大小int corePoolSize = Integer.parseInt("100");// 最大线程池大小int maxNumPoolSize = Integer.parseInt("200");// 任务队列queue = new LinkedBlockingDeque<Runnable>();// 创建线程池executor = new ThreadPoolExecutor(corePoolSize, maxNumPoolSize, 100, TimeUnit.MILLISECONDS, queue);executor.allowCoreThreadTimeOut(true);// 线程池饱和处理executor.setRejectedExecutionHandler(new RejectedExecutionHandler() {@Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {if (r instanceof CanceledCallable) {CanceledCallable cc = ((CanceledCallable) r);AsyncContext asyncContext = cc.asyncContext;try {ServletRequest request = asyncContext.getRequest();String uri = (String) request.getAttribute(URI);Map params = (Map) request.getAttribute(PARAMS);LogUtil.error(String.format("async request %s, uri:%s, params:%s", "rejectedExecution", uri, JSON.toJSONString(params)));} catch (Exception ex) {}try {HttpServletResponse response = (HttpServletResponse) asyncContext.getResponse();response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);} finally {asyncContext.complete();}}}});// 创建监听器if (Objects.isNull(asyncListener)) {asyncListener = new AsyncListener() {@Overridepublic void onComplete(AsyncEvent asyncEvent) throws IOException {}@Overridepublic void onTimeout(AsyncEvent asyncEvent) throws IOException {AsyncContext asyncContext = asyncEvent.getAsyncContext();try {ServletRequest request = asyncContext.getRequest();String uri = (String) request.getAttribute(URI);Map params = (Map) request.getAttribute(PARAMS);LogUtil.error(String.format("async request timeout, uri:%s, params:%s", uri, JSON.toJSONString(params)));} catch (Exception e) {}try {HttpServletResponse resp = (HttpServletResponse) asyncContext.getResponse();resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);} finally {asyncContext.complete();}}@Overridepublic void onError(AsyncEvent asyncEvent) throws IOException {AsyncContext asyncContext = asyncEvent.getAsyncContext();try {ServletRequest request = asyncContext.getRequest();String uri = (String) request.getAttribute(URI);Map params = (Map) request.getAttribute(PARAMS);LogUtil.error(String.format("async request error, uri:%s, params:%s", uri, JSON.toJSONString(params)));} catch (Exception e) {}try {HttpServletResponse resp = (HttpServletResponse) asyncContext.getResponse();resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);} finally {asyncContext.complete();}}@Overridepublic void onStartAsync(AsyncEvent asyncEvent) throws IOException {}};}}}
2. javap分析Class文件
javap命令分析Class文件,如:javap -verbose OneLevelAsyncContext.class,代码所示。
Classfile /E:/Idea Project/instance-demo/target/classes/com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext.classLast modified 2023-7-22; size 4120 bytesMD5 checksum ab1d73e3259040031896505e9ed1e1bbCompiled from "OneLevelAsyncContext.java"
public class com.common.instance.demo.core.serviceLevel.OneLevelAsyncContext implements org.springframework.beans.factory.InitializingBeanminor version: 0major version: 52flags: ACC_PUBLIC, ACC_SUPER
Constant pool:#1 = Methodref #42.#99 // java/lang/Object."<init>":()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."<init>":(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."<init>":()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."<init>":(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."<init>":(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."<init>":(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<Ljava/lang/Runnable;>;#55 = Utf8 executor#56 = Utf8 Ljava/util/concurrent/ThreadPoolExecutor;#57 = Utf8 <init>#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<Ljava/lang/Object;>;#79 = Utf8 Ljava/util/Map<Ljava/lang/String;[Ljava/lang/String;>;#80 = Utf8 Ljava/util/concurrent/Future<Ljava/lang/Object;>;#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;>;)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 // "<init>":()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 // "<init>":(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 // "<init>":(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 // "<init>":(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: ()Vflags: ACC_PUBLICCode:stack=2, locals=1, args_size=10: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: aload_05: ldc #2 // String uri7: putfield #3 // Field URI:Ljava/lang/String;10: aload_011: ldc #4 // String params13: putfield #5 // Field PARAMS:Ljava/lang/String;16: returnLineNumberTable:line 23: 0line 25: 4line 26: 10LocalVariableTable:Start Length Slot Name Signature0 17 0 this Lcom/common/instance/demo/core/serviceLevel/OneLevelAsyncContext;public java.lang.Object submitFuture(javax.servlet.http.HttpServletRequest, java.util.concurrent.Callable<java.lang.Object>) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;descriptor: (Ljavax/servlet/http/HttpServletRequest;Ljava/util/concurrent/Callable;)Ljava/lang/Object;flags: ACC_PUBLICCode:stack=5, locals=7, args_size=30: aload_11: invokeinterface #6, 1 // InterfaceMethod javax/servlet/http/HttpServletRequest.getRequestURI:()Ljava/lang/String;6: astore_37: aload_18: invokeinterface #7, 1 // InterfaceMethod javax/servlet/http/HttpServletRequest.getParameterMap:()Ljava/util/Map;13: astore 415: aload_116: invokeinterface #8, 1 // InterfaceMethod javax/servlet/http/HttpServletRequest.startAsync:()Ljavax/servlet/AsyncContext;21: astore 523: aload 525: invokeinterface #9, 1 // InterfaceMethod javax/servlet/AsyncContext.getRequest:()Ljavax/servlet/ServletRequest;30: ldc #2 // String uri32: aload_333: invokeinterface #11, 3 // InterfaceMethod javax/servlet/ServletRequest.setAttribute:(Ljava/lang/String;Ljava/lang/Object;)V38: aload 540: invokeinterface #9, 1 // InterfaceMethod javax/servlet/AsyncContext.getRequest:()Ljavax/servlet/ServletRequest;45: ldc #4 // String params47: aload 449: invokeinterface #11, 3 // InterfaceMethod javax/servlet/ServletRequest.setAttribute:(Ljava/lang/String;Ljava/lang/Object;)V54: aload 556: ldc2_w #12 // long 2000l59: invokeinterface #14, 3 // InterfaceMethod javax/servlet/AsyncContext.setTimeout:(J)V64: aload_065: getfield #15 // Field asyncListener:Ljavax/servlet/AsyncListener;68: invokestatic #16 // Method java/util/Objects.nonNull:(Ljava/lang/Object;)Z71: ifeq 8574: aload 576: aload_077: getfield #15 // Field asyncListener:Ljavax/servlet/AsyncListener;80: invokeinterface #17, 2 // InterfaceMethod javax/servlet/AsyncContext.addListener:(Ljavax/servlet/AsyncListener;)V85: aload_086: getfield #18 // Field executor:Ljava/util/concurrent/ThreadPoolExecutor;89: new #19 // class com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext$192: dup93: aload_094: aload_295: invokespecial #20 // Method com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext$1."<init>":(Lcom/common/instance/demo/core/serviceLevel/OneLevelAsyncContext;Ljava/util/concurrent/Callable;)V98: invokevirtual #21 // Method java/util/concurrent/ThreadPoolExecutor.submit:(Ljava/util/concurrent/Callable;)Ljava/util/concurrent/Future;101: astore 6103: aload 5105: invokeinterface #22, 1 // InterfaceMethod javax/servlet/AsyncContext.complete:()V110: aload 6112: invokeinterface #23, 1 // InterfaceMethod java/util/concurrent/Future.get:()Ljava/lang/Object;117: areturnLineNumberTable:line 34: 0line 36: 7line 39: 15line 40: 23line 41: 38line 43: 54line 44: 64line 45: 74line 49: 85line 58: 103line 59: 110LocalVariableTable:Start Length Slot Name Signature0 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 Signature0 118 2 task Ljava/util/concurrent/Callable<Ljava/lang/Object;>;15 103 4 params Ljava/util/Map<Ljava/lang/String;[Ljava/lang/String;>;103 15 6 future Ljava/util/concurrent/Future<Ljava/lang/Object;>;StackMapTable: number_of_entries = 1frame_type = 254 /* append */offset_delta = 85locals = [ class java/lang/String, class java/util/Map, class javax/servlet/AsyncContext ]Exceptions:throws java.util.concurrent.ExecutionException, java.lang.InterruptedExceptionMethodParameters:Name Flagsrequest finaltask finalSignature: #89 // (Ljavax/servlet/http/HttpServletRequest;Ljava/util/concurrent/Callable<Ljava/lang/Object;>;)Ljava/lang/Object;public void afterPropertiesSet() throws java.lang.Exception;descriptor: ()Vflags: ACC_PUBLICCode:stack=9, locals=3, args_size=10: ldc #24 // String 1002: invokestatic #25 // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I5: istore_16: ldc #26 // String 2008: invokestatic #25 // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I11: istore_212: aload_013: new #27 // class java/util/concurrent/LinkedBlockingDeque16: dup17: invokespecial #28 // Method java/util/concurrent/LinkedBlockingDeque."<init>":()V20: putfield #29 // Field queue:Ljava/util/concurrent/LinkedBlockingDeque;23: aload_024: new #30 // class java/util/concurrent/ThreadPoolExecutor27: dup28: iload_129: iload_230: ldc2_w #31 // long 100l33: getstatic #33 // Field java/util/concurrent/TimeUnit.MILLISECONDS:Ljava/util/concurrent/TimeUnit;36: aload_037: getfield #29 // Field queue:Ljava/util/concurrent/LinkedBlockingDeque;40: invokespecial #34 // Method java/util/concurrent/ThreadPoolExecutor."<init>":(IIJLjava/util/concurrent/TimeUnit;Ljava/util/concurrent/BlockingQueue;)V43: putfield #18 // Field executor:Ljava/util/concurrent/ThreadPoolExecutor;46: aload_047: getfield #18 // Field executor:Ljava/util/concurrent/ThreadPoolExecutor;50: iconst_151: invokevirtual #35 // Method java/util/concurrent/ThreadPoolExecutor.allowCoreThreadTimeOut:(Z)V54: aload_055: getfield #18 // Field executor:Ljava/util/concurrent/ThreadPoolExecutor;58: new #36 // class com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext$261: dup62: aload_063: invokespecial #37 // Method com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext$2."<init>":(Lcom/common/instance/demo/core/serviceLevel/OneLevelAsyncContext;)V66: invokevirtual #38 // Method java/util/concurrent/ThreadPoolExecutor.setRejectedExecutionHandler:(Ljava/util/concurrent/RejectedExecutionHandler;)V69: aload_070: getfield #15 // Field asyncListener:Ljavax/servlet/AsyncListener;73: invokestatic #39 // Method java/util/Objects.isNull:(Ljava/lang/Object;)Z76: ifeq 9179: aload_080: new #40 // class com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext$383: dup84: aload_085: invokespecial #41 // Method com/common/instance/demo/core/serviceLevel/OneLevelAsyncContext$3."<init>":(Lcom/common/instance/demo/core/serviceLevel/OneLevelAsyncContext;)V88: putfield #15 // Field asyncListener:Ljavax/servlet/AsyncListener;91: returnLineNumberTable:line 68: 0line 70: 6line 72: 12line 74: 23line 76: 46line 78: 54line 105: 69line 106: 79line 155: 91LocalVariableTable:Start Length Slot Name Signature0 92 0 this Lcom/common/instance/demo/core/serviceLevel/OneLevelAsyncContext;6 86 1 corePoolSize I12 80 2 maxNumPoolSize IStackMapTable: number_of_entries = 1frame_type = 253 /* append */offset_delta = 91locals = [ 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_<n>、aload、aload_<n>、......; 2._<n>:其中n表示局部变量表的slot索引位置。 |
操作数栈存储到局部表 | 1.istore、istore_<n>、astore、astore_<n>、......; 2._<n>:其中n表示局部变量表的slot索引位置。 | |
常量加载到操作数栈 | 1.iconst_<i>、aconst_null、bipush、sipush、ldc、......; 2.iconst_<i>表示:int型的常量<i>加载到操作数栈。 | |
扩充局部变量表的访问索引 | 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博客
相关文章:

HotSpot虚拟机之Class文件及字节码指令
目录 一、javac编译 1. 编译过程 2. 语法糖 二、Class文件 1. 文件格式 2. 常量池项目 3. 属性类型 三、Class文件实例 1. 源代码 2. javap分析Class文件 四、字节码指令 五、参考资料 一、javac编译 1. 编译过程 javac命令由Java语言编写,目的将Ja…...

关于盐雾试验
盐雾实验一般被称为盐雾试验,是一种主要利用盐雾试验设备所创造的人工模拟盐雾环境条件来考核产品或金属材料耐腐蚀性能的环境试验。 盐雾实验的主要目的是考核产品或金属材料的耐盐雾腐蚀性能,盐雾试验结果也是对产品质量的判定,是正确衡量…...

windows美化任务栏,不使用软件
1.任务栏透明: 效果图: (1).winr打开命令行 输入regedit回车打开注册表 regedit (2).在注册表中打开 \HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced 这个路径 \HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explore…...

24考研数据结构-并查集
目录 5.5.2 并查集(双亲表示法)1. 并查集的存储结构2. 并查集的代码实现初始化并查时间复杂度union操作的优化(不要瘦高的树)并查集的进一步优化(find的优化,压缩路径)优化总结 数据结构&#x…...

Redis 和 Mysql 如何保证数据一致性
项目场景: 一般情况下,Redis 用来实现应用和数据库之间读操作的缓存层,主要目的是减少数据库 IO,还可以提升数据的 IO 性能。 如下图所示,这是它的整体架构。 当应用程序需要去读取某个数据的时候,首先会先…...

WSL1升级为WSL2
首先需要启用组件 使用管理员打开Powershell并运行 Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform启用后会要求重启计算机 从https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi获取WSL2 Linux内核更新包,…...

力扣 1049. 最后一块石头的重量 II
题目来源:https://leetcode.cn/problems/last-stone-weight-ii/description/ C题解(思路来源代码随想录):本题其实就是尽量让石头分成重量相同的两堆,相撞之后剩下的石头最小,这样就化解成01背包问题了。 …...

【广州华锐视点】葡萄种植VR虚拟仿真实训平台
随着虚拟现实(VR)技术的不断发展,越来越多的教育领域开始尝试将VR技术应用于教学中。在葡萄栽培这一专业领域,我们开发了一款创新的VR实训课件,旨在为学生提供沉浸式的互动学习体验。本篇文案将为您介绍葡萄种植VR虚拟仿真实训平台所提供的互…...

PBR材质理解整理
PBR Material 草履虫都能看懂的PBR讲解(迫真) 先前看了很多遍类似的了,结合《Unity Shader 入门精要》中的内容整理了下便于以后理解,以后有补充再添加。 光与材质相交会发生散射和吸收,散射改变光的方向,…...
从c++的角度来看ffmpeg 的架构
------------------------------------------------------------------------- author: hjjdebug date: 2023年 08月 01日 星期二 11:26:40 CST descriptor: 从c的角度来看ffmpeg 的架构 ------------------------------------------------------------------------…...

Ubuntu安装JDK与IntelliJ IDEA
目录 前言 Ubuntu 安装 JDK 1、更新软件包列表 2、安装OpenJDK 3、验证安装 Ubuntu安装IntelliJ IDEA 1、下载 IntelliJ IDEA 2、解压缩 IntelliJ IDEA 安装包 3、移动 IntelliJ IDEA 到安装目录 4、启动 IntelliJ IDEA 前言 APT(Advanced Package Tool&…...

【雕爷学编程】Arduino动手做(182)---DRV8833双路电机驱动模块2
37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的&am…...

一个完整的http请求响应过程
一、 HTTP请求和响应步骤 以上完整表示了HTTP请求和响应的7个步骤,下面从TCP/IP协议模型的角度来理解HTTP请求和响应如何传递的。 二、TCP/IP协议 TCP/IP协议模型(Transmission Control Protocol/Internet Protocol),包含了一系…...

Unity通过代码切换材质
效果展示 代码 using System.Collections; using System.Collections.Generic; using UnityEngine;public class MaterialSwitcher : MonoBehaviour {public Material newMaterial; // 新材质private Material oldMaterial; // 旧材质private Renderer renderer; // 渲染器组件…...

Java根据坐标经纬度计算两点距离(5种方法)、校验经纬度是否在圆/多边形区域内的算法推荐
目录 前言 一、根据坐标经纬度计算两点距离(5种方法) 1.方法一 2.方法二 3.方法三 4.方法四 5.方法五 5.1 POM引入第三方依赖 5.2 代码 6.测试结果对比 二、校验经纬度是否在制定区域内 1.判断一个坐标是否在圆形区域内 2.判断一个坐标是否…...
PIC单片机如何设计延时
PIC单片机如何设计延时 PIC单片机的延时基本有两种,一种是自己设计的delay()函数,另一种就是利用其自带的Time定时器。当然一般Time定时器的精度要高于自己设计delay()函数,Time定时器是单片机内部的硬件寄存器模块,而delay()函数是利用自加自减来实现延时,代码进行顺序执…...

FFmpeg常见命令行(二):FFmpeg转封装
前言 在Android音视频开发中,网上知识点过于零碎,自学起来难度非常大,不过音视频大牛Jhuster提出了《Android 音视频从入门到提高 - 任务列表》。本文是Android音视频任务列表的其中一个, 对应的要学习的内容是:如何使…...

全面升级:华为鸿蒙HarmonyOS4正式发布,玩趣个性化,小艺AI升级
8月4日新闻,今天下午,华为正式发布了最新版本的鸿蒙操作系统——HarmonyOS 4! 在华为发布会上,鸿蒙HarmonyOS迎来了一系列令人激动的功能升级。其中包括个性化空间、多种生产力工具以及增强的手机AI助手"小艺"。这次更…...

【python】使用Selenium和Chrome WebDriver来获取 【腾讯云 Cloud Studio 实战训练营】中的文章信息
文章目录 前言导入依赖库设置ChromeDriver的路径创建Chrome WebDriver对象打开网页找到结果元素创建一个空列表用于存储数据遍历结果元素并提取数据提取标题、作者、发布时间等信息判断是否为目标文章提取目标文章的描述、阅读数量、点赞数量、评论数量等信息将提取的数据存储为…...
使用Feign 的远程调用,把mysql数据导入es
要把数据库数据导入到elasticsearch中,包括下面几步: 1)将商品微服务中的分页查询商品接口定义为一个FeignClient,放到feign-api模块中 2)搜索服务编写一个测试业务,实现下面功能: 调用item-ser…...

Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...

【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果
C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...

深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...

wpf在image控件上快速显示内存图像
wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像(比如分辨率3000*3000的图像)的办法,尤其是想把内存中的裸数据(只有图像的数据,不包…...
前端中slice和splic的区别
1. slice slice 用于从数组中提取一部分元素,返回一个新的数组。 特点: 不修改原数组:slice 不会改变原数组,而是返回一个新的数组。提取数组的部分:slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...