2013-02-02 4 views
10

JNIを使​​用して静的なJavaメソッドを呼び出すと、スイングJFrameが作成され、表示されます。コードはかなりシンプルで、JavaコードはJNIを使​​用してCから呼び出されたときにスタンドアロンで動作します(つまり、java StartAWTが必要です)。プロセスがハングします。Java JNI:CからのJNIを使​​用したスイングウィンドウの作成

私はMac OS X 10.8 Mountain LionでJDK 1.7.0_09を使用しています。

これは、私は、静的メソッドを呼び出すために使用しているCコードです:

JavaVM* jvm; 
JNIEnv* env = create_vm(&jvm); 

jclass class = (*env)->FindClass(env, "StartAWT"); 
jmethodID method = (*env)->GetStaticMethodID(env, class, "run", "()V"); 

(*env)->CallStaticVoidMethod(env, class, method); 

(*jvm)->DestroyJavaVM(jvm); 

StartAWTクラスは次のようになります。私は、アプリケーションを起動すると

public class StartAWT { 

    public static class Starter implements Runnable { 
     public void run() { 
      System.out.println("Runnning on AWT Queue."); 

      JFrame.setDefaultLookAndFeelDecorated(true); 
      JFrame frame = new JFrame("That's a frame!"); 
      JLabel label = new JLabel("A Label"); 
      frame.getContentPane().add(label); 

      frame.pack(); 
      frame.setVisible(true); 
     } 
    } 

    public static class GUI implements Runnable { 
     public void run() { 
      try { 
       System.out.println("Going to put something on the AWT queue."); 
       SwingUtilities.invokeAndWait(new Starter()); 
      } catch (Exception exc) { 
       throw new RuntimeException(exc); 
      } 
     } 
    } 

    public static void run() { 
     Thread gui = new Thread(new GUI()); 
     gui.start(); 
    } 
} 

、私はGoing to put something on the AWT queueを見ていますしかしRunning on AWT Queueではありません。

私のCプロセス内の仮想マシンはAWTイベントキューを持っていないと思いますが、それを設定する方法もわかりません(これは理由もありません)。

JNIを使​​用してAWTベースのGUIを表示するにはどうすればよいですか?

-

編集:私は、スレッドが生きているとどのは(this gistで見ることができる)されていないかを確認するためにループを挿入した。このバージョンでは、別のスレッドでSwingUtilities.invokeAndWaitの呼び出しを行います。結果:メインスレッドは生きています(C)。 Java(メインスレッドではない)によってディスパッチされた最初のスレッドは生きています。呼び出しinvokeAndWaitを実行しているスレッドはブロックされています(私はinvokeAndWaitが返されたとは思わない)、EventQueueで実行される関数は入力されていません。

私も次のようなメッセージを与えるであろう、直接SwingUtilities.invokeAndWaitを起動しようとしました:これは私は1つのコメントで示唆したような、ここでStackOverflowの上の他の質問には何を読んでもある

2013-02-02 13:50:23.629 swing[1883:707] Cocoa AWT: Apple AWT Java VM was loaded on first thread -- can't start AWT. (
    0 liblwawt.dylib      0x0000000117e87ad0 JNI_OnLoad + 468 
    1 libjava.dylib      0x00000001026076f1  Java_java_lang_ClassLoader_00024NativeLibrary_load + 207 
    2 ???         0x000000010265af90 0x0 + 4335185808 
) 

を以下。しかし、私は元の問題の解決策を見つけることができませんでした。おそらく、上記のメッセージが現れた後、メインスレッドがまだ生きている、つまりプロセスデッドロックもクラッシュも起こっていないことに気付くかもしれません。

-

EDIT:予想通り、私はそれが動作しているLinux上でコードをテストしました。だから私はこれがCocoa AWTのMac OS Xの問題だと思っていますが、それを回避する方法はわかりません。

-

EDIT:私はまた、新しいネイティブスレッドにJVMの全体の呼び出しを動かしてみました。これはMac OS X 10.6でApples Java 32ビット(1.6.0_37)で動作しますが、上記と同じデッドロックが発生します。 Mac OS X 10.8では、アプリケーションが「Trace/BPT trap:5」(seems to be related to loading dynamic libraries)という唯一のメッセージで壊れてしまいます。

Iはまた、in this Q&Aを説明するが、起動が不明のエラーでメッセージlsopenurlswithrole() failed with the message -10810、で失敗し、りんごLaunch Services Referenceに従ってとしてバイナリを束ねてみました。後者はAWTを使用しようとせずにも発生します(単なるJVM呼び出しは失敗します)。

+0

この[Q&A](http://stackoverflow.com/q/8750690/230513)も参照してください。 – trashgod

+0

ありがとう、私はそのQ&Aをチェックし、私のアプリケーションで遊んだ。しかし、それはすべての後に動作しません(他の質問のように、そこに解決策も与えられていません)。 – scravy

+0

私は同様の結果を得ました。私は 'JavaApplicationStub'を使うだけですが、どのように動作するのか分かりません。私は 'JVM TI'(ここではhttp://stackoverflow.com/a/14492574/230513)に関連する何かがあるかどうか疑問に思います。 – trashgod

答えて

7

最後に解決策が見つかりました。

問題は仮想マシンが作成されているスレッドではなく、AWTイベントキューが初期化されているスレッドに問題があります。言い換えると、AWTクラスが初めてロードされたときに、メインスレッドにロードされないことがあります。したがって、手順1:別のスレッドでjava.awt.Componentをロードします(たとえば)。

しかし、EventQueueは実行されていないCocoa Main Event Queueに作業を委任するのでブロックされます。これは、メインスレッドでのみ実行され、メインスレッドは自分のアプリケーションであるためです。このように、メイン実行ループは、メインスレッド上で開始する必要があります

void 
runCocoaMain() 
{ 
    void* clazz = objc_getClass("NSApplication"); 
    void* app = objc_msgSend(clazz, sel_registerName("sharedApplication")); 

    objc_msgSend(app, sel_registerName("run")); 
} 

私はCocoaフレームワークで自分のアプリケーションをリンクして<objc/objc-runtime.h>を含める必要がありました。メインスレッドは、runCocoaMainの呼び出し後に(イベントループがそこで実行されているので)ブロックされるため、アプリケーション自体の別のスレッドを使用する必要があります。

上記のスニペットを使用してEventQueueを実行した後、他のスレッドでのAWTクラスのロードは成功し、そこで進むことができます。

+0

+1忍耐力。 – trashgod

+0

ありがとうございます!それは魅力のように働く。 :) –

+0

完全に理解できません。 AWTクラスを他のスレッドにロードする方法を教えてください。 –

関連する問題