static List<Field> getFields(Class<?> clazz) { if (clazz == null || clazz == PhantomReference.class || clazz == Class.class || java.lang.reflect.Member.class.isAssignableFrom(clazz)) return emptyList(); List<Field> fields = fieldMap.get(clazz); if (fields != null) return fields; fieldMap.put(clazz, fields = new ArrayList<>()); for (Field field : clazz.getDeclaredFields()) { if (field.getType().isPrimitive() || Modifier.isStatic(field.getModifiers())) continue; field.setAccessible(true); fields.add(field); } fields.addAll(getFields(clazz.getSuperclass())); return fields; }
/** * Constructs a new queue. */ public FinalizableReferenceQueue() { // We could start the finalizer lazily, but I'd rather it blow up early. queue = new ReferenceQueue<Object>(); frqRef = new PhantomReference<Object>(this, queue); boolean threadStarted = false; try { startFinalizer.invoke(null, FinalizableReference.class, queue, frqRef); threadStarted = true; } catch (IllegalAccessException impossible) { throw new AssertionError(impossible); // startFinalizer() is public } catch (Throwable t) { logger.log(Level.INFO, "Failed to start reference finalizer thread." + " Reference cleanup will only occur when new references are created.", t); } this.threadStarted = threadStarted; }
@Override public void run() { while (true){ if(phantomQueue!=null){ PhantomReference<TraceCanReliveObj> objt=null; try { objt=(PhantomReference<TraceCanReliveObj>)phantomQueue.remove(); }catch (InterruptedException e){ e.fillInStackTrace(); } if(objt!=null){ System.out.println("TraceCanReliveObj is delete"); } } } }
public static void main(String[] args) throws InterruptedException{ Thread t=new CheckRefQueue(); t.setDaemon(true); t.start(); phantomQueue=new ReferenceQueue<TraceCanReliveObj>(); obj=new TraceCanReliveObj(); PhantomReference<TraceCanReliveObj> phantomRef=new PhantomReference<TraceCanReliveObj>(obj,phantomQueue); obj=null; System.gc(); Thread.sleep(1000); if(obj==null){ System.out.println("obj 是null"); }else { System.out.println("obj 可用"); } System.out.println("第二次gc"); obj=null; System.gc(); Thread.sleep(1000); if(obj==null){ System.out.println("obj是null"); }else { System.out.println("obj 可用"); } }
private static void phantom() throws InterruptedException { //Strong Reference BigObject a = new BigObject(); //Creating ReferenceQueue ReferenceQueue<BigObject> refQueue = new ReferenceQueue<>(); //Creating Phantom Reference to A-type object to which 'a' is also pointing PhantomReference<BigObject> phantomA = new PhantomReference<>(a, refQueue); System.out.println("Ref in pool before GC: " + refQueue.poll()); a = null; //Now, A-type object to which 'a' is pointing earlier is available for garbage collection. //But, this object is kept in 'refQueue' before removing it from the memory. a = phantomA.get(); //it always returns null System.gc(); Thread.sleep(100); System.out.println("Ref in pool after GC: " + refQueue.poll()); }
private Map<Object,Object> getWeakHashMap(Map<Object,Object> backingMap) { /* * Construct a weak hash map by copying the backingMap * The backing map must be kept alive as long as the returned map is * in scope, otherwise the contents will all end up garbage collected. * Track the WeakhashMap using a PhantomReference queue, so that the * backingmaps can be freed when the WeakHashMap has been GC. */ WeakHashMap<Object,Object> rv = new WeakHashMap<Object,Object>(backingMap); PhantomReference<WeakHashMap<Object,Object>> ref = new PhantomReference<WeakHashMap<Object,Object>>(rv, backingMapQueue); synchronized(backingMaps){ backingMaps.put(ref, backingMap); } return rv; }
/** * Constructs a new queue. */ public FinalizableReferenceQueue() { // We could start the finalizer lazily, but I'd rather it blow up early. queue = new ReferenceQueue<Object>(); frqRef = new PhantomReference<Object>(this, queue); boolean threadStarted = false; try { startFinalizer.invoke(null, FinalizableReference.class, queue, frqRef); threadStarted = true; } catch (IllegalAccessException impossible) { throw new AssertionError(impossible); // startFinalizer() is public } catch (Throwable t) { logger.log( Level.INFO, "Failed to start reference finalizer thread." + " Reference cleanup will only occur when new references are created.", t); } this.threadStarted = threadStarted; }
private static void phantom() throws InterruptedException { //Strong Reference BigObject a = new BigObject(); //Creating ReferenceQueue ReferenceQueue<BigObject> refQueue = new ReferenceQueue<>(); //Creating Phantom Reference to A-type object to which 'a' is also pointing PhantomReference<BigObject> phantomA = new PhantomReference<>(a, refQueue); System.out.println("Big object length:" + refQueue.poll()); a = null; //Now, A-type object to which 'a' is pointing earlier is available for garbage collection. //But, this object is kept in 'refQueue' before removing it from the memory. a = phantomA.get(); //it always returns null System.gc(); Thread.sleep(100); System.out.println("Big object length:" + refQueue.poll()); }
/** * Test that releasing the reference to the Cleaner service allows it to be * be freed. */ @Test void testCleanerTermination() { ReferenceQueue<Object> queue = new ReferenceQueue<>(); Cleaner service = Cleaner.create(); PhantomReference<Object> ref = new PhantomReference<>(service, queue); System.gc(); // Clear the Reference to the cleaning service and force a gc. service = null; System.gc(); try { Reference<?> r = queue.remove(1000L); Assert.assertNotNull(r, "queue.remove timeout,"); Assert.assertEquals(r, ref, "Wrong Reference dequeued"); } catch (InterruptedException ie) { System.out.printf("queue.remove Interrupted%n"); } }
/** * Create a CleanableCase for a PhantomReference. * @param cleaner the cleaner to use * @param obj an object or null to create a new Object * @return a new CleanableCase preset with the object, cleanup, and semaphore */ static CleanableCase setupPhantomSubclassException(Cleaner cleaner, Object obj) { if (obj == null) { obj = new Object(); } Semaphore s1 = new Semaphore(0); Cleaner.Cleanable c1 = new PhantomCleanable<Object>(obj, cleaner) { protected void performCleanup() { s1.release(); throw new RuntimeException("Exception thrown to cleaner thread"); } }; return new CleanableCase(new PhantomReference<>(obj, null), c1, s1, true); }
@SuppressWarnings("all") @Override public void run() { try { System.out.println("Waiting for GC"); /* * Aquí se bloqueara hasta que la referencia sea recolectada, * otra opción es el método poll pero este no es bloqueante, * sino que devuelve NULL si no hay referencias en la cola */ PhantomReference<Object> phantomReference = (PhantomReference<Object>) queue.remove(); System.out.println("Reference processed for GC"); } catch (InterruptedException e) { // Log and Handle exception e.printStackTrace(); } }
public static void startFinalizer(Class<?> paramClass, ReferenceQueue<Object> paramReferenceQueue, PhantomReference<Object> paramPhantomReference) { if (!paramClass.getName().equals("com.google.common.base.FinalizableReference")) { throw new IllegalArgumentException("Expected com.google.common.base.FinalizableReference."); } Thread localThread = new Thread(new Finalizer(paramClass, paramReferenceQueue, paramPhantomReference)); localThread.setName(Finalizer.class.getName()); localThread.setDaemon(true); try { if (e != null) { e.set(localThread, null); } localThread.start(); return; } catch (Throwable localThrowable) { for (;;) { a.log(Level.INFO, "Failed to clear thread local values inherited by reference finalizer thread.", localThrowable); } } }
/** * Constructs a new queue. */ @SuppressWarnings("unchecked") public FinalizableReferenceQueue() { // We could start the finalizer lazily, but I'd rather it blow up early. queue = new ReferenceQueue<Object>(); frqRef = new PhantomReference<Object>(this, queue); boolean threadStarted = false; try { startFinalizer.invoke(null, FinalizableReference.class, queue, frqRef); threadStarted = true; } catch (IllegalAccessException impossible) { throw new AssertionError(impossible); // startFinalizer() is public } catch (Throwable t) { logger.log(Level.INFO, "Failed to start reference finalizer thread." + " Reference cleanup will only occur when new references are created.", t); } this.threadStarted = threadStarted; }
/** * Allocates a byte buffer of the given size. * <p> * This {@code BufferSource} places no restrictions on the requested size of * the buffer. */ @Override public Page allocate(int size, boolean thief, boolean victim, OffHeapStorageArea owner) { while (true) { processQueue(); long now = max.get(); if (now < size) { return null; } else if (max.compareAndSet(now, now - size)) { ByteBuffer buffer; try { buffer = ByteBuffer.allocateDirect(size); } catch (OutOfMemoryError e) { return null; } bufferSizes.put(new PhantomReference<>(buffer, allocatedBuffers), size); return new Page(buffer, owner); } } }
/** Constructs a new finalizer thread. */ private Finalizer(Class<?> finalizableReferenceClass, Object frq) { super(Finalizer.class.getName()); this.finalizableReferenceClassReference = new WeakReference<Class<?>>(finalizableReferenceClass); // Keep track of the FRQ that started us so we know when to stop. this.frqReference = new PhantomReference<Object>(frq, queue); setDaemon(true); try { if (inheritableThreadLocals != null) { inheritableThreadLocals.set(this, null); } } catch (Throwable t) { logger.log(Level.INFO, "Failed to clear thread local values inherited" + " by reference finalizer thread.", t); } // TODO(user): Priority? }
public void testEntriesAreRemovedIfKeyIsGarbageCollected() throws InterruptedException { String key = new String("key"); ReferenceQueue refQueue = new ReferenceQueue(); Reference ref = new PhantomReference(key, refQueue); Map map = new WeakCache(); map.put(key, "value"); key = null; int i = 0; while (refQueue.poll() == null) { ref.get(); // always null assertTrue("Key still alive even after "+i+" forced garbage collections", i++ < 5); Thread.sleep(10); System.gc(); } assertEquals(0, map.size()); }
public void testSelfReferencingEntriesAreRemovedIfKeyIsGarbageCollected() throws InterruptedException { String key = new String("key"); ReferenceQueue refQueue = new ReferenceQueue(); Reference ref = new PhantomReference(key, refQueue); Map map = new WeakCache(); map.put(key, Collections.singleton(key)); key = null; int i = 0; while (refQueue.poll() == null) { ref.get(); // always null assertTrue("Key still alive even after "+i+" forced garbage collections", i++ < 5); Thread.sleep(10); System.gc(); } assertEquals(0, map.size()); }
public void testEntriesAreRemovedIfValueIsGarbageCollected() throws InterruptedException { String value = new String("value"); ReferenceQueue refQueue = new ReferenceQueue(); Reference ref = new PhantomReference(value, refQueue); Map map = new WeakCache(); map.put("key", value); value = null; int i = 0; while (refQueue.poll() == null) { ref.get(); // always null assertTrue("Value still alive even after "+i+" forced garbage collections", i++ < 5); Thread.sleep(10); System.gc(); } assertEquals(0, map.size()); }
public void testSelfReferencingEntriesAreRemovedIfValueIsGarbageCollected() throws InterruptedException { String key = new String("key"); Set value = Collections.singleton(key); ReferenceQueue refQueue = new ReferenceQueue(); Reference ref = new PhantomReference(value, refQueue); Map map = new WeakCache(); map.put(key, value); value = null; int i = 0; while (refQueue.poll() == null) { ref.get(); // always null assertTrue("Value still alive even after "+i+" forced garbage collections", i++ < 5); Thread.sleep(10); System.gc(); } assertEquals(0, map.size()); }
public void testCanUseDifferentMapImplementation() throws InterruptedException { String value = new String("value"); ReferenceQueue refQueue = new ReferenceQueue(); Reference ref = new PhantomReference(value, refQueue); Map map = new WeakCache(new TreeMap()); map.put("key", value); value = null; int i = 0; while (refQueue.poll() == null) { ref.get(); // always null assertTrue("Value still alive even after "+i+" forced garbage collections", i++ < 5); Thread.sleep(10); System.gc(); } assertEquals(0, map.size()); }
/** * @tests java.lang.ref.Reference#clear() */ @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "clear", args = {} ) public void test_clear() { tmpA = new Object(); tmpB = new Object(); tmpC = new Object(); SoftReference sr = new SoftReference(tmpA, new ReferenceQueue()); WeakReference wr = new WeakReference(tmpB, new ReferenceQueue()); PhantomReference pr = new PhantomReference(tmpC, new ReferenceQueue()); assertTrue("Start: Object not cleared.", (sr.get() != null) && (wr.get() != null)); assertNull("Referent is not null.", pr.get()); sr.clear(); wr.clear(); pr.clear(); assertTrue("End: Object cleared.", (sr.get() == null) && (wr.get() == null)); assertNull("Referent is not null.", pr.get()); // Must reference tmpA and tmpB so the jit does not optimize them away assertTrue("should always pass", tmpA != sr.get() && tmpB != wr.get()); }
/** * @tests java.lang.ref.PhantomReference#get() */ @TestTargetNew( level = TestLevel.COMPLETE, notes = "", method = "get", args = {} ) public void test_get() { ReferenceQueue rq = new ReferenceQueue(); bool = new Boolean(false); PhantomReference pr = new PhantomReference(bool, rq); assertNull("get() should return null.", pr.get()); pr.enqueue(); assertNull("get() should return null.", pr.get()); pr.clear(); assertNull("get() should return null.", pr.get()); }