10

मुझे पता है कि यह पूछा गया है और बहुत उत्तर दिया गया है लेकिन मेरे पास अभी भी कोई अच्छा समाधान नहीं है और मैं अभी भी कुछ हिस्सों को समझ नहीं पा रहा हूं। तो मुझे प्रोग्रामिंग रूप से * .java फ़ाइलों को संकलित करने की आवश्यकता है।प्रोग्राम फ़ाइलों को संकलित करें

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 

मैं क्या उपयोग कर रहा हूँ और (उम्मीद के रूप में) संकलक null है। अब, मुझे पता है कि मुझे जेडीके का उपयोग करना है, न कि जेआरई को "रनटाइम" के रूप में, लेकिन यहां कुछ ऐसा है जो मुझे समझ में नहीं आता है: क्या यह केवल tools.jar को एप्लिकेशन के क्लासपाथ में रखना पर्याप्त नहीं है और फिर जावा कंपाइलर एपीआई तक पहुंच है? यदि यह सच है, तो क्या स्टैंडअलोन जावा एप्लिकेशन और वेब-आधारित एप्लिकेशन के बीच अंतर है (मुझे लगता है कि) है। दरअसल, मैं PlayCramework वेबपैप से JavaCompiler को बुलावा देने की कोशिश कर रहा हूं, इसलिए मुझे पता चला, शायद यह समाधान (tools.jar सहित) केवल स्टैंड-अलोन अनुप्रयोगों के लिए काम करता है?

मैं भी एक कस्टम classloader बना सकते हैं और प्रतिबिंब के साथ ऊपर उल्लेख किया विधि को लागू करने की कोशिश की, लेकिन सब मैं हो रही है compiler वस्तु के लिए null है:

    :

    ClassLoader classloader = app.classloader(); 
    File file = new File("lib/tools.jar");   
    URL url = file.toURI().toURL(); 
    URL[] urls = new URL[]{url}; 
    ClassLoader newCL = new URLClassLoader(urls, classloader) { 
    }; 
    Class<?> loadClass = newCL.loadClass("javax.tools.ToolProvider"); 
    Method method = loadClass.getMethod("getSystemJavaCompiler", null);    
    Object object = method.invoke(null); 
    System.out.println("Object: " + object); // NULL 
    

    ऊपर कोड के लिए स्पष्टीकरण

  • मैंने सादगी के लिए प्रयास/कैच शामिल नहीं किया है।
  • app.classloader() एक प्ले-विधि है जो अनुप्रयोग
  • tools.jar की classloader रिटर्न प्ले परियोजना (यह संकेत मिलता है कि यह परियोजना की classpath पर है की मेरी lib फ़ोल्डर में शामिल किया गया है है - प्ले प्रलेखन के अनुसार)

मुझे पूरा यकीन है कि Play को जावा कंपाइलर क्लास लोड करने में सक्षम होने से पहले मुझे कुछ और करने की ज़रूरत है, मुझे नहीं पता कि मैं क्या खो रहा हूं।

Runtime.exec("javac myFile.java") जैसे विकल्प और ग्रहण जेडीटी कंपाइलर मुझे ज्ञात हैं, लेकिन यह वह नहीं है जिसे मैं ढूंढ रहा हूं।

ओह, और System.setProperty("java.home", "PATH_TO_YOUR_JDK"); जैसे कुछ और फिर ToolProvider.getSystemJavaCompiler(); काम कर रहा है लेकिन मुझे यह समाधान इतना बदसूरत लगता है।

सादर

संपादित: (अतिरिक्त जानकारी देने और पिछले स्थिति दिखाने) इस वेब-एप्लीकेशन-संरचना की एक बुनियादी प्रतिनिधित्व है:

myApp 
|-conf\... 
|-lib\MyJar.jar 
|-lib\tools.jar 
|-logs\... 
|-... 

MyJar.jar अब है निम्नलिखित सामग्री के साथ एक META-INF/MANIFEST.MF फ़ाइल:

Manifest-Version: 1.0 
Sealed: true 
Main-Class: here.comes.my.main.class 
Class-Path: tools.jar 

