Java安全发布的理解
看《Java并发编程实战》遇到如下问题
代码:
/**
* Created by yesiming on 16/11/11.
*/
public class Holder {
private int n; public Holder(int n) {
this.n = n;
} public void assertSanity() {
if(n != n) {
throw new AssertionError("This statment is false.");
}
}
} 疑问是:assertSanity() 方法中的判断 n != n
n它怎么就能不等于n呢,它们是同一个变量呀 解惑:设想一下场景
有2个线程 A,B
A做的操作:Holder holder = new Holder(42);
B做的操作:
if(holder != null) {
holder.assertSantiy();
}
对于线程A的操作,jvm执行时的步骤:1.栈里生成holder引用,2.执行构造函数,在堆里生成Holder的内存空间,并且给n赋值为42,3.把holder指向堆里生成的内存空间
问题是:上面的1,2,3步骤不是按照1,2,3的顺序执行的,执行引擎对指令重排序后,可能会按照1,3,2的顺序执行,也可能是别的顺序
结果:这样就导致当holder指向了堆里的内存空间时(这时holder不是null了),但是构造函数执行尚未完成,n还没有被赋值为42。 对于线程B的操作,assertSanity()方法编译后的指令如下:
public void assertSanity();
flags: ACC_PUBLIC
Code:
stack=3, locals=1, args_size=1
0: aload_0
1: getfield #2 // Field n:I
4: aload_0
5: getfield #2 // Field n:I
8: if_icmpeq 21
11: new #3 // class java/lang/AssertionError
14: dup
15: ldc #4 // String This statment is false.
17: invokespecial #5 // Method java/lang/AssertionError."<init>":(Ljava/lang/Object;)V
20: athrow
21: return
LineNumberTable:
line 14: 0
line 15: 11
line 17: 21
LocalVariableTable:
Start Length Slot Name Signature
0 22 0 this Lo1/Holder;
}
注意看绿色部分的指令,
第一步:1: getfield #2 // Field n:I
取得n的值
第二部:5: getfield #2 // Field n:I
取得n的值
也就是说,在执行比较指令if_icmpeq之前,要让比较的两个数都进栈,然后做比较
那么,既然要进栈2次,也就可以推导出,当线程B操作第一步getField时,n没有被线程A赋值,那么这个n是0,之后,线程A修改了n的值,第二次进栈时,n的值已经是修改后的42了
这样,就会导致栈顶2个slot中的数,一个0,一个是42,必然会导致8: if_icmpeq的结果为真 解决方案:
把n定义成final,并且在声明Holder时,使用valetile关键字
final能保证Holder在构造方法执行时,不会被执行引擎重排序,也就不会出现holder指向了Holder构造产生的内存空间,但是构造方法没有执行完成的情况(n没有被赋值)
valetile保证了在外部程序中,线程A和线程B对Holder的更新状态是随时可见的
Java安全发布的理解的更多相关文章
- Java语言的个人理解
Java语言的个人理解(比价深层次吧) 大四的生活确实十分的奢靡,不锻炼,不读书,几乎就是当一天和尚撞一天钟的生活,太颓废了,还好自己不是这个样子,不过身体确实差了很多,昨天跑了一圈内环(4KM),今 ...
- Java常量字符串String理解
Java常量字符串String理解 以前关于String的理解仅限于三点:1.String 是final类,不可继承2.String 类比较字符串相等时时不能用“ == ”,只能用 "eq ...
- java的final变量理解
java的final变量理解 final基本类型是数值不能改变 final对象是引用不能改变,对象其自身是可以被修改的.
- 谈谈我对Java中CallBack的理解
谈谈我对Java中CallBack的理解 http://www.cnblogs.com/codingmyworld/archive/2011/07/22/2113514.html CallBack是回 ...
- Gradle 1.12用户指南翻译——第46章. Java 库发布插件
本文由CSDN博客貌似掉线翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...
- java项目发布到linux服务器,tomcat正常启动但没加载项目
问题描述: java项目发布到linux服务器,一切操作正确,linux命令启动tomcat后,查看日志启动tomcat正常,上传的war包已经解压成功,但是tomcat没加载项目. 解决方法: 1. ...
- 【Java】「深入理解Java虚拟机」学习笔记(1) - Java语言发展趋势
0.前言 从这篇随笔开始记录Java虚拟机的内容,以前只是对Java的应用,聚焦的是业务,了解的只是语言层面,现在想深入学习一下. 对JVM的学习肯定不是看一遍书就能掌握的,在今后的学习和实践中如果有 ...
- Java提高篇之理解java的三大特性——继承
在<Think in java>中有这样一句话:复用代码是Java众多引人注目的功能之一.但要想成为极具革命性的语言,仅仅能够复制代码并对加以改变是不够的,它还必须能够做更多的事情.在这句 ...
- 【转】java提高篇(二)-----理解java的三大特性之继承
[转]java提高篇(二)-----理解java的三大特性之继承 原文地址:http://www.cnblogs.com/chenssy/p/3354884.html 在<Think in ja ...
随机推荐
- sudo and su
sudo bash : change the current user into root su u1: change the current user into u1 useradd: add ne ...
- Paths on a Grid
http://poj.org/problem?id=1942 题意:一个n*m的格子,从左下角走到右上角有多少种走法,规定只能向上或向右走: 思路:解法挺水的,高中学组合数的时候老师给讲过:求C[m+ ...
- HDOJ(HDU) 2192 MagicBuilding(用Java的Map做了下)
Problem Description As the increase of population, the living space for people is becoming smaller a ...
- bzoj 2330 [SCOI2011]糖果(差分约束系统)
2330: [SCOI2011]糖果 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3574 Solved: 1077[Submit][Status ...
- 《A First Course in Probability》-chaper8-极限定理-切比雪夫不等式
基于对概率问题的抽象化,通过期望.方差.随机变量X及其概率,我们想要通过几个量推出另外几个量的特征,笼统的来说,极限定理起到的作用便在于此 切比雪夫不等式: 在证明切比雪夫不等式之前,我们先要完成对马 ...
- java中字节流和字符流的区别
流分类: 1.Java的字节流 InputStream是所有字节输入流的祖先,而OutputStream是所有字节输出流的祖先.2.Java的字符流 Reader是所有读取字符串输入流的祖先,而 ...
- Linux 环境变量 $PATH
我们知道查阅文件属性的指令 ls 完整文件名为:/bin/ls(这是绝对路径),那为什么可以在任何地方执行/bin/ls 这个指令呢? 为什么在任何目录下输入 ls 就一定可以显示出一些讯息而不会说 ...
- Multipath多路径冗余全解析
一.什么是multipath 普通的电脑主机都是一个硬盘挂接到一个总线上,这里是一对一的关系.而到了有光纤组成的SAN环境,由于主机和存储通过了光纤交换机连接,这样的话,就构成了多对多的关系.也就是说 ...
- Hibernate三 关联关系
Hibernate的关联映射 客观世界中很少有对象是独立存在的,比如我们可以通过某个老师获取该老师教的所有学生,我们也可以通过某个学生获得教他的对应的老师,实体之间的互相访问就是关联关系.在Hiber ...
- iOS 开发 入门:使用Ad Hoc 进行用户测试
在完成iOS开发,准备进行发布之前,我们都希望App能在周围的朋友之间先进行测 试,提提意见,修改完善之后再发布到App Store上.Apple考虑到这一点,因此通过Ad Hoc来实现发布前的用户测 ...