获取jdk12中java.lang.reflect.fields的声明字段
在java8中,可以使用例如获取jdk12中java.lang.reflect.fields的声明字段,java,unit-testing,reflection,java-12,Java,Unit Testing,Reflection,Java 12,在java8中,可以使用例如 Field.class.getDeclaredFields(); 在java12中(从java9开始?),它只返回一个空数组。这一点即使有了变化也不会改变 --add-opens java.base/java.lang.reflect=ALL-UNNAMED 设定 有什么办法可以做到这一点吗? (显然,这可能不是一个好主意,我希望在junit测试期间通过反射更改代码中的“static final”字段 )你不能。这是故意的改变 例如,您可以使用PowerMock
Field.class.getDeclaredFields();
在java12中(从java9开始?),它只返回一个空数组。这一点即使有了变化也不会改变
--add-opens java.base/java.lang.reflect=ALL-UNNAMED
设定
有什么办法可以做到这一点吗?
(显然,这可能不是一个好主意,我希望在junit测试期间通过反射更改代码中的“static final”字段
)你不能。这是故意的改变 例如,您可以使用
PowerMock
,它是@PrepareForTest
——如果您想将其用于测试目的,则可以在它使用的引擎盖下使用(字节码操作)。这正是评论中的bug所建议的
换句话说,既然
java-12
,就没有办法通过普通java访问它 你不能。这是故意的改变
例如,您可以使用PowerMock
,它是@PrepareForTest
——如果您想将其用于测试目的,则可以在它使用的引擎盖下使用(字节码操作)。这正是评论中的bug所建议的
换句话说,既然
java-12
,就没有办法通过普通java访问它 这在Java12中不再有效的原因是。该CSR表示:
总结
Core reflection有一种过滤机制,可以从类getXXXField和getXXXMethod中隐藏对安全性和完整性敏感的字段和方法。过滤机制已用于多个版本,以隐藏安全敏感字段,如System.security和Class.classLoader
此CSR建议扩展过滤器,以隐藏java.lang.reflect和java.lang.invoke中许多高度安全敏感类的字段
问题
java.lang.reflect和java.lang.invoke包中的许多类都有私有字段,如果直接访问这些字段,将影响运行时或使VM崩溃。理想情况下,java.base中类的所有非公共/非保护字段都将通过核心反射进行过滤,并且不能通过不安全的API进行读/写,但目前我们还没有做到这一点。同时,过滤机制被用作创可贴
解决方案
将筛选器扩展到以下类中的所有字段:
java.lang.ClassLoader
java.lang.reflect.AccessibleObject
java.lang.reflect.Constructor
java.lang.reflect.Field
java.lang.reflect.Method
以及java.lang.invoke.MethodHandles.Lookup中用于查找类和访问模式的私有字段
规范
没有规范更改,这是对非公共/非保护字段的过滤,java.base之外的任何内容都不应依赖这些字段。没有一个类是可序列化的
基本上,它们会过滤掉java.lang.reflect.Field
中的字段,这样你就不会像目前那样滥用它们。你应该找到另一种方法去做你需要的事情;似乎至少提供了一个选项
注意:上述CSR表明最终目标是防止对
java.base
模块内部代码的所有反射访问。然而,这种过滤机制似乎只影响核心反射API,可以通过使用Invoke API来解决。我不确定这两个API是如何联系在一起的,因此,如果这不是所希望的行为,除了更改静态最终字段的可疑性之外,应该有人(首先检查现有字段)。换句话说,使用下面的hack,风险自负;试着找到另一种方法来做你首先需要的事情
这就是说,至少在OpenJDK 12.0.1中,使用
java.lang.invoke.VarHandle
似乎仍然可以侵入modifiers
字段
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public final class FieldHelper {
private static final VarHandle MODIFIERS;
static {
try {
var lookup = MethodHandles.privateLookupIn(Field.class, MethodHandles.lookup());
MODIFIERS = lookup.findVarHandle(Field.class, "modifiers", int.class);
} catch (IllegalAccessException | NoSuchFieldException ex) {
throw new RuntimeException(ex);
}
}
public static void makeNonFinal(Field field) {
int mods = field.getModifiers();
if (Modifier.isFinal(mods)) {
MODIFIERS.set(field, mods & ~Modifier.FINAL);
}
}
}
下面使用上述方法更改ArrayList
中的静态finalEMPTY\u ELEMENTDATA
字段。当使用0
的容量初始化ArrayList
时,使用此字段。最终结果是创建的ArrayList
包含元素,而没有实际添加任何元素
import java.util.ArrayList;
public class Main {
public static void main(String[] args) throws Exception {
var newEmptyElementData = new Object[]{"Hello", "World!"};
updateEmptyElementDataField(newEmptyElementData);
var list = new ArrayList<>(0);
// toString() relies on iterator() which relies on size
var sizeField = list.getClass().getDeclaredField("size");
sizeField.setAccessible(true);
sizeField.set(list, newEmptyElementData.length);
System.out.println(list);
}
private static void updateEmptyElementDataField(Object[] array) throws Exception {
var field = ArrayList.class.getDeclaredField("EMPTY_ELEMENTDATA");
FieldHelper.makeNonFinal(field);
field.setAccessible(true);
field.set(null, array);
}
}
使用
--根据需要添加打开的。这在Java 12中不再有效的原因是。该CSR表示:
总结
Core reflection有一种过滤机制,可以从类getXXXField和getXXXMethod中隐藏对安全性和完整性敏感的字段和方法。过滤机制已用于多个版本,以隐藏安全敏感字段,如System.security和Class.classLoader
此CSR建议扩展过滤器,以隐藏java.lang.reflect和java.lang.invoke中许多高度安全敏感类的字段
问题
java.lang.reflect和java.lang.invoke包中的许多类都有私有字段,如果直接访问这些字段,将影响运行时或使VM崩溃。理想情况下,java.base中类的所有非公共/非保护字段都将通过核心反射进行过滤,并且不能通过不安全的API进行读/写,但目前我们还没有做到这一点。同时,过滤机制被用作创可贴
解决方案
将筛选器扩展到以下类中的所有字段:
java.lang.ClassLoader
java.lang.reflect.AccessibleObject
java.lang.reflect.Constructor
java.lang.reflect.Field
java.lang.reflect.Method
以及java.lang.invoke.MethodHandles.Lookup中用于查找类和访问模式的私有字段
规范
没有规范更改,这是对非公共/非保护字段的过滤,java.base之外的任何内容都不应依赖这些字段。没有一个类是可序列化的
基本上,它们会过滤掉java.lang.reflect.Field
中的字段,这样你就不会像目前那样滥用它们。你应该找到另一种方法去做你需要的事情;似乎至少提供了一个选项
注意:上述CSR表明最终目标是防止对java.base
模块内部代码的所有反射访问。这种过滤机制似乎只影响Core Reflection API,但是