2013-12-21 3 views
2

Я новичок в области JNI, и моя цель - изучить собственные методы java.lang.Thread, такие как registerNatives и start0(), чтобы я понял на уровне ОС, какие операции с ОС происходят, когда Thread is a) Создано b) начатоЧто такое поток JNI для собственных функций класса Thread?

Таким образом, я участвую в различных учебниках для JNI, чтобы понять только основы. Похоже, есть 4 основных этапа: 0) a) написать декларацию собственного метода (-ов) в классе (например, start0() в Thread.java) b) использовать инструмент javah в jdk/bin для создания файла .h c) включить эти сгенерированные файлы .h и другие общие файлы .h в jdk/include в проект c/C++ env d) записать требуемую функцию C++.

Пожалуйста, исправьте меня, если я пропустил шаг.

Вопросы- 1) Когда я применяю шаг b) к стандартному java-файлу, например Thread.java, я не мог найти что-то вроде Thread.h в JDK и его источнике. Какое должно быть точное местоположение того же самого? Я получил ссылку Thread.h в apache harmony http://svn.apache.org/repos/asf/harmony/enhanced/sandbox/bootjvm/bootJVM/jni/src/harmony/generic/0.0/include/java_lang_Thread.h, и это точно тот же файл, который я ожидал увидеть в jdk. 2) Я вижу файл под названием Thread.C в jdk \ src \ share \ native \ java, этот файл содержит файл, который я ожидал в пункте № 1, java_lang_Thread.h. Thread.C файл содержит код

Java_java_lang_Thread_registerNatives(JNIEnv *env, jclass cls) 

{ (* ENV) -> RegisterNatives (окр, ЦБС, методы, ARRAY_LENGTH (методы)); } В идеале я бы ожидал, что этот код будет в Thread.h, почему он существует в Thread.C и каково его значение? 3) Существует файл с именем thread.cpp в OpenJDK \ точка доступа \ SRC \ доля \ ут \ выполнения и содержит все определения методов, в настоящее время, начиная с Thread.h

JNIEXPORT void JNICALL Java_java_lang_Thread_start(JNIEnv *, jobject); 

как мы можем сопоставить его Thread.start, потому что я не мог заметить сопоставление между start0() и start(). 4) Так как я программист на Java и, возможно, трудно понять код C++ в Thread.CPP, может ли кто-нибудь привести меня к ссылке, которая может содержать теорию этих методов, таких как set_stack_base (NULL) и т. Д.?

+0

Здесь есть много вопросов XY. Что вы на самом деле пытаетесь открыть? – EJP

ответ

2

У меня нет ссылки на источник jdk или java threading. Возможно, если бы вы предоставили его, я мог бы решить вашу проблему.

Однако, что я собрал из вашего вопроса: «Как ссылка Thread.h на Thread.cpp?» Если это то, что вы просите, тогда подумайте об этом так:

Thread.h просто содержит кучу объявлений. Аналогично интерфейсу Java. Thread.c содержит реализацию этого интерфейса.

Что касается моего второго предположения относительно того, что вы спрашиваете: «Как Java создает собственный поток?».

Если бы мне пришлось взять огромный догадку на Java создает поток на Windows, я бы сказал, что определение либо написаны с использованием WINAPI (только для Windows) или СТЛ C++ (портативный):

Предположим, у вас есть a java Тип резьбы:

public class Threading { 
    static{ System.LoadLibrary("Threading"); } 

    private Runnable r = null; 
    private native void StartNativeThread(Runnable r); 

    public Threading(Runnable r) { 
     this.r = r; 
    } 

    public void start() { 
     StartNativeThread(this.r); 
    } 
} 

Вышеупомянутый класс передается в свой конструктор.Когда вы вызываете start, он вызывает собственную функцию «StartNativeThread», и эта функция будет принимать runnable в качестве параметра. На стороне C++ он создаст поток, и этот поток вызовет Runnable.run, который он получил со стороны java.

WINAPI-C++:

//object that will hold all thread information. 
struct ThreadParams 
{ 
    JNIEnv* env; 
    jobject runnable; 
}; 

//function that the thread will call. 
DWORD __stdcall RunnableThreadProc(void* ptr) 
{ 
    ThreadParams* p = reinterpret_cast<ThreadParams*>(ptr); //get our thread info from the parameter. 
    JNIEnv* env = p->env; //grab our env. 
    jobject runnable = p->runnable; //grab our runnable object. 
    delete p; //since we allocated on the heap using new, we must delete from the heap. 
    //this is because c++ does not have garbage collection. 

    jclass RunnableInterface = env->GetObjectClass(runnable); //get our java runnable interface instance. 
    jmethodID Run = env->GetMethodID(RunnableInterface, "run","()V"); //get the run method function pointer. 
    env->CallObjectMethod(RunnableInterface, Run); //call RunnableInterface.run(); 
} 

