Ответ 1
Для Android вы должны изучить dalvik/vm/Native.c, который определяет интерфейс JNI.
Наиболее подходящей функцией является следующая:
bool dvmLoadNativeCode(const char* pathName, Object* classLoader);
Это место, где библиотека dlopen()
-ed. И самая интересная его часть:
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
, ничего действительно захватывающее.
Я считаю, что он должен выглядеть примерно так же для других виртуальных машин - так что просто grep для dlopen()
и dlsym()
- ведь это просто обычная загрузка библиотеки и разрешение символа.
Изменить: Говоря о конкретном файле, который вы упомянули, Android.mk
в том же каталоге компилирует и связывает этот файл с libandroid_servers
разделяемой библиотекой. Grepping around для этого имени библиотеки показывает services/java/com/android/server/SystemServer.java.
Что важно:
public static void main(String[] args) {
// ...
System.loadLibrary("android_servers");
// ...
}
Таким образом, загрузка библиотеки (и, следовательно, вызов JNI_OnLoad()
в onload.cpp
) выполняется в контексте запуска системной службы Android. Если вы хотите узнать больше о том, как/когда загружается системный сервис, я рекомендую эту презентацию.