2013-03-19 69 views
2

我正在调试使用预编译的jar的程序。我想在某些类中记录对函数的调用。我们的想法是原来的类文件Xxx.class重命名为Xxx0.class和定义原始类的名称为:如何重命名Java .class文件?

class Xxx extends Xxx0 { 
    void func() { 
     Log.d(...); 
     super.func(); 
    } 
} 

任何想法?

(我曾尝试反编译:有在反编译的代码奇怪的控制结构,反编译器可能不会产生正确的代码对这一计划)

+0

@Juvanis看起来像是二进制的小数形式[1111111111111111111111111111111111111111111111111111111111111111](http://www.wolframalpha.com/input/?i=+18446744073709551615),还是2^64-1。 – Kapep 2013-03-19 07:13:56

+0

@Juvanis我用来生成我的用户名是无关紧要的。 – 18446744073709551615 2013-03-19 07:41:09

+0

@Juvanis请留在话题上。虽然它是一个聪明的用户名,但是stackoverflow不适合脱离主题讨论。 – DankMemes 2013-03-20 06:14:07

回答

1

你不能只重命名一个类文件,因为加载它时不仅使用类的名称来计算类文件的名称,而且该类的名称也存储在类文件中,并且必须与请求的类匹配。

因此,如果你想重命名一个类,你需要在源代码中重新编译。

+0

是的,但由于有反编译器,有人可以实现一个重命名工具。 – 18446744073709551615 2013-03-19 07:35:40

+0

当然,但我觉得使用JPDA或其他方式来改变活动虚拟机中的功能可能更简单,也更简单。 :) – Dolda2000 2013-03-19 07:38:59

+1

嗯,这可能是夸张的,但我想说明,它不会像在类文件中更改名称一样简单;例如,您也必须在常量池中更改对它的所有引用,并且我不知道类的其他格式是否足够好,以便说明是否还有其他需要更新的符号引用。 – Dolda2000 2013-03-19 07:45:30

0

您无法更改.class文件的名称,因为它与java的公共类相关联(相同)。如果您更改了.class文件的名称,那么您仍然需要更改类的名称,否则会导致错误。

一旦它符合(.java到.class)它将转换为字节码,所以如果您更改了类文件的名称,您将无法直接更改字节码,但可以将.cl​​ass文件转换为.java使用反编译器(反射),然后将公共类名更改为您更改的文件名,再次构建并使用它。

您可以获得很多可用的反编译器,它们可以很容易地将.class转换为.java,并且80%相同。

+1

Java编译器不会将Java源代码转换为OS本机代码,它会将其编译为与JVM兼容的字节码。 JVM然后将字节码转换为本地代码。 – Logan 2013-03-19 07:19:00

+0

是的,它的字节码本地代码:)谢谢 – Amol 2013-03-19 09:21:20

1

如果要重命名一个类的蚂蚁,你没有Java源代码文件,然后执行以下步骤:

我)首先在JD(Java反编译器)打开该文件,然后保存(Ctrl + S)源文件。
ii)重命名java文件(F2)以及java文件中的类名。
iii)再次编译java文件(使用任何java编译器)到.class文件。

这将解决您的问题。
试试这个,让我知道万一有任何顾虑。

备注:如果您在使用java解压缩程序时遇到问题,请尝试使用其他版本的JD。
Please visit here to download latest JD

+0

不幸的是,因为那个类jd显示'// INTERNAL ERROR //'。 – 18446744073709551615 2013-03-19 07:32:05

+0

你用JD打开过类文件吗?它显示的是java代码吗? – 2013-03-19 07:37:59

+0

不,它显示'// INTERNAL ERROR //'。如果它显示java代码,那就没有问题了。 – 18446744073709551615 2013-03-19 08:24:10

0

Java类文件不应该根据自己的意愿重命名。当您这样做时,由于错误,您编辑的类文件将不会再次可用。这是因为类文件的名称对应于您的java类名称。因此,您只需在eclipse中使用.class查看器,即可复制.class文件中显示的java代码。制作另一个.java文件,并使用所需的文件名重命名类名。编译你的.java文件并找到相应的.class。

现在,您已经成功更名.class。

但是,存在缺点。只要确保将变化反映到受影响的其他课程。

0

我会使用像ASM这样的字节码操作库并更改class visitor中的名称。

但是,我不确定是否仍需要更新对其他类型的引用,即使您提供了自己的替代方法 - 是否将合成访问器转换为子类型?

如果目的是日志记录,那么比替换类型更少复杂的方法:用AOP或上述的字节码操作来检测方法。

0

我确实重命名了类文件,但这是一个漫长而无聊的故事。在我的情况下,这是一个Android应用程序,您可能需要将您的类转换为Android应用程序来重复我所做的:)。序列如下:

  1. 反编译APK apktool。你得到子目录yourApkName/smali/packageName /你的类的反编译源。
  2. 将类及其子类复制到一个新文件,例如Stuff.smali成为Xtuff.smali东西$ Useless.smali成为Xtuff $ Useless.smali
  3. 在文本编辑器打开这些新文件,我用的gedit。
  4. 将所有出现的完整课程路径替换为例如Lfoo/bar/baz/qux/Stuff变成Lfoo/bar/baz/qux/Xtuff;最好看到你正在做的每个替换,但最有可能的是你会替换所有的替换(注意:你替换字符串像Lfoo/bar/baz/qux/Stuff $ Data,但不要替换Lfoo/bar/baz之类的字符串/ qux/StuffData)
  5. 用“Xtuff”替换类名“Stuff”的全部(或不全部)出现;在这种情况下,您很可能会替换并非所有的事件。在这一步你需要了解你在做什么。使用apktool重建apk,使用-f标志:apktool b -f AppName AppName.apk
  6. 从该新apk中提取classes.dex(在步骤6获得);我用了午夜指挥官,它显示压缩档案(包括地塞米松和jar)作为目录
  7. 转换DEX到罐子:~/Downloads/dex2jar-0.0.9.13/d2j-jar2dex.sh classes.jar,你得到的类 - dex2jar.jar
  8. 提取新(重命名)类的Eclipse项目( Xtuff.class,Xtuff $无用等),从顶级重命名类(class Stuff extends Xtuff)派生类,编译,你会得到新的Stuff.class。 (如果您现在可以进行调试,则可以开始调试并跳过以下步骤。)
  9. 将classes-dex2jar.jar复制到classes-X.jar,将在第9步获得的类文件(包括嵌套类)添加到classes- X.jar
  10. 转换类,X.jar到classes.dex
  11. 地方这个新classes.dex原来的APK
  12. 签署apk:jarsigner -verbose -keystore ./my.keystore ./AppName.apk mykey
  13. 删除原来的应用程序,安装APK修改。

很明显,一个专用工具会使这个长序列更容易执行。

PS此方法当然不适用于生产代码。

PPS这不是一般情况下的配方:如果你的类包含静态工厂方法,所需的修改变得更加棘手。