Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在jdk11中重写静态final字段?_Java_Java 11 - Fatal编程技术网

Java 如何在jdk11中重写静态final字段?

Java 如何在jdk11中重写静态final字段?,java,java-11,Java,Java 11,过去,在单元测试期间,可以将静态最终字段eg更改如下: static void setFinalStatic(Field field, Object newValue) { field.setAccessible(true); Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.se

过去,在单元测试期间,可以将
静态最终
字段eg更改如下:

static void setFinalStatic(Field field, Object newValue) {
    field.setAccessible(true);

    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);

    field.set(null, newValue);
  }
class MyObject {
   public static final Boolean myfield = "true";
}
致电:

setFinalStatic(MyObject.class.getField("myfield"), "newval");
但从Java11(甚至更早)开始,这似乎不再可能了(目标字段没有更改)

现在强制进行静态最终场更改的可能性有多大

我知道这是一种黑客行为。但在特殊情况下,例如在一次junit测试中,这是对不必导入更大的库(如
PowerMock
)的拯救


今天还可能吗?

我发现测试值如下:

static void setFinalStatic(Field field, Object newValue) {
    field.setAccessible(true);

    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);

    field.set(null, newValue);
  }
class MyObject {
   public static final Boolean myfield = "true";
}
我不知道为什么,但是如下更改字段现在让我再次通过反射更改字段:

 public static final Boolean myfield = Boolean.TRUE;

我发现测试值如下:

static void setFinalStatic(Field field, Object newValue) {
    field.setAccessible(true);

    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);

    field.set(null, newValue);
  }
class MyObject {
   public static final Boolean myfield = "true";
}
我不知道为什么,但是如下更改字段现在让我再次通过反射更改字段:

 public static final Boolean myfield = Boolean.TRUE;

您应该使用的是来自PowerMock的
@PrepareForTest
;在它使用的引擎盖下,它使用了仪器API,这将使您能够模拟您以前拥有的任何东西


java-12中只使用了普通的java方式,因为使用
修饰符的黑客将不再有效

您应该使用的是PowerMock的
@PrepareForTest
;在它使用的引擎盖下,它使用了仪器API,这将使您能够模拟您以前拥有的任何东西


java-12中只使用了普通的java方式,因为使用
修饰符的黑客将不再有效

“似乎不再可能了”为什么?当您尝试时会发生什么?@Andreas应该更改的静态final字段没有更改。您是否可能被编译器内联的静态final常量表达式(原语、字符串)弄糊涂了?静态字段可能已更改,但它可能不会影响使用这些字段的代码,因为原始值已由编译器内联。“似乎不再可能”为什么?当您尝试时会发生什么?@Andreas应该更改的静态final字段没有更改。您是否可能被编译器内联的静态final常量表达式(原语、字符串)弄糊涂了?静态字段可能已更改,但它可能不会影响使用这些字段的代码,因为原始值已由编译器内联。嗯,
静态最终字符串
是一个常量表达式,因此它将被内联。常量表达式内容是它未更改的原因。请记住,
修饰符
在Java12中是不可访问的,因此它也将在那里停止工作。其他解决方法是执行
myfield=newstring(“true”)
,或者将初始化放入
{}
blockDoes
public static final myfield
甚至编译?@Petesh fun事实:即使使用可访问的修饰符,这种方法也不起作用,如果
jdk.internal.reflect.ReflectionFactory
中没有明确的代码支持这种攻击(jdk 11中仍然存在)。与此同时,JVM的优化器被允许理所当然地使用不变的
静态final
字段……这个问题似乎改变了它的主题。反射式更改编译时常量从来都不起作用,即使在最早的Java版本中也是如此。反射性地改变
静态final
字段而不是编译时常量是一种黑客行为,在某些情况下似乎是可行的(如前所述,优化器仍然可以破坏它),但可以通过检测读取字段的代码来代替。这将在所有支持插装的JVM中可靠地工作。
静态最终字符串
是一个常量表达式,因此它将被内联。常量表达式是它不改变的原因。请记住,
修饰符
在Java12中是不可访问的,因此它也将在那里停止工作。其他解决方法是执行
myfield=newstring(“true”)
,或者将初始化放入
{}
blockDoes
public static final myfield
甚至编译?@Petesh fun事实:即使使用可访问的修饰符,这种方法也不起作用,如果
jdk.internal.reflect.ReflectionFactory
中没有明确的代码支持这种攻击(jdk 11中仍然存在)。与此同时,JVM的优化器被允许理所当然地使用不变的
静态final
字段……这个问题似乎改变了它的主题。反射式更改编译时常量从来都不起作用,即使在最早的Java版本中也是如此。反射性地改变
静态final
字段而不是编译时常量是一种黑客行为,在某些情况下似乎是可行的(如前所述,优化器仍然可以破坏它),但可以通过检测读取字段的代码来代替。这将在所有支持检测的JVM中可靠地工作。