2011-07-28 9 views
9

Mam aplikacji 3rd party, które ma błąd, który powoduje, że aby zarejestrować kilka haków zamykaniem gdy tylko potrzebuje 1.muszę notować haki zarejestrowani java.lang.ApplicationShutdownHooks

Moje pytanie brzmi jak mogę zobaczyć, jakie są zarejestrowane haki zamykające? Chcę iterować je, a następnie wywołać metodę usuwania. Kolekcja trzymająca haczyki jest statyczna i nie zawiera akcesora. Próbowaliśmy refleksji, ale ponieważ klasa jest pakietem prywatnym, musimy stworzyć naszą część crackera z java.lang, która jest zabronionym pakietem.

Wszelkie pomysły?

/* 
* %W% %E% 
* 
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. 
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 
*/ 
class ApplicationShutdownHooks { 
static { 
    Shutdown.add(1 /* shutdown hook invocation order */, 
     new Runnable() { 
      public void run() { 
       runHooks(); 
      } 
     }); 
} 

/* The set of registered hooks */ 
private static IdentityHashMap<Thread, Thread> hooks = new IdentityHashMap<Thread, Thread>(); 

private void ApplicationShutdownHooks() {} 

/* Add a new shutdown hook. Checks the shutdown state and the hook itself, 
* but does not do any security checks. 
*/ 
static synchronized void add(Thread hook) { 
if(hooks == null) 
    throw new IllegalStateException("Shutdown in progress"); 

if (hook.isAlive()) 
    throw new IllegalArgumentException("Hook already running"); 

if (hooks.containsKey(hook)) 
    throw new IllegalArgumentException("Hook previously registered"); 

    hooks.put(hook, hook); 
} 

/* Remove a previously-registered hook. Like the add method, this method 
* does not do any security checks. 
*/ 
static synchronized boolean remove(Thread hook) { 
if(hooks == null) 
    throw new IllegalStateException("Shutdown in progress"); 

if (hook == null) 
    throw new NullPointerException(); 

return hooks.remove(hook) != null; 
} 

/* Iterates over all application hooks creating a new thread for each 
* to run in. Hooks are run concurrently and this method waits for 
* them to finish. 
*/ 
static void runHooks() { 
Collection<Thread> threads; 
synchronized(ApplicationShutdownHooks.class) { 
    threads = hooks.keySet(); 
    hooks = null; 
} 

for (Thread hook : threads) { 
    hook.start(); 
} 
for (Thread hook : threads) { 
    try { 
    hook.join(); 
    } catch (InterruptedException x) { } 
} 
} 
} 

Odpowiedz

10

Pakiet prywatny nie powinien Cię spowalniać, to Odbicie! Wszystkie rodzaje magii voodoo są dozwolone.

W takim przypadku należy uzyskać klasę, następnie pole, a następnie ustawić ją jako dostępną, a następnie odczytać jej wartość.

Class clazz = Class.forName("java.lang.ApplicationShutdownHooks"); 
    Field field = clazz.getDeclaredField("hooks"); 
    field.setAccessible(true); 
    Object hooks = field.get(null); 
    System.out.println(hooks); //hooks is a Map<Thread, Thread> 

Prostszym sposobem, aby tego rodzaju informacje mogą być tylko do take a heap dump zgłoszenia i analizować je w pamięci analizatora jak MAT (Eclipse) lub JProfiler.

+0

To było MAT, które zaprowadziło mnie tutaj. http://stackoverflow.com/questions/6847580/i-need-help-finding-my-memory-leak-using-mat – Preston

+0

Ah, OK. Cóż powyższe powinno ci wtedy pomóc. –