我可以用sun.misc.Unsafe覆盖对象吗?

kof*_*cii 9 java unsafe

如果它们是同一个类的实例,它们的大小是相同的,使用sun.misc.Unsafe,我可以覆盖一个obejct与另一个obejct吗?

编辑:通过"覆盖"我的意思是"删除"第一个对象,蚂蚁用第二个填充内存.可能吗?

Jér*_*nge 9

通过"覆盖"我的意思是"删除"第一个对象,蚂蚁用第二个填充内存.可能吗?

是的,不是.

- 如果你使用Unsafe分配一些内存并写一个long,然后在其中写另一个long(例如),那么是的,你删除了第一个对象并用第二个对象填充了内存.这类似于你可以用ByteBuffer做的.当然,long是一种原始类型,所以它可能不是你所说的'对象'.

Java允许这样做,因为它可以控制已分配的内存.

- Java使用对象的引用,仅提供对这些对象的引用.而且,它倾向于在存储器中移动对象(即,用于垃圾收集).

没有办法获取"物理地址"并将内存内容从一个对象地址移动到另一个对象地址,如果这是你正在尝试的.而且,您实际上无法"删除"该对象,因为它可能会从代码中的其他位置引用.

但是,总是有可能将引用A指向另一个objectB而不是objectA,A = objectB;你甚至可以使用这个原子Unsafe.compareAndSwapObject(...).

解决方法 - 现在,让我们假设引用A1,A2,A3指向同一个对象A. 如果你想让所有人突然指向objectB,你就不能使用Unsafe.compareAndSwapObject(...),因为只有A1指向objectB,而A2和A3仍指向objectA.它不是原子的.

有一个解决方法:

public class AtomicReferenceChange {

    public static Object myReference = new Object();

    public static void changeObject(Object newObject) {
        myReference = newObject;
    }

    public static void main(String[] args) {

        System.out.println(AtomicReferenceChange.myReference);
        AtomicReferenceChange.changeObject("333");
        System.out.println(AtomicReferenceChange.myReference);

    }

}
Run Code Online (Sandbox Code Playgroud)

您可以定义公共静态引用,并让代码AtomicReferenceChange.myReference在任何地方使用,而不是对同一个对象进行多次引用.如果要以原子方式更改引用的对象,请使用静态方法changeObject(...).

  • 扩展此解决方案,如果您可以控制相关类,则可以使用代理模式(http://en.wikipedia.org/wiki/Proxy_pattern)更优雅地解决此问题.代理类将提供实际类的所有方法,但它只会将它们委托给包装对象.客户端不需要知道他们是否正在使用代理,并且通过交换包装对象,您可以使它看起来好像他们正在使用的对象被替换. (2认同)