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

使用-XX:+PrintAssembly打印asm代码遇到的问题

 
阅读更多

       要用PrintAssembly的目的 应该会另开帖子说明,本帖只是为了记录为了简单的记录使用这个命令遇到的问题.

 

      1 ,直接使用,用的是

写道
C:\Users\zhenghui>java -version
java version "1.7.0_25"
Java(TM) SE Runtime Environment (build 1.7.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 23.25-b01, mixed mode)

 该版本,当然,必须用不了咯..继续google.发现,需要用fastjson版本的jdk.然后,继续找.

       2,找到对应的下载地址. http://download.java.net/jdk6/6u25/promoted/b03/index.html

 注意,需要下载debug版本的.下载下来是一个jar,双击运行.然后就可以安装.

这里下载的b03版本,有可能在window下跑不通,每次运行都会造成jvm crash.可以换一下b01的试试

http://download.java.net/jdk6/6u25/promoted/b01/index.html  

 

     3  然后,就运行试试.继续遇到问题

写道
D:\software\jdk6_fastdebug\jdk1.6.0_25\fastdebug\bin>java -XX:+UnlockDiagnosticV
MOptions -XX:+PrintAssembly Test
VM option '+UnlockDiagnosticVMOptions'
VM option '+PrintAssembly'
Java HotSpot(TM) Client VM warning: PrintAssembly is enabled; turning on DebugNo
nSafepoints to gain additional output
Could not load hsdis-i386.dll; library not loadable; PrintAssembly is disabled

  4 后续就是找hsdis-i386.dll 的问题了.这也是我用时间最久的地方.我按照stackoverflow的说明,自己build这货,但是死的很惨,一直没成功.具体就不多说了,最后还是万能的撒迦告诉了我答案. 

RednaxelaFX 写道
是撒迦…  

这个疑问在之前某帖的回复里有提到:HotSpot的JIT编译器遇到简单无限循环时
RednaxelaFX 写道
lvgang 写道
好文,很有深度,就是看不太懂,呵呵。有个问题向博主请教,从上面打印出来的汇编代码来看,貌似是 gnu as,windows 上也能用 gnu as?

是的,这个是由GNU binutils里的as提供反汇编功能。
Sun HotSpot需要一个反汇编插件才可以使用-XX:+PrintAssembly参数来打印JIT编译生成的代码。该插件有一组通用接口,本来是可以用任意反汇编器套个适配器就行。官方提供了一个现成的版本(hsdis)是基于gas的,我懒于是就直接用它了。在Windows上直接build我还没成功过,用MinGW和Cygwin都试过不行。我用的版本是在Ubuntu上cross-compile出来的,根据插件作者提供的cross-compile指引来做没有遇到问题。
编译出来的hsdis-i386.dll放到JDK安装目录中jre/bin/server和jre/bin/client中即可。


不太记得是不是从Sun JDK 6 update 20开始,在product build的HotSpot里要用-XX:+PrintAssembly参数必须同时带上-XX:+UnlockDiagnosticVMOptions参数才可以。
java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly YourMainClass

debug与fastdebug build就不用带。

而在比较老的Sun JDK 6里这个插件的名字要改为hdis-i486.dll才行。具体是从哪个版本开始变的我可以回头查查看。

如果有人需要我编译好的这个插件的话,待会儿可以上传一个到圈子共享里。
已经上传到圈子的共享里了

OpenJDK 7里可以看到还有另外一个附加的选项,-XX:PrintAssemblyOptions,可以用来向反编译插件传递参数。

借助HotSpot SA来反汇编
这帖提到的也是其中一个办法。看图:


=======================================

上面是针对Sun JDK的HotSpot而言。
JRockit的话要用别的办法,不过由于Oracle在输出的日志里说那信息是confidential的,所以抱歉我不能在这里说。
IBM J9的话我还没找到简单的办法。
Harmony、Jikes RVM、Maxine这些都有提供命令行参数可以让JVM把动态编译的汇编吐出来。

    然后 在JE的虚拟机圈子里找到了下载链接.

http://hllvm.group.iteye.com/group/share

 

     最后就是下载对应的 hsdis-i386.dll ,在DK目录下jre/bin/client和jre/bin/server中各放一份 .这个问题终于搞定..

 

