Java 为什么会这样

2018-12-13 19:48:42 +08:00
 choice4
![]( )
3542 次点击
所在节点    Java
16 条回复
choice4
2018-12-13 19:51:29 +08:00
坐标 java.io.OutputStream
jdk8 中是 1108 行
方法是
private void writeObject0(Object obj, boolean unshared) throws IOException
choice4
2018-12-13 19:51:55 +08:00
错了 是 java.io.ObjectOutputStream
misaka19000
2018-12-13 21:38:55 +08:00
jvm 是不认布尔类型的,编译器会把 bool 转为 byte
choice4
2018-12-13 21:45:54 +08:00
@misaka19000 为什么自己代码里的 boolean 就可以计算出布尔呢
leido
2018-12-13 22:37:11 +08:00
整数运算是最快的,java 在硬件层面搞个 bool 计算得不偿失
szq8014
2018-12-14 08:59:44 +08:00
@misaka19000 +1
不怀疑一下你使用的工具吗?真想看值打印出来最好。
可能是 IDE 没推出正确的类型,只知道是 0x01 了,不知道是该转成 bool, byte, short, int 中的哪个?
choice4
2018-12-14 09:23:47 +08:00
@szq8014 这个是 jdk 里面的中间值我打印不出来。我点进那个方法里面跟到 return 部分是对一个布尔类型取非 那个布尔是 false. 也就是 return !false;. 但是 boolean 接收到的返回值是个 1。开源中国上有人在 BigDecimal 中发现过这个问题,但是底下评论好像也没说出个一二三来。
szq8014
2018-12-14 09:38:26 +08:00


我自己打断点看也是显示为数值 0 或 1,然后图中显示变量在 slot_3 中。

javap 那个 `javap -verbose -p ObjectOutputStream.class >> out`
里面显示
`
private void writeObject0(java.lang.Object, boolean) throws java.io.IOException;
descriptor: (Ljava/lang/Object;Z)V
flags: ACC_PRIVATE
Code:
stack=4, locals=10, args_size=3
0: aload_0
1: getfield #538 // Field bout:Ljava/io/ObjectOutputStream$BlockDataOutputStream;
4: iconst_0
5: invokevirtual #601 // Method java/io/ObjectOutputStream$BlockDataOutputStream.setBlockDataMode:(Z)Z
8: istore_3
9: aload_0
10: dup
11: getfield #532 // Field depth:I
14: iconst_1
15: iadd
16: putfield #532 // Field depth:I
19: aload_0
20: getfield #542 // Field subs:Ljava/io/ObjectOutputStream$ReplaceTable;
23: aload_1
24: invokevirtual #630 // Method java/io/ObjectOutputStream$ReplaceTable.lookup:(Ljava/lang/Object;)Ljava/lang/Object;
27: dup
`
哎呀,JVM 知识不够用了,到第 8 行看起来应该是根本没有 getfield oldMode 相关的字样,也就是直接在栈桢上就操作完了,给优化成了匿名变量了 0.0 ?找不到对应的 NameAndType ?如果是这样的话 IDE 怎么知道 oldMode 在 slot_3 的?

有没有大神愿意出来讲讲 0.0
szq8014
2018-12-14 09:59:57 +08:00
说错了一些…… NameAndType 是方法描述, 变量是在 constant pool 里有对应的类型和名称,上面 [应该是] 给优化成了匿名变量,我没在 javap 导出的内容里面找到 oldMode 相关字样 0.0
DonaldY
2018-12-14 10:12:40 +08:00
在讨论 boolean 为什么会是 0 和 1 ?

这不是常识?
choice4
2018-12-14 10:21:58 +08:00
@szq8014 执行表达式执行 System.out.println(oldMode) 抛出了 com.sun.jdi.VMMismatchException : 1

Oracle Docs 中
public class VMMismatchException extends RuntimeException
Thrown to indicate that the requested operation cannot be completed because the a mirror from one target VM is being combined with a mirror from another target VM.
Since:
1.3
szq8014
2018-12-14 10:40:14 +08:00
@DonaldY 大神,请问下为什么分析工具没正确把 1 解析成 true,有没有这块相关的常识可以分享一下
lurenw
2018-12-14 10:52:39 +08:00
因为 jdk 的 classes 是不携带 local variable 的 debug info,所以 idea 在 debug 到这些类的时候,只能靠 slot 上的值和 variable map 对应起来进行猜测。

这是 idea 的特性
https://blog.jetbrains.com/idea/2013/10/show-local-variables-in-debugger-even-with-no-debug-info/
szq8014
2018-12-14 11:01:43 +08:00
@lurenw 学到了! thx
choice4
2018-12-14 11:20:16 +08:00
@lurenw 3q
xzy
2018-12-14 12:25:06 +08:00
JVM boolean 就是一个整数,Unsafe.putBoolean 其实就是 x&1

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/517328

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX