我试图弄清楚 JNI_OnLoad 是如何在内部调用的。我最终找到了下面的教程,但它并没有说明哪个代码部分实际将 JNI_OnLoad 调用为内部函数调用。请帮助我找到显式调用 JNI_OnLoad 的链接函数。我观察到 System.loadLibrary 调用再次调用 Classloader 的运行时。但是还是找不到原生链接。
我对 OnLoad.cpp (android/platform_frameworks_base/blob/master/services/jni/onload.cpp) 中的那个特别感兴趣
JNI_OnLoad
jint JNI_OnLoad(JavaVM *vm, void *reserved);
The VM calls JNI_OnLoad when the native library is loaded (for example, through
System.loadLibrary). JNI_OnLoad must return the JNI version needed by the native library.
In order to use any of the new JNI functions, a native library must export a JNI_OnLoad function that returns JNI_VERSION_1_2. If the native library does not export a JNI_OnLoad function, the VM assumes that the library only requires JNI version JNI_VERSION_1_1. If the VM does not recognize the version number returned by JNI_OnLoad, the native library cannot be loaded.
编辑:我的文件跟踪基于@Code Painters 的响应如下:
System.loadLibrary("android_servers");
|
|The call System.loadLibrary(name) is effectively equivalent
| to the call
|
V
Runtime.getRuntime().loadLibrary(name)
|
|public static Runtime getRuntime() {
| return currentRuntime;}
|
| // Here, also,Classloader.loadlibrary is called,
| but this is over-ridden (?)
| by the Native function of Runtime.java below
V
/dalvik/vm/native/java_lang_Runtime.cpp (The jni native
implementation of Runtime.java):
/*
* static String nativeLoad(String filename, ClassLoader loader)
*
* Load the specified full path as a dynamic library filled with
* JNI-compatible methods. Returns null on success, or a failure
* message on failure.
*/
static void Dalvik_java_lang_Runtime_nativeLoad{
//
success = dvmLoadNativeCode(fileName, classLoader, &reason);
}
我现在明白了 Runtime.loadlibrary 是用 Dalvik_java_lang_Runtime_nativeLoad native 函数重载的 并且没有调用 Classloader.loadlibrary。如果我错了,请纠正我。
最佳答案
对于 Android,您应该查看 dalvik/vm/Native.c ,它定义了 JNI 接口(interface)。
最相关的功能是这个:
bool dvmLoadNativeCode(const char* pathName, Object* classLoader);
这是库被 dlopen() 编辑的地方。其中最有趣的部分:
vonLoad = dlsym(handle, "JNI_OnLoad");
if (vonLoad == NULL) {
LOGD("No JNI_OnLoad found in %s %p\n", pathName, classLoader);
} else {
/*
* Call JNI_OnLoad. We have to override the current class
* loader, which will always be "null" since the stuff at the
* top of the stack is around Runtime.loadLibrary(). (See
* the comments in the JNI FindClass function.)
*/
OnLoadFunc func = vonLoad;
Object* prevOverride = self->classLoaderOverride;
self->classLoaderOverride = classLoader;
oldStatus = dvmChangeStatus(self, THREAD_NATIVE);
LOGV("+++ calling JNI_OnLoad(%s)\n", pathName);
version = (*func)(gDvm.vmList, NULL);
dvmChangeStatus(self, oldStatus);
self->classLoaderOverride = prevOverride;
如您所见,JNI_OnLoad 仅使用 dlsym() 解析并使用返回的指针调用。此代码部分的其余部分是检查 JNI_OnLoad 返回的值,没有什么特别令人兴奋的。
我相信它对于其他 VM 应该看起来几乎相同 - 所以只是 grep 用于 dlopen() 和 dlsym() - 毕竟它只是简单的共享库加载和符号解析。
编辑说到您提到的确切文件,同一目录中的Android.mk 将此文件编译并链接到libandroid_servers 共享库.搜索此库名称会显示 services/java/com/android/server/SystemServer.java .
相关内容:
public static void main(String[] args) {
// ...
System.loadLibrary("android_servers");
// ...
}
因此,库的加载(因此调用
的上下文中执行的>onload.cpp 中的 JNI_OnLoad())是在 Android 的系统服务<的上下文中执行的 m=""> 启动。如果您想了解更多有关系统服务加载方式/时间的信息,我推荐this presentation .
关于java - 哪个方法最终调用了 JNI_OnLoad,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13509961/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案
我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby1.9+ 关于ruby-主要:Objectwhenrun
我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)