我有一个代码,我想知道可以阻止JIT优化方法 clearArraySafely 吗? 是否有可能选择性地禁用部分代码的JIT?
或者我如何确定此代码不会被优化?
private static char[] password;
public static void clearArraySafely() {
// Overwritting array
for (int i = 0 ; i <= password.length; i++) {
password[i] = 0;
//System.out.print(i); // <- I don't want to do this trick to be sure
}
password = null;
}
是否有任何好的类来存储char数组的密码?
答案 0 :(得分:2)
这个问题有两个答案:
AFAIK,没有办法“关闭”某种方法的优化,而不会为所有方法关闭它。
您可以执行可能禁止您担心当前一代Java编译器的特定优化的事情。例如:
private static char[] password;
public static String dummy;
public static void clearArraySafely() {
// Overwritting array
for (int i = 0 ; i <= password.length; i++) {
password[i] = 0;
}
dummy = new String(password);
password = null;
}
JIT编译器无法优化零分配。如果是,那么将使用“错误”内容创建虚拟字符串。由于dummy
可以通过反射访问而不会破坏任何JLS规则,因此JIT无法应用转义分析来避免创建它。
但请注意,总有可能会有一些下一代JIT编译器......更加聪明。如果你想避免这种情况,你需要确保dummy
以某种方式影响程序的输出;例如通过打印它。
是否有任何好的类来存储char数组的密码?
AFAIK,没有人会遇到同样的问题。
话说回到这个级别来保护密码是(IMO)接近偏执狂。如果某人具有从堆中无法访问的对象中窃取密码所需的访问级别,则他们很可能以其他方式获取密码;例如通过截取OS级别的字符,或“调试”JVM。
我的偏执与调试JVM有关。
不幸的是,你的妄想症无济于事。
例如,您设计用于阻止某人连接调试器的方案可以通过逆向工程然后修改exe
文件来解决。您设计的任何其他方案也是如此。
如果用户控制执行程序的平台,则无法阻止他/她“调试”正在运行的程序。防止它的唯一方法是仅在您控制的平台上运行应用程序。
(BTW - 这不是Java特有的问题。它适用于所有编程语言。有些比其他语言更容易“破解”,但如果不道德的用户熟练,他们可以所有被黑客攻击并有动力,并有时间发展“黑客”。)
答案 1 :(得分:0)
编译器无法优化那些分配,因为它不知道是否对该数组有其他引用。变量password
是对数组的引用,而不是对实际数组的引用。考虑一下:
char[] passwordCopy = password;
clearArraySafely();
// do something with passwordCopy
如果编译器删除了调零,则此代码将中断。如果Java使用引用计数,那么我认为如果refcount为1,它可以“优化”它,但这似乎不值得做。大多数情况下,人们不是在编写代码来更改后来被丢弃的东西。
您可能还想考虑使用GuardedString
。