Java 17环境下Android单元测试反射访问Field的modifiers字段报NoSuchFieldException的解决方案求助
Java 17环境下Android单元测试反射访问Field的modifiers字段报NoSuchFieldException的解决方案求助
各位好,我现在遇到一个头疼的问题,想请教大家有没有不用大规模重构的解决办法:
为了支持Android 35系统上的16KB页大小设备,我们把AGP版本升级到了最新的8.7,但这个版本要求必须用Java 17。结果升级到Java 17之后,所有单元测试里用到反射访问私有变量或方法的地方全挂了,尤其是修改final私有字段的那段代码。
我们项目里有大量遗留测试用例,要是逐个去重构的话,时间和成本都根本扛不住,所以想找个不用重构的方案。
先给大家看一下出问题的核心代码:
fun getFinalPrivateVariable(clazz: Class<*>, fieldName: String): Field { val field = getPrivateVariable(clazz, fieldName) val modifiers = Field::class.java.getDeclaredField("modifiers") modifiers.isAccessible = true modifiers.setInt(field, field.modifiers and Modifier.FINAL.inv()) return field }
我已经试过好几种办法了,但都没效果:
- 第一种:在
gradle.properties里添加了下面的参数,没用--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED - 第二种:在
build.gradle的testOptions里配置jvmArgs,同样没解决问题android { testOptions { unitTests.all { jvmArgs += [ '--add-opens=java.base/java.lang.reflect=ALL-UNNAMED', '--add-opens=java.base/java.lang=ALL-UNNAMED' ] } } } - 第三种:尝试用VarHandle重构了代码,但还是没搞定
@Throws(Exception::class) fun getFinalPrivateVariable(clazz: Class<*>, fieldName: String): Field { val field = getPrivateVariable(clazz, fieldName) field.isAccessible = true // Obtain a VarHandle for the "modifiers" field in the Field class val modifiersHandle: VarHandle = MethodHandles.privateLookupIn(Field::class.java, MethodHandles.lookup()) .findVarHandle(Field::class.java, "modifiers", Int::class.javaPrimitiveType) // Remove the FINAL modifier val mods = modifiersHandle.get(field) as Int modifiersHandle.set(field, mods and Modifier.FINAL.inv()) return field }
有没有大佬能指点一下,这种情况怎么搞才能不用重构大量测试用例,解决Java 17下反射访问Field的modifiers字段的问题?
备注:内容来源于stack exchange,提问作者user_8275
相关产品推荐
相关产品推荐

