热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

java字节码执行_深入浅出JVM之字节码执行

1.javap反汇编工具javap是jdk自带的反汇编工具,可以通过该命令查看编译后的class文件的常量池、字段以及方法等信息。对于下面的这个类:pu

1.javap反汇编工具

javap是jdk自带的反汇编工具,可以通过该命令查看编译后的class文件的常量池、字段以及方法等信息。

对于下面的这个类:

public class CalcCirc {

public int doCalc() {

int a=10;

int b=20;

int c=2;

return (a+b)*c;

}

}

使用javap -v CalcCirc.class可以看到该类的反汇编信息如下:

public int doCalc();

descriptor: ()I

flags: ACC_PUBLIC

Code:

stack=2, locals=4, args_size=1

0: bipush 10

2: istore_1

3: bipush 20

5: istore_2

6: iconst_2

7: istore_3

8: iload_1

9: iload_2

10: iadd

11: iload_3

12: imul

13: ireturn

.....//这里省去了LineNumberTable以及LocalVariableTable

stack=2表示在操作数栈的深度为2,这个一般是在编译的时候确定的,与方法中单一语句的执行复杂度有关,如果这条语句比较复杂,那么statck的数值就会增大。

locals=4表示有4个局部变量,源代码定义了a、b、c三个,再加上this变量,一共是4个局部变量。

args_size=1表示参数的个数,默认是1个参数,如果在方法中增加其他的参数则该数量会增加。

2.简单的字节码执行过程

字节码的执行过程需要关注的有以下内容:程序计数器、局部变量表、操作数栈。程序计数器用来指定程序当前运行的指针,也就是字节码的偏移量,对应的是字节码操作符前面的数字。局部变量表用来保存局部变量的最终结果,这里有4个局部变量,那么局部变量表的大小为4。操作数栈是保存执行过程中的实际内容,可以是局部变量的值,也可以是对象的引用。

执行第一条语句:0: bipush 10,程序计数器指向偏移量0,局部变量表中有this变量,将数字10压入操作数栈,执行后的结果如下:

​程序计数器0局部变量表0this123操作数栈10

执行第二条语句:2: istore_1,将栈顶中的数值赋值给变量1:

​程序计数器2局部变量表0this11023操作数栈

执行第三条语句:3: bipush 20,将数值20压入栈中:

​程序计数器3局部变量表0this11023操作数栈20

执行第四条语句:5: istore_2,将栈顶中元素赋值给局部变量2:

​程序计数器5局部变量表0this1102203操作数栈

执行第五条语句:6: iconst_2,将常量2压入栈中, 当int取值-1~5采用iconst指令,取值-128~127采用bipush指令,取值-32768~32767采用sipush指令,取值-2147483648~2147483647采用 ldc 指令 :

​程序计数器6局部变量表0this1102203操作数栈2

执行第六条语句:7: istore_3,将栈顶中元素赋值给局部变量3:

​程序计数器5局部变量表0this11022032操作数栈

后面的语句依次是加载局部变量1和局部变量2,iadd是从栈顶中取两个元素做加法,然后将结果放入栈中,然后加载局部变量3,imul从栈中获取两个元素做乘法,并将结果返回栈中,ireturn是将栈顶元素返回,这个返回值作为函数的返回值。

3.常用的字节码

字节码指令为一个byte整数,不同的整数代表不同的执行命令,常用的字节码指令如下:

常量入栈:

局部变量入栈: xload_n(n为0 1 2 3):x分别表示int,long,float,double,object ref,n表示局部变量下表 xaload(x为i l f d a b c s):x分别表示int, long, float, double, obj ref ,byte,char,short,该指令将从数组中取得给定索引的值,将该值压栈。比如iaload,执行前,栈:..., arrayref, index,它取得arrayref所在数组的index的值,并将值压栈。执行后,栈:..., value

出栈装载入局部变量: xstore_n(x为i l f d a,n为 0 1 2 3):将栈顶元素出栈,存入第n个局部变量 xastore(x为i l f d a b c s):将值存入数组中,iastore 执行前,栈:...,arrayref, index, value 执行后,栈:... 将value存入arrayref[index]

通用操作:nop, pop:弹出栈顶元素,dup:复制栈顶元素,复制的内容压入栈中

类型转化:i2l,i2f,d2l:将int转化为long,int转化为float,double转化为long

整数运算:iadd:int相加

浮点运算:fadd:float相加

对象操作:new:新建一个对象,getfield:获取一个对象字段,getstatic:获取静态变量

条件控制:ifeq:如果是0,则跳转,比较栈顶元素是否为0,如果是0则跳转到指定语句。

方法调用:

invokevirtual:调用实例方法,它是动态分配的调用指令,引用的类型并不能决定方法属于哪个类型,需要在实际运行的时候才能确定。 invokespecial: 调用实例初始化,父类初始化和私有方法。 invokestatic: 调用一个类(static)方法。 invokeinterface:调用类的接口方法 xreturn(x为 i l f d a 或为空):返回值,a为返回一个对象的引用