在实际的使用中,我们通过直接加-XX:+PrintAssembly 打印ASM码会有两个问题

1 ASM码非常多.因为系统会打印出类似loadclass toString对应这些方法的ASM码.但是我们可能只关心对应的某一个方法而已.系统会打印8W行+的输出,但是我们可能只关心里面的100行

2 经常会帮我们内联.这个其实很纠结.之前为了这个内联,每次都想方设法如何让方法不被内联.当然,对应的解决方法也很简单.

 

对应的代码(我懒得自己写,就直接copy网上的了)

public class Test{
	int a = 1;
	static int b = 2;

	public int sum(int c){
		return a + b + c;
	}
	
	public static void main(String[] args){
		new Test().sum(3);
	}
}

 运行的代码如下

写道
D:\software\jdk6_fastdebug\jdk1.6.0_25\fastdebug\bin>java -Xcomp -XX:+PrintAssembly -XX:CompileCommand=dontinline,*Test.sum -XX:CompileCommand=compileonly,*Test.sum Test > log.txt

 其中,

  -XX:CompileCommand=dontinline,*Test.sum 这个表示不要把sum方法给内联了.这是解决内联问题

-XX:CompileCommand=compileonly,*Test.sum 这个表示只编译sum方法,这样的话,只会输出sum方法的ASM码.

对应的输出如下

写道
Java HotSpot(TM) Client VM warning: PrintAssembly is enabled; turning on DebugNonSafepoints to gain additional output
VM option '+PrintAssembly'
VM option 'CompileCommand=dontinline,*Test.sum'
VM option 'CompileCommand=compileonly,*Test.sum'
CompilerOracle: dontinline *Test.sum
CompilerOracle: compileonly *Test.sum
Loaded disassembler from D:\software\jdk6_fastdebug\jdk1.6.0_25\fastdebug\jre\bin\client\hsdis-i386.dll
Decoding compiled method 0x026ab608:
Code:
[Disassembling for mach='i386']
[Entry Point]
[Constants]
# {method} 'sum' '(I)I' in 'Test'  //这个好理解,记录一下这个方法名对应的描述符
# this: ecx = 'Test'  //表示this指针在ecx寄存器中
# parm0: edx = int  //sum 方法对应的参数在edx寄存器中.
# [sp+0x20] (sp of caller)
;; block B1 [0, 0]

0x026ab700: nop
0x026ab701: nop
0x026ab702: nop
0x026ab703: nop
0x026ab704: nop
0x026ab705: nop
0x026ab706: nop
0x026ab707: cmp 0x4(%ecx),%eax
0x026ab70a: jne 0x0266ad90 ; {runtime_call}
[Verified Entry Point]
0x026ab710: mov %eax,-0x8000(%esp) //检查栈溢出
0x026ab717: push %ebp //保存上一栈帧基址
0x026ab718: sub $0x18,%esp ;*aload_0 //给新栈帧分配空间.这个18很奇怪,我试了好多,无聊方法写成什么样,都是$0x18.
; - Test::sum@0 (line 13)
;; block B0 [0, 10]

