2010-10-18 15 views
5

अंतर्निहित समस्या की पृष्ठभूमि यहां है, मैं एक परियोजना पर एक समूह के साथ सहयोग कर रहा हूं जो Swt पुस्तकालयों का उपयोग करता है और मैं तैनाती के लिए सॉफ़्टवेयर को पैकेज करने का प्रयास कर रहा हूं। जैसा कि यह पता चला है SWT बहुत मंच/वास्तुकला निर्भर है। मैं एक ही पैकेज में सभी छः jar एस (लिनक्स, मैक, जीत और 32/64-बिट) को पैकेज करने में सक्षम होना चाहता हूं और सिस्टम के आधार पर उचित लाइब्रेरी का उपयोग करना चाहता हूं। मुझे एहसास है कि यह एक कठिन चुनौती है हालांकि, Swing (या कुछ और) पर स्विच करना वास्तव में अभी एक विकल्प नहीं है।निष्पादन के दौरान संसाधन लोड करने में समस्या

मुझे कई प्रासंगिक धागे (@Aaron Digulla's thread और @mchr's thread) मिले हैं जो मुझे समस्या के बारे में मूल्यवान अंतर्दृष्टि प्रदान करते हैं। मैंने @Alexey Romanov here द्वारा प्रस्तावित समाधान को लागू करने का प्रयास किया है। एक अंतर के साथ, loadSwtJar() विधि के रूप में वह प्रस्ताव स्थिर नहीं है, मैं ऑब्जेक्ट को तुरंत चालू करता हूं, और उसके तुरंत बाद, ऑब्जेक्ट पर कुछ भी करने से पहले विधि को चलाता हूं।

ऐसा प्रतीत होता है क्योंकि लोडिंग प्रक्रिया ठीक से काम नहीं करती है। इस बयान के लिए मेरे तर्क इस प्रकार है:

  • सभी Swt जार निष्पादन योग्य जार फ़ाइल के classpath से हटा रहे हैं, तो Exception in thread "main" java.lang.NoClassDefFoundError: org/eclipse/swt/events/MouseListener फेंक दिया जाता है जो के कारण होता है: java.lang.ClassNotFoundException: org.eclipse.swt.events.MouseListener
मेरे लिए

इस साधन कि पुस्तकालयों को कक्षा में नहीं मिला है, क्या मुझे गलती है?

  • यदि swt कक्षाओं को कक्षाओं पर छोड़ दिया गया है तो पहली जार फ़ाइल को निष्पादन के दौरान सिस्टम द्वारा उपयोग किया जाता है। इसका अर्थ यह है कि यदि gtk-linux-x86_64 जार की सूची पर पहला स्विट जार होता है तो सिस्टम उस का उपयोग करने का प्रयास करता है, भले ही सिस्टम Win32 या Mac OSX है।

मैं कुछ उत्पादन को जोड़ने के लिए है, तो loadSwtJar() विधि सही जार चुनने है यह देखने की कोशिश की है, और उत्पादन, सही सभी प्लेटफार्मों मैं कोशिश की है पर लगता है सही पैकेज में के रूप में चयन किया गया है (और फ़ाइलों मौजूद है चलने योग्य जार में)। लेकिन फिर भी सही लाइब्रेरी लोड नहीं की गई है इसलिए निष्पादन त्रुटियां होती हैं: Exception in thread "main" java.lang.reflect.InvocationTargetException पूर्व के कारण: Caused by: java.lang.UnsatisfiedLinkError: Cannot load 32-bit SWT libraries on 64-bit JVM (ध्यान दें कि यह मेरी लिनक्स मशीन पर त्रुटि है यदि मैं 64-बिट और 32 बिट स्विट की उपस्थिति का क्रम बदलता हूं build.xml फ़ाइल पर पुस्तकालय)

तो, यहां समस्या क्या प्रतीत होती है? क्या मैं कुछ विस्तार से चूक रहा हूं, या क्या सिस्टम गुणों की जांच करना और उचित अनुसार लाइब्रेरी लोड करना संभव नहीं है?

अंत में नीचे मेरी बिल्ड फ़ाइल का एक अंश है, यह अनुमान लगाया गया है कि यह समस्या के स्रोत को खोजने में मदद कर सकता है।

अग्रिम धन्यवाद,


