0

我有一个代码,我想知道是否可以防止 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;
}

有没有什么好的类来存储字符数组的密码?

4

2 回答 2

2

这个问题有两个答案:

  1. AFAIK,如果不关闭所有方法,就无法“关闭”优化。

  2. 您可以做一些可能会抑制您担心当前一代 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以某种方式影响程序的输出;例如通过打印它。

有没有什么好的类来存储字符数组的密码?

AFAIK,没有一个不会遇到同样的问题。


话虽如此,进入这个级别来保护密码是(IMO)接近偏执狂。如果某人具有从堆中无法访问的对象中窃取密码所需的访问级别,他们很可能可以通过其他方式获取密码;例如通过在操作系统级别截取字符,或者通过“调试”你的JVM。


我的偏执与调试 JVM 有关。

不幸的是,你的妄想症无济于事。

例如,您设计的用于防止有人附加调试器的方案可能会被逆向工程然后修改exe文件所破坏。你设计的任何其他方案也可以。

如果用户控制执行程序的平台,则无法阻止他/她“调试”正在运行的程序。防止它的唯一方法是仅在控制的平台上运行应用程序。

(顺便说一句——这不是 Java 特有的问题。它适用于所有编程语言。有些语言比其他语言更容易“破解”,但如果不道德的用户熟练且有动力,并且有时间开发“黑客”。)

于 2013-06-05T02:14:07.263 回答
0

编译器无法优化这些赋值,因为它不知道是否有其他对该数组的引用。该变量password是对数组的引用,而不是实际的数组。考虑一下:

char[] passwordCopy = password;
clearArraySafely();
// do something with passwordCopy

如果编译器删除归零,此代码将中断。如果 Java 使用引用计数,那么我想如果它看到 refcount 为 1,它可以“优化”它,但这似乎并不值得做。大多数时候,人们不会编写代码来更改随后被丢弃的东西。

您可能还想考虑使用GuardedString.

于 2019-08-26T22:57:22.340 回答