java 反射操作字段_x86上的Java最终字段没有操作?

java 反射操作字段

我一直很乐于深入研究多线程编程的细节,并且尽管阅读了多年的CPU内存一致性模型,无等待和无锁算法,Java内存模型,实践中的Java并发性等知识,但我总是很喜欢。等等-我仍然会创建多线程编程错误。 总是令人惊奇的谦卑经历,使我想起这个问题有多复杂。

如果您已经阅读过JMM,那么您可能会记得,他们加强的领域之一是保证构造函数完成后最终字段的可见性。 例如,

public class ClassA {public final String b;public ClassA(String b) {this.b = b;}
}
... 
ClassA x = new ClassA("hello");

JMM指出,每个线程(甚至构成ClassA实例x的线程除外)都将
始终将 xb视为“ hello”,并且永远不会看到null值(参考字段的默认值)。

真是太好了! 这意味着我们可以通过将字段标记为final来创建不可变对象,并且任何构造的实例都可以自动在线程之间共享,而无需进行其他工作来保证内存可见性。 ! 不利的一面是,如果将ClassA.b标记为final,那么您将没有此类保证。 其他线程可能会观察到xb ==空结果(如果未使用其他“安全发布”机制来获得可见性)

当他们创建新的JMM时,每个人都喜欢的JCP成员Doug Lea创建了一个食谱,以帮助JVM开发人员实现新的内存模型规则。 如果阅读此内容,那么您将看到“规则”状态,即JIT编译器应在构造函数返回之前立即发出StoreStore内存屏障。 StoreStore障碍是一种“内存围栏”。 如果在汇编指令中发出该信息,则意味着对栅栏进行重新排序之前, 栅栏之前出现的内存写之前,不能对内存进行任何写(存储)操作。 请注意,它并没有说明读取内容,它们可以沿任一方向“跳”栅栏。

那么这是什么意思? 如果考虑一下在调用构造函数时编译器会执行的操作,那么很好:

String x = new ClassA("hello");get's broken down in to pseudo-code steps of:1. pointer_to_A = allocate memory for ClassA (mark word, class object pointer, one reference field for String b)
2. pointer_to_A.whatever class meta data = ...
3. pointer_to_A.b = address of "hello" string
4. emit a StoreStore memory barrier per the JMM
5. x = pointer_to_A

步骤4的StoreStore屏障可确保任何写入(例如类元数据和对字段b的写入)都不会在步骤5中对x进行重新排序。这可以确保x是否对其他任何线程都是可见的-没有StoreStore内存屏障的情况下,其他线程也无法看到x。如果没有StoreStore内存屏障,则可以对第3步和第5步进行重新排序,并且在写入xb和另一个cpu之前可能会显示对x的主内存写入内核可以观察到pointer_to_A.b为0(空),这将违反JMM。

好消息! 但是,如果您看一看该菜谱,就会发现一些有趣的事情:(1)很多人在许多处理器体系结构上编写JVM! (2)x86上的所有*存储屏障都是无操作的,除了StoreLoad屏障! 这意味着在x86上,上面的此StoreStore内存屏障为空操作,因此不会为此发出任何程序集。 什么也没做! 这是因为x86的内存模型是强大的 “总存储排序”(TSO)。 X86确保观察到所有内存写入,就像它们都是以相同顺序进行的一样。 因此,由于TSO的原因,写入5永远不会出现在任何其他线程的3之前,并且不需要发出内存隔离。 其他cpu体系结构的内存模型较弱,无法保证这种性能,因此需要StoreStore内存围墙。 请注意,较弱的内存模型虽然可能更难编程或较不直观,但通常要快得多,因为cpu可以对事物进行重新排序以更有效地使用缓存写入并减少缓存一致性工作。

显然,您应该继续按照JMM编写正确的代码。 但是,这也意味着(不幸或幸运的是)如果您在x86上运行,忘记它不会导致错误……就像我在工作中所做的那样。