संपादित करें: एक सहयोगी के साथ एक लंबी डिबग सत्र के बाद, समस्या (MacOS पर धागा प्रबंधन मैं here उल्लेख किया के बारे में एक कष्टप्रद बग को छोड़कर) हल हो गई है। इसमें एएनटी बिल्ड के साथ-साथ मुख्य वर्ग के तरीके के साथ tweaking शामिल थे।(मुख्य वर्ग, जैसा कि यह निकला, & एसडब्ल्यूटी लाइब्रेरी से संदर्भों को लागू करने का विस्तार कर रहा था जिसका मतलब था कि कोड बिल्कुल संकलित नहीं होगा, मुख्य वर्ग को किसी अन्य वर्ग के साथ लपेटा जाएगा और वहां से एसडब्ल्यूटी जार लोड किया जाएगा जो पर्याप्त प्रतीत होता है समस्या से निपटने के लिए)

धन्यवाद और योगदान देने वाले हर किसी के लिए विशेष रूप से @Aaron। काबिल ए तारीफ़!

उत्तर

5

यहां मेरी मुख्य कक्षा के नवीनतम संस्करण की एक प्रति है। मुझे बताना अगर ये आप के लिए काम करता है। मैंने इसे लिनक्स (32/64 बिट) और विंडोज (32 बिट) पर परीक्षण किया।

package de.pdark.epen.editor; 

import java.io.File; 
import java.lang.reflect.Constructor; 
import java.lang.reflect.Method; 
import java.net.URL; 
import java.net.URLClassLoader; 

import org.apache.commons.lang.SystemUtils; 
import org.apache.commons.lang.exception.ExceptionUtils; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

import ch.qos.logback.classic.LoggerContext; 
import ch.qos.logback.core.util.StatusPrinter; 
import de.pdark.epen.exceptions.WikiException; 

public class Main 
{ 
    public final static String VERSION = "V0.9 (13.05.2010)"; //$NON-NLS-1$ 
    private final static Logger log = LoggerFactory.getLogger (Main.class); 

    private static final String ORG_ECLIPSE_SWT_WIDGETS_SHELL = "org.eclipse.swt.widgets.Shell"; //$NON-NLS-1$ 

    /** 
    * @param args 
    */ 
    @SuppressWarnings({"nls", "PMD.SystemPrintln"}) 
    public static void main (String[] args) 
    { 
     String msg = "Starting ePen "+VERSION; 
     System.out.println (msg); 
     log.info (msg); 

     LoggerContext lc = (LoggerContext)LoggerFactory.getILoggerFactory(); 
     StatusPrinter.print (lc); 

     int rc = 1; 
     try 
     { 
      Main main = new Main(); 
      main.run (args); 
      rc = 0; 
     } 
     catch (Throwable t) //NOPMD 
     { 
      ExceptionUtils.printRootCauseStackTrace (t); 
     } 
     finally 
     { 
      System.out.println ("Done."); 
      log.info ("Exit {}", rc); 
      System.exit (rc); //NOPMD 
     } 
    } 

    @SuppressWarnings({"nls", "PMD.SystemPrintln", "PMD.SignatureDeclareThrowsException"}) 
    private void run (String[] args) throws Exception 
    { 
     if (!SystemUtils.isJavaVersionAtLeast (150)) 
     { 
      System.out.println ("Version="+SystemUtils.JAVA_VERSION_INT); 
      throw new WikiException ("Need at least Java 5 but this Java is only "+SystemUtils.JAVA_VERSION); 
     } 

     loadSwtJar(); 

     URLClassLoader cl = (URLClassLoader) getClass().getClassLoader(); //NOPMD 
     Class<?> c = cl.loadClass ("de.pdark.epen.editor.EPenEditor"); 
     Class<?> shellClass = cl.loadClass (ORG_ECLIPSE_SWT_WIDGETS_SHELL); 

     Constructor<?> ctor = c.getConstructor (shellClass); 
     Object obj = ctor.newInstance (new Object[] { null }); 
     Method run = c.getMethod ("run", args.getClass()); //$NON-NLS-1$ 
     run.invoke (obj, new Object[] { args }); 
    } 