4.使用ASM生成Java字节码

ASM是java字节码操作框架,可以用于修改现有类或者动态生成新类,比如spring,AspectJ等都使用了asm框架。cglib对ASM做了一层封装,其他的框架会使用cglib来对类进行操作。

5.JIT及其相关的参数

字节码执行性能较差,对于热点代码编译成机器码再执行,在运行时的编译,叫做JIT:Just-In-Time。

所谓的热点代码是只调用的方法,或者被多次调用的循环体。jvm里会有方法调用计数器(方法调用次数)和回边计数器(方法内循环次数),通过判断这些计数器的数值是否超过阈值来判断是否将热点代码编译成机器码来执行。

-XX:CompileThreshold=1000:设置计数器的阈值 -XX:+PrintCompilation:打印出已经编译成机器码的方法



推荐阅读
  • 深入解析Java虚拟机(JVM)架构与原理
    本文旨在为读者提供对Java虚拟机(JVM)的全面理解,涵盖其主要组成部分、工作原理及其在不同平台上的实现。通过详细探讨JVM的结构和内部机制,帮助开发者更好地掌握Java编程的核心技术。 ... [详细]
  • 2017-2018年度《网络编程与安全》第五次实验报告
    本报告详细记录了2017-2018学年《网络编程与安全》课程第五次实验的具体内容、实验过程、遇到的问题及解决方案。 ... [详细]
  • Linux系统中Java程序Too Many Open Files问题的深入解析与解决方案
    本文详细分析了在Linux环境下运行的Java应用程序中可能出现的“Too many open files”异常现象,探讨其成因及解决方法。该问题通常出现在高并发文件访问或大量网络连接场景下,对系统性能和稳定性有较大影响。 ... [详细]
  • 2018-2019学年第六周《Java数据结构与算法》学习总结
    本文总结了2018-2019学年第六周在《Java数据结构与算法》课程中的学习内容,重点介绍了非线性数据结构——树的相关知识及其应用。 ... [详细]
  • 深入理解Java字符串池机制
    本文详细解析了Java中的字符串池(String Pool)机制,探讨其工作原理、实现方式及其对性能的影响。通过具体的代码示例和分析,帮助读者更好地理解和应用这一重要特性。 ... [详细]
  • 本文介绍了在Java环境中使用PDFBox和XPDF工具从PDF文件中提取文本内容的方法。重点讨论了处理中文字符集及解决相关错误的技术细节,特别是针对某些特定格式的PDF文件(如网上填写的报名表和下载的论文)遇到的问题及解决方案。 ... [详细]
  • 深入解析Java枚举及其高级特性
    本文详细介绍了Java枚举的概念、语法、使用规则和应用场景,并探讨了其在实际编程中的高级应用。所有相关内容已收录于GitHub仓库[JavaLearningmanual](https://github.com/Ziphtracks/JavaLearningmanual),欢迎Star并持续关注。 ... [详细]
  • 实用正则表达式有哪些
    小编给大家分享一下实用正则表达式有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下 ... [详细]
  • 本文详细介绍了如何正确配置Java环境变量PATH,以确保JDK安装完成后能够正常运行。文章不仅涵盖了基本的环境变量设置步骤,还提供了针对不同操作系统下的具体操作指南。 ... [详细]
  • 洞态IAST Java Agent 实现AOP技术详解
    本文深入探讨了洞态IAST Java Agent如何通过AOP技术实现方法调用链和污点值传播等功能,为读者提供了详细的源码分析。 ... [详细]
  • 本文详细介绍了Java中的注解功能,包括如何定义注解类型、设置注解的应用范围及生命周期,并通过具体示例展示了如何利用反射机制访问注解信息。 ... [详细]
  • 前言无论是对于刚入行工作还是已经工作几年的java开发者来说,面试求职始终是你需要直面的一件事情。首先梳理自己的知识体系,针对性准备,会有事半功倍的效果。我们往往会把重点放在技术上 ... [详细]
  • 本文探讨了Web开发与游戏开发之间的主要区别,旨在帮助开发者更好地理解两种开发领域的特性和需求。文章基于作者的实际经验和网络资料整理而成。 ... [详细]
  • Java 架构:深入理解 JDK 动态代理机制
    代理模式是 Java 中常用的设计模式之一,其核心在于代理类与委托类共享相同的接口。代理类主要用于为委托类提供预处理、过滤、转发及后处理等功能,以增强或改变原有功能的行为。 ... [详细]
  • 本文详细介绍了JSP的三大指令:page、include和taglib,重点探讨了静态包含与动态包含的区别及其应用场景,并解释了如何使用taglib指令引入第三方标签库。 ... [详细]
author-avatar
独自从不变
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有