Open asuka-mio opened 1 year ago
Unfortunately runtime behavior switching like that is not as viable as you may think.
The use of method handles (or, presumably, var handles) involves generation of an invokedynamic
instruction in the Java bytecode. This gets translated to an invoke-custom
or invoke-polymorphic
instruction in Dalvik bytecode, and that instruction is only available on API 26 and newer (Android 8.0 and newer).
Even if the codepath isn't taken at runtime, the bytecode for the alternate codepath must be compiled and thus will raise the minimum API level of the library to 26. If this were the JVM, you could use multi-release jars and put the new codepaths behind a compile-time indirection, but Android has no analagous feature.
So, unfortunately, until you can raise your minimum supported version to API 26 you can't even conditionally use these APIs if Android is to remain a target.
Is it really the case that Android has no "multi-release jars" analogue? Can't you try to emulate it with some sort of R8 instructions?
It could be emulated with a separate Dex file that is conditionally loaded similar to how one might do a jar. But it likely has performance implications because of that and may not have a JIT cache and won't participate in baseline profiles. It likely would undo any gains from using the new mechanism.
VarHandle now is available on Android API 33 https://developer.android.com/reference/java/lang/invoke/VarHandle https://android.googlesource.com/platform/libcore/+/refs/heads/master/ojluni/src/main/java/java/lang/invoke/VarHandle.java
And AtomicXxx is backed by VarHandle now https://android.googlesource.com/platform/libcore/+/refs/heads/master/ojluni/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java
As we all known a compatibility layer is feasible if (Build.VERSION.SDK_INT >= 33) { // VarHandle Impl } else { // AtomicXxxFieldUpdater Impl }