我想重新定义StackOverflowError
构造函数的字节码,以便在发生堆栈溢出时有一个“挂钩”。我想要做的就是在构造函数的开头插入一个方法调用到我选择的静态方法。有可能这样做吗?
答案 0 :(得分:2)
您应该能够使用以下两种方式中的一种方式(除非在过去的1 - 2年内发生了变化,在这种情况下,我喜欢一些指向更改日志/文档的链接):
在评论中提到,我认为不太可行,修改你感兴趣的类,将它们放在一个jar中,然后使用-bootclasspath
选项加载它们而不是默认的。如前所述,这可能会产生一些法律问题(一般来说都很痛苦)。
你应该能够(或者至少你曾经能够)instrument几乎所有的核心课程(iirc Class
是我见过的唯一例外)。您可能遇到的许多问题之一是,在您提供的代理(或者他们的premain
方法确切)被咨询之前,许多核心类正在初始化。为了解决这个问题,你必须将Can-Retransform-Classes
属性添加到你的代理jar中,然后重新转换你感兴趣的类。请注意,重新转换的功能稍微强一点,并不能给你所有您通常使用仪器的选项,您可以在文档中阅读更多相关信息。
我假设你知道怎么做仪器?
答案 1 :(得分:1)
有几件事需要考虑。
java.lang.StackOverflowError
。我在1.7.0_40
上成功尝试了。 isModifiableClass(java.lang.StackOverflowError.class)
返回true
并成功重新定义了将方法调用插入其所有构造函数中ClassLoader
关系强加的可见性。由于StackOverflowError
由引导加载程序加载,因此它只能调用引导加载程序加载的类的方法。你必须add the target method’s class(es) to the bootstrap loader throw
是StackOverflowError
手动,则此方法有效。但是,当发生真正的堆栈溢出时,JVM最后要做的就是调用其他方法(记住错误说的是,堆栈已满)。因此,它创建StackOverflowError
的实例而不调用其构造函数(JVM可以这样做)。所以在这种情况下你的仪器毫无意义。1.7.0_40
支持重新定义StackOverflowError
的事实并不意味着其他版本或其他JVM也可以这样做。答案 2 :(得分:0)
您无法在java。*中重新定义任何内容,否则您将获得SecurityException。您可以通过修改环境(安全策略和自定义运行时类)在某种程度上解决这个问题,但我建议不要搞乱它。
话虽如此,如果堆栈已被溢出/删除,您如何调用您的方法?你将不得不使用一些JNI伏都教来获得你想要的东西。另外,为什么只是抓住它不适合你?你究竟想要从抛出/传播后无法得到的异常中“获得”什么?