2016-09-19 30 views
1

我有一个JAR文件,有一个静态类,我不能反编译它,它会搞砸。有一种方法,它返回一个不存在的类。不知道如何,但我得到NoClassDefFoundError。尽管我没有使用这种方法,但它仍然崩溃。所以我需要以某种方式删除它,它应该工作正常。我知道可以使用Reflection或Javassist,但不知道如何。如何从已编译的Java类/ jar文件中移除一个方法?

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

+0

这是否与http://stackoverflow.com/questions/39579166/how-to-extend-a-final-classreflection-javassist/39579401#39579401.If是的,你可以继续在那里讨论..: - ) –

回答

2

我想你错了:如果该方法永远不会被调用,那么JVM将很可能不是尝试加载该类。

你看,类加载的全部 - 它发生懒惰;当你加载类X,并且X需要Y,Z ...时,只有当某些代码被执行时需要加载Y,Z才会加载Y和Z.

换句话说:NoClassDefFound错误实际上告诉你,东西(也许你的JAR中某个地方的静态init)正在调用该方法。

因此,解决方案不是“切除”一种方法(这只会导致另一个异常,如MethodNotFound!)。相反,您应该尝试创建一个虚拟类,以便根本不会遇到该异常。或者:您的JAR至少缺少一个依赖关系。你可以尝试决心这种依赖性 - 也许你可以在某个地方找到了类,或者,你“建设”你自己的版本(第二个想法可能是大概很难得到正确的)。

+1

嗯,不知道...建设自己的版本,它的工作,但我不得不使用JVM PARAM'-noverify'。上帝该死的这是骗人的烂摊子,但是感谢bro –

+1

随时通过接受来表达你的感激之情。和/或提高主要的其他答案。我即将达到每日上限;我喜欢打*是*墙;-) – GhostCat

+2

“从不”太强了,因为你没有指定特定的JVM。规范中关于JVM尝试解析类的时间有很大的自由度。惰性类加载不是规范所要求的,这经常与保证的惰性*初始化*相混淆。对于Oracle/OpenJDK,它确实不会尝试解决永不调用的方法的返回类型,但具有*可能调用它的(条件)代码路径可以在验证期间触发类加载。 – Holger

1

GhostCat已经解释了为什么你的问题没有删除一个方法。但我想我应该回答原来的问题,以防其他人想知道。

从类文件中删除方法的最好方法是用Krakatau反汇编它,从.j文件中删除所需的方法,然后重新组合。这种方法允许你编辑任何类文件,无论多么奇怪。 (如果您发现Krakatau反汇编程序无法处理的任何有效的类文件,请提交错误)。

拆解时,您可能还想通过-roundtrip选项。这对于正确性来说并不是必需的,但它可以防止重新排列常量池,从而减少生成的类文件的二进制差异。另一方面,-roundtrip也使得在.j文件中找到所需的方法更加困难。

相关问题