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

Is possible to annotate the exported function name?

我有以下接口,映射一个 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);
}

像"I dont care the name of your method, I'll call the "ProcessBytes”调用方法anyname时的函数。

您可以创建自定义注释并使用 FunctionMapper 来解析函数名称。当使用 loadLibrary.

加载库时,可以将此 class 传递给 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 需要在运行时访问这些注释值,因此它们将包含在输出中。确保您的混淆器保留这些注释。

如果您已经在使用函数映射器,请考虑创建一个 "aggregate" 函数映射器 class,它允许您传递多个映射器。

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