JNIEXPORT void JNICALL Java_JNIExample_StartNativeThread(JNIEnv* env, jobject obj, jobject runnable) 
{ 
    ThreadParams* ptr = new ThreadParams(); //create an object to store our parameters. 
    ptr->env = env; //store the env parameter. 
    ptr->runnable = runnable; //store the runnable object. 

    //create a thread that calls "RunnableThreadProc" and passes it "ptr" as a param. 
    CreateThread(0, 0, RunnableThreadProc, reinterpret_cast<void*>(ptr), 0, 0); 
} 

Теперь выше выглядит довольно сложным, чтобы быть полностью честным, но это то, что WINAPI есть. Это API, написанный для окон на языке C.

Если у вас есть компилятор C++ x11 и вы хотите избежать winapi и использовать STL-C++, это можно сделать в пару строк. Предположим, что у нас есть один и тот же класс Java, как указано выше, то наша функция становится:

JNIEXPORT void JNICALL Java_JNIExample_StartNativeThread(JNIEnv* env, jobject obj, jobject runnable) 
{ 
    std::thread([&]{ 
     jclass RunnableInterface = env->GetObjectClass(runnable); 
     jmethodID Run = env->GetMethodID(RunnableInterface, "run","()V"); 
     env->CallObjectMethod(RunnableInterface, Run); 
    }).detach(); 
} 

Обратите внимание, что [&]{....} является лямбда-функции. Это означает функцию, которая может быть создана внутри другой функции или параметра.

выше также могут быть переведены/эквивалентно:

void ThreadProc(JNIEnv* env, jobject runnable) 
{ 
    jclass RunnableInterface = env->GetObjectClass(runnable); 
    jmethodID Run = env->GetMethodID(RunnableInterface, "run","()V"); 
    env->CallObjectMethod(RunnableInterface, Run); 
} 

JNIEXPORT void JNICALL Java_JNIExample_StartNativeThread(JNIEnv* env, jobject obj, jobject runnable) 
{ 
    std::thread(ThreadProc, env, obj).detach(); 
} 

Теперь реализации других вещей, как стоп и пауза так же легко. Вы просто делаете это на стороне java внутри вашего runnable. ИЛИ вы можете сделать это на стороне C++, используя WINAPI TerminateThread и WaitObject и тому подобное. ИЛИ, если вы решите использовать STL-C++, вы должны использовать std::condition_variable.

Я надеюсь, что это прояснит некоторые вещи. Если у вас есть дополнительные вопросы, вы можете просто оставить комментарий или создать новый поток. Вам решать. В противном случае, если я что-то пропустил или неправильно понял ваш вопрос, пожалуйста, проясните его.


EDIT .. Так что для фактической реализации, мы можем видеть, что Thread.c включает jvm.h. Таким образом, мы должны найти jvm.h и jvm.cpp.

Быстрый поиск придумывает:

Thread.h: http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/00cd9dc3c2b5/src/share/native/java/lang/Thread.c

JVM.h: http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/tip/src/share/vm/prims/jvm.h

JVM.cpp: http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/9b0ca45cd756/src/share/vm/prims/jvm.cpp

Если мы теперь искать какой-либо из функции из thread.c .. В thread.c мы видим, что start0 сопоставляется с JVM_StartThread, а все другие функции потока сопоставляются с JVM_XXXXSomeThreadFunc ...

Теперь мы должны искать эти JVM_-функции в JVM.h и JVM.cpp. Найдя, у вас есть источник того, как все это делается.

+0

@ CantChooseUsernames-Спасибо за ваш ответ Ссылка на Thread.C [ссылка] http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/00cd9dc3c2b5/src/share/native/java/lang /Thread.c Ссылка на Thread.CPP [ссылка] http://cr.openjdk.java.net/~rbackman/7127792.1/src/share/vm/runtime/thread.cpp.cdiff.html Как я сказал Thread.h, я не смог найти местоположение в исходном коде jdk и нуждался бы в помощи. – 100pipers

+0

Я закончил конец своего сообщения, чтобы отразить ссылки на функции потока JVM. – Brandon

Смежные вопросы