JDK17中fieldClass.getDeclaredFields()返回空数组问题求助
问题解决:JDK17中Field.getDeclaredFields()返回空数组的处理方案
问题原因
JDK17的模块系统对java.lang.reflect.Field这类核心反射类做了特殊限制:即使添加了--add-opens=java.base/java.lang.reflect=ALL-UNNAMED打开包的反射访问权限,JVM默认仍会过滤掉Field类的内部私有字段,导致getDeclaredFields()返回空数组。这是因为这些字段属于JDK内部实现细节,被JVM刻意隐藏,防止外部代码依赖不稳定的内部结构。
具体解决操作
方案1:使用废弃参数临时绕过全局限制(最简单)
在Eclipse的VM参数中补充--illegal-access=permit,完整参数如下:
--add-opens=java.base/java.lang.reflect=ALL-UNNAMED --illegal-access=permit
该参数在JDK17中虽已废弃,但仍能生效,它会允许所有非法反射访问,包括获取Field类的内部字段。
方案2:通过内部API获取字段(无废弃参数,更规范)
如果不想依赖废弃参数,可以通过JDK内部的私有方法Class.getDeclaredFields0(boolean)来获取所有字段(包括被JVM隐藏的),但需要额外打开相关包的访问权限:
- 配置VM参数:
--add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED
- 修改代码,调用内部私有方法获取字段:
import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; public class TestField { public static void checkFields() { try { Class<?> fieldClass = Field.class; System.out.println("\nFields in " + fieldClass.getName() + ":"); // 调用Class类的私有方法getDeclaredFields0,传入true获取所有字段(包括隐藏的) Method getDeclaredFields0 = Class.class.getDeclaredMethod("getDeclaredFields0", boolean.class); getDeclaredFields0.setAccessible(true); Field[] fields = (Field[]) getDeclaredFields0.invoke(fieldClass, true); for (Field field : fields) { System.out.println(" " + Modifier.toString(field.getModifiers()) + " " + field.getType().getSimpleName() + " " + field.getName()); } } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { checkFields(); } }
方案3:检查Eclipse参数配置是否生效
确保你是在正确的位置配置VM参数:
- 打开
Run Configurations-> 选中你的运行配置 -> 切换到Arguments标签 -> 在VM arguments输入框中添加参数,注意参数之间用空格分隔,不要有拼写错误。
内容的提问来源于stack exchange,提问作者xjfromsh
相关产品推荐
相关产品推荐

