最近在讀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
讀完以後有幾個問題還沒有深究,回頭考慮補充:htm
一、是否能夠在必定程度上,使用該類去替代一些反射的調用。對象
二、聽說Unsafe的操做,是會繞過jvm的GC的,那如同上文那樣的操做,allocateInstance出來的對象,是否須要手動釋放?
檢查了下,經過allocateInstance生成的對象,內存空間屬於Java Heap,會被gc,不須要也不能夠進行手動釋放。