java jit compilation_关于java:如何在JVM中看到JIT编译的代码?

有没有办法在JVM中看到JIT生成的本机代码?

您确定要查看JIT编译(本机)代码,还是仅查看字节代码? 我问,因为在这里提出这个问题会导致一些疑问,如果你真的想看到本机代码......而且,对不起,我也不知道这样的工具。

我想看看exaclty JIT编译的本机代码。 当然,我不需要完成工作,而是进行实验和调查。

一般用法

如其他答案所述,您可以使用以下JVM选项运行:

-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly

过滤特定方法

您还可以使用以下语法过滤特定方法:

-XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*MyClass.myMethod

笔记:

您可能需要根据操作系统等将第二个参数放在引号内。

如果方法被内联,你可能会错过一些优化

如何:在Windows上安装所需的库

如果您运行的是Windows,则此页面提供了有关如何构建和安装hsdis-amd64.dll和hsdis-i386.dll以使其正常工作的说明。我们在下面复制并扩展该页面的内容*以供参考:

哪里可以获得预建的二进制文件

您可以从fcml项目下载Windows的预构建二进制文件

hsdis-amd64.dll

hsdis-i386.dll

如何在Windows上构建hsdis-amd64.dll和hsdis-i386.dll

此版本的指南是使用64位Cygwin在Windows 8.1 64位上编写的,并生成hsdis-amd64.dll

安装Cygwin。在Select Packages屏幕上,添加以下软件包(通过展开Devel类别,然后在每个软件包名称旁边的Skip标签上单击一次):

make

mingw64-x86_64-gcc-core(仅hsdis-amd64.dll需要)

mingw64-i686-gcc-core(仅hsdis-i386.dll需要)

diffutils(Utils类别)

运行Cygwin终端。这可以使用安装程序创建的桌面或开始菜单图标来完成,并将创建您的Cygwin主目录(默认情况下为C:\cygwin\home\\或C:\cygwin64\home\\)。

下载最新的GNU binutils源包并将其内容解压缩到Cygwin主目录。在撰写本文时,最新的软件包binutils-2.25.tar.bz2。这应该会导致Cygwin主目录中名为binutils-2.25(或最新版本)的目录。

通过转到JDK 8 Updates存储库,选择与已安装的JRE版本对应的标记,然后单击bz2,下载OpenJDK源。将hsdis目录(在src\share\tools中找到)解压缩到您的Cygwin主目录。

在Cygwin终端中,输入cd ~/hsdis。

要构建hsdis-amd64.dll,请输入

make OS=Linux MINGW=x86_64-w64-mingw32 'AR=$(MINGW)-ar' BINUTILS=~/binutils-2.25

要构建hsdis-i386.dll,请输入

make OS=Linux MINGW=i686-w64-mingw32 'AR=$(MINGW)-ar' BINUTILS=~/binutils-2.25

在任何一种情况下,将2.25替换为您下载的binutils版本。 OS=Linux是必要的,因为虽然Cygwin是类似Linux的环境,但hsdis makefile无法识别它。

构建将失败,消息为./chew: No such file or directory和gcc: command not found。在Wordpad或Notepad ++等文本编辑器中编辑\hsdis\build\Linux-amd64\bfd\Makefile,将SUBDIRS = doc po(第342行,如果使用binutils 2.25)更改为SUBDIRS = po。重新运行上一个命令。

现在可以通过将hsdis\build\Linux-amd64或hsdis\build\Linux-i586复制到JRE的bin\server或bin\client目录来安装DLL。您可以通过搜索java.dll在系统中找到所有此类目录。

额外提示:如果您更喜欢英特尔ASM语法到AT&T,请指定-XX:PrintAssemblyOptions=intel以及您使用的任何其他PrintAssembly选项。

*页面许可证是Creative Commons sub>

其他平台的预构建二进制文件 - kenai.com/projects/base-hsdis/downloads

@AshwinJayaprakash我应该把这些文件放在Mac OS中?

@KorayTugay将它们放在/usr/lib/中

我通过从最新版本的链接页面进行复制来更新答案,但这突出了我们通常链接到外部资源而不是逐字复制它们的原因。

@AleksandrDubinsky感谢您的更新。我故意复制它:如果该网站被删除我的答案仍然是自包含的......

仅供参考,请勿使用此其他指南jpbempel.blogspot.com/2013/07/how-to-build-hsdis-amd64dll.html尝试使用MSYS / MinGW构建hsdis。它不起作用。

假设您正在使用Sun Hotspot JVM(即Oracle提供的java.com上的JVM),您可以添加标志

-XX:+PrintOptoAssembly

在运行代码时。这将打印出JIT编译器生成的优化代码,并将其余部分排除在外。

如果要查看整个字节码,包括未经优化的部分,请添加

-XX:CompileThreshold=#

当你运行你的代码时。

您可以在此处阅读有关此命令和JIT功能的更多信息。

此选项仅出现在调试版本中或其他任何内容中吗?因为我的JVM("Java(TM)SE运行时环境(版本1.6.0_16-b01")无法识别它,即使Web上的源指示此功能在Sun Java 6和OpenJDK中可用。

是的,需要DEBUG二进制文件。 blogs.warwick.ac.uk/richardwarburton/entry/

