编译hotspot_从Hotspot JIT编译器打印生成的汇编代码

编译hotspot

有时,在对Java应用程序进行性能分析时,有必要了解Hotspot JIT编译器生成的汇编代码。 这对于确定已做出的优化决策以及我们的代码更改如何影响生成的汇编代码非常有用。 在调试并发算法以确保已按预期应用可见性规则时,知道何时发出什么指令也很有用。 通过这种方式,我已经在各种JVM中发现了很多错误。

该博客说明了如何安装反汇编程序插件,并提供了针对特定方法的命令行选项。

安装

以前,有必要获取调试版本,以打印由Hotspot JIT为Oracle / SUN JVM生成的汇编代码。 从Java 7开始,如果在标准Oracle Hotspot JVM中安装了反汇编程序插件 ,就可以打印生成的汇编代码。 要为64位Linux安装插件,请按照以下步骤操作:

  1. 从https://kenai.com/projects/base-hsdis/downloads下载适当的二进制文件或从源代码构建
  2. 在Linux上,将linux-hsdis-amd64.so重命名为libhsdis-amd64.so
  3. 将共享库复制到$ JAVA_HOME / jre / lib / amd64 / server

您现在已经安装了插件!

测试程序

为了测试插件,我们需要一些代码,这些代码既对程序员很有趣,又执行得足够热,可以被JIT优化。 JIT何时进行优化的一些细节可以在这里找到。 下面的代码可用于通过读写易失字段来测量两个线程之间的平均延迟。 这些易失字段很有趣,因为它们需要关联的硬件篱笆来遵守Java内存模型 。

