JVM性能优化(五)源码图解jvm字节码

Jenna ·
更新时间:2024-09-20
· 675 次阅读

一、前言

前面我们通过tomcat本身的参数以及jvm的参数对tomcat做了优化,详情查看:tomcat优化,其实要想将应用程序跑的更快,效率更高,除了对tomcat容器以及jvm优化外,应用程序代码本身如果写的效率不高的,那么也是不行的,所以对于程序本身的优化也就很重要了。

对于程序本身的优化,可以借鉴很多前辈的经验,但是有些时候,在从源码角度分析的话,不好鉴别出哪个效率高,如对字符串拼接的操作,是直接“+”号拼接效率高还是使用StringBuilder效率高呢?

这个时候,就需要通过查看编译好的class文件中的字节码,就可以找到答案。

我们都知道,java编写应用,需要先通过javac命令编译成class文件,在通过jvm执行,jvm执行时是需要将class文件中的字节码载入到jvm进行运行的

二、通过javap命令查看class文件的字节码内容

首先,看一下简单的Test类的代码:

public class Test { public static void main(String[] args) { int a = 2; int b = 5; int c = b - a; System.out.println(c); } }

通过javap命令查看class文件中的字节码内容:
javap -v Test.class > Test.txt

用法: javap 其中, 可能的选项包括: -help --help -? 输出此用法消息 -version 版本信息 -v -verbose 输出附加信息 -l 输出行号和本地变量表 -public 仅显示公共类和成员 -protected 显示受保护的/公共类和成员 -package 显示程序包/受保护的/公共类 和成员 (默认) -p -private 显示所有类和成员 -c 对代码进行反汇编 -s 输出内部类型签名 -sysinfo 显示正在处理的类的 系统信息 (路径, 大小, 日期, MD5 散列) -constants 显示最终常量 -classpath 指定查找用户类文件的位置 -cp 指定查找用户类文件的位置 -bootclasspath 覆盖引导类文件的位置

当我们运行javap命令后会得到一个Test.txt的文件
内容如下:

# 显示生成这个class的java源文件、版本信息、生成时间等 Classfile /F:/project/test/target/classes/com/lyy/Test.class Last modified 2020-5-7; size 562 bytes MD5 checksum 58100edcdfebfd9769cdbb1b634baf3c Compiled from "Test.java" public class com.lyy.Test minor version: 0 major version: 49 flags: ACC_PUBLIC, ACC_SUPER # 显示了该类中所涉及的常量池,共35个常量 Constant pool: #1 = Class #2 // com/lyy/Test #2 = Utf8 com/lyy/Test #3 = Class #4 // java/lang/Object #4 = Utf8 java/lang/Object #5 = Utf8 #6 = Utf8 ()V #7 = Utf8 Code #8 = Methodref #3.#9 // java/lang/Object."":()V #9 = NameAndType #5:#6 // "":()V #10 = Utf8 LineNumberTable #11 = Utf8 LocalVariableTable #12 = Utf8 this #13 = Utf8 Lcom/lyy/Test; #14 = Utf8 main #15 = Utf8 ([Ljava/lang/String;)V #16 = Fieldref #17.#19 // java/lang/System.out:Ljava/io/PrintStream; #17 = Class #18 // java/lang/System #18 = Utf8 java/lang/System #19 = NameAndType #20:#21 // out:Ljava/io/PrintStream; #20 = Utf8 out #21 = Utf8 Ljava/io/PrintStream; #22 = Methodref #23.#25 // java/io/PrintStream.println:(I)V #23 = Class #24 // java/io/PrintStream #24 = Utf8 java/io/PrintStream #25 = NameAndType #26:#27 // println:(I)V #26 = Utf8 println #27 = Utf8 (I)V #28 = Utf8 args #29 = Utf8 [Ljava/lang/String; #30 = Utf8 a #31 = Utf8 I #32 = Utf8 b #33 = Utf8 c #34 = Utf8 SourceFile #35 = Utf8 Test.java #显示该类的构造器,编译器自动插入的 { public com.lyy.Test(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #8 // Method java/lang/Object."":()V 4: return LineNumberTable: line 3: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcom/lyy/Test; # 显示了main方的信息(这个是我们需要重点关注的) public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=4, args_size=1 0: iconst_2 1: istore_1 2: iconst_5 3: istore_2 4: iload_2 5: iload_1 6: isub 7: istore_3 8: getstatic #16 // Field java/lang/System.out:Ljava/io/PrintStream; 11: iload_3 12: invokevirtual #22 // Method java/io/PrintStream.println:(I)V 15: return LineNumberTable: line 6: 0 line 7: 2 line 8: 4 line 9: 8 line 10: 15 LocalVariableTable: Start Length Slot Name Signature 0 16 0 args [Ljava/lang/String; 2 14 1 a I 4 12 2 b I 8 8 3 c I } SourceFile: "Test.java"

生成的内容虽然看上去很多,但是总体来说,大致分为4个部分:

第一部分: 显示生成这个class的java源文件、版本信息、生成时间等
第二部分: 显示了该类中所涉及的常量池,共35个常量
第三部分: 显示该类的构造器,编译器自动插入的
第四部分: 显示了main方的信息(这个是我们需要重点关注的)

这么看的话我们是很难看懂里面的内容说的是什么的,我们需要对里面的参数一一作出说明,请往下看。

三、常量池

https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4-140

Constant Type Value 说明
CONSTANT_Class 7 类或接口的符号引用
CONSTANT_Fieldref 9 字段的符号引用
CONSTANT_Methodref 10 类中方法的符号引用
CONSTANT_InterfaceMethodref 11 接口中方法的符号引用
CONSTANT_String 8 字符串类型常量
CONSTANT_Integer 3 整形常量
CONSTANT_Float 4 浮点型常量
CONSTANT_Long 5 长整型常量
CONSTANT_Double 6 双精度浮点型常量
CONSTANT_NameAndType 12 字段或方法的符号引用
CONSTANT_Utf8 1 UTF-8编码的字符串
CONSTANT_MethodHandle 15 表示方法句柄
CONSTANT_MethodType 16 标志方法类型
CONSTANT_InvokeDynamic 18 表示一个动态方法调用点
四、描述符 4.1 字段描述符

api文档:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.3.2

术 语 类型 描述
B byte signed byte
C char Unicode character code point in the Basic Multilingual Plane, encoded with UTF-16
D double double-precision floating-point value
F float single-precision floating-point value
I int integer
J long long integer
L ClassName ; reference an instance of class ClassName
S short signed short
Z boolean true or false
[ reference one array dimension
4.1 方法描述符

示例:

方法的方法描述符:
原创文章 66获赞 512访问量 22万+ 关注 私信 展开阅读全文
作者:牧小农



jvm 优化 源码

需要 登录 后方可回复, 如果你还没有账号请 注册新账号