2010-02-01 17 views
16

तो, प्रत्येक जावा टेक्स्ट बुक इस बारे में बात करती है कि जावा कितना लचीला है क्योंकि यह रन टाइम पर कक्षाएं लोड कर सकता है। बस एक स्ट्रिंग को एक साथ दबाएं और इसे Class.forName() पर दें, और ClassNotFoundException पकड़ें और इसे संभाल लें। सिद्धांत के लिए बहुत कुछ।लोग कक्षा लोडिंग का उपयोग किसके लिए करते हैं?

क्या आप उदाहरण दे सकते हैं कि आप एक ऐसी सुविधा प्राप्त करने के लिए जावा क्लास लोडिंग का उपयोग कैसे कर रहे हैं जो अन्यथा संभव या आसान नहीं होता? ध्यान दें कि मैं नहीं पूछ रहा हूं "क्या महान चीजें हम कर सकते हैं?" - मैं असली दुनिया के उदाहरणों की तलाश में हूं, चाहे वह एक ओपन-सोर्स एप्लीकेशन हो या - यदि आप बहुत अधिक विवरण दिए बिना इसका वर्णन कर सकते हैं - एक मालिकाना आवेदन।

संपादित करें: निश्चित रूप से, वीएम कक्षाओं को आलसी रूप से लोड करता है क्योंकि इसकी आवश्यकता होती है। जब तक मुझे यकीन है कि सभी वर्गों की मुझे कभी आवश्यकता होगी, यह एक पीछे की चीजें हैं। मैं ClassNotFoundException कैसे संभालूं? मान लीजिए मैंने दस पृष्ठों के टेक्स्ट लिखे हैं, और PrinterDriver कक्षा नहीं मिल सकती है।

+0

हाइबरनेट और AspectJ फ्लाई पर कक्षाएं बनाने के उदाहरण हैं। –

उत्तर

10

प्लगइन्स पहली बात है जो दिमाग में आती है। जावा क्लास लोडिंग सी ++ जैसी भाषाओं की तुलना में इसे बहुत आसान बनाता है।

एक बिंदु जो आपको पता नहीं हो सकता है कि कोई भी जावा आभासी मशीन आंतरिक रूप से कक्षा लोडिंग पर निर्भर करती है। प्रत्येक बार, संदर्भ, बाइटकोड दुभाषिया द्वारा एक विधि को देखा जाता है, यह जांचता है कि जिस विधि से संबंधित विधि पहले से लोड की गई है, और यदि यह नहीं है, तो विधि को हल करने से पहले Class.forName() के पीछे उसी तंत्र का उपयोग करके इसे लोड करता है। यह मैकेनिज्म बहुत शक्तिशाली है क्योंकि कोई भी जावा एप्लिकेशन वास्तव में प्रतिस्थापन योग्य घटकों के सेट के रूप में कार्य करता है जो सभी गतिशील रूप से लोड होते हैं। यदि वीएम अच्छी तरह लिखा गया है तो यह एक कस्टम क्लास लोडर के माध्यम से कक्षाओं को लोड कर सकता है जो नियमित फ़ाइलों की बजाय नेटवर्क से कक्षाएं लाता है।

कक्षा लोडिंग समय वर्चुअल मशीन कार्यान्वयन पर निर्भर करता है, लेकिन अधिकांश इस बाध्यकारी तंत्र पर भरोसा करते हैं जो पहली बार वीएम इसे पूरा करता है।

+0

खैर, जीकेआरएलएम, सी में लागू, प्लगइन बस ठीक है। उन्हें अपने ~/.gkrellm2/plugins/निर्देशिका में रखें और उन्हें खोजने के लिए GKrellM को पुनरारंभ करें (यह कॉन्फ़िगरेशन संवाद खोले जाने पर प्रत्येक बार नए प्लगइन की जांच भी हो सकता है)। – doppelfish

+0

यह निश्चित रूप से करता है - मेरा मुद्दा यह है कि कक्षा लोडिंग का उपयोग करके प्लगइन को कार्यान्वित करना सी और सी ++ प्रोग्रामों द्वारा उपयोग की जाने वाली पारंपरिक गतिशील लाइब्रेरी लोडिंग का उपयोग करने से बहुत आसान और पोर्टेबल है - मैं यह कहने की कोशिश नहीं कर रहा हूं कि यह आपको सी से अधिक करने की अनुमति देता है (और हाँ, GKremmM यह बहुत अच्छा करता है!)। – Gnurou

3

ठीक है, मैंने इसे जेडीईसी ड्राइवरों को गतिशील रूप से जेडीईई अनुप्रयोगों में लोड करने के लिए उपयोग किया है। Wheteher यह एक बेहतर तरीका किया जा सकता था, मुझे नहीं पता है।