बिना प्ले ऐप शुरू करने के के बिना, मैं कोशिश कर रहा हूं (lib फ़ोल्डर में): java -jar MyJar.jar - मेरा सरल main विधि कंपाइलर (ToolProvider.getSystemJavaCompiler();) को आमंत्रित करने का प्रयास करती है और null लौटाती है। तो इससे मुझे विश्वास होता है कि समस्या के साथ खेलने के लिए कुछ भी नहीं है - आम तौर पर जब मैं अपने जार चलाता हूं तो मैं कंपाइलर भी नहीं प्राप्त कर सकता!

उत्तर

0

यह documentation में कहा गया है कि To run the Play framework, you need JDK 6 or later. आपने इसे जेरे के साथ चलाने के लिए कैसे प्रबंधित किया?

वैसे भी, यदि getSystemJavaCompiler शून्य लौटाता है तो इसका मतलब है कि आपके क्लासपाथ में tools.jar नहीं है या यह दूषित है। यदि यह सूर्य/ओरेकल जावा है, तो सुनिश्चित करें कि इसमें com.sun.tools.javac.api.JavacTool कक्षा है।

और यदि आप कस्टम क्लास लोडर का उपयोग करना चाहते हैं, तो यह JavacTool क्लास है जिसे आपको लोड करने की आवश्यकता है, टूलप्रोवाइडर नहीं। JavaCompiler को

 URL[] urls = {file.toURI().toURL()}; 
     ClassLoader cl = URLClassLoader.newInstance(urls); 
     cl.setPackageAssertionStatus("com.sun.tools.javac", true); 
     return Class.forName(defaultJavaCompilerName, false, cl); 

जहां defaultJavaCompilerName = "com.sun.tools.javac.api.JavacTool"

उपवर्ग यह और नया उदाहरण मिल - आप अपने संकलक होगा: जावा 6 में तो जिस तरह से यह करता है पर एक नजर डालें।

+0

'जावा' एचओएमईई 'मेरी देव मशीन पर सेट है, जो पूछे जाने पर जेडीके के रास्ते को वापस कर रहा है। लेकिन प्ले एप्लिकेशन चलाने से 'java.home" 'संपत्ति प्राप्त हो रही है (' System.getProperty (...) 'के साथ) जेआरई के लिए मार्ग लौटाता है। तो शायद यह एक समस्या है। लेकिन मेरे क्लासपाथ में 'tools.jar' होने पर कोई समस्या नहीं होनी चाहिए। और मुझे पूरा यकीन है कि 'tools.jar' मेरे क्लासपाथ में है (इसे वेब ऐप के चलाने के दौरान चेक किया गया है) और फ़ाइल दूषित नहीं है। मैं उपर्युक्त वर्गीकृत सामानों को आजमाने की कोशिश कर रहा हूं। – user2229298

+0

मैं अपने उबंटू पर खेल गया और मुझे बिना किसी समस्या के स्कैला एक्शन से जावा कंपाइलर मिल सकता था। शायद आपके सेटअप में कुछ गड़बड़ है? –

+0

बस 'JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler(); \t \t \t System.out.println ("जावा कंपाइलर:" + जावा कॉम्पेलर); 'ऐप/ग्लोबल.जावा' में 'ऑनस्टार्ट' विधि से - 'ऐप के क्लासपाथ में' tools.jar' के साथ- यहां तक ​​कि वह लौट रहा है 'null' – user2229298

1

वेब अनुप्रयोगों और स्टैंडअलोन अनुप्रयोगों के बीच कोई अंतर नहीं है।

आपको अपने वेबपैप क्लासपाथ में tools.jar पैकेज नहीं करना चाहिए। जावा में क्लासलोडर आमतौर पर केवल नीचे काम करता है। इस प्रकार टूलप्रोवाइडर जो जेडीके का हिस्सा है, आपके टूल.जर को वेबपैप क्लासपाथ में नहीं देखेगा (यह वेबपैप क्लासपाथ में नहीं देख सकता है)।

समाधान: जेडीके का उपयोग करें और सुनिश्चित करें कि आप इसे इंगित करते हैं या Java ext dir में tools.jar डालते हैं। आप संपत्ति को डीजेवा.ext.dir को अपनी पसंद की किसी भी निर्देशिका में सेट करके ext dir को ओवरराइड कर सकते हैं।

+0

यह सही लगता है। मैं सुझाव देता हूं कि उपकरण जार को एक आम जगह में रखें या जेडीके का उपयोग करें। – tgkprog

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