为了真正地钻研这个家并确保没有食谱中可能没有描述的其他副作用,我按此处所述运行了x86程序集输出程序,并捕获了为ClassA调用构造函数的输出(最后一个在引用类型字段)和ClassB的构造函数,该类与ClassA相同,除了在类成员上没有final关键字之外。 x86程序集的输出是相同的 。 因此,从JIT角度来看,在x86(非钛合金,非arm等)上,final关键字没有任何影响。

如果您想知道汇编代码的外观,则如下所示。 请注意,没有任何锁定说明。 当Oracle的7u25 JRE发出x86 StoreLoad内存隔离栅时,它是通过发出锁addl $ 0x0,(%rsp)来完成的,该锁只会向堆栈指针添加零(无操作, 由于其被锁定),因此具有完全栅栏(符合StoreLoad栅栏的条件)。 x86中有几种导致完全隔离的效果的方法,这些方法在OpenJDK邮件列表中进行了讨论。 他们观察到至少在nehelem intel上,锁添加0是最紧凑/有效的空间。

0x00007f152c020c60: mov    %eax,-0x14000(%rsp)0x00007f152c020c67: push   %rbp0x00007f152c020c68: sub    $0x20,%rsp         ;*synchronization entry; - com.argodata.match.profiling.FinalConstructorMain::callA@-1 (line 60)0x00007f152c020c6c: mov    %rdx,(%rsp)0x00007f152c020c70: mov    %esi,%ebp0x00007f152c020c72: mov    0x60(%r15),%rax0x00007f152c020c76: mov    %rax,%r100x00007f152c020c79: add    $0x18,%r100x00007f152c020c7d: cmp    0x70(%r15),%r100x00007f152c020c81: jae    0x00007f152c020cd60x00007f152c020c83: mov    %r10,0x60(%r15)0x00007f152c020c87: prefetchnta 0xc0(%r10)0x00007f152c020c8f: mov    $0x8356f3d0,%r11d  ;   {oop('com/argodata/match/profiling/FinalConstructorMain$ClassA')}0x00007f152c020c95: mov    0xb0(%r11),%r100x00007f152c020c9c: mov    %r10,(%rax)0x00007f152c020c9f: movl   $0x8356f3d0,0x8(%rax)  ;   {oop('com/argodata/match/profiling/FinalConstructorMain$ClassA')}0x00007f152c020ca6: mov    %r12d,0x14(%rax)   ;*new  ; - com.argodata.match.profiling.FinalConstructorMain::callA@0 (line 60)0x00007f152c020caa: mov    %ebp,0xc(%rax)     ;*putfield a; - com.argodata.match.profiling.FinalConstructorMain$ClassA::@6 (line 17); - com.argodata.match.profiling.FinalConstructorMain::callA@6 (line 60)0x00007f152c020cad: mov    (%rsp),%r100x00007f152c020cb1: mov    %r10d,0x10(%rax)   ;*new  ; - com.argodata.match.profiling.FinalConstructorMain::callA@0 (line 60)0x00007f152c020cb5: mov    %rax,%r100x00007f152c020cb8: shr    $0x9,%r100x00007f152c020cbc: mov    $0x7f152b765000,%r110x00007f152c020cc6: mov    %r12b,(%r11,%r10,1)  ;*synchronization entry; - com.argodata.match.profiling.FinalConstructorMain::callA@-1 (line 60)0x00007f152c020cca: add    $0x20,%rsp0x00007f152c020cce: pop    %rbp0x00007f152c020ccf: test   %eax,0x9fb932b(%rip)        # 0x00007f1535fda000;   {poll_return}0x00007f152c020cd5: retq   0x00007f152c020cd6: mov    $0x8356f3d0,%rsi   ;   {oop('com/argodata/match/profiling/FinalConstructorMain$ClassA')}0x00007f152c020ce0: xchg   %ax,%ax0x00007f152c020ce3: callq  0x00007f152bfc51e0  ; OopMap{[0]=Oop off=136};*new  ; - com.argodata.match.profiling.FinalConstructorMain::callA@0 (line 60);   {runtime_call}0x00007f152c020ce8: jmp    0x00007f152c020caa  ;*new; - com.argodata.match.profiling.FinalConstructorMain::callA@0 (line 60)0x00007f152c020cea: mov    %rax,%rsi0x00007f152c020ced: add    $0x20,%rsp0x00007f152c020cf1: pop    %rbp0x00007f152c020cf2: jmpq   0x00007f152bfc8920  ;   {runtime_call}