0x026ab71b: mov 0x8(%ecx),%eax ;*getfield a //获取实例变量a,放入eax寄存器中, %ecx在上面已经说了,是存放this指针的寄存器. 0x8(%ecx)表示越过test对象头(对象头占8个字节,后面就是跟着实例变量a的内存位置)
; - Test::sum@1 (line 13)
0x026ab71e: mov $0x2024d7d8,%esi ; {oop('Test')}//获取Test在方法区的指针, 可以看标记oop(methodName),$0x2024d7d8就是对应的Test方法区位置
0x026ab723: mov 0x150(%esi),%esi ;*getstatic b //获取对应的类变量b,放到esi寄存器中,0x150(%esi)表示在Test方法区指针开始的150偏移量的位置存放类变量b
; - Test::sum@4 (line 13)
0x026ab729: add %esi,%eax// esi存放的是b,eax存放的是a.两者相加,放到eax寄存器中
0x026ab72b: add %edx,%eax //edx 存放的是sum方法对应的参数c,eax存放着a+b的和.两者相加放到eax寄存器中
0x026ab72d: add $0x18,%esp //esp为对应的栈帧指针,之前sub 0x18 ,现在加回去.也就是撤销栈帧
0x026ab730: pop %ebp //恢复上一个栈帧
0x026ab731: test %eax,0x230100 ; {poll_return} //轮询方法返回处的SafePoint
0x026ab737: ret  //返回.
0x026ab738: nop
0x026ab739: nop
;; Unwind handler
0x026ab73a: mov %fs:0x0(,%eiz,1),%esi
0x026ab742: mov -0xc(%esi),%esi
0x026ab745: mov 0x198(%esi),%eax
0x026ab74b: movl $0x0,0x198(%esi)
0x026ab755: movl $0x0,0x19c(%esi)
0x026ab75f: add $0x18,%esp
0x026ab762: pop %ebp
0x026ab763: jmp 0x026a7be0 ; {runtime_call}
0x026ab768: hlt
0x026ab769: hlt
0x026ab76a: hlt
0x026ab76b: hlt
0x026ab76c: hlt
0x026ab76d: hlt
0x026ab76e: hlt
0x026ab76f: hlt
[Exception Handler]
[Stub Code]
0x026ab770: mov $0xdead,%ebx ; {no_reloc}
0x026ab775: mov $0xdead,%ecx
0x026ab77a: mov $0xdead,%esi
0x026ab77f: mov $0xdead,%edi
0x026ab784: call 0x026a9c40 ; {runtime_call}
0x026ab789: push $0x83c8bc0 ; {external_word}
0x026ab78e: call 0x026ab793
0x026ab793: pusha
0x026ab794: call 0x0822c2e0 ; {runtime_call}
0x026ab799: hlt
[Deopt Handler Code]
0x026ab79a: push $0x26ab79a ; {section_word}
0x026ab79f: jmp 0x0266bac0 ; {runtime_call}

 指令码的解析,上面基本都写了.

 

 

参照链接

http://stackoverflow.com/questions/1503479/how-to-see-jit-compiled-code-in-jvm/4149878#4149878

http://hllvm.group.iteye.com/group/topic/21769

https://blogs.oracle.com/kto/entry/mustang_jdk_6_0_fastdebug

 

 

分享到:
评论

