關於sum.misc.Unsafe的一點記錄

最近在讀Undertow的源碼,對於ServletPrintWriterDelegate類的實現比較感興趣,作個記錄。html

源碼github座標:ServletPrintWriterDelegate.javajava

該類繼承的是PrintWriter,可是因爲並不實用PrintWriter中的OutputStream,因此實用Unsafe.allocateInstance構造了一個newInstance,完美的繞過了父類的構造方法,並可用於全部適用接口。git

作個記錄,備忘。github

生成實例:jvm

public static ServletPrintWriterDelegate newInstance(final ServletPrintWriter servletPrintWriter) {
    final ServletPrintWriterDelegate delegate;
    if (System.getSecurityManager() == null) {
        try {
            delegate = (ServletPrintWriterDelegate) UNSAFE.allocateInstance(ServletPrintWriterDelegate.class);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        }
    } else {
        delegate = AccessController.doPrivileged(new PrivilegedAction<ServletPrintWriterDelegate>() {
            @Override
            public ServletPrintWriterDelegate run() {
                try {
                    return  (ServletPrintWriterDelegate) UNSAFE.allocateInstance(ServletPrintWriterDelegate.class);
                } catch (InstantiationException e) {
                    throw new RuntimeException(e);
                }
            }
        });
    }
    delegate.setServletPrintWriter(servletPrintWriter);
    return delegate;
}

獲取Unsafe:ide

private static Unsafe getUnsafe() {
    if (System.getSecurityManager() != null) {
        return AccessController.doPrivileged(new PrivilegedAction<Unsafe>() {
            public Unsafe run() {
                return getUnsafe0();
            }
        });
    }
    return getUnsafe0();
}

private static Unsafe getUnsafe0()  {
    try {
        Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
        theUnsafe.setAccessible(true);
        return (Unsafe) theUnsafe.get(null);
    } catch (Throwable t) {
        throw new RuntimeException("JDK did not allow accessing unsafe", t);
    }
}

關於Unsafe進行了簡單的查看,除了用於繞過jvm生成對象以外,該類還提供了很是多的基於底層的操做,請參見:spa

sun.misc.Unsafe的理解code

讀完以後有幾個問題還沒有深究,回頭考慮補充:htm

一、是否能夠在必定程度上,使用該類去替代一些反射的調用。對象

二、聽說Unsafe的操做,是會繞過jvm的GC的,那如同上文那樣的操做,allocateInstance出來的對象,是否須要手動釋放?

檢查了下,經過allocateInstance生成的對象,內存空間屬於Java Heap,會被gc,不須要也不能夠進行手動釋放。

相關文章
相關標籤/搜索