参考: x86上的Java final字段是否没有操作? 来自我们的JCG合作伙伴史蒂夫·阿什(Steve Ash),来自“多杯咖啡”博客。

翻译自: https://www.javacodegeeks.com/2013/11/java-final-fields-on-x86-a-no-op.html

java 反射操作字段

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

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

相关文章

卡方分布分位数_卡方检验和精确概率法及两两比较

看过许多统计教程,这篇是我最推荐的介 绍数值变量如果服从正态分布,采用均数标准差进行统计描述,采用方差分析进行组间比较,如果组间差异有统计学意义,进一步采用LSD法(也可以是其它方法)进行两两比较。如果不服从正…

arcgis渔网分割提取栅格图_【操作】ArcGIS中字段的合并、分割、提取

由于种种原因,可能涉及到要对ArcGIS属性字段进行合并、分割、提取等操作,我们可以在Excel中进行运算,然后连接到ArcGIS中,这里主要介绍下通过属性表字段计算器的操作方法。目标① 合并“名称”、“代码”字段内容到新建字段“用地…

ds排序--希尔排序_图解直接插入排序和希尔排序

前言这次我们介绍插入类排序中的 直接插入排序 和 希尔排序 。对于直接插入排序,虽然它的时间复杂度也是 O(n^2) ,但是在元素 有序或近乎有序 的情况下,时间复杂度可以降为 O(n) ,效率比 O(nlogn) 的算法还要高。然而对于大规模的…

jsf 配置_JSF Tomcat配置示例

jsf 配置JavaServer Faces (JSF)是一个Web应用程序框架,旨在简化基于Web的用户界面的开发集成。 它用于开发和构建服务器端用户界面组件,并在Web应用程序中使用它们。 JSF技术基于Model-View-Controller (MVC)架构,并且通过在页面中使用可重用…

tomcat8日志乱码_Tomcat输出日志乱码解决

请先检查一下是不是由于log4J没有指定编码方式所导致的.log4j.appender.File org.apache.log4j.DailyRollingFileAppender#重点是看一下有没有这个,如果没有则加上.#加上之后需要将之前的日志文件删除,否则有可能不会重新写入日志.log4j.appender.File.Encoding UTF-8log4j.a…

使用Datastax Java驱动程序与Cassandra进行交互

今天,我这次返回了更多的Cassandra和Java集成,重点是使用Datastax Java驱动程序,而不是我已经写了很多文章的Spring Data Cassandra。 Spring Data实际上使用了Datastax驱动程序来与Cassandra进行交互,但是在其之上还附带了一些额…

java forkjoin MySQL_Java并发fork-join框架

fork-join框架允许在几个工作进程中断某个任务,然后等待结果组合它们。 它在很大程度上利用了多处理器机器的生产能力。 以下是fork-join框架中使用的核心概念和对象。ForkFork是一个进程,其中任务将其分成可以并发执行的较小且独立的子任务。语法Sum le…

无法加载可扩展计数器_多核可扩展计数器

无法加载可扩展计数器到处都需要计数器,例如,查找应用程序的关键KPI,应用程序的负载,服务的请求总数,用于查找应用程序吞吐量的一些KPI等。 由于所有这些需求,并发复杂性也增加了,这使这个问题…

linux忘记mysql密码_linux下忘记mysql root密码解决办法 | 系统运维