forName() कॉल करने के समय में यह आसान था।

+0

वास्तव में, मैंने कभी भी जेडीबीसी ड्राइवर प्राप्त करने का कोई और तरीका नहीं देखा है। एक बेहतर तरीका होना चाहिए, लेकिन मैंने इसे नहीं देखा है। अभिरुचि कि। – doppelfish

+1

ड्राइवर को jdbc.drivers सिस्टम प्रॉपर्टी में सेट करने का विकल्प है। –

0

मैं इसका उपयोग तब करता हूं जब मैं ऑफ-द-शेल्फ एप्लिकेशन बना रहा हूं जिसे ग्राहक या विशिष्ट आवश्यकताओं को पूरा करने के लिए स्वयं या ग्राहक द्वारा तैयार किया जाना आवश्यक है।

2

मुझे यकीन है कि जावा में प्लगइन लोडिंग उस पर बहुत निर्भर करती है।

नामित कार्यों के लिए आवेदन की जांच और उन्हें

Eclipse actually uses that for plugins

कुंजी विचार कोड कि developpement समय में नियोजित नहीं था निष्पादित करने के लिए है निष्पादित करता है।

2

यह उन परिस्थितियों में बेहद उपयोगी हो सकता है जहां आप एक एपीआई का उपयोग कर रहे हैं और एपीआई डिजाइनरों ने वास्तव में कुछ संस्करणों को एक संस्करण से अगले संस्करण में हटा दिया है (उदाहरण के लिए एंड्रॉइड में Contacts)।

स्ट्रिंग नाम के आधार पर प्रतिबिंब और गतिशील वर्ग लोडिंग के बिना, इस उदाहरण में प्लेटफॉर्म के दोनों संस्करणों पर एक ही प्रोग्राम चलाने के लिए असंभव होगा, बिना किसी कक्षा को रनटाइम पर अपवाद नहीं मिला। लेकिन इसके साथ, एक ही कार्यक्रम थोड़ा सा tweaked था और फिर दोनों प्लेटफार्मों पर चला सकता है।

5

"प्लगइन" और यह बड़ा शब्द है।

असल में, आप एक कक्षा को लोड कर सकते हैं जिसे आप नहीं जानते हैं जब आप अपने प्रोग्राम को लिखते और संकलित करते हैं।

उदाहरण के लिए, यदि आप एक प्रोग्राम वर्तनी जाँच करना चाहते हैं, आप एक इंटरफेस SpellChecker लिख सकते हैं तो एक विन्यास फाइल कि SpellChecker इंटरफ़ेस को लागू से एक वर्ग को लोड। उसके बाद, आप कोई स्पेल चेकर लिख सकते हैं और कॉन्फ़िगरेशन फ़ाइल में वास्तविक फ़ाइल नाम सेट कर सकते हैं। इस तरह, आपके प्रोग्राम को यह जानने की आवश्यकता नहीं है कि वर्तनी जांच कौन सी कक्षा करेगी।

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

उम्मीद है कि इससे मदद मिलती है।

2

कक्षा-लोडर का भी गैर-वर्ग संसाधनों के लिए उपयोग किया जाता है। विन्यास फाइलों को ध्यान में आता है। चूंकि एक अच्छी तरह से परिभाषित खोज आदेश है, इसलिए अपने "log4j.xml" या "hibernate.properties" में ड्रॉप करना आसान है, और एप्लिकेशन इसे ढूंढ और उपयोग करेगा।

1

मुझे लगता है कि जुनीट परीक्षण ढांचे को सामान्य बनाने के लिए कई प्रतिबिंब सुविधाओं का भी उपयोग कर सकता है।

-2

कक्षा कक्षा में है, तो कक्षा कक्षा के लिए नाम विधि का उपयोग कर सकते हैं। हालांकि यदि आपको कक्षा के नाम के साथ पथ देने की आवश्यकता है i.e c: \ document \ xyz.class आपको URLClassLoader क्लास का उपयोग करना होगा।

+1

उत्तर इस तरह गलत नहीं है, लेकिन यह वास्तव में प्रश्न का उत्तर नहीं देता है। –

0

उदाहरण के लिए स्प्रिंग फ्रेमवर्क में ओरेकल LOB handling के लिए समर्थन देखें। केवल इसलिए कि ढांचा ओरेकल के लिए विशिष्ट समर्थन प्रदान करता है, संभवतः आप ओरेकल डेटासोर्स को अपनी उदासीनता के लिए निर्भरता के रूप में तैनात नहीं करना चाहते हैं। MySQL परियोजनाओं। इसलिए आप ओआरकल ड्राइवरों को एलओबी हैंडलर के उदाहरण के दायरे में प्रतिबिंबित करते हैं।

5

