如何从已编译的Java类/jar文件中删除方法?

如何从已编译的Java类/jar文件中删除方法?,java,reflection,bytecode,javassist,Java,Reflection,Bytecode,Javassist,我有一个JAR文件,有一个静态类,我不能反编译它,它会搞砸。其中有一个方法返回一个不存在的类。不知道怎么做,但我得到了NoClassDefFoundError。即使我没有使用这种方法,它仍然崩溃。所以我需要以某种方式移除它,它应该可以正常工作。我知道可以使用反射或Javassist,但不知道如何使用 请注意,这显然不是生产版本,只是一些白帽黑客行为。我认为您错了:如果永远不会调用该方法,那么JVM很可能不会加载该类 你看,类加载的全部要点——它发生得很慢;当你加载类X,X需要Y,Z。。。然后,只

我有一个JAR文件,有一个静态类,我不能反编译它,它会搞砸。其中有一个方法返回一个不存在的类。不知道怎么做,但我得到了
NoClassDefFoundError
。即使我没有使用这种方法,它仍然崩溃。所以我需要以某种方式移除它,它应该可以正常工作。我知道可以使用反射或Javassist,但不知道如何使用


请注意,这显然不是生产版本,只是一些白帽黑客行为。

我认为您错了:如果永远不会调用该方法,那么JVM很可能不会加载该类

你看,类加载的全部要点——它发生得很慢;当你加载类X,X需要Y,Z。。。然后,只有在执行某些需要加载Y,Z的代码时,才加载Y和Z

换句话说:NoClassDefFound错误实际上告诉您,某物(可能是JAR中某个地方的静态init)正在调用该方法


因此,解决方案不是“删除”一个方法(这只会导致另一个异常,如MethodNotFound!)。相反,您应该尝试创建一个伪类,以避免遇到该异常。或者:您的JAR至少缺少一个依赖项。您可以尝试解决该依赖关系-也许您可以在某个地方找到该类,或者“构建”自己的版本(第二个想法可能是很难纠正)。

GhostCat已经解释了为什么您的问题不是删除某个方法。但我想我应该回答最初的问题,以防其他人感到疑惑

从类文件中删除方法的最佳方法是使用反汇编,从
.j
文件中删除所需的方法,然后重新组装它。这个方法允许你编辑任何类文件,不管它有多奇怪。(如果您发现Krakatau反汇编程序无法处理的任何有效类文件,请提交一个bug)


反汇编时,您可能还希望传递
-roundtrip
选项。这对于正确性不是必需的,但它可以防止常量池被重新排列,从而减少生成的类文件的二进制差异。另一方面,
-roundtrip
也使得在
.j
文件中查找所需的方法变得更加困难。

它与否相关?是的,您可以在那里继续讨论…:-)嗯,不知道。。。构建我自己的版本是可行的,但我必须使用JVM参数
-noverify
。该死的,这真是个骗人的烂摊子,不过谢谢你,请接受我,表达你的感激之情。和/或向上表决main的另一个答案。我接近每日极限;我喜欢撞那堵墙;-)考虑到您没有指定特定的JVM,“从不”太强了。关于JVM尝试解析类的时间,规范中有很大的自由度。规范没有强制要求惰性类加载,这常常与保证的惰性初始化相混淆。对于Oracle/OpenJDK,它确实不会尝试解析从未调用过的方法的返回类型,但如果有一个(条件)代码路径可以调用它,则在验证过程中可能已经触发类加载。@Holger感谢您的输入。我相应地改变了我的措辞。我将“正在调用那个方法”改为“正在潜在地调用那个方法”,然后,它合并了由验证器加载的场景,而没有太多细节。