这个问题倒不是因为以后要换值类型无法同步导致的,而是容易犯这种编程失误:
Integer i = 1; for (int j = 0; j < 10; j++) { synchronized(i) { i++; //下次循环就变成另一个对象了,没有真正按照预期锁住 } }2.使用 identity 相关的操作可能未来会发生变化,所以不建议使用,例如:
调用 System.identityHashCode(对象) 获取基于对象在堆内存地址实现的哈希码,如果 Value-based Classes 变成值类型,值类型确定在栈上分配后,这个方法目前的机制就会有问题。
调用 synchronize(obj) 同步对象,如果 Value-based Classes 变成值类型,没有普通对象的对象头,那么无法使用正常的锁膨胀同步机制,同时重量锁 mutex 由于可能值类型对象没有堆上位置也无法使用现有的机制实现。
调用对象的 wait(),notify(),notifyAll(),由于上一条同样的影响,这些方法调用可能在未来版本带来异常。
在 Java 16 之后,如果有这些用法,就会在编译阶段有报警提醒:
Integer integer = 1; synchronized (integer) { }编译阶段会提示 Attempt to synchronize on an instance of a value-based class ,如果想关闭可以增加编译参数 -Xlint:synchronization
如果想在运行阶段针对这种使用有提示或者错误,可以通过添加如下启动参数实现:
-XX:+UnlockDiagnosticVMOptions -XX:DiagnoseSyncOnValueBasedClasses=1:加上这个,程序遇到这种使用,会抛出 FATAL ERROR,同时退出 JVM
-XX:+UnlockDiagnosticVMOptions -XX:DiagnoseSyncOnValueBasedClasses=2:加上这个,程序遇到这种使用,会有日志提示:
[0.152s][info][valuebasedclasses] Synchronizing on object 0x000000069aed7788 of klass java.lang.Integer [0.152s][info][valuebasedclasses] at com.github.hashjang.shenandoah.Main.main(Main.java:8) [0.152s][info][valuebasedclasses] - locked <0x000000069aed7788> (a java.lang.Integer)同样的,由于原始类型包装类已经属于 Value-based Class,所以就不应该使用它的构造器而是使用 valueOf() 代替了,为了给大家修改的时间,目前仅仅是将构造器标记为 Deprecate for Removal :
@Deprecated(since="9", forRemoval = true) public Integer(int value) { this.value = value; }如果有使用会提示 'Integer(int)' is deprecated and marked for removal。
目前 JDK 中的未来可能会用值类型代替的 Value-based Classes目前 JDK 中的 Value-based Classes 都带有 jdk.internal.ValueBased 注解,或者他们的实现接口,父类带有这个注解,包括:
java.lang 包:
原始类型的封装类,例如 java.lang.Integer
java.lang.Runtime.Version 类
操作系统进程的句柄 java.lang.ProcessHandle 和他的实现类 java.lang.ProcessHandleImpl
java.time 包下的一些时间封装类
java.util 包:
Optional 相关,例如:java.util.Optional, java.util.OptionalInt, java.util.OptionalLong, java.util.OptionalDouble
所有不可变集合以及底层实现的不可变元素,例如:Set.of 的返回 java.util.ImmutableCollections.AbstractImmutableSet
一点趣事儿Java 16 的 Record 还让我闹了个笑话,我以为这个是 Project Valhala 的 Inline Object 已经实现了,还去 *** 问,这个 Record 为啥能有 wait() 方法,并且可以进行 synchronized 同步(因为如果是 Project Valhala 的 Inline Object 的话是没有普通类的对象头的,没法用普通类对象的方法实现同步),结果。。。。。最后还是 Goetz 大佬一眼就看出我是误会了:
微信搜索“我的编程喵”关注公众号,每日一刷,轻松提升技术,斩获各种offer: