Мне нужно перечислить хуки, зарегистрированные в java.lang.ApplicationShutdownHooks - PullRequest
10 голосов
/ 29 июля 2011

У меня есть стороннее приложение, которое имеет ошибку, из-за которой оно регистрирует несколько перехватчиков завершения работы, когда ему нужно только 1.

Мой вопрос: как мне увидеть, что такое зарегистрированные хуки отключения? Я хочу повторить их, а затем вызвать метод удаления. Коллекция, содержащая крючки, является частной статической и не содержит аксессора. Мы пробовали рефлексию, но так как класс является частным пакетом, мы должны сделать наш взломщик частью java.lang, который является запрещенным пакетом.

Есть идеи?

/*
 * %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) { }
}
}
}

1 Ответ

16 голосов
/ 29 июля 2011

Пакет приватный не должен вас тормозить, это отражение! Разрешены все виды магии вуду.

В этом случае вам нужно получить класс, затем поле, затем установить его как доступный, а затем прочитать его значение.

    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>

Более простым способом просмотра информации такого рода может быть просто взять дамп кучи приложения и проанализировать его в анализаторе памяти, например MAT (для Eclipse) или JProfiler .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...