2010-06-08 10 views
5

का उपयोग कर कक्षा का उदाहरण बनाते समय, यह जावा 1.4 (प्रोजेक्ट प्रतिबंध) है। मैं एक एप्लिकेशन मैनेजर बनाने की कोशिश कर रहा हूं। यह कस्टम क्लासलोडर के अपने उदाहरण का उपयोग करके प्रत्येक एप्लिकेशन की मुख्य कक्षा को लोड करता है। उसके बाद, यह प्रतिबिंब का उपयोग करके मुख्य वर्ग का एक उदाहरण बनाता है। प्रत्येक एप्लिकेशन एक सामान्य इंटरफ़ेस लागू करता है ताकि इंस्टेंस बनने के बाद, यह एप्लिकेशन की पूर्वनिर्धारित विधि चलाता है।क्लासकास्ट अपवाद जब प्रतिबिंब और क्लासलोडर

हालांकि, मुझे CRASH POINT 1 (कोड देखें) में कुछ परेशानी हो रही है। कक्षा को इसके इंटरफ़ेस के कार्यान्वयन के रूप में पहचाना नहीं गया है। यदि मैं इस कोड खंड को संगत करता हूं, तो मुझे CRASH POINT 2 पर क्लासकास्ट एक्सेप्शन मिलता है।

मुझे लगता है कि दोनों त्रुटियां एक ही समस्या से संबंधित हैं (बेशक)।

क्या कोई मेरी मदद कर सकता है? कोड का प्रासंगिक भाग निम्नानुसार है (आयात हटा दिए जाते हैं) ...

बहुत बहुत धन्यवाद।

मार्कस

// AppManager.java

public class AppManager { 
    public ThreadGroup threadGroup; 
    private Class appClass; 
    private AppInstance appInst; 
    public AppContextImpl context; 

    private AppManager(CustomClassLoader cl, String mainClass) throws ClassNotFoundException { 
     final String className = mainClass; 
     final CustomClassLoader finalLoader = cl; 

     appClass = cl.loadClass(mainClass); 

     // DEBUG CODE: 
     Class[] k1 = AppInstance.class.getInterfaces(); 
     System.out.println(k1.length + " interfaces for AppInstance.class:"); 
     for (int ii = 0; ii < k1.length; ii++) { 
      System.out.println(" " + ii + " - " + k1[ii].getName() + " (" + k1[ii].getClassLoader() + ")"); 
     } 

     Class[] k2 = appClass.getInterfaces(); 
     System.out.println(k2.length + " interfaces for appClass instance:"); 
     for (int ii = 0; ii < k2.length; ii++) { 
      System.out.println(" " + ii + " - " + k2[ii].getName() + " (" + k2[ii].getClassLoader() + ")"); 
     } 

     // CRASH POINT 1 
     if (!(AppInstance.class.isAssignableFrom(appClass))) { 
      throw new IllegalArgumentException("Attempt to run a non-AppInstance class: " + appClass); 
     } 

     context = new AppContextImpl(mainClass, this); 
     cl.setAppManager(this); 
     Constructor m; 
     try { 
      m = appClass.getConstructor(new Class[0]); 
      // CRASH POINT 2 
      appInst = (AppInstance) m.newInstance(new Object[0]); 
      appInst.init(context); 
     } catch (Exception e) { 
      System.out.println("Got ClassCastException here!\n"); 
      e.printStackTrace(); 
     } 
    } 

    public static void main(String[] args) { 
     App app1; 

     String path1 = "/home/user/workspace/MultiTaskTest/bin/"; 
     String app1Name = "App1"; 

     Vector v1 = new Vector(); 
     try { 
      v1.add(new URL(path1)); 
     } catch (MalformedURLException e1) { 
      final File file1 = new File(path1); 
      try { 
       URL path1aux = (URL) AccessController.doPrivileged(
        new PrivilegedExceptionAction() { 
         public Object run() throws IOException { 
          if (!file1.exists()) { 
           System.out.println("Warning: \"" + file1.getPath() + "\" not found"); 
           return null; 
          } 
         return file1.toURI().toURL(); 
         } 
        }); 

       if (path1aux != null) { 
        v1.add(path1aux); 
       } 
      } catch (PrivilegedActionException e) { 
       e.getException().printStackTrace(); 
      } 
    } 

     final URL[] array1 = (URL[]) v1.toArray(new URL[v1.size()]); 
     CustomClassLoader cl1 = (CustomClassLoader) AccessController.doPrivileged(
      new PrivilegedAction() { public Object run() { 
       return new CustomClassLoader(array1); 
      }}); 
     System.out.println("ClassLoader 1 created: " + cl1); 
     try { 
      app1 = new App(cl1, app1Name); 
     } catch (ClassNotFoundException e) { 
      e.printStackTrace(); 
      System.out.println("Cannot find class App1."); 
     } 
    } 
} 