    @SuppressWarnings({"nls", "PMD"}) 
    private void loadSwtJar() 
    { 
     try { 
      Class.forName (ORG_ECLIPSE_SWT_WIDGETS_SHELL); 
      // Already on classpath 
      return; 
     } catch (ClassNotFoundException e) { 
      // Add the JAR 
     } 

     String osName = SystemUtils.OS_NAME.toLowerCase(); 
     String osArch = SystemUtils.OS_ARCH.toLowerCase(); 

     String swtFileNameOsPart = 
      osName.contains("win") ? "win32" : 
      osName.contains("mac") ? "macosx" : 
      osName.contains("linux") || osName.contains("nix") ? "linux" : 
      null; 
     String swtFileNameUiPart = 
      osName.contains("win") ? "win32" : 
      osName.contains("mac") ? "cocoa" : 
      osName.contains("linux") || osName.contains("nix") ? "gtk" : 
      null; 

     if (null == swtFileNameOsPart) 
     { 
      throw new RuntimeException ("Can't determine name of SWT Jar from os.name=[" + osName + "] and os.arch=[" 
        + osArch + "]"); 
     } 

     String swtFileNameArchPart = osArch.contains ("64") ? ".x86_64" : ".x86"; 
     if(".x86".equals(swtFileNameArchPart) && "macosx".equals(swtFileNameOsPart)) { 
      swtFileNameArchPart = ""; 
     } 

     String swtFileName = "org.eclipse.swt." + swtFileNameUiPart + "." + swtFileNameOsPart + swtFileNameArchPart + "-3.6.0.jar"; 
     File file = new File ("swt", swtFileName); 
     if (!file.exists()) 
     { 
      throw new RuntimeException ("Can't locate SWT Jar " + file.getAbsolutePath()); 
     } 
     try 
     { 
      URLClassLoader classLoader = (URLClassLoader) getClass().getClassLoader(); 
      Method addUrlMethod = URLClassLoader.class.getDeclaredMethod ("addURL", URL.class); 
      addUrlMethod.setAccessible (true); 

      URL swtFileUrl = file.toURI().toURL(); 
      log.info ("Adding {} to the classpath", swtFileUrl); 
      addUrlMethod.invoke (classLoader, swtFileUrl); 
     } 
     catch (Exception e) 
     { 
      throw new RuntimeException ("Unable to add the swt jar to the class path: " + file.getAbsoluteFile(), e); 
     } 
    } 
} 
+0

धन्यवाद हारून पर एक महान संदर्भ (http://mindprod.com/jgloss/properties.html#OSNAME) मिला है। मुझे यह कहना है कि मुझे यकीन नहीं है कि आप swtFiles को खोजने के लिए कैसे खोदते हैं, क्या आपके पास अन्य सभी निर्भरताओं या किसी अन्य तरीके से एक बड़ी जार के अंदर आपकी swt फ़ाइलें हैं? – posdef

+0

@Aaron: एक और सवाल, क्या आपने एसडब्ल्यूटी पैकेजों को बिना हस्ताक्षर किए किसी भी समस्या का अनुभव किया है? या यह सिर्फ मुझे है ... – posdef

+0

@posdef: मैंने सभी सामान्य जेएआर को 'lib/'और छह SWT JARs नामक निर्देशिका में' swt /' में डाल दिया है। यदि आप उन्हें सभी को एक निर्देशिका में डालते हैं, तो संभावना है कि मुख्य जेएआर के मेनिफेस्ट से क्लासपाथ गलत लोड करने का प्रयास करेगा। –

0

आप अपने वेब प्लेटफ़ॉर्म एसडब्ल्यूटी एप्लिकेशन के लिए बूटस्ट्रैप तंत्र के रूप में जावा वेब स्टार्ट का उपयोग कर सकते हैं। एसडब्ल्यूटी एफएक्यू में corresponding entry देखें।

वैकल्पिक रूप से, आप प्रत्येक प्लेटफ़ॉर्म के लिए अलग-अलग फ़ोल्डर्स में एसडब्ल्यूटी मूल पुस्तकालय डाल सकते हैं और उन्हें अपने प्लेटफ़ॉर्म-विशिष्ट स्टार्टअप स्क्रिप्ट में -Djava.library.path निर्दिष्ट कर सकते हैं।

+0

मैंने एसडब्ल्यूटी एफएक्यू एंट्री को देखा है, और इससे बचने की उम्मीद थी कि दूसरे शब्दों में प्रबंधन के लिए 6 अलग-अलग फाइलें होंगी। लेकिन मुझे लगता है कि यह बी-प्लान होना होगा यदि यह अंत में काम नहीं करता है। वैसे; सिर्फ स्पष्टीकरण के लिए, एफएक्यू एसडब्ल्यूटी-पुस्तकालयों को शेष निर्भरताओं से अलग करने का सुझाव देता है और जेएनएलपी फ़ाइल द्वारा निष्पादन के समय उन्हें शामिल करता है, क्या यह सही है? – posdef

+0

सही, जेएनएलपी लोडर आपके लिए मंच-विशिष्ट libs और जार लोड करने का ख्याल रखेगा। –

+0

मैं बैकअप योजना के रूप में इस उदाहरण में और अधिक देख रहा हूं, और मुझे यह कहना है कि यह संदिग्ध है कि उन्होंने उदाहरण में शामिल नहीं किया है (यहां तक ​​कि सनोस भी शामिल है)। इसके अलावा, '<संसाधन os = ... arch = ...>' कॉल के लिए संभावित वापसी मूल्यों की पूरी सूची है? – posdef

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