एप्लिकेशन सर्वर विभिन्न तैनाती मॉड्यूल को अलग करने के लिए ClassLoaders पर भी भारी निर्भर करता है। जैसे

  • आप अलग अलग पथ के अंतर्गत दो बार एक ही वेब अनुप्रयोग तैनात कर सकते हैं
  • दो आवेदन बिना किसी संघर्ष के ही पुस्तकालय के दो विभिन्न संस्करण पर निर्भर कर सकते हैं।

वर्ग लोडर के जादू को धन्यवाद ...

+0

सच है, लेकिन (1) मैं एक ही बाइनरी दो बार एक अलग विन्यास के साथ दो बार शुरू कर सकता हूं, और (2) मेरे पास एक डीएलएल (साझा ऑब्जेक्ट) का अलग संस्करण हो सकता है, और द्विआधारी अपने पसंदीदा संस्करण के खिलाफ लिंक कर सकते हैं। अगली चीज़ जो आप जानते हैं, डीएल नरक। – doppelfish

0

बिलाव की तरह सर्वलेट कंटेनर वेब-INF/web.xml से अपने युद्ध/webapp विन्यास फाइल पढ़ सकते हैं और अपने सर्वलेट/फ़िल्टर/आदि लोड। आपके द्वारा XML फ़ाइल में डाले गए स्ट्रिंग मानों के आधार पर उप-वर्ग। डेटाबेस कनेक्शन के लिए, वे क्लास नाम को आपके कॉन्फ़िगरेशन से लोड करने के लिए खींचते हैं, उदा। MySQL के लिए "com.mysql.jdbc.Driver"।

2

मुझे कक्षाओं को दूरस्थ रूप से लोड करने के लिए कक्षा लोडर बनाना याद है। एप्लिकेशन एक नोड पर चल रहा था जबकि कक्षाओं को किसी अन्य नोड पर संग्रहीत किया गया था।

और कक्षा लोडर को अनुकूलित करके आप वर्गों को लोड कर सकते हैं क्योंकि वे लोड होते हैं। इसका उपयोग कुछ ओआरएम ढांचे के साथ-साथ कुछ एओपी ढांचे द्वारा किया जाता है।

0

वास्तविक दुनिया का उदाहरण (जैसा कि आपके प्रश्न में अनुरोध किया गया है), स्वामित्व आवेदन (जैसा कि आपके प्रश्न द्वारा स्पष्ट रूप से अनुमत है) ...

स्टार्टअप पर, क्लाइंट-साइड सॉफ़्टवेयर हमारे सर्वर से संपर्क करता है और कहता है "इंटरफ़ेस बार का डिफ़ॉल्ट कार्यान्वयन मेरे पास है (क्योंकि वास्तव में प्रत्येक संस्करण 1.03, उदाहरण के लिए, Foo का उपयोग कर रहे हैं), क्या आपके पास बेहतर है एक?" यदि इस बीच हमने एक बेहतर कार्यान्वयन लिखा, तो हम जवाब देते हैं कि "यूप, बार पुराना है, बुज़ का उपयोग करें, यह बेहतर है"।

फिर ग्राहक पक्ष पर एक क्लास लोडर का उपयोग नवीनतम कार्यान्वयन को लोड करने के लिए किया जाता है।

यह अतिसंवेदनशील है लेकिन यह वास्तविक दुनिया का उदाहरण है। यह जेआरएल के उदाहरण के लिए पूरी तरह से भिन्न नहीं है: जहां बहिष्कृत वर्ग स्वचालित रूप से नए लोगों द्वारा प्रतिस्थापित किए जाते हैं।

2

जेडीबीसी एपीआई इसके लिए एक उत्कृष्ट उदाहरण है। इस तरह आप उदाहरण के लिए में बाहर से कॉन्फ़िगर कर सकते हैं JDBC ड्राइवर एक गुण फ़ाइल:

 
driver = com.dbvendor.jdbc.Driver 
url = jdbc:dbvendor://localhost/dbname 
username = stackoverflow 
password = youneverguess 

..which आप उपयोग कर सकते हैं के रूप में:

Properties properties = new Properties(); 
properties.load(Thread.currentThread().getResourceAsStream("jdbc.properties")); 

String driver = properties.getProperty("driver"); 
String url = properties.getProperty("url"); 
String username = properties.getProperty("username"); 
String password = properties.getProperty("password"); 

Class.forName(driver); 
Connection connection = DriverManager.getConnection(url, username, password); 

हर JDBC ड्राइवर कार्यान्वयन मूल रूप से एक के अंदर DriverManager में खुद को पंजीकृत करता है static प्रारंभकर्ता ब्लॉक। यह अर्थात् Class#forName() के दौरान निष्पादित किया जाता है।

package com.dbvendor.jdbc; 

public class Driver implements java.sql.Driver { 

