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核心方法。

HotSpot虚拟机之Class文件及字节码指令_第1张图片

        javac编译过程:一个准备(初始化插入式注解处理器);三个处理(解析与填充符号表、处理注解处理器、语义分析与字节码生成),如下图所示。

HotSpot虚拟机之Class文件及字节码指令_第2张图片

HotSpot虚拟机之Class文件及字节码指令_第3张图片

        需要注意的是:生成()、()方法在编译期完成;Lombok操作通过插入式注解处理器完成对字段的getter()和setter()方法

2. 语法糖 

HotSpot虚拟机之Class文件及字节码指令_第4张图片

二、Class文件

1. 文件格式 

        Class文件是字节为单位的二进制流,有两种数据类型:无符号数、表,如下图所示。Class文件不保存方法、字段最终的内存布局信息,JVM运行期才能找到内存入口地址

HotSpot虚拟机之Class文件及字节码指令_第5张图片

        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_infoCode;

3.“描述符:字段的数据类型、方法的参数列表及返回值

4.不会列出父类或接口的方法(重写除外)

5.可能含有JVM自动生成的方法,如:()()方法

u2

attributes_count

1

属性表数量

attribute_info

attributes

attributes_count

1.Class文件、字段、方法都有自己的属性;

2.属性只要不重名,任何编译器都可以添加自己的属性信息

2. 常量池项目

        常量池有两大类常量:字面量、符号引用。当类加载时,从常量池获得对应的符号引用,再在类创建或运行解析时,翻译到具体的内存地址中。如下表所示是17种不同类型的常量。

HotSpot虚拟机之Class文件及字节码指令_第6张图片

        “描述符”作用是描述字段的数据类型、方法的参数列表(包括:数量、类型、顺序)、返回值。数组类型,每一个维度用前置的“[”标识,如:void inc(int[ ] ints)其描述符为([I)V。下表所示是描述符标识字符含义。

HotSpot虚拟机之Class文件及字节码指令_第7张图片

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.如:实例构造器()、类构造器();

其他: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 queue;
    private ThreadPoolExecutor executor;

    public Object submitFuture(final HttpServletRequest request, final Callable task) throws ExecutionException, InterruptedException {
        // 获取请求URI
        final String uri = request.getRequestURI();
        // 获取请求参数
        final Map 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 future = executor.submit(new Callable() {
            @Override
            public Object call() throws Exception {
                // 业务处理
                Object result = task.call();
                return result;
            }
        });
        // 完成异步上下文,否则报超时等异常
        asyncContext.complete();
        return future.get();
    }



    // 完成初始化配置
    @Override
    public void afterPropertiesSet() throws Exception {
        // 线程池大小
        int corePoolSize = Integer.parseInt("100");
        // 最大线程池大小
        int maxNumPoolSize = Integer.parseInt("200");
        // 任务队列
        queue = new LinkedBlockingDeque();
        // 创建线程池
        executor = new ThreadPoolExecutor(corePoolSize, maxNumPoolSize, 100, TimeUnit.MILLISECONDS, queue);

        executor.allowCoreThreadTimeOut(true);
        // 线程池饱和处理
        executor.setRejectedExecutionHandler(new RejectedExecutionHandler() {
            @Override
            public 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() {
                @Override
                public void onComplete(AsyncEvent asyncEvent) throws IOException {

                }

                @Override
                public 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();
                    }
                }

                @Override
                public 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();
                    }
                }

                @Override
                public 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.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

HotSpot虚拟机之Class文件及字节码指令_第8张图片

HotSpot虚拟机之Class文件及字节码指令_第9张图片

HotSpot虚拟机之Class文件及字节码指令_第10张图片

HotSpot虚拟机之Class文件及字节码指令_第11张图片

四、字节码指令

        Java各种语法、关键字、常量变量、符号运算的语义最终都会由多个字节码指令组合来表达。Java虚拟机字节码指令组成如下所示:操作码(Opcode)、操作数(Operand)。

       Java虚拟机面向操作数栈而不是面向寄存器的架构,其总数不超过256条(单字节),指令分类如下表所示。 

指令类型

指令作用

指令

加载和存储

局部表加载到操作数栈

1.iload、iload_、aload、aload_、......;

2._:其中n表示局部变量表的slot索引位置

操作数栈存储到局部表

1.istore、istore_、astore、astore_、......;

2._:其中n表示局部变量表的slot索引位置。

常量加载到操作数栈

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博客

你可能感兴趣的:(JVM,Class文件,语法糖,javac,字节码)