如何在运行时检查java.lang.Integer.IntegerCache.high的设置值?
你需要验证程序是否以-Djava.lang.Integer.IntegerCache.high=10000参数启动,但System.getProperty拿不到这个值——因为Java把它存在“saved properties”里。Java 19的Integer类原本是通过VM.getSavedProperty读取该值,但直接导入jdk.internal.misc.VM会触发模块访问错误,报错信息如下:
Exception in thread "main" java.lang.IllegalAccessError: class percolation.Main (in unnamed module @0x1e80bfe8) cannot access class jdk.internal.misc.VM (in module java.base) because module java.base does not export jdk.internal.misc to unnamed module @0x1e80bfe8
at percolation.Main.main(Main.java:14)
下面是几种可行的解决办法:
方法1:反射读取IntegerCache的high字段(推荐)
直接通过反射获取Integer内部类IntegerCache的high字段值,这是最可靠且兼容性较好的方式:
import java.lang.reflect.Field; public class CheckIntegerCache { public static void main(String[] args) { try { // 拿到Integer的内部类IntegerCache Class<?> cacheClass = Class.forName("java.lang.Integer$IntegerCache"); // 获取high字段 Field highField = cacheClass.getDeclaredField("high"); // 开启字段访问权限 highField.setAccessible(true); // 读取字段值(IntegerCache是静态内部类,传入null即可) int highValue = (int) highField.get(null); System.out.println("IntegerCache.high = " + highValue); } catch (Exception e) { e.printStackTrace(); } } }
方法2:反射调用VM.getSavedProperty(不推荐)
如果一定要读取saved property的原始值,可以通过反射调用内部API,避开直接导入的模块限制,但这种方式依赖JDK内部实现,版本兼容性差:
import java.lang.reflect.Method; public class CheckSavedProperty { public static void main(String[] args) { try { // 获取jdk.internal.misc.VM类 Class<?> vmClass = Class.forName("jdk.internal.misc.VM"); // 拿到getSavedProperty方法 Method getSavedPropMethod = vmClass.getDeclaredMethod("getSavedProperty", String.class); // 开启方法访问权限 getSavedPropMethod.setAccessible(true); // 调用方法获取属性值 String highPropValue = (String) getSavedPropMethod.invoke(null, "java.lang.Integer.IntegerCache.high"); System.out.println("java.lang.Integer.IntegerCache.high 属性值:" + highPropValue); } catch (Exception e) { e.printStackTrace(); } } }
方法3:间接验证缓存范围
如果不需要精确数值,只想验证high是否达到某个值,可以通过判断Integer对象是否来自缓存:比如设置了high=10000的话,Integer.valueOf(10000)和new Integer(10000)会是同一个对象(引用相等),而默认high=127时不会。
public class CheckCacheByInstance { public static void main(String[] args) { int testValue = 10000; Integer cachedInt = Integer.valueOf(testValue); Integer newInt = new Integer(testValue); // 引用相等说明testValue在缓存范围内,即high>=testValue System.out.println(testValue + " 是否在Integer缓存中:" + (cachedInt == newInt)); } }
内容的提问来源于stack exchange,提问作者traveh

