我刚刚将我的j2objc工具从1.0.2更新到2.8。据我所知,从1.1版本开始,反射发生了一些变化。现在代码不再起作用了。
我们有IApplicationSupport.java接口。如下所示:
public interface IApplicationSupport
{
void openSupport();
}使用j2objc成功地将此代码转换为Objective-С
然后我们有与平台相关的类AndroidApplicationSupport和IosApplicationSupport,它们不会被翻译。Android部分没问题,但iOS有一些问题。
稍后在代码中的某个地方,我需要调用[IOSClass classForIosName:@"IosApplicationSupport"]。这就是问题所在。每次com.google.j2objc.ReflectionStrippedError: IosApplicationSupport: Reflection is unavailable. Fix this by avoiding reflection or building without --strip-reflection.时我都会得到下一个异常,当然我在翻译过程中没有使用--strip-reflection标志(但我相信问题不在这里)。在我的例子中,避免反射似乎非常困难,因为使用了太多带有反射的类。
据我所知,翻译后的类有相当大的__metadata方法。有没有办法模拟本地类的元数据来启用反射支持?如果我必须添加元数据,是否有关于如何生成元数据的规则?我们的项目是沉重的依赖于它。
谢谢你的帮助!
发布于 2021-10-20 15:40:22
当然,可以很容易地添加__metadata method。最简单的方法是创建一个简单的存根文件,它定义了包、类和方法,然后转换它一次,并将生成的方法复制到您的本机类中。下面是IosApplicationSupport.java的一个示例存根(我不得不猜测IApplicationSupport在哪个包中):
import foo.bar.IApplicationSupport;
public class IosApplicationSupport implements IApplicationSupport {
public void openSupport() {
}
}在这个类上运行j2objc之后,它的元数据是:
+ (const J2ObjcClassInfo *)__metadata {
static J2ObjcMethodInfo methods[] = {
{ NULL, NULL, 0x1, -1, -1, -1, -1, -1, -1 },
{ NULL, "V", 0x1, -1, -1, -1, -1, -1, -1 },
};
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-multiple-method-names"
#pragma clang diagnostic ignored "-Wundeclared-selector"
methods[0].selector = @selector(init);
methods[1].selector = @selector(openSupport);
#pragma clang diagnostic pop
static const J2ObjcClassInfo _IosApplicationSupport = { "IosApplicationSupport", NULL, NULL, methods, NULL, 7, 0x1, 2, 0, -1, -1, -1, -1, -1 };
return &_IosApplicationSupport;
}(这看起来很大,但在64位处理器(NSLog(@"sizeof metadata: %ld", sizeof(_IosApplicationSupport) + sizeof(methods));)上只有128字节。)
但是,如果您只是加载一个类并创建它的一个默认实例,那么元数据就不是必需的,因为Objective-C运行时直接支持它。由于您没有说明IApplicationSupport在哪个包中,因此使用foo.bar包可以在没有元数据的情况下成功执行此代码:
IOSClass *appSupportClass = [IOSClass classForIosName:@"IosApplicationSupport"];
id<FooBarIApplicationSupport> appSupport = [appSupportClass newInstance];
[appSupport openSupport];由于类加载和实例创建工作正常,所以听起来像是IosApplicationSupport使用了需要元数据的java.lang.reflect应用程序接口。然而,从1.0.2开始,有一种比手工编写IosApplicationSupport更简单的方法:使用OCNI。OCNI允许您将Objective-C直接嵌入到Java本地方法中。我们在JRE模拟库中经常使用它,比如here, where native iOS MD5 signing is done in a Java class。这避免了定义和维护元数据结构,只需用Java编写代码并在必要的地方插入Objective-C即可。
因此,我的建议是用Java语言重写IosApplicationSupport,并在需要本机代码的地方用OCNI定义本机Java方法。
https://stackoverflow.com/questions/69642359
复制相似问题