Что делает метод registerNatives ()? - PullRequest
66 голосов
/ 18 июня 2009

В java, что делает закрытый статический метод registerNatives() класса Object?

Ответы [ 2 ]

103 голосов
/ 18 июня 2009

Другие ответы технически правильны, но не очень полезны для тех, кто не имеет опыта JNI. : -)

Обычно для того, чтобы JVM могла найти ваши собственные функции, они должны быть названы определенным образом. например, для java.lang.Object.registerNatives соответствующая функция C называется Java_java_lang_Object_registerNatives. Используя registerNatives (или, точнее, функцию JNI RegisterNatives), вы можете называть свои функции на C как хотите.

Вот соответствующий код C (из OpenJDK 6):

static JNINativeMethod methods[] = {
    {"hashCode",    "()I",                    (void *)&JVM_IHashCode},
    {"wait",        "(J)V",                   (void *)&JVM_MonitorWait},
    {"notify",      "()V",                    (void *)&JVM_MonitorNotify},
    {"notifyAll",   "()V",                    (void *)&JVM_MonitorNotifyAll},
    {"clone",       "()Ljava/lang/Object;",   (void *)&JVM_Clone},
};

JNIEXPORT void JNICALL
Java_java_lang_Object_registerNatives(JNIEnv *env, jclass cls)
{
    (*env)->RegisterNatives(env, cls,
                            methods, sizeof(methods)/sizeof(methods[0]));
}

(Обратите внимание, что Object.getClass отсутствует в списке; он по-прежнему будет вызываться «стандартным» именем Java_java_lang_Object_getClass.) Для перечисленных функций соответствующие функции C перечислены в той таблице, которая удобнее, чем писать кучу функций пересылки.

Регистрация собственных функций также полезна, если вы встраиваете Java в вашу C-программу и хотите ссылаться на функции внутри самого приложения (в отличие от общей библиотеки) или используемые функции не «экспортируются» в противном случае. , поскольку они обычно не могут быть найдены стандартным механизмом поиска метода. Регистрация собственных функций также может быть использована для «повторного связывания» собственного метода с другой функцией C (полезно, например, если ваша программа поддерживает динамическую загрузку и выгрузку модулей).

Я призываю всех прочесть книгу JNI , в которой говорится об этом и многом другом. : -)

8 голосов
/ 07 ноября 2012

Что может слегка запутать, так это то, что код, показанный для java.lang.Object.registerNatives в предыдущем ответе, является просто примером того, как зарегистрировать собственные функции. Это код, который (в реализации OpenJDK) регистрирует собственные функции для класса Object. Чтобы зарегистрировать нативные функции для вашего собственного класса, вы должны вызвать функцию JNI RegisterNatives из нативного кода в вашей собственной библиотеке. Это может звучать немного округло, но есть несколько способов разорвать петлю.

  1. Следуйте примеру этой реализации класса Object:

    а. В вашем Java-классе объявите собственный метод (предпочтительно статический) с именем registerNatives (или любым другим именем. Это не имеет значения).

    б. В своем собственном коде определите функцию с именем Java_<your fully qualified class name>_registerNatives, которая содержит вызов функции JNI RegisterNatives.

    с. Убедитесь, что в вашем коде Java ваш метод Java registerNatives вызывается до любых вызовов других собственных методов.

OR

  1. Использование JNI_OnLoad

    а. В вашей нативной библиотеке определите функцию jint JNI_OnLoad(JavaVM *vm, void *reserved). В теле этой функции вызовите функцию JNI RegisterNatives.

    б. Java VM будет автоматически искать и вызывать JNI_OnLoad, когда ваша нативная библиотека будет загружена System.loadLibrary, которую вы уже должны вызывать, вероятно, в статическом инициализаторе для вашего класса. (Вы получаете требуемый указатель env, вызывая функцию GetEnv в таблице, на которую указывает указатель vm.)

...