2013-02-02 15 views
10

से जेएनआई का उपयोग करके एक स्विंग विंडो बनाना मैं एक स्थिर जावा विधि का आह्वान करने के लिए जेएनआई का उपयोग कर रहा हूं जो बदले में स्विंग जेएफआरएएम बनाता है और इसे प्रदर्शित करता है। कोड काफी सरल है, और जावा-कोड स्टैंडअलोन काम कर रहा है (यानी java StartAWT जो करता है वह करता है) जबकि जब जेएनआई का उपयोग कर सी से कहा जाता है तो प्रक्रिया लटकती है।जावा जेएनआई: सी

मै मैक ओएस एक्स 10.8 माउंटेन शेर पर जेडीके 1.7.0_09 का उपयोग कर रहा हूं।

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 नहीं।

मेरा मानना ​​है कि मेरी सी प्रक्रिया के अंदर वर्चुअल मशीन में एडब्ल्यूटी इवेंट कतार नहीं है लेकिन मुझे नहीं पता कि इसे एक या तो रखने के लिए इसे कैसे सेट अप किया जाए (न ही मुझे यकीन है कि यह कारण है)।

जेएनआई का उपयोग कर एडब्ल्यूटी आधारित जीयूआई दिखाने के लिए क्या किया जाना है?

-

संपादित करें: मैं डाला है जो धागे जीवित हैं और नहीं (this gist में देखा जा सकता) कर रहे हैं जो देखने के लिए लूप। इस संस्करण में मैं SwingUtilities.invokeAndWait का अन्य थ्रेड में आमंत्रण करता हूं। नतीजा: मुख्य धागा जीवित है (सी)। जावा (मुख्य धागा नहीं) द्वारा प्रेषित पहला धागा जीवित है; कॉल invokeAndWait कॉल करने वाला धागा अवरुद्ध है (मुझे नहीं लगता कि invokeAndWait भी वापस आ गया है), इवेंटक्यूयू पर चलने वाला फ़ंक्शन भी दर्ज नहीं किया गया है।

मैं भी सीधे SwingUtilities.invokeAndWait लागू है, जो निम्न संदेश दे देंगे की कोशिश की है:

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 
) 

यह भी है कि मैं क्या अन्य प्रश्न में StackOverflow पर यहाँ पढ़ा है, जैसे एक टिप्पणी में सुझाव दिया है नीचे। हालांकि, मुझे मूल समस्या का हल नहीं मिला। हो सकता है कि यह ध्यान देने योग्य है कि उपर्युक्त संदेश आने के बाद मुख्य धागा अभी भी जिंदा है, यानी न तो प्रक्रिया डेडलॉक और न ही क्रैश।

-

संपादित करें: मैं अपेक्षा के अनुरूप है, जहां यह काम कर रहा है लिनक्स पर कोड का परीक्षण किया। तो मेरा मानना ​​है कि यह कोको एडब्ल्यूटी के साथ एक मैक ओएस एक्स मुद्दा है, लेकिन मुझे नहीं पता कि इसे कैसे रोकें।

-

संपादित करें: मैं भी एक नया देशी धागा पर JVM के पूरे मंगलाचरण चलती की कोशिश की। यह एप्पल जावा 32-बिट (1.6.0_37) के साथ मैक ओएस एक्स 10.6 पर काम करता है, लेकिन ऊपर वर्णित अनुसार उसी डेडलॉक में परिणाम मिलता है। मैक ओएस एक्स 10.8 पर यह बदतर है, एप्लिकेशन एकमात्र संदेश "ट्रेस/बीपीटी जाल: 5" (जो seems to be related to loading dynamic libraries) से मेल खाता है।

मैं भी वर्णित in this Q&A के रूप में द्विआधारी bundling कोशिश की, लेकिन प्रक्षेपण के संदेश lsopenurlswithrole() failed with the message -10810 है, जो एक अज्ञात त्रुटि है, सेब Launch Services Reference के अनुसार के साथ विफल रहता है। उत्तरार्द्ध एडब्ल्यूटी का उपयोग किए बिना भी होता है (केवल जेवीएम आमंत्रण विफल रहता है)।

+0

भी देखें इस [क्यू एंड ए] (http://stackoverflow.com/q/8750690/230513)। – trashgod

+0

धन्यवाद, मैंने उस प्रश्नोत्तर की जांच की है और मेरे आवेदन के साथ खेला है; लेकिन यह सब के बाद काम नहीं करता है (जैसा कि दूसरे प्रश्न में, वहां कोई समाधान भी नहीं दिया गया है)। – scravy

+0

मुझे एक समान परिणाम मिला; मैं बस 'JavaAplicationStub' का उपयोग करता हूं, लेकिन मुझे नहीं पता कि यह कैसे काम करता है। मुझे आश्चर्य है अगर 'JVM TI', उद्धृत [यहां] (http://stackoverflow.com/a/14492574/230513), प्रासंगिक कुछ भी नहीं है। – trashgod

उत्तर

7

अंत में मैं एक समाधान मिल गया।

समस्या यह नहीं है कि वर्चुअल मशीन किस धागे को बनाया जा रहा है, समस्या यह है कि एडब्ल्यूटी इवेंट कतार प्रारंभ किया जा रहा है। दूसरे शब्दों में: पहली बार जब एक एडब्ल्यूटी वर्ग लोड होता है, तो इसे मुख्य धागे पर लोड नहीं किया जा सकता है। इस प्रकार चरण 1: लोड (उदाहरण के लिए) java.awt.Component किसी अन्य धागे पर।

लेकिन अब इवेंटक्यूयू ब्लॉक करेगा, क्योंकि यह कोको मुख्य इवेंट कतार में काम करता है जो कि नहीं चल रहा है - निश्चित रूप से पर्याप्त है, क्योंकि यह केवल मुख्य धागे पर ही चलाएगा और मुख्य धागा मेरा आवेदन है। इस प्रकार मुख्य रन पाश मुख्य थ्रेड पर शुरू कर दिया जाना चाहिए:

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

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

मैं कोको ढांचे के साथ अपने आवेदन लिंक और <objc/objc-runtime.h> शामिल करने के लिए किया था। मुख्य थ्रेड runCocoaMain करने के लिए कॉल (के बाद से घटना पाश वहाँ चल रहा है), इसलिए एक आवेदन के लिए ही एक और धागा का सहारा की जरूरत है के बाद अवरुद्ध है।

उपरोक्त स्निपेट का उपयोग करके EventQueue चलाने के बाद अन्य थ्रेड पर एडब्ल्यूटी कक्षा की लोडिंग सफल हो जाएगी और आप वहां आगे बढ़ सकते हैं।

+0

दृढ़ता के लिए +1 देख। – trashgod

+0

धन्यवाद! यह आकर्षण की तरह काम करता है। :) –

+0

पूरी तरह से समझ में नहीं आता है। क्या आप कृपया मुझे बता सकते हैं कि "अन्य धागे पर एडब्ल्यूटी वर्ग की लोडिंग" कैसे? –

1

मैं OSX: JavaVM, AWT/Swing and possibly a deadlock के निर्देश से समान समस्या हल हो गई, कि एक और धागा में शुरू JVM के बाद CFRunLoopRun() शुरू करने के लिए है।

संबंधित मुद्दे