`
lijingyao8206
  • 浏览: 219285 次
  • 性别: Icon_minigender_2
  • 来自: 杭州
社区版块
存档分类
最新评论

JVM StackMapTable 属性的作用及理解

阅读更多

 

      Java 6版本之后JVM引入了栈图(Stack Map Table)概念。为了提高验证过程的效率,在字节码规范中添加了Stack Map Table属性,以下简称栈图,其方法的code属性中存储了局部变量和操作数的类型验证以及字节码的偏移量。也就是一个method需要且仅对应一个Stack Map Table。在Java 7版本之后把栈图作为字节码文件中的强制部分。 本来程序员是不需要关心JVM 中的JIT编译器的细节,也不用知道编译原理或者数据流、控制流的细节。但栈图强制了,如果要生成bytecode,必须准确知道每个字节码指令对应的局部变量和操作数栈的类型。这是因为Java7在编译的时期做了一些验证期间要做的事情,那就是类型检查,也就是栈图包含的内容。

     想想都比较抓狂,但是JVM 做的这一点点性能优化对整体性能提升也没起到什么卵用。Java的验证在类加载的时候只会运行一次,而占据了大部分时间的操作是IO的消耗,而不是验证过程。即使现在有了栈图,验证过程依然会执行,栈图的存在只是节省了一部分的验证时间。并且JVM的设计者还必须兼容没有栈图的验证的实现,因为Java7以前版本是没有强制栈图这个概念的,然而Java8 依然延续了栈图的字节码结构。

     下面来结合一个例子看一下栈图的结构。

   Java代码如下:

package bytecode;
 
/**
 * Created by yunshen.ljy on 2015/6/16.
 */
public class Coffee {
 
    int bean;
 
    public void getBean(int var) {
        if (var > 0) {
            this.bean = var;
        } else {
            throw new IllegalArgumentException();
        }
    }
 
}

 

 

     来看一下getBean方法中的字节码,然后重点看StackMapTable,栈图包含了两个entry

public void getBean(int);
  Code:
   Stack=2, Locals=2, Args_size=2
   0:        iload_1
   1:        ifle    12
   4:        aload_0
   5:        iload_1
   6:        putfield    #2; //Field bean:I
   9:        goto 20
   12:      new #3; //class java/lang/IllegalArgumentException
   15:      dup
   16:      invokespecial   #4; //Method java/lang/IllegalArgumentException."<init>":()V
   19:      athrow
   20:      return
  LineNumberTable:
   line 11: 0
   line 12: 4
   line 14: 12
   line 16: 20
 
  StackMapTable: number_of_entries = 2
   frame_type = 12 /* same */
   frame_type = 7 /* same */

 

 

       最后三行,看到了StackMapTable,没错这个就是栈图。StackMapTable包含了attribute_name_indexattribute_lengthnumber_of_entries以及entries结构。其中number_of_entries代表了栈图frame的个数。在这里我们的entries  frame_type = 12 /* same */ frame_type = 7 /* same */。每一个entry元素都代表了一个方法的StackMapFrame。其包含了字节码的偏移量和局部变量表、操作数栈的验证类型,所以entry的顺序是很重要的。其实第一个StackMapFrame是隐式的,并且是通过类型检查器的方法描述计算出来。这里我们看到的frame_type = 12 /* same */ 其实是方法的第二个StackMapFrame,只不过是显示的StackMapFrame

     这里先补充一点字节码指令和参数概念,字节码的指令,是由一个字节长度的助记符表示的操作码(Opcode)以及其随后的需要操作的若干参数构成。有的指令并不一定需要参数。但这里注意不要混淆一个概念,这里的参数和操作数(oprends)不是同一个概念。这里的arguments(参数)是静态的值,编译期就存储在编译后的字节码中,而Oprends(操作数)的值第一节介绍的操作数栈中运行期才知道值的数据结构。不知道讲清楚没有,但发现很多译文以及文章都会混淆指令集的“参数”和操作数栈的“操作数”。其实参数是以一个字节为单位的有符号整型,用于指向跳转目标地址,如果是超过一个字节,就以两个参数存储,两个参数还是依照高位在前的方式存储。 如:目标指令地址 = goto指令地址 + ( 参数1 << 8 | 参数2 )

     所以这里的偏移量要这样计算,在本例中frame_type =12 ,这里12 是这一个frame的字节码偏移量,即offset_delta。下一个StackMapFrame的偏移量是offset_delta+1。在本例中是7+1=8。所以我们看到ifle  12,字节码指令的参数是12,所以entries中第一个StackMapFrameoffset_delta=12,同理 goto 20 其实是goto 12+8entries第二个StackMapFrameoffset_delta=8。所以StackMapTable通过记录偏移量来保证字节序,并且不会重复记录。

    本例中的StackMapFrame frame_type /* same */项表示当前帧和前一帧有相同的局部变量,并且当前操作数栈为空。对于当前局部变量表和操作数栈的数据流可以参考之前的一篇例子。http://yunshen0909.iteye.com/blog/2221144 。本文主要结合JVM 8规范,如有错误请指正。

 

 

7
3
分享到:
评论
3 楼 lijingyao8206 2017-11-22  
爱淘宝的大伟 写道
美女cto,

StackMapTable: number_of_entries = 2 
   frame_type = 12 /* same */ 
   frame_type = 7 /* same */



12,7 是怎么计算出来的的?分别代表什么?

现在文章都在csdn维护了,可以看http://blog.csdn.net/lijingyao8206/article/details/46715405 。前两天更新了一下文章内容,对于计算字节码偏移量会有更详细的解释
2 楼 爱淘宝的大伟 2017-09-01  
美女cto,

StackMapTable: number_of_entries = 2 
   frame_type = 12 /* same */ 
   frame_type = 7 /* same */



12,7 是怎么计算出来的的?分别代表什么?
1 楼 haohaokan123 2015-08-10  
膜拜中!!新手值得收藏的中文API帮助,新手且英文不好的福音,全是中文翻译的,一个很不错的中文API帮助
需要的朋友自己去看看。www.apicx.com

相关推荐

    全面理解JVM虚拟机.pdf

    全面理解JVM虚拟机.pdf

    深入理解jvm虚拟机

    了解这些组件各自的作用和工作方式,是理解JVM运行机制的基础。 2. 类加载机制:Java类文件在被JVM执行之前,需要通过类加载器加载到内存中。类加载器采用双亲委派模型来完成类的加载。类加载过程涉及加载、验证、...

    深入理解JVM.rar

    每个使用Java的开发者都知道Java字节码是在JRE中运行,而JVM则是JRE中的核心组成部分,承担分析和执行Java字节码的工作,而Java程序员通常并不需要深入了解JVM运行情况就可以开发出大型应用和类库。尽管如此,如果你...

    JVM规范与深入理解

    《JVM规范与深入理解》这个主题涵盖了Java虚拟机(Java Virtual Machine)的全面解析,旨在帮助开发者深入了解JVM的工作原理及其对程序性能的影响。在这个主题中,我们主要关注两个核心资源:周志明的《深入理解Java...

    深入理解JVM&G1; GC

    《深入理解JVM & G1 GC》一书深入剖析了Java虚拟机(JVM)的工作原理,特别是针对垃圾收集器(GC)中的G1(Garbage-First)算法进行了详尽的探讨。JVM是Java程序运行的基础,它负责解析、编译、执行Java代码,并管理...

    jvm和gc详解及调优

    了解这些组件的作用和交互方式是理解JVM工作流程的基础。 2. **内存模型**:JVM的内存分为堆内存(Heap)、栈内存(Stack)、方法区(Method Area)、程序计数器(PC Register)和本地方法栈(Native Method Stack...

    jvm 详细介绍,了解jvm各个组成部分和功能

    ### JVM 详细介绍:掌握 JVM 的各个组成部分与功能 #### 一、Java 源文件编译及执行 Java 应用程序的核心...理解 JVM 的内部工作原理有助于开发者更好地编写高质量的 Java 应用程序,并有效解决运行时遇到的问题。

    深入理解JVM.

    深入理解JVM,首先要明白Java技术的组成部分,包括Java编程语言、Java类文件格式、Java虚拟机(JVM)和Java应用程序接口(Java API)。这些组件共同构成了Java平台,使得Java程序能够实现跨平台运行。 Java虚拟机是...

    圣思园张龙 深入理解jvm

    根据提供的文件信息,“圣思园张龙 深入理解jvm”,我们可以推断出这份资料主要关注于Java虚拟机(JVM)的深入理解和实践应用。JVM是Java开发环境中非常核心的一个组成部分,它不仅为Java程序提供了运行时环境,还负责...

    jvm视频及笔记

    "jvm视频及笔记"这个资源显然是一份全面学习JVM的材料,结合了视频教程和书面笔记,帮助学习者深入理解JVM的工作原理及其在实际开发中的应用。 JVM的学习可以从以下几个重要的知识点开始: 1. **JVM架构**:JVM...

    深入理解Java虚拟机JVM高级特性与最佳实践1

    《深入理解Java虚拟机JVM高级特性与最佳实践》是一本专注于Java开发人员提升技术水平的著作,由周志明撰写。这本书旨在填补Java技术体系中关于Java虚拟机(JVM)知识的空白,帮助读者深入理解JVM的工作原理及其对...

    JVM 完整深入解析.pdf

    本地方法栈的作用与虚拟机栈相似,区别在于它服务于虚拟机使用到的本地方法(native方法)。Java虚拟机规范并未规定其具体实现,通常由具体的虚拟机实现来决定如何处理。 #### 方法区 方法区是线程共享的内存区域,...

    深入理解jvm

    《深入理解Java虚拟机》是一本深度探讨Java虚拟机(JVM)的权威著作,旨在帮助读者全面了解和掌握JVM的工作原理与优化技术。这本书的内容涵盖了JVM的基础概念、内存管理、类加载机制、执行引擎、垃圾收集、性能调优...

    深入理解JVM内幕:从基本结构到Java 7新特性

    Java虚拟机(JVM)是Java程序的核心组件,它负责解析和执行Java字节码,使得Java具有“一次编译,到处运行”的特性。...深入理解JVM,可以帮助开发者更好地应对各种运行时问题,提升应用程序的稳定性和效率。

    [转载]深入理解JVM

    ### 深入理解JVM #### 一、Java技术与Java虚拟机 Java不仅仅是一种编程语言,更是一项综合性的技术。它主要包括四个关键组成部分: 1. **Java编程语言**:这是一种面向对象的编程语言,提供了丰富的类库支持,...

    jvm_code深入理解.zip

    《深入理解JVM虚拟机》是一本深受Java开发者喜爱的经典著作,它详尽地剖析了Java虚拟机的工作原理,帮助读者提升对Java程序运行机制的深入理解。这本书的第二版更是加入了更多最新的JVM特性,使得学习内容更加全面且...

    深入理解JVM&G1GC

    《深入理解JVM & G1 GC》主要为学习Java语言的学生、初级程序员提供GC的使用参考建议及经验,着重介绍了G1 GC。中国的软件开发行业已经有几十年了,从目前的行业发展来看,单纯的软件公司很难有发展,目前流 资源太...

    深入理解Java虚拟机.rar_JAVA虚拟机_java_深入理解JVM:pdf_深入理解Java_深入理解jvm

    了解jvm的pdf,高清pdf,希望大家下载

    jvm初识及JIT优化

    jvm初识及JIT优化jvm初识及JIT优化jvm初识及JIT优化jvm初识及JIT优化jvm初识及JIT优化jvm初识及JIT优化jvm初识及JIT优化jvm初识及JIT优化jvm初识及JIT优化jvm初识及JIT优化jvm初识及JIT优化jvm初识及JIT优化jvm初识...

Global site tag (gtag.js) - Google Analytics