不应该(现在)-XX:+ PrintAssembly,至少现在?在我的机器上测试,并匹配这里所说的内容:wikis.sun.com/display/HotSpotInternals/PrintAssembly在此选项和反汇编程序插件之前,您需要-XX:+ UnlockDiagnosticVMOptions。

@Blaisorblade我得到:错误指定的VM选项'PrintAssembly'错误:无法创建Java虚拟机。错误:发生了致命异常。程序将会退出。

@KorayTugay请参阅其他答案 - 更新后的链接是wikis.oracle.com/display/HotSpotInternals/PrintAssembly,如stackoverflow.com/a/15146962/53974或stackoverflow.com/a/4149878/53974中所述。如果以下说明不起作用,请在适当的地方询问详细信息(不确定是否应该针对您的案例提出另一个问题,参考此案例)。

您需要一个hsdis插件才能使用PrintAssembly。一个方便的选择是基于FCML库的hsdis插件。

它可以为类UNIX系统编译,在Windows上,您可以使用Sourceforge上的FCML下载部分中提供的预构建库:

要在Windows中安装:

提取dll(可以在hsdis-1.1.2-win32-i386.zip和hsdis-1.1.2-win32-amd64.zip中找到)。

将dll复制到任何位置java.dll(使用Windows搜索)。在我的系统上,我在两个位置找到它:

C:\Program Files\Java\jre1.8.0_45\bin\server

C:\Program Files\Java\jdk1.8.0_45\jre\bin\server

要在Linux中安装:

下载源代码,解压缩

cd

./configure && make && sudo make install

<5233>

sudo ln -s /usr/local/lib/libhsdis.so /lib/amd64/hsdis-amd64.so

sudo ln -s /usr/local/lib/libhsdis.so /jre/lib/amd64/hsdis-amd64.so

在我的系统上,JDK位于/usr/lib/jvm/java-8-oracle中

如何运行它:

java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly

-XX:+LogCompilation -XX:PrintAssemblyOptions=intel,mpad=10,cpad=10,code

-jar fcml-test.jar

其他配置参数:

代码在助记符之前打印机器代码

intel使用Intel语法。

gas使用AT&T汇编语法(兼容GNU汇编程序)

dec将IMM和位移打印为十进制值

mpad = XX填充指令的助记符部分。

cpad = XX填充机器代码。

seg显示默认的段寄存器

零在HEX文字的情况下显示前导零

对于Windows,Intel语法是默认语法,而AT&T语言是GNU / Linux的默认语法。

有关更多详细信息,请参阅"FCML库参考手册"

感谢您修复lib。它在Linux上也很棒。我正在删除我的旧评论以保持混乱。

在Linux上,在我安装libhsdis.so并建立到hsdis-amd64.so的软链接后,我运行java命令,它prmpts找不到hsdis-amd64.so。我重启然后重新运行java,没关系。如何避免重启以使软链接立即生效?登出?

只需添加一点:在某些Linux发行版中,您只需安装一个软件包,例如在Ubuntu中:apt-get install libhsdis0-fcml(askubuntu.com/a/991166/489909)。自己构建这个可能没有必要。

对于HotSpot(是Sun)JVM,即使在产品模式下:

http://wikis.oracle.com/display/HotSpotInternals/PrintAssembly

需要一些程序集:它需要一个插件。

您的答案中的链接似乎已经消失。请您更新一下吗?提前致谢。

我相信如果你在Windows机器上运行WinDbg会有所帮助。

我刚跑了一个罐子。

然后我附加了java进程

通过Windbg

通过?命令检查线程;有11个线程,0个线程是主要工作线程

切换到0线程 - ~0s

通过kb查看未受损的callstack有:

0008fba8 7c90e9c0 ntdll!KiFastSystemCallRet

0008fbac 7c8025cb ntdll!ZwWaitForSingleObject + 0xc

0008fc10 7c802532 kernel32!WaitForSingleObjectEx + 0xa8

0008fc24 00403a13 kernel32!WaitForSingleObject + 0x12

0008fc40 00402f68 java + 0x3a13

0008fee4 004087b8 java + 0x2f68

0008ffc0 7c816fd7 java + 0x87b8

0008fff0 00000000 kernel32!BaseProcessStart + 0x23

突出显示的行是在JVM上直接运行JIT编码。

然后我们可以找到方法地址:

java + 0x2f68是00402f68

在WinDBG上:单击"查看" - >

拆卸。单击编辑 - >转到

地址。把00402f68放在那里

得到了

00402f68 55推ebp

00402f69 8bec mov ebp,尤其是

00402f6b 81ec80020000 sub esp,280h

00402f71 53推ebx

00402f72 56推esi

00402f73 57推edi

... 等等

有关其他信息,请参阅示例如何使用process explorer和WinDbg从内存转储中追溯JIT-ed代码。

查看机器代码和一些性能数据的另一种方法是使用AMD的CodeAnalyst或OProfile,它具有Java插件,可将执行的Java代码可视化为机器代码。

使用JMH的perfasm剖析器(LinuxPerfAsmProfiler或WinPerfAsmProfiler)打印热点的组件。 JMH确实需要hsdis库,因为它依赖于PrintAssembly。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值