`

JVM学习笔记(五):根据字节码指令介绍方法执行流程

 
阅读更多

在上一篇博客中介绍了《Class文件结构》,其中就提到了一个例子,下面我们依然根据该例子的字节码来对方法的执行流程进行讲解。

     java类源码如下:

 

Java代码 复制代码 收藏代码
  1. public class TestClass{   
  2.     private int num;   
  3.        
  4.     public int inc(){   
  5.         for(int i=0; i<10; i++){   
  6.             num = i;   
  7.         }   
  8.         return num;   
  9.     }   
  10.        
  11.     public static void main(String[] args){   
  12.         new TestClass().inc();   
  13.     }   
  14.        
  15. }  
public class TestClass{
	private int num;
	
	public int inc(){
		for(int i=0; i<10; i++){
			num = i;
		}
		return num;
	}
	
	public static void main(String[] args){
		new TestClass().inc();
	}
	
}

使用javap -verbose命令反编译后,输出常量表和字节码如下:

 

Txt代码 复制代码 收藏代码
  1. D:\JVM>javap -verbose TestClass   
  2. Compiled from "TestClass.java"  
  3. public class TestClass extends java.lang.Object   
  4.   SourceFile: "TestClass.java"  
  5.   minor version: 0  
  6.   major version: 50  
  7.   Constant pool:   
  8. const #1 = Method       #6.#20; //  java/lang/Object."<init>":()V   
  9. const #2 = Field        #3.#21; //  TestClass.num:I   
  10. const #3 = class        #22;    //  TestClass   
  11. const #4 = Method       #3.#20; //  TestClass."<init>":()V   
  12. const #5 = Method       #3.#23; //  TestClass.inc:()I   
  13. const #6 = class        #24;    //  java/lang/Object   
  14. const #7 = Asciz        num;   
  15. const #8 = Asciz        I;   
  16. const #9 = Asciz        <init>;   
  17. const #10 = Asciz       ()V;   
  18. const #11 = Asciz       Code;   
  19. const #12 = Asciz       LineNumberTable;   
  20. const #13 = Asciz       inc;   
  21. const #14 = Asciz       ()I;   
  22. const #15 = Asciz       StackMapTable;   
  23. const #16 = Asciz       main;   
  24. const #17 = Asciz       ([Ljava/lang/String;)V;   
  25. const #18 = Asciz       SourceFile;   
  26. const #19 = Asciz       TestClass.java;   
  27. const #20 = NameAndType #9:#10;//  "<init>":()V   
  28. const #21 = NameAndType #7:#8;//  num:I   
  29. const #22 = Asciz       TestClass;   
  30. const #23 = NameAndType #13:#14;//  inc:()I   
  31. const #24 = Asciz       java/lang/Object;   
  32.   
  33. {   
  34. public TestClass();   
  35.   Code:   
  36.    Stack=1, Locals=1, Args_size=1  
  37.    0:   aload_0   
  38.    1:   invokespecial   #1; //Method java/lang/Object."<init>":()V   
  39.    4:   return   
  40.   LineNumberTable:   
  41.    line 10  
  42.   
  43.   
  44. public int inc();   
  45.   Code:   
  46.    Stack=2, Locals=2, Args_size=1  
  47.    0:   iconst_0        //定义一个常量0,放入操作数栈   
  48.    1:   istore_1        //把该常量弹出栈顶存入到局部变量表   
  49.    2:   iload_1         //把该局部变量放入操作数栈   
  50.    3:   bipush  10      //把常量10放入操作数栈   
  51.    5:   if_icmpge   19  //把i和10进行比较   
  52.    8:   aload_0         //加载局部变量表index为0的变量放入操作数栈   
  53.    9:   iload_1         //加载局部变量表index为1的变量放入操作数栈   
  54.    10:  putfield        #2; //Field num:I   //把i的值赋给num字段   
  55.    13:  iinc    11    //局部变量i自增1  
  56.    16:  goto    2       //跳转到第2行   
  57.    19:  aload_0         //加载局部变量表index为0的变量放入操作数栈   
  58.    20:  getfield        #2; //Field num:I   //获取字段num的值   
  59.    23:  ireturn         //返回   
  60.   LineNumberTable:   
  61.    line 50  
  62.    line 68  
  63.    line 513  
  64.    line 819  
  65.   
  66.   StackMapTable: number_of_entries = 2  
  67.    frame_type = 252 /* append */   
  68.      offset_delta = 2  
  69.      locals = [ int ]   
  70.    frame_type = 250 /* chop */   
  71.      offset_delta = 16  
  72.   
  73.   
  74. public static void main(java.lang.String[]);   
  75.   Code:   
  76.    Stack=2, Locals=1, Args_size=1  
  77.    0:   new     #3; //class TestClass   
  78.    3:   dup   
  79.    4:   invokespecial   #4; //Method "<init>":()V //调用实例初始化方法   
  80.    7:   invokevirtual   #5; //Method inc:()I        //调用普通方法inc()   
  81.    10:  pop   
  82.    11:  return   
  83.   LineNumberTable:   
  84.    line 120  
  85.    line 1311  
  86.   
  87.   
  88. }  
D:\JVM>javap -verbose TestClass
Compiled from "TestClass.java"
public class TestClass extends java.lang.Object
  SourceFile: "TestClass.java"
  minor version: 0
  major version: 50
  Constant pool:
const #1 = Method       #6.#20; //  java/lang/Object."<init>":()V
const #2 = Field        #3.#21; //  TestClass.num:I
const #3 = class        #22;    //  TestClass
const #4 = Method       #3.#20; //  TestClass."<init>":()V
const #5 = Method       #3.#23; //  TestClass.inc:()I
const #6 = class        #24;    //  java/lang/Object
const #7 = Asciz        num;
const #8 = Asciz        I;
const #9 = Asciz        <init>;
const #10 = Asciz       ()V;
const #11 = Asciz       Code;
const #12 = Asciz       LineNumberTable;
const #13 = Asciz       inc;
const #14 = Asciz       ()I;
const #15 = Asciz       StackMapTable;
const #16 = Asciz       main;
const #17 = Asciz       ([Ljava/lang/String;)V;
const #18 = Asciz       SourceFile;
const #19 = Asciz       TestClass.java;
const #20 = NameAndType #9:#10;//  "<init>":()V
const #21 = NameAndType #7:#8;//  num:I
const #22 = Asciz       TestClass;
const #23 = NameAndType #13:#14;//  inc:()I
const #24 = Asciz       java/lang/Object;

{
public TestClass();
  Code:
   Stack=1, Locals=1, Args_size=1
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return
  LineNumberTable:
   line 1: 0


public int inc();
  Code:
   Stack=2, Locals=2, Args_size=1
   0:   iconst_0		//定义一个常量0,放入操作数栈
   1:   istore_1		//把该常量弹出栈顶存入到局部变量表
   2:   iload_1			//把该局部变量放入操作数栈
   3:   bipush  10		//把常量10放入操作数栈
   5:   if_icmpge   19	//把i和10进行比较
   8:   aload_0			//加载局部变量表index为0的变量放入操作数栈
   9:   iload_1			//加载局部变量表index为1的变量放入操作数栈
   10:  putfield     	#2; //Field num:I	//把i的值赋给num字段
   13:  iinc    1, 1	//局部变量i自增1
   16:  goto    2		//跳转到第2行
   19:  aload_0			//加载局部变量表index为0的变量放入操作数栈
   20:  getfield        #2; //Field num:I	//获取字段num的值
   23:  ireturn			//返回
  LineNumberTable:
   line 5: 0
   line 6: 8
   line 5: 13
   line 8: 19

  StackMapTable: number_of_entries = 2
   frame_type = 252 /* append */
     offset_delta = 2
     locals = [ int ]
   frame_type = 250 /* chop */
     offset_delta = 16


public static void main(java.lang.String[]);
  Code:
   Stack=2, Locals=1, Args_size=1
   0:   new     #3; //class TestClass
   3:   dup
   4:   invokespecial   #4; //Method "<init>":()V	//调用实例初始化方法
   7:   invokevirtual   #5; //Method inc:()I		//调用普通方法inc()
   10:  pop
   11:  return
  LineNumberTable:
   line 12: 0
   line 13: 11


}

 

方法的调用指令分为以下几种:

  1. invokevirtual指令用于调用所有的虚方法。
  2. invokeinterface指令用于调用接口方法,它会在运行时搜索一个实现了这个接口方法的对象,找出适合的方法进行调用。
  3. invokespecial指令用于调用一些需要特殊处理的实例方法,包括实例构造器<init>化方法、私有方法和父类方法。
  4. invokestatic指令用于调用静态方法(static方法)。
分享到:
评论

相关推荐

    jvm指令手册 +JVM必知必会,掌握虚拟机编译过程.rar

    《JVM必知必会》记录了对JVM的总结及学习笔记,详解的介绍了什么是jvm,以及弄清楚jvm的工作原理等等,会深入了解JVM有一定的帮助。 Java Virtual Machine(Java虚拟机),它bai是一个虚构出来du的计算机,是通过在...

    JVM学习笔记

    ### JVM学习笔记 #### JVM内存模型 (JMM) JVM内存模型主要分为以下几个部分: - **Java堆**:这是所有线程共享的一块区域,在虚拟机启动时创建。主要用于存放对象实例,几乎所有的对象实例都在这里分配内存。 - *...

    jvm中篇笔记.md

    Class 文件作为 Java 程序的基石,不仅定义了程序的逻辑结构,还通过字节码指令提供了程序执行的具体指导。此外,通过深入理解字节码指令,开发者可以更深刻地了解 Java 语言的行为,并利用这些知识来优化代码性能。...

    狂神说JVM探究.rar

    - 程序计数器:记录当前线程执行的字节码指令地址。 - Java虚拟机栈:每个方法对应一个栈帧,存储局部变量表、操作数栈、动态链接和方法出口等信息。 - 本地方法栈:与JVM栈类似,但服务于Java Native Interface...

    JVM的学习笔记PDF版

    类装载器负责加载类文件,运行数据区存储程序运行时的数据,执行引擎负责执行字节码,本地方法接口用于调用非Java语言编写的本地方法,而本地库则包含这些本地方法。 2. **类加载机制**:Java的类加载过程包括加载...

    HelloWorld的javap -verbose HelloWorld 字节码初探

    JVM指令集是Java字节码的具体实现,每一行字节码对应一个或多个JVM指令,这些指令控制着JVM的运行流程。了解JVM指令有助于深入理解Java程序的执行机制,例如内存管理、方法调用、运算操作等。 结合以上信息,我们...

    jvm学习笔记

    《JVM学习笔记》 Java虚拟机(JVM)是Java平台的核心组成部分,它负责运行所有的Java应用程序。这篇笔记将深入探讨JVM的工作原理、内存管理、类加载机制以及优化策略,帮助读者全面理解JVM并提升Java程序的性能。 ...

    深入JVM笔记word版

    - **字节码执行**: 字节码解释器通过修改程序计数器的值来选择下一条需要执行的字节码指令。 - **多线程支持**: 当线程切换时,程序计数器确保线程能够恢复到正确的执行位置。由于每个线程都需要一个独立的程序...

    JVM学习笔记核心知识点整理

    ### JVM学习笔记核心知识点整理 #### 一、引言与背景 随着软件开发技术的不断发展,Java作为一种广泛应用的编程语言,其背后的核心技术——Java虚拟机(JVM)的重要性日益凸显。掌握JVM不仅可以帮助开发者更好地理解...

    JVM思维导图,学习思维笔记

    4. 程序计数器(Program Counter Register):每个线程都有一个独立的程序计数器,记录当前线程正在执行的字节码指令地址。 5. 本地方法栈(Native Method Stack):与Java方法栈类似,但服务于本地(非Java)方法...

    java之jvm学习笔记十二(访问控制器的栈校验机制)

    本篇学习笔记将深入探讨这一主题,主要关注Java字节码的执行过程以及如何通过栈校验来防止非法操作。 Java字节码是由Java编译器生成的中间代码,它在JVM上运行前会经过类加载器的验证,其中栈校验是验证的一部分。...

    JVM+学习笔记资源合集

    JVM在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器指令执行。 JVM一直是java知识里面进阶阶段的重要部分,如果希望在java领域研究的更深入,则JVM则是如论如何也避开不了的话题,本系列试图通过...

    java之jvm学习笔记十而(访问控制器的栈校验机制)

    Java虚拟机(JVM)是Java程序运行的核心,它负责解释和执行字节码,确保程序的正确运行。在JVM的设计中,访问控制器扮演着关键角色,它负责执行严格的类型检查,确保代码的安全性。本文将深入探讨“访问控制器的栈...

    JVM性能学习笔记思维导图

    - **程序计数器**(PC Register):记录当前线程正在执行的字节码指令地址。 - **方法区/元空间**(Method Area/Metaspace):存储已加载的类信息、常量、静态变量、即时编译后的代码等数据。 3. **JVM性能优化核心**...

    JVM内存管理学习笔记

    5. 程序计数器:记录当前线程正在执行的字节码指令地址,用于多线程环境下切换线程时恢复执行状态。 二、垃圾收集机制 Java的垃圾收集器负责自动回收不再使用的对象所占用的内存,避免内存泄漏。主要的垃圾收集...

    java之jvm学习笔记十而(访问控制器的栈校验机制)-步骤2源码

    在JVM的解释器中,每当遇到一个字节码指令,如`istore`(存储int类型到局部变量表)或`invokevirtual`(调用虚方法)时,都会触发栈校验。这个过程发生在类加载的验证阶段,确保类的方法体不会进行非法操作。 步骤2...

    jvm-study:jvm学习笔记

    - **程序计数器**:记录当前线程正在执行的虚拟机字节码指令的地址。 - **本地方法栈**:非Java方法(如C++的JNI方法)的调用栈。 3. **类加载机制** - 类加载分为加载、验证、准备、解析和初始化五个阶段。 - ...

    学习jvm笔记.zip

    Java虚拟机(JVM)是Java程序运行的基础,它是一个抽象的计算机系统,负责执行Java字节码。在深入理解JVM之前,我们先要明白它的核心概念:类加载、内存管理、执行引擎、垃圾回收以及性能优化。 一、类加载机制 JVM...

Global site tag (gtag.js) - Google Analytics