Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.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
获取jdk12中java.lang.reflect.fields的声明字段_Java_Unit Testing_Reflection_Java 12 - Fatal编程技术网

获取jdk12中java.lang.reflect.fields的声明字段

获取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

在java8中,可以使用例如

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
中的静态final
EMPTY\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,但是