2

我正在调试一个使用预编译 jar 的程序。我想记录对某个类中函数的调用。思路是将原类文件 Xxx.class 重命名为 Xxx0.class 并将原类名定义为:

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

有任何想法吗?

(我确实尝试过反编译器:反编译代码中有奇怪的控制结构,反编译器可能不会为该程序生成正确的代码。)

4

7 回答 7

1

不能只重命名一个类文件,因为不仅是类名在加载时用于计算类文件名,而且类名也存储在类文件中,而且必须匹配请求的课程。

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

于 2013-03-19T07:09:29.780 回答
1

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

  1. 使用 apktool 反编译 apk。你会得到你的子目录yourApkName /smali/ packageName / 那里有你的类的反编译源。
  2. 将类及其子类复制到一个新文件中,例如Stuff.smali变为Xtuff.smali并且Stuff$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”的出现;在这种情况下,您很可能不会替换所有匹配项。在此步骤中,您需要了解自己在做什么。
  6. (保存原始 apk 并)使用 apktool 重建 apk,使用 -f 标志:apktool b -f AppName AppName.apk
  7. 从新的 apk 中提取 classes.dex(在第 6 步获得);我使用了午夜指挥官,它将压缩档案(包括 dex 和 jar)显示为目录
  8. 将 dex 转换为 jar: ~/Downloads/dex2jar-0.0.9.13/d2j-jar2dex.sh classes.jar,得到 classes-dex2jar.jar
  9. 将新的(重命名的)类提取到 Eclipse 项目(Xtuff.class、Xtuff$Useless 等),从顶级重命名的类派生类(class Stuff extends Xtuff),编译,得到新的 Stuff.class。(如果您现在可以调试,则可以开始调试并跳过以下步骤。)
  10. 将classes-dex2jar.jar复制到classes-X.jar,将第9步得到的类文件(包括嵌套类)添加到classes-X.jar
  11. 将 classes-X.jar 转换为 classes.dex
  12. 把这个新的 classes.dex 放到原来的 apk
  13. 签署apk:jarsigner -verbose -keystore ./my.keystore ./AppName.apk mykey
  14. 删除原始应用程序,安装修改后的apk。

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

PS 当然,这种方法不适用于生产代码。

PPS 这不是一个通用案例:如果您的类包含静态工厂方法,则所需的修改变得更加棘手。

于 2013-03-20T05:55:15.660 回答
1

如果要重命名没有源 java 文件的类 ant,请执行以下步骤:

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

这将解决您的问题。
试试这个,如果有任何问题,请告诉我。

注意:如果您遇到 java 反编译器的问题,请尝试使用其他版本的 JD。
请访问这里下载最新的京东

于 2013-03-19T07:21:28.160 回答
0

Java 类文件不应随意重命名。当您这样做时,您编辑的类文件将由于错误而永远无法再次使用。这是因为类文件的名称对应于您的 java 类名称。

有了它,您需要做的就是在 Eclipse 中使用 .class 查看器,复制 .class 文件中显示的 java 代码。制作另一个 .java 文件并用您想要的文件名重命名类名。编译您的.java 文件并找到相应的.class。

现在,您已经成功重命名了 .class。

但是,也有缺点。只需确保将更改反映到其他受影响的类。

于 2013-03-19T07:41:08.193 回答
0

我会使用ASM之类的字节码操作库并更改类访问者中的名称。

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

如果目的是记录日志,则没有比替换类型更复杂的方法:使用AOP或上面的字节码操作来检测方法。

于 2013-03-19T08:45:10.727 回答
0

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

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

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

于 2013-03-19T07:14:29.920 回答
-1

这是面向方面编程的经典任务。例如,请参阅面向方面的 Android 开发 - 工具集成

于 2013-03-20T06:57:27.030 回答