专栏名称: OSC开源社区
OSChina 开源中国 官方微信账号
目录
相关文章推荐
程序员的那些事  ·  突发!美国 CDN 发明者 Akamai ... ·  3 天前  
程序猿  ·  DeepSeek ... ·  4 天前  
程序员的那些事  ·  因 Bug 被用户薅走 28 万,这款小程序凉了 ·  4 天前  
程序员小灰  ·  2025开年,跌爆了! ·  5 天前  
OSC开源社区  ·  夜莺开源监控突破一万 ... ·  5 天前  
51好读  ›  专栏  ›  OSC开源社区

在 Java 9 里对 IntegerCache 进行修改?

OSC开源社区  · 公众号  · 程序员  · 2017-05-20 08:42

正文


协作翻译

原文:Hacking the IntegerCache in Java 9?

链接:https://dzone.com/articles/hacking-the-integercache-in-java-9

译者:-_-struggle, Tocy, 无若, cassia_tora


侵入 Java 运行时是非常有必要的,而且有显而易见的好处。当你在编写侵入代码时,你会对反射的工作机制以及 Integer 类的实现过程有一个更加深入的理解。


五年前,我在 Hungarian 上发表了一篇关于“怎样在 JDK 中修改 IntegerCahe”的文章。侵入 Java 运行时是非常有必要的,而且有显而易见的好处。当你在编写侵入代码时,你会对反射的工作机制以及 Integer 类的实现过程有一个更加深入的理解。


Integer 类有一个私有嵌套类——IntegerCache,包含 int 值从 -127 到 128 的 Integer 对象。


当代码要把一个 int 数据类型封装成 Integer 对象,并且 int 值在范围 -127~128 内时,Java 运行时环境使用缓存而不是重新创建一个 Integer 对象。


这是为了加快代码优化的速度,要记住:编程中的 int 数据类型在很多情况下是在规定的范围内的(类似数组的索引)。


这样做的副作用是,在很多时候,使用等号运算符来比较两个整数对象可能会工作,只要整数值在该范围内。这通常发生在单元测试期间。 在操作模式下,当某些值大于 128 时,此代码执行失败。


使用反射对 IntegerCache 做修改也可能导致奇怪的副作用,而且这会对整个 JVM 产生影响。如果一个 servlet 重新定义了小整数的缓存值,那么在同一个 JVM 上的相同 Tomcat 中运行的所有其他 servlet 都将受到影响。

请输入标题     abcdefg

请输入标题     bcdef

现在我已经上手了 Java 9 的早期公开版本,我想到可以用新版的 Java 来做相同的侵入操作。在开始用 Java 9 侵入之前,我们先用 Java 8 做一次。



上面的代码通过反射获取了 IntegerCache,然后把随机数赋值给 cache 成员变量。


我们在 Java 9 中也能执行这些代码。但是,不要高兴得太早。当人们试图在 Java 9 中进行违规操作时,后果会更严重。



会抛出一个 Java 8 中没有的异常。说是"对象不可访问",因为 java.base 模块(每个 java 程序都会自动导入的 JDK 运行时的一部分)不会将模块打开(侵入)到未知的模块。当我们试图设置该成员变量(cache)为“可访问的”的时候,就会抛出这个异常。


在 Java 8 中轻易就能访问到的对象在 Java 9 中变得不可访问了,因为 Java 9 中模块系统会对对象进行保护。代码只有在类处于同一模块下,或为了所有模块或本模块能进行反射性访问,模块打开包时,才能访问成员变量、方法以及其他内容。这些都是在"module-info.java"模块定义文件里配置的:



“java.base”模块不会为了编程人员开放它本身,尤其是不会为了未知的模块——也就是我们自己运行的代码。如果我们为了自己的代码创建一个模块,并且对它进行命名,然后错误信息就会包括我们模块的名字(而不是说未知的模块)。

请输入标题     abcdefg

请输入标题     bcdef

那我们是不是可以用 Java 9 本身有的方法来达到我们的目的呢?


在“java.lang.reflect.Module”模块有一个"addOpens"方法。


那这样做可以吗?


这样做是不行的,对于我们这些想这样做的人来说是个坏消息。如果包已经被模块通过上面的方法打开了,那么我们只能将模块下的包打开到别的模块。这样的话,模块可以传递给其他模块,虽然 Java 9 不对外开放的内容我们还是无法访问到 ,但是通过反射模块已经可以访问到一些包了。


但是同时,对于我们来说这也是一个好消息。不像 Java 8,Java 9 的安全性比较好,不容易被攻击。至少这个小漏洞被堵住了。看起来 Java 好像开始变成专业级别的,而不再是一个小玩物了(不好意思,开个玩笑)。在不久的将来,我们可以从 RPG 和 COBOL 迁移一些重要的程序到 Java 上来。

请输入标题     abcdefg



推荐阅读

20 个开源 Android App,帮助提高开发技巧

让开发更快更顺畅的 VS Code 插件推荐(二)

一名 40 岁“老”程序员的反思

用于构建优秀命令行的 4 个 Python 库

“放码过来”邀您亮“项”,一不小心就火了!

点击“阅读原文”查看更多精彩内容