【问题标题】:can JIT be prevented from optimising method?可以防止 JIT 优化方法吗?
【发布时间】:2013-05-31 13:23:37
【问题描述】:

我有一个代码,我想知道是否可以阻止 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数组的密码?

【问题讨论】:

  • 禁用优化将如何阻止某人输入System.out.print 或以其他方式捕获数据(即使用附加的调试器)......?看来问题是把自己逼到一个角落。
  • 您似乎正试图防止某种攻击。除非您确定这实际上是足够的保护,否则您只是在浪费时间。如果敌人可以读取 JVM 内存的内容,即使没有 GC 保留路径,那是不是游戏就结束了?
  • 密码,无论是纯文本还是散列值,都只是 Java 的字符串。不要担心保护字符串免受恶意用户的侵害。担心一些必要的“全局”手段,例如防火墙等......
  • Matt Ball@你是对的,我正在阻止什么,我认为你是对的 - 我太偏执了,一方面我在想怎么可能破解它,同时它又是怎样的无论如何都可以确保安全。
  • 我想知道:这可以优化吗?我的意思是,它有实际的语义,一个对象发生了变异——JIT 是否会优化它(远离——我想那是你的麻烦)只是因为在调用方法后对象不可用? JIT 是否必须假设该引用仍然可以在某处使用?另外,为什么要先存储密码?

标签: java compiler-construction jit


【解决方案1】:

这个问题有两个答案:

  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 以某种方式影响程序的输出;例如打印出来。

有什么好的类来存储char数组的密码吗?

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


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


我的偏执与调试 JVM 有关。

不幸的是,你的偏执无济于事。

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

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

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

【讨论】:

  • 我的妄想症与调试 JVM 有关。因此,将生成的打包应用程序 JAR 文件转换为 EXE 文件并设置 JVM 参数“-XX: + DisableAttachMechanism”和“-Dcom.ibm.tools.attach.enable = false”。
  • 现在我的想法是为 JAR 文件创建一个校验和系统,并在应用程序启动时对其进行检查。在一个JAR文件的情况下不会有问题,相反,我还在思考如何为一个EXE文件的形式做到这一点(自检-JAR+小型EXE启动器呢?)。最糟糕的是我完全不相信这种类型的校验和,它应该确保文件不会被第三方修改。
【解决方案2】:

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

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

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

您可能还想考虑使用GuardedString。

【讨论】:

    猜你喜欢
    • 2012-08-23
    • 2018-06-04
    • 1970-01-01
    • 2017-06-25
    • 2021-05-06
    • 1970-01-01
    • 1970-01-01
    • 2013-07-18
    • 1970-01-01
    相关资源
    最近更新 更多