// AppInstance.java

public interface AppInstance { 
    public void init(ContextImpl context); 
} 

// App1.java

public class App1 implements AppInstance { 
    private AppContextImpl contextObj; 

    public void init(AppContextImpl context) { 
     this.contextObj = context; 
     System.out.println("Running App1..."); 
    } 
} 

// AppContextImpl.java

public class AppContextImpl { 
    public String mainClass; 
    public AppManager app; 

    public AppContextImpl(String mainClass, AppManager app) { 
     this.mainClass = mainClass; 
     this.app = app; 
    } 
} 

// CustomClassLoader.java

public class CustomClassLoader extends URLClassLoader { 
    AppManager appInst; 

    public CustomClassLoader(URL[] paths) { super(paths, null); } 
    public void setAppManager(AppManager app) { this.appInst = app; } 
} 

AppManager.java फ़ाइल में डिबग कोड के लिए उत्पादन होता है:

0 interfaces for AppInstance.class: 
1 interfaces for appClass instance: 
    0 - AppInstance ([email protected]) 
+1

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

+0

क्लास.getGenericInterfaces() और Class.getInterfaces() का आउटपुट क्या है? – TheLQ

+0

लॉर्ड। क्वाकस्टार: प्रश्न फिर से जांचें।मैंने आपके द्वारा मांगी गई जानकारी प्रदान करने के लिए कुछ टिप्पणियां डाली हैं। – Marcus

उत्तर

4

आपका AppInstance वर्ग शायद प्रत्येक कस्टम द्वारा अलग से भरी हुई है classloader। चूंकि वर्ग वस्तुएं वास्तविक वर्ग और क्लासलोडर पर निर्भर करती हैं, इसलिए वे वास्तव में अलग-अलग कक्षाएं हैं। तो AppInstance classloader 1 से classloader से AppInstance रूप में एक ही 2.

आपको बस इतना करना मानक classloader पदानुक्रम उपयोग कर रहा है की जरूरत है क्या नहीं है: आपके आवेदन के लिए एक रूट classloader उपयोग करते हैं, और पुरुष यह सुनिश्चित करें कि AppInstance classloader से लोड करने योग्य है । फिर रूट से अपने कस्टम क्लासलोडर बच्चों को बनाओ। जब भी उन्हें AppInstance क्लास तक पहुंचने की आवश्यकता होती है, तो वे रूट से लोड होने वाली चीज़ों का उपयोग करेंगे।

तो, बजाय इस की:

public CustomClassLoader(URL[] paths) { super(paths, null); } 

आप अपने CustomClassLoader को एक माता पिता को देने के लिए

+0

अलग-अलग क्लासलोडर्स द्वारा प्रदान किया गया अलगाव बिल्कुल लक्ष्य है। यदि मैं उनके लिए अभिभावक क्लासलोडर सेट करता हूं, तो अलगाव टूट जाएगा, घायल नहीं होगा? मैं यह सुनिश्चित करने के लिए क्लासलोडर्स के बारे में थोड़ा और अधिक शोध करूंगा कि मैं कुछ गलत समझ नहीं रहा हूं। मैं बहुत जल्द वापस आऊंगा। इस बीच, आपके उत्तर के लिए धन्यवाद। – Marcus

+1

आपको यह तय करने की ज़रूरत है कि आपके आवेदन का कौन सा हिस्सा सामान्य आधार होगा और मॉड्यूल विशिष्ट कौन सा हिस्सा होगा। ऐसा लगता है कि आप ओएसजीआई को फिर से शुरू करने की कोशिश कर रहे हैं, आप इसे देखना चाहेंगे;) – Guillaume

+0

मैंने जांच की है कि ओएसजीआई क्या है। मुझे बस इतना करना है कि वह है। हालांकि, मैं ओएसजीआई का उपयोग नहीं कर सकता क्योंकि मेरा आवेदन सार्वजनिक परिभाषित विनिर्देश पर आधारित है जो कुछ प्रतिबंध लगाता है। मुझे अपने स्वयं के कस्टम क्लासलोडर का उपयोग करके प्रत्येक एप्लिकेशन को लोड करने की आवश्यकता है। उसके बाद, मैं सामान्य जमीन में एक निगरानी धागा रखूंगा। ऐप्स स्वयं के बीच बातचीत करने के लिए एक विशेष एपीआई का उपयोग करेंगे। क्या आप जानते हैं कि प्रत्येक कस्टम क्लासलोडर के लिए पैरेंट क्लासलोडर सेट किए बिना CRASH POINT (1 और 2) में समस्याओं को हल करना संभव है? एक बार फिर धन्यवाद। – Marcus

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