    static { 
     java.sql.DriverManager.registerDriver(new Driver()); 
    } 

    private Driver() { 
     // ... 
    } 

    public boolean acceptsURL(String url) { 
     return url.startsWith("jdbc:dbvendor"); 
    } 

} 

के बाद से DriverManagerमोटे तौर पर देखो इस तरह

private static final Set<Driver> drivers = new HashSet<Driver>(); 

public static void registerDriver(Driver driver) { 
    drivers.add(driver); 
} 

public static Connection getConnection(String url, String username, String password) throws SQLException { 
    for (Driver driver : drivers) { 
     if (driver.acceptsURL(url)) { 
      return driver.connect(url, username, password); 
     } 
    } 
    throw new SQLException("No suitable driver"); 
} 

(यह वास्तव में पुराने जमाने Vector उपयोग करता है) ... आप ड्राइवर खुद का दृष्टांत की आवश्यकता के बिना इसे से एक कनेक्शन प्राप्त कर सकते हैं !

इस तरह जेडीबीसी कोड अत्यधिक पोर्टेबल है। आप कोड को बदलने/हैक/पुनर्निर्माण की आवश्यकता के बिना अलग-अलग डीबी के उपयोगकर्ताओं के बीच डीबी को बदल सकते हैं या कोड वितरित कर सकते हैं।

यह केवल JDBC जो इस दृष्टिकोण का उपयोग करता है, यह भी अन्य एपीआई सर्वलेट एपीआई, ORM के हाइबरनेट/जेपीए की तरह, निर्भरता इंजेक्शन चौखटे, आदि वर्गों लोड करने के लिए प्रतिबिंब का उपयोग करता है के रूप में इस तरह के आधार पर बाहर से configureable propertiesfiles, एक्सएमएल config फ़ाइलें नहीं है और/या एनोटेशन। यह सब कोड को और अधिक पोर्टेबल और प्लग करने योग्य बनाता है।

1

जावा classloader तंत्र शक्तिशाली है, क्योंकि यह वास्तव में समय पर किसी अमूर्त बिंदु है जहां कोड भरी हुई है, जो की मदद से आप इस तरह के रूप बातें करते हैं प्रदान करता है: classpath के अलावा अन्य किसी ऐसे स्थान पर वर्ग बिट्स खोजने

  • (db दूरदराज के यूआरएल, फाइल सिस्टम, आदि)
  • लोड हो रहा है स्रोत कोड आपने अभी बनाया और (अपने आप को संकलित javac एपीआई के साथ)
  • लोड हो रहा है बाइट कोड आप बस अपने आप उत्पन्न (एएसएम के साथ कहते हैं)
  • कोड डालने और इसे संशोधित मैं आप का उपयोग करने से पहले टी
  • मक्खी पर फिर से लोड कोड
  • श्रृंखला लोडर एक साथ पेड़ों में (सामान्य प्रतिनिधिमंडल) या जाले (भाई आधारित OSGi शैली) या आप चाहते हैं जो कुछ भी
(एएसएम, जावा एजेंटों, आदि आदि के साथ)

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

0

गतिशील वर्ग लोडिंग का उपयोग करना कॉन्फ़िगरेशन फ़ाइलों को लोड करने के लिए भी बहुत उपयोगी है क्योंकि थिलो का उल्लेख है। अधिक आम तौर पर, गतिशील वर्ग लोडिंग कई स्थितियों में एक अच्छी फ़ाइल सिस्टम अबास्ट्रक्शन परत बना सकती है, लेखन वरीयता और कॉन्फ़िगरेशन संवेदनशील कोड को सरल बना सकती है। बस सुनिश्चित करें कि आपको आवश्यक संसाधन क्लासपाथ पर है और इसे इनपुटस्ट्रीम के रूप में लोड करें।

इसके अलावा, जावा में कस्टम प्रोटोकॉल हैंडलर के साथ URL के माध्यम से कक्षापथ पर आइटमों तक पहुंच बनाना संभव है। यह गतिशील वर्ग लोडिंग के लिए विशिष्ट लाभ नहीं है, लेकिन यह दर्शाता है कि क्लासपाथ संसाधनों को उसी संसाधन के माध्यम से अन्य संसाधनों (यहां तक ​​कि दूरस्थ वाले) के रूप में कैसे पहुंचा जा सकता है। http://java.sun.com/developer/onlineTraining/protocolhandlers/

0

कॉन्फ़िगरेशन आधारित (स्ट्रैट्स, जेएसएफ, वसंत, हाइबरनेट, इत्यादि) कोई भी ढांचा इस तंत्र का उपयोग करता है। प्लगइन आर्किटेक्चर पर आधारित कोई भी उत्पाद भी इस सुविधा का उपयोग करता है।

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