Есть ли в Java какой-либо способ регистрировать * каждое * прерывание потока?

StackOverflow https://stackoverflow.com/questions/799023

Вопрос

Я хотел бы каким-то образом регистрироваться каждый раз Thread.interrupt() вызывается, регистрируя, какой поток выдал вызов (и его текущий стек), а также идентифицируя информацию о том, какой поток прерывается.

Есть ли способ сделать это?В поисках информации я увидел, как кто-то упоминал о возможности внедрения менеджера безопасности.Это что-то, что можно сделать во время выполнения (например, в апплете или клиенте Web Start), или для этого вам нужно использовать установленную JVM?

Или есть лучший способ сделать это?

Это было полезно?

Решение

В качестве быстрого взлома, это был много сделать это легче, чем я думал, что это будет.Поскольку это быстрый взлом, я не делал таких вещей, как обеспечение достаточной глубины трассировки стека перед разыменованием массива и т.д.Я вставил следующее в конструктор моего подписанного апплета:

log.info("Old security manager = " + System.getSecurityManager());
System.setSecurityManager(new SecurityManager() {
      @Override
      public void checkAccess(final Thread t) {
        StackTraceElement[] list = Thread.currentThread().getStackTrace();
        StackTraceElement element = list[3];
        if (element.getMethodName().equals("interrupt")) {
          log.info("CheckAccess to interrupt(Thread = " + t.getName() + ") - "
                   + element.getMethodName());
          dumpThreadStack(Thread.currentThread());
        }
        super.checkAccess(t);
      }
    });

и тот dumpThreadStack способ заключается в следующем:

public static void dumpThreadStack(final Thread thread) {
  StringBuilder builder = new StringBuilder('\n');
  try {
    for (StackTraceElement element : thread.getStackTrace()) {
      builder.append(element.toString()).append('\n');
    }
  } catch (SecurityException e) { /* ignore */ }
  log.info(builder.toString());
}

Конечно, я никогда не смог бы оставить это в производственном коде, но этого было достаточно, чтобы точно сказать мне, какой поток вызывал interrupt() этого я не ожидал.То есть, с этим кодом на месте, я получаю дамп стека для каждого вызова Thread.interrupt().

Другие советы

Прежде чем попробовать что-нибудь слишком дикое, рассматривали ли вы возможность использования Отладка Java API?Я бы подумал, что захват MethodEntryEvents в Thread.interrupt() сделает это.

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

Я бы посмотрел на Аспект J и его возможности для переноса вызовов методов.Ан сокращение точки выполнения вокруг interrupt() здесь должен помочь метод.

Обратите внимание, что, поскольку вы хотите перехватить вызов системного метода Java (в отличие от кода вашего приложения), приведенное выше мочь не подходит. Этот поток кажется, предполагают, что это возможно, но обратите внимание, что он создал сплетенный rt.jar .

Как говорили другие...Если это одноразовая вещь, JVMTI, вероятно, самый хардкорный способ.Однако не менее интересно было бы использовать библиотеку asm и API инструментария для создания агента, который вставляет вызов статического метода, созданного вами непосредственно перед вызовом Thread.interrupt() (или, возможно, изменяет метод Thread.interrupt(), чтобы сделать то же самое, я думаю, вы можете это сделать).

Изучение обоих требует некоторого времени, но работать с ними довольно забавно, и как только вы овладеете ими, вы сможете использовать их для всевозможных забавных вещей в будущем :-) На самом деле у меня нет хороших фрагментов для вставки сюда прямо сейчас, но если вы погуглите в поисках ASM и, возможно, заглянете в JIP для творческого использования ASM, я думаю, вы найдете вдохновение.

ДЖИП: Интерактивный Профилировщик Java

Вы могли бы попробовать также с JMX:

ManagementFactory.getThreadMXBean().getThreadInfo(aThreadID)

с помощью Информация о потоке объект, который вы можете зарегистрировать:

  • трассировка стека потока
  • общая полезная информация, такая как имя, статус и т. Д
  • и т.д.

Редактировать

используйте getAllThreadIds(), чтобы получить список идентификаторов текущего потока:

long[] ids = ManagementFactory.getThreadMXBean().getAllThreadIds();
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top