引言:在linux系统中,如果忘记了MySQL的root密码,有没有办法重新设置新密码呢?答案是肯定的,下面教大家一个比较简单的重置MySQL root密码的办法:1、编辑MySQL配置文件my.cnf系统运维www.osyunwei.com温馨提…

Java 10中的本地类型推断,或者如果它像鸭子一样嘎嘎叫

最近,Oracle采用了一种新策略,即每六个月发布一次新的语言版本。 该策略假定只有每个第3版都将提供长期支持或LTS。 快速说明: 具有LTS的当前版本是Java 8; Java 9仅应在2018年3月之前获得支持,因此已经结束。 Java…

mysql从dos界面_从DOS界面进入MYSQL数据库

新手学习数据库,从比较简单的mysql开始。从DOS界面进入mysql数据库其实跟配置java环境变量一样,要先设置环境变量(右击我的电脑-属性-高级-环境变量)。找到mysql的安装位置,把安装目录下“...mysql\bin\"这个地址放到环境变量Path值中&a…

更快地重复访问Java的Java类名?

Claes Redestad在core-libs-dev邮件列表上发布了消息“ RRF:8187123 :(反映)Class#getCanonicalName和Class#getSimpleName是性能问题的一部分 ”,他在邮件列表中要求审查建议的更改“以启用缓存…

mysql中cast函数_mysql中cast函数的使用 用于强制类型转换 (转载)

例子:SELECTstr_to_date(concat(year(a.tb_time),date_format(a.tb_time,%m),01),%Y%m%d) tb_time,cast(a.category_id as char) category_id,a.category_name,sum(a.tendered_sum)/sum(a.winbid) tendered_sum,sum(a.winbid_sum)/sum(a.winbid) winbid_avgfrom( SE…

dht11温湿度传感器_Arduino不调用库实现DHT11数据读取

DHT11概述DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性和卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性…

rete_RIP RETE时间来获得PHREAKY

rete我刚刚完成了有关新规则算法PHREAK的高级文档,PHREAK是混合推理中的一个文字游戏。 它仍然有点粗糙和高水平,但希望仍然很有趣。 它建立在ReteOO之上,非常好阅读。 ReteOO算法 ReteOO是在3、4和5系列发行版中开发的。 它采用了RETE算法并…

mysql 存储过程 插入记录_mysql 存储过程 插入记录

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":4,"count":4}]},"card":[{"des":"阿里云数据库专家保驾护航,为用户…

Java技巧:创建监视友好的ExecutorService

在本文中,我们将扩展具有监视功能的ExecutorService实现。 这种监视功能将帮助我们在实时生产环境中测量多个池参数,即活动线程,工作队列大小等。 它还将使我们能够衡量任务执行时间,成功任务计数和失败任务计数。 监控库 至于监…

java如果把字符串转成对象_Java中的重复对象:不仅仅是字符串

当Java应用程序消耗大量内存时,它本身就会出现问题,并可能导致GC压力增加和GC暂停时间过长。在我之前的一篇文章中,我讨论了Java中常见的内存浪费源:重复字符串。两个 java.lang.String 对象, a 并 b 在重复时 a ! b &…

mysql五大子句_MySQL的查询语句中可以使用以下哪个子句来表示分组查询

【多选题】人类行为遗传学工作者倾向于把人的行为遗传分为哪几类【填空题】MySQL的连接操作包括内连接、( )和交叉连接。【判断题】社会生活类尤其是人文风光类纪录片的解说则多用文学、 散文手法, 既抒情又有解释说明, 语言华丽富于美感,情感真挚浓郁。【单选题】1 、作业区边…

批处理 设置电脑最佳性能_批处理最佳做法

批处理 设置电脑最佳性能大多数应用程序至少具有一个批处理任务,在后台执行特定的逻辑。 编写批处理作业并不复杂,但是您需要了解一些基本规则,我将列举一些我发现最重要的规则。 从输入类型的角度来看,处理项目可以通过轮询处理…