是否可以注释导出的函数名称?

时间:2017-12-21 20:43:35

标签: java jna

我有以下界面,映射DLL的导出函数:

interface Foo extends Library {
    int ProcessBytes(byte[] bytes, int size);
}

我使用Proguard来混淆我的应用程序。而且,现在我使用-keep配置来维护上面的接口代码。所以,JNA可以找到该函数并调用它。

我也希望对界面进行模糊处理。如果我删除-keep配置,我的界面将如下所示:

interface a extends Library {
    int a(byte[] a, int b);
}

JNA无法处理它,因为导出的函数中不存在a函数。所以,我的问题是:是否可以注释导出的函数名称?像这样:

interface Foo extends Library {  
   @Function("ProcessBytes")
   int anyname(byte[] bytes, int size);
}

喜欢"我不关心你方法的名字,我会打电话给" ProcessBytes"调用方法anyname时的函数。

1 个答案:

答案 0 :(得分:1)

您可以创建自定义注释并使用FunctionMapper来解析函数名称。在使用loadLibrary加载库时,可以将此类传递给JNA。

@Target(value = ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
@interface NativeFunctionName {
    String name() default "";
}

class FunctionNameAnnotationMapper implements FunctionMapper {
    @Override
    public String getFunctionName(NativeLibrary nativeLibrary, Method method) {
        NativeFunctionName annotation = method.getAnnotation(NativeFunctionName.class);
        // just return the function's name if the annotation is not applied
        return annotation == null ? method.getName() : annotation.name();
    }
}

用法如下:

public class Program {
    public static void main(String... args) {
        Map<String, Object> opts = new HashMap<>();
        opts.put(Library.OPTION_FUNCTION_MAPPER, new FunctionNameAnnotationMapper());

        Obfuscated lib = Native.loadLibrary("my-library", Obfuscated.class, opts);
        lib.obfuscated1(0, null);
    }
}

interface Obfuscated extends Library {
    @NativeFunctionName(name = "main")
    public int obfuscated1(int argc, Pointer argv);
}

请注意,JVM需要在运行时访问这些注释值,因此它们将包含在输出中。确保你的混淆器保留这些注释。

如果您已经在使用函数映射器,请考虑创建一个“聚合”函数映射器类,它允许您传递多个映射器。

有关函数映射的更多信息,请访问:http://java-native-access.github.io/jna/4.5.0/javadoc/overview-summary.html#function-mapping