相关推荐

    ASM 设备操作手册

    综上所述,“ASM 设备操作手册”提供了关于AD830高速银浆固晶机的详细操作指导,涵盖了从设备安装到日常维护的各个方面,并且在全球范围内设有多个服务支持点,以便用户在遇到问题时能够迅速获得帮助和支持。...

    asm-util-4.0_RC1.jar.zip

    标题中的"asm-util-4.0_RC1.jar.zip"是一个归档文件,它是一个ZIP格式的压缩包,其中包含了ASM工具库的一个特定版本——ASM Util 4.0 Release Candidate 1(RC1)。ASM是一个Java字节码操控和分析框架,广泛用于动态...

    asm----masm615+mirro+good1+good2

    【标题】"asm----masm615+mirro+good1+good2" 提供的是一个关于汇编语言学习的资源包,其中包含了MASM615汇编器、Mirror反汇编器以及两个名为"good1"和"good2"的学习示例程序。这些工具和例子对于深入理解汇编语言至...

    asm-all-5.0.2-API文档-中文版.zip

    赠送jar包:asm-all-5.0.2.jar; 赠送原API文档:asm-all-5.0.2-javadoc.jar; 赠送源代码:asm-all-5.0.2-sources.jar; 赠送Maven依赖信息文件:asm-all-5.0.2.pom; 包含翻译后的API文档:asm-all-5.0.2-javadoc-...

    asm-util.jar

    asm-util-1.3.4.jar, asm-util-1.3.5.jar, asm-util-1.4.1.jar, asm-util-1.4.3.jar, asm-util-1.5.1.jar, asm-util-1.5.2.jar, asm-util-1.5.3.jar, asm-util-2.0.jar, asm-util-2.1.jar, asm-util-2.2.1-sources....

    asm.jar各个版本

    asm-1.3.3.jar, asm-1.3.4.jar, asm-1.3.5.jar, asm-1.4.1.jar, asm-1.4.2.jar, asm-1.4.3.jar, asm-1.4.jar, asm-1.5.1.jar, asm-1.5.2.jar, asm-1.5.3.jar, asm-2.0.jar, asm-2.1.jar, asm-2.2.1-sources.jar, asm...

    JavaEE源代码 asm-2.2.2

    JavaEE源代码 asm-2.2.2JavaEE源代码 asm-2.2.2JavaEE源代码 asm-2.2.2JavaEE源代码 asm-2.2.2JavaEE源代码 asm-2.2.2JavaEE源代码 asm-2.2.2JavaEE源代码 asm-2.2.2JavaEE源代码 asm-2.2.2JavaEE源代码 asm-2.2.2...

    asm-all-5.2.jar

    asm-all-5.2.jar asm-all-5.2.jar asm-all-5.2.jar asm-all-5.2.jar asm-all-5.2.jar asm-all-5.2.jar asm-all-5.2.jar asm-all-5.2.jar asm-all-5.2.jar asm-all-5.2.jar asm-all-5.2.jar asm-all-5.2.jar asm-all-...

    oracle 11G rac_asm搭建实测

    ### Oracle 11g RAC_ASM 搭建详解 #### 一、环境配置与准备 在进行Oracle 11g RAC_ASM的实际部署前,首先需要准备好合适的硬件及软件环境。 **1.1 主机配置** - **RAC1.vm 和 Rac2.vm** - 公共IP (Public IP): ...

    Oracle 11gR2 RAC + ASM on AIX-6.1安装指导手册

    Oracle 11gR2 RAC (Real Application Clusters) 和 ASM (Automatic Storage Management) 是在AIX-6.1操作系统上部署企业级数据库环境的关键组件。本安装指南将涵盖预安装检查、规划以及安装过程中的重要步骤。 1. ...

    asm-2.2.3.jar,asm-commons-2.2.3.jar,asm-util-2.2.3.jar,cglib-nodep-2.1_3.jar

    这些文件是Java编程语言中用于动态代码生成和字节码操作的重要库,主要涉及ASM和CGLIB两个框架。ASM是一个轻量级的Java字节码操控和分析框架,而CGLIB是一个强大的代码生成库,它在许多情况下作为Spring框架的依赖...

    彻底解决usb错误-device descriptor read/64, error -62

    1. **时钟问题**:从上述代码可以看出,问题的根本在于USB主机控制器的48MHz时钟未能正确启动。这是由于在启动过程中没有正确配置PLL导致的。S3C2410芯片支持多个PLL(包括APLL、MPLL和EPLL),其中EPLL用于USB主机...

    suse使用udev管理asm.docx

    总之,SUSE Linux Enterprise Server 11使用udev管理ASM,确保了在Oracle 11gR2 RAC环境中设备的稳定识别和操作,这是成功部署RAC的关键部分。通过正确的配置和依赖包安装,可以保证Oracle RAC在SLES上的高效运行。

    babel-plugin-asm-js:将JavaScript + Flow编译为asm.js(WIP)

    仍然是JavaScript的子集,但更适合手写(这样您就不需要使用C / C ++-> Emscripten-> asm.js进行数学运算) 工作正在进行中。目前支持: ES6 import并命名export 自动var , let , const提取和转换自动功能布局...

    asm-analysis-5.0.3.jar

    asm-analysis-5.0.3.jar;asm-analysis-5.0.3.jar;asm-analysis-5.0.3.jar

    asm-util.jar.zip

    ASM库通常被用于编译器、代码分析工具以及一些需要在运行时修改Java类的框架。 描述中提到的“asm, util, jar.zip包下载, 依赖包”揭示了这个压缩包的核心内容。"asm"是ASM库的简称,"util"可能指的是包含了一些...

    JavaEE源代码 asm-attrs

    JavaEE源代码 asm-attrsJavaEE源代码 asm-attrsJavaEE源代码 asm-attrsJavaEE源代码 asm-attrsJavaEE源代码 asm-attrsJavaEE源代码 asm-attrsJavaEE源代码 asm-attrsJavaEE源代码 asm-attrsJavaEE源代码 asm-...

Global site tag (gtag.js) - Google Analytics