【问题标题】:Bug JDK-8191002 unclear if programming error or JRE error错误 JDK-8191002 不清楚是编程错误还是 JRE 错误
【发布时间】:2018-08-16 17:45:57
【问题描述】:

关于 JDK-8191002 中描述的问题,Java Cipher - PBE thread-safety issue 中也有讨论: 我不清楚 finalize() 方法中 Arrays.fill() 的使用是正确的还是错误的。一些答案表明应该使用reachabilityFence,但这是否意味着它是一个错误,或者这是否意味着reachabilityFence 是解决VM 中错误的一种解决方法? 谁能澄清/评论?

https://docs.oracle.com/javase/specs/jls/se9/html/jls-12.html#jls-12.6复制:“此外,该对象的字段的预终结读取都不会看到在启动该对象的终结之后发生的写入。” 这表明 JDK-8191002 中 NewlyAllocatedArrayFilledByOtherInstanceFinalizer 的代码是正确的,并且失败是由于 JVM 造成的。或不?

【问题讨论】:

    标签: java garbage-collection thread-safety finalize


    【解决方案1】:

    简而言之,这是 Java 代码中的错误,而不是 JVM 中的错误。

    此 Code Pattern 已在 JDK-8191002 中抽象出来

    static class ArrayHolder 
    { 
        private byte[] _bytes; 
    
        ArrayHolder(final byte[] bytes) { _bytes = bytes.clone(); } 
    
        byte[] getBytes() { return _bytes.clone(); } 
    
        @Override 
        protected void finalize() throws Throwable 
        { 
            if (_bytes != null) 
            { 
                Arrays.fill(_bytes, (byte) 'z'); 
                _bytes = null; 
            } 
            super.finalize(); 
        } 
    } 
    

    其中getBytes() 可能确实会虚假地返回z 填充的数组,而不是反映原始内容的数组(理论上,它甚至可以返回部分填充的数组)。

    “读取一个字段”是读取数组reference。数组的克隆(或数组的任何处理)发生在之后,因此,不会阻止该字段的所有者被垃圾收集。

    由于没有强制线程间内存可见性的操作,这种“读取字段”甚至不需要实际发生,线程可以重用以前读取的值(仍然在谈论 的值参考 这里),允许更早的对象集合。如果终结器更改了引用,这仍然遵守不感知对终结器所做的字段的写入的要求。

    如前所述,这并没有说明数组的内容,因为它不是已被垃圾回收的数组。数组和包含对数组的引用的对象是两个完全不同的对象。

    在阵列克隆后在持有人上放置可达性栅栏会创建一个新的依赖关系,因为在阵列克隆完成之前无法收集阵列持有人。

    byte[] getBytes() { 
        byte[] result = _bytes.clone(); 
        Reference.reachabilityFence(this); 
        return result; 
    }
    

    没有它,对对象的最后一次访问是调用clone() 之前,但如上所述,通过重用以前读取的引用可能会优化访问。如 JLS §12.6.1 所述:

    可以设计程序的优化转换,将可到达对象的数量减少到少于那些天真地认为是可到达的对象的数量。

    【讨论】:

    • 谢谢,解释清楚。恕我直言,JDK-8191002 应该被拒绝(而不是“重复”),但是好的,这是另一个讨论。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-08
    • 2011-08-28
    • 2014-02-18
    • 2023-03-28
    • 2012-08-06
    • 1970-01-01
    • 2018-06-14
    相关资源
    最近更新 更多