import static java.lang.System.out;public class InterThreadLatency
{private static final int REPETITIONS = 100 * 1000 * 1000;private static volatile int ping = -1;private static volatile int pong = -1;public static void main(final String[] args)throws Exception{for (int i = 0; i < 5; i++){final long duration = runTest();out.printf("%d - %dns avg latency - ping=%d pong=%d\n",i,duration / (REPETITIONS * 2),ping,pong);}}private static long runTest() throws InterruptedException{final Thread pongThread = new Thread(new PongRunner());final Thread pingThread = new Thread(new PingRunner());pongThread.start();pingThread.start();final long start = System.nanoTime();pongThread.join();return System.nanoTime() - start;}public static class PingRunner implements Runnable{public void run(){for (int i = 0; i < REPETITIONS; i++){ping = i;while (i != pong){// busy spin}}}}public static class PongRunner implements Runnable{public void run(){for (int i = 0; i < REPETITIONS; i++){while (i != ping){// busy spin}pong = i;}}}
}

印刷汇编代码

可以使用以下语句打印所有生成的汇编代码。

java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly InterThreadLatency

但是,这会使您处于无法看到树木的森林的情况。 通常,针对特定方法更有用。 对于此测试,Hotspot将优化run()方法并生成两次。 一次用于OSR版本,然后一次用于标准JIT版本。 标准的JIT版本如下。

java -XX:+UnlockDiagnosticVMOptions '-XX:CompileCommand=print,*PongRunner.run' InterThreadLatencyCompiled method (c2)   10531    5             InterThreadLatency$PongRunner::run (30 bytes)total in heap  [0x00007fed81060850,0x00007fed81060b30] = 736relocation     [0x00007fed81060970,0x00007fed81060980] = 16main code      [0x00007fed81060980,0x00007fed81060a00] = 128stub code      [0x00007fed81060a00,0x00007fed81060a18] = 24oops           [0x00007fed81060a18,0x00007fed81060a30] = 24scopes data    [0x00007fed81060a30,0x00007fed81060a78] = 72scopes pcs     [0x00007fed81060a78,0x00007fed81060b28] = 176dependencies   [0x00007fed81060b28,0x00007fed81060b30] = 8
Decoding compiled method 0x00007fed81060850:
Code:
[Entry Point]
[Constants]# {method} 'run' '()V' in 'InterThreadLatency$PongRunner'#           [sp+0x20]  (sp of caller)0x00007fed81060980: mov    0x8(%rsi),%r10d0x00007fed81060984: shl    $0x3,%r100x00007fed81060988: cmp    %r10,%rax0x00007fed8106098b: jne    0x00007fed81037a60  ;   {runtime_call}0x00007fed81060991: xchg   %ax,%ax0x00007fed81060994: nopl   0x0(%rax,%rax,1)0x00007fed8106099c: xchg   %ax,%ax
[Verified Entry Point]0x00007fed810609a0: sub    $0x18,%rsp0x00007fed810609a7: mov    %rbp,0x10(%rsp)    ;*synchronization entry; - InterThreadLatency$PongRunner::run@-1 (line 58)0x00007fed810609ac: xor    %r11d,%r11d0x00007fed810609af: mov    $0x7ad0fcbf0,%r10  ;   {oop(a 'java/lang/Class' = 'InterThreadLatency')}0x00007fed810609b9: jmp    0x00007fed810609d00x00007fed810609bb: nopl   0x0(%rax,%rax,1)   ; OopMap{r10=Oop off=64};*goto; - InterThreadLatency$PongRunner::run@15 (line 60)0x00007fed810609c0: test   %eax,0xaa1663a(%rip)        # 0x00007fed8ba77000;*goto; - InterThreadLatency$PongRunner::run@15 (line 60);   {poll}0x00007fed810609c6: nopw   0x0(%rax,%rax,1)   ;*iload_1; - InterThreadLatency$PongRunner::run@8 (line 60)0x00007fed810609d0: mov    0x74(%r10),%r9d    ;*getstatic ping; - InterThreadLatency::access$000@0 (line 3); - InterThreadLatency$PongRunner::run@9 (line 60)0x00007fed810609d4: cmp    %r9d,%r11d0x00007fed810609d7: jne    0x00007fed810609c00x00007fed810609d9: mov    %r11d,0x78(%r10)0x00007fed810609dd: lock addl $0x0,(%rsp)     ;*putstatic pong; - InterThreadLatency::access$102@2 (line 3); - InterThreadLatency$PongRunner::run@19 (line 65)0x00007fed810609e2: inc    %r11d              ;*iinc; - InterThreadLatency$PongRunner::run@23 (line 58)0x00007fed810609e5: cmp    $0x5f5e100,%r11d0x00007fed810609ec: jl     0x00007fed810609d0  ;*if_icmpeq; - InterThreadLatency$PongRunner::run@12 (line 60)0x00007fed810609ee: add    $0x10,%rsp0x00007fed810609f2: pop    %rbp0x00007fed810609f3: test   %eax,0xaa16607(%rip)        # 0x00007fed8ba77000;   {poll_return}0x00007fed810609f9: retq                      ;*iload_1; - InterThreadLatency$PongRunner::run@8 (line 60)0x00007fed810609fa: hlt    0x00007fed810609fb: hlt    0x00007fed810609fc: hlt    0x00007fed810609fd: hlt    0x00007fed810609fe: hlt    0x00007fed810609ff: hlt    
[Exception Handler]
[Stub Code]0x00007fed81060a00: jmpq   0x00007fed8105eaa0  ;   {no_reloc}
[Deopt Handler Code]0x00007fed81060a05: callq  0x00007fed81060a0a0x00007fed81060a0a: subq   $0x5,(%rsp)0x00007fed81060a0f: jmpq   0x00007fed81038c00  ;   {runtime_call}0x00007fed81060a14: hlt    0x00007fed81060a15: hlt    0x00007fed81060a16: hlt    0x00007fed81060a17: hlt    
OopMapSet contains 1 OopMaps#0 
OopMap{r10=Oop off=64}

有趣的观察

上面的汇编代码用红色突出显示的行非常有趣。 当一个
写入volatile字段后,在Java内存模型下,写入必须顺序一致 ,即,由于通常应用的优化(例如将写入暂存到存储缓冲区)而不会重新排序。 这可以通过插入适当的内存屏障来实现。 在上述情况下,Hotspot选择通过执行MOV指令(寄存器到内存地址-即写操作),然后再执行具有排序语义的LOCK ADD指令(不使用栈指针作为篱笆惯用法)来强制执行排序。 这在x86处理器上并不理想。 使用单个LOCK XCHG指令进行写入,可以更有效,更正确地执行相同的操作。 这使我想知道JVM是否存在一些重大折衷,以使其可以跨许多体系结构移植,而不是在x86上可以做到的最好。

参考:在Mechanical Sympathy博客上,从我们的JCG合作伙伴 Martin Thompson 的Hotspot JIT编译器打印生成的汇编代码 。

翻译自: https://www.javacodegeeks.com/2013/07/printing-generated-assembly-code-from-the-hotspot-jit-compiler.html

编译hotspot

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/348272.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机硬盘按不同接口,硬盘接口不同 速度差别竟然这么大

硬盘接口是硬盘与主机系统间的连接部件&#xff0c;作用是在硬盘缓存和主机内存之间传输数据。不同的硬盘接口决定着硬盘与计算机之间的连接速度&#xff0c;在整个系统中&#xff0c;硬盘接口的类型以及好坏都会直接影响程序运行快慢。说到硬盘接口我们常见的有SATA、PCI-E、M…

计算机导论设计实验,基于抽象知识点的《计算机导论》实验软件设计

Development of Experiment Software for《Computing Essentials》based on the Abstract Knowledge Points1、 College of Computer and Information Science, Southwest University, Chongqing, 400715Abstract&#xff1a;This paper develops an experiment software for 《…

使用Java的@Deprecated前瞻

我偶尔遇到一种情况&#xff0c;我需要引入新的API或构造以供其他人试用&#xff0c;但是我知道在使用某些API后&#xff0c;它可能会根据其他人的反馈而改变。 在这种情况下&#xff0c;我想以某种方式注释该构造&#xff0c;以警告其他开发人员此新添加的构造的暂定性。 在这…

计算机组成原理setb,计算机组成原理与汇编语言4

第四章指令系统指令系统概述指令系统是指某一种计算机所有指令的集合。对计算机而言&#xff0c;这是一组二进制数的输入&#xff0c;实际上是一组电平的输入。这些输入能在一个指令周期内产生人们预先规定的动作。显然这不是一组随机的二进制数据输入。指令系统是联系硬件和软…

计算机通信系统分哪两类,通信系统的组成(数字通信系统由哪几部分组成)

基本系统一般由信源(始发设备)、信宿(接收设备)和信道(传输介质)方式来自源的信息(语言、字符、图像或数据)由终端设备(如电话、电传打字机、传真机或数据终端设备等)转换成电信号。)在发送方&#xff0c;然后由始发设备编码、调制、放大或发送&#xff0c;然后基带信号被转换成…

nosql非关系型数据库_从Datomic出发,革命性的非NoSQL数据库

nosql非关系型数据库我终于设法了解了当今最不寻常的数据库之一&#xff0c;Datomic&#xff0c;并希望与您分享。 感谢Stuart Halloway和他的工作室&#xff01; 为什么&#xff1f;&#xff01;&#xff1f; 我们很快就会看到&#xff0c;Datomic与传统的RDBMS数据库以及各种…

你活在一个计算机模拟中吗,一麻省理工教授认为,我们更有可能生活在计算机模拟宇宙中...

一位麻省理工学院的教授表示&#xff0c;我们“更有可能”生活在某种模拟宇宙中&#xff0c;因为我们自己离能够创造超现实的模拟也不远了。(参见在接受解释性网站Vox采访时&#xff0c;计算机科学家Rizwan Virk认为&#xff0c;如果我们生活在信息世界而不是物质世界中&#x…

尽早查看针对Java 11的功能

随着JDK 10即将进入其发布候选阶段 &#xff0c;有趣的是&#xff0c;开始通过JDK 11观察之后会发生什么。 在撰写本文时&#xff0c;四个JEP &#xff08; JDK增强建议 &#xff09;已正式成为JDK 11的目标&#xff08;可能会出现&#xff09;。 这篇文章总结了当前针对JDK 11…

如何在命令行情重启计算机,如何应对“命令式”行情

如果说十月维稳行情&#xff0c;是以劝说&#xff0c;号召并佐以缓发新股为主要行政手段&#xff0c;那么十一月行情的主要特征就是“命令式”的。实践证明&#xff0c;十月行情并不咋地&#xff0c;虎头蛇尾&#xff0c;说明主力并不十分听话&#xff0c;也不卖力&#xff0c;…

服务器系统开机提示0xc000007b,0xc000007b蓝屏解决方法

0xc000007b是一种常见的蓝屏代码&#xff0c;导致出现此蓝屏代码的原因有很多&#xff0c;BIOS设置问题&#xff0c;驱动问题&#xff0c;硬件问题等等。硬件问题对于我们小白来说解决起来有点困难。我给大家带来了解决0xc000007b蓝屏软件问题的方法&#xff0c;赶紧来瞧瞧吧0x…

tms tck_记录合规性–关于TCK,规格和测试

tms tck使用软件规格非常困难。 不论在哪个地方提出&#xff1b; 您最终遇到了一个大问题&#xff1a;是否已实现所有指定的内容并对其进行了测试&#xff1f; 在瀑布驱动的方法学时代&#xff0c;这一直是一个问题&#xff0c;即使在撰写本文的今天&#xff0c;敏捷性和用户故…

3D环动画css3实现,CSS3 3D酷炫立方体变换动画的实现

我爱撸码&#xff0c;撸码使我感到快乐&#xff01;大家好&#xff0c;我是Counter&#xff0c;本章微博主要利用了CSS3的一些新特性&#xff0c;主要用到关键帧来使3D图形运动起来&#xff0c;涉及到了一些抽象的思想&#xff0c;立体的想象。先给大家看看完成的效果&#xff…

Spring项目的按层打包已过时

我认为Spring应用程序不应该以逐层方法构建。 在我看来&#xff0c;按功能打包更有意义。 首先&#xff0c;让我简要描述每种方法。 “按层打包”&#xff08;在非Java世界中为“按类型折叠”&#xff09; 该项目结构根据源代码文件所属的体系结构层将它们分为包/目录&#x…

css怎么控制两个字母,css英文字母数字自动换行且不断词方法

本文章来给各位同学介绍css怎样让英文字母数字自动换行且不断词方法总结&#xff0c;有需要了解的同学可进入参考。当一个定义了宽度的块状元素中填充的全部为纯英文或者纯数字的时候&#xff0c;在IE和FF中都会撑大容器&#xff0c;不会自动换行并且当数字或者英文中带有汉字时…

nmap 查看服务器版本信息,nmap命令-nmap命令扫描服务器信息的格式

用这条命令就可以扫描出目标网络的操作系统和开放端口号nmap-O...0/24上面的扫描信息直接输出到终端&#xff0c;如果想把结果写到文件里&#xff0c;可以用-oN&#xff0c;-oX选项输出到文本文件或xml文件。nmap-O...0/24-oXnmap_info.xml&#xff0c;结果会输出到XML文件&…

java构造函数内部调用_具有内部类构造函数参数的Java Reflection奇数

java构造函数内部调用关于Java内部类 Java允许成员类&#xff08;在其他类内定义的类&#xff09;&#xff0c;局部类&#xff08;在语句块内定义的类&#xff09;和匿名类&#xff08;无名称的类&#xff09;&#xff1a; class Outer {Object anonymous new Object(){}; //…

Java的新视差控件(JavaFX)

介绍 视差是一种视觉效果&#xff0c;您可以组合以不同速度移动的两个分层图像以获得深度感。 想想一下&#xff0c;当您在道路上行驶时&#xff0c;您会看到附近的树木在快速移动&#xff0c;而距离较远的树木将沿相同的方向移动&#xff0c;但速度较慢&#xff0c;结果是您感…

ajax提交file空指针,excel导入上传文件报空指针错误

页面入口全选导入导出${msg[globals.button.delete.more]}导出jsfunction excelImport() {top.layer.open({type: 1,area: [500, 300],title:"导入数据",content:$("#importBox").html() ,btn: [下载模板,确定, 关闭],btn1: function(index, layero){windo…

mockito 静态方法_Mockito –带有注释和静态方法的额外接口

mockito 静态方法在代码中&#xff0c;我最近遇到了一段非常糟糕的代码&#xff0c;该代码基于对对象执行某些操作的类转换。 当然&#xff0c;代码需要重构&#xff0c;但是如果您首先没有对该功能进行单元测试&#xff0c;则有时您可能无法做到/或者不想这样做&#xff08;这…

手机推送信息到本地服务器,服务器信息推送到手机

服务器信息推送到手机 内容精选换一换服务器的计费方式为“包年/包月”&#xff0c;如果在计费周期内不想再继续使用&#xff0c;请参考本节指导进行退订。执行退订操作前&#xff0c;请确保待退订的服务器数据已完成备份或者迁移&#xff0c;退订完成后资源将被完全删除&#…