Java "implibs" aka 没有实际代码的罐子,只包含带有空主体的方法定义?



Windows有"导入库"的概念,也就是"implibs"——当你想要将你的代码链接到动态库时,你不需要将它链接到。dll本身,而是链接到包含调用。dll的代码的特殊静态库。好吧,这绝对是Windows的特点,但有时,这个想法并没有那么糟糕。

例如,考虑您有一个复杂的系统,由100个动态库组成,每个库平均2MB,然后这个系统有10个版本。因此,要为所有版本的此类系统提供完整支持而发布的SDK只有2GB的库可供链接。如果使用只包含符号和小符号的隐含符号,则会少得多。

implibs的概念可以很容易地应用到普通的unix共享库中——你只需要转储符号,用C语言制作简单的代码,编译,瞧,你可以链接到那个库,而不是原始库。

现在,我想把同样的想法扩展到Java。所以,理想情况下,我会寻找一个工具,将jar,然后重写字节码类在其中删除方法的主体,只留下方法定义与空(尽可能多)的主体。如果这样的工具不存在,我会寻找指向Java字节码转换框架的指针,这将使编写这样的工具变得容易。如果做不到这一点,我至少要寻找一种工具,它可以从jar中转储所有方法签名,以遵循与本机共享库类似的方法(当然,这会更复杂,因为我不能只是向其中添加空Java体,而是需要返回有效类型的值)。

取决于您想要做什么,您可以很容易地破解Krakatau来完成此操作。只需将method.py的第93行更改为设置self.code = None而不是调用self._loadCode()。然后拆卸和重新组装罐子。Krakatau目前不支持jar输出,所以你必须将生成的类压缩回jar中,但这很容易。

这将导致在没有任何Code属性和仅由字节码使用的任何常量池项的情况下重新组装类,但保留了所有其他内容以重新排序。这将留下字段和可选属性之类的东西,但如果您的目标是拥有可以编译的存根类,则可能需要这些东西。

注意,如果编译器试图实际加载要编译的类,这可能不起作用。由于它们缺少Code属性,这些类实际上是无效的(假设它们首先包含任何带字节码的方法),因此JVM将拒绝加载它们。

披露:我是Krakatau的作者。

最新更新