是否可以挂钩线程创建?

时间:2021-07-30 00:10:45

标签: java hook

我正在制作一个插件系统,我需要查看插件何时调用 Thread.start() 是否有一种类似于 Runtime.getRuntime().addShutdownHook 的方法,但用于在线程启动时挂钩?

4 个答案:

答案 0 :(得分:3)

您可以使用 Byteman 将您自己的代码注入到 thread.start() 方法中。

事实上,在他们的网站上使用 Byteman 和 JVM 类的第一个例子是一个展示如何在线程启动时打印到控制台的例子。

来自他们教程的 Byteman 脚本示例:

RULE trace thread start

CLASS java.lang.Thread

METHOD start()

IF true

DO traceln("*** start for thread: "+ $0.getName())

ENDRULE

请参阅 https://developer.jboss.org/docs/DOC-17213#how_do_i_inject_code_into_jvm_classes 了解更多实施详情。

答案 1 :(得分:0)

您可以枚举线程,但无法同步创建线程。

答案 2 :(得分:0)

嗯。也许有办法。

如果当前上下文有SecurityManager,则检查当前线程是否被允许访问新的ThreadGroup的{​​{1}}。构建。

所以……

您可以(理论上)设置自定义 Thread 并使用线程组访问检查作为“挂钩”新 SecurityManager 创建的一种方式。但这只会告诉您正在创建一个线程,而不是该线程实际上是什么。因此,这种方法可能足以满足您的需求,也可能不够。

而且没有办法钩住 Thread 调用。


另一种方法是扩展 Thread.start() 并在线程创建或在子类中启动时实现钩子。

您可以将调试器附加到您的 JVM 并将断点设置为 Thread。或者甚至使用 JVMTI 等以编程方式执行此操作。但是,应用程序 (AFAIK) 不可能针对其自己的 JVM1 使用 JVMTI ......所以这是不是传统的“挂钩”。

最后,总是可以选择下载 OpenJDK、修改 Thread.start() 类、构建自定义 JVM 并安装它。这对于做一些实验来说可能没问题,但对于生产应用程序来说这将是一件疯狂的事情。 (您不想让自己……或您的客户……负担维护 OpenJDK 的永久分支。)


1 - 即使在某些情况下是可能的,Thread 类也会带来额外的困难。例如,考虑在类加载器加载类之前必须完成诸如字节码重写之类的事情。但是 Thread 类必须在 JVM 引导期间加载......并且在加载任何应用程序代码之前。

答案 3 :(得分:0)

不是以正常方式,但请记住 EXPECT_CALL(*vulkanLibMock, vkCreateDescriptorSetLayout); VulkanDescriptorManager manager(nullptr); 是公开的和非最终的,因此您可以创建 Thread 的子类,以便在开始之前执行您的自定义逻辑。 但这显然不足以解决这个问题。

可能有效的黑魔法解决方案是从运行时删除现有的 Thread.start 类(这意味着修改您的 JRE/JDK)并将其替换为您的“丰富”版本。只要新版本和“普通”版本做同样的事情(注册本地人,调用本地代码)就可以了。

另一种黑魔法替代方法是实际查看由 Thread 调用的本机代码是什么并对其进行修改。但这意味着再次使用您的运行时环境。

最后的想法是让应用程序始终以类似于调试模式的方式运行,并在到达断点时执行某些操作。这是可行的,因为这是 IDE 所做的。尽管我们刚刚转向了双进程设计及其所需要的东西。

我还想知道 Java instrumentation package 是否可能不会在这里提供某种替代方案。