我读到JPMS的优点之一是更好的封装(除非明确打开,否则所有内容都将受到限制)。
但是我有一个问题:是什么阻止程序员替换第三方模块JAR中的module-info.class
并导出所有包,甚至制作open
模块,所以一切都可以通过反射访问(包括{ {1}}名成员。
JPMS确实可以真正帮助隐藏内部代码吗?或者就像Java 8和更早版本一样:所有都可以通过反射API访问,甚至private
成员(从Java 9开始需要额外的步骤来打开模块)?
答案 0 :(得分:1)
我认为可以说,安全 / 防篡改代码意义上的保护不是JPMS的主要目标。
如果仍然有可能进行篡改,则能够检测还是很有价值的,无论给定的应用程序是否遵守规则(或在什么程度上放宽了规则)
一个明显的动机是或多或少地温和地推动开发人员以产生“良好的模块化”代码。逐渐地,“更好”的代码仍然比“不好”的代码“更好”。在某些情况下,需要采取其他措施是抵制诱惑的原因。
不太明显的动机是在运行时支持先进的模块化流分析,这将使JIT可以安全执行的优化受益。
很多年前,我创造了“渐进式封装”一词来表示一种方法和技术,该方法和技术实施了“尽可能多的封装”,但同样重要的是,它也没有超出您的负担(建立完美的封装有其代价) )。一组用于调整模块化的JPMS命令行选项可以看作是一个工具集,用于精确声明无法承受完美封装的异常(由于多种可能的原因之一)。伪造jar文件当然是可能,但是如果对原始文件进行了签名,它也是可检测的。在所有这些方面,即使您不能做到“完美”,保持“诚实”也很有价值。
(所有引号中的术语显然都是p.o.v.的问题。)
答案 1 :(得分:1)
修补存储的模块与使用反射访问私有成员而不修改存储的类之间存在根本的区别。
通常,没有绝对的安全性。安全性始终与攻击者的工作量有关。最好的情况是,成功的攻击所需的工作量远远超过攻击者可能从中获得的收益。
如果您有权访问代码(包括更改代码或创建修改后的副本的可能性),则所有选择均不可行。
但是主要的重点不是那种安全性,而是指导开发人员正确使用库。在模块系统之前,任何public
类及其public
或protected
成员都是可以访问的,甚至可以由IDE建议,例如,自动完成代码,并且需要付出额外的努力才能告诉IDE某些类或成员不是API的一部分,因此,在编译引用它们的代码时,不应建议甚至拒绝这些类或成员。
如今,使用一个模块,需要付出额外的努力才能再次访问非API工件,从而极大地改变了游戏。现在,无论是否具有访问修饰符,再次使非API工件都变得很难访问,因此您不能错误地认为某物是API的一部分,只是因为它是public
。
同样,您不能期望库开发人员在内部对其反射黑客保持向后兼容性。您无法完全阻止此类访问。但是,开发人员需要花更多的精力来创建这样的代码,他们会更好地知道他们偏离了轨道,并且无法期望结果在下一个版本中继续有效。