java - आप बाहरी जावा वर्गों को गतिशील रूप से संकलित और लोड कैसे करते हैं?




dynamic compilation (2)

(यह प्रश्न मैंने देखा है कि कई प्रश्नों के समान है, लेकिन अधिकांश जो मैं कर रहा हूं उसके लिए पर्याप्त विशिष्ट नहीं हैं)

पृष्ठभूमि:

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

मेरा सवाल यह है कि, मैं इसे कैसे प्राप्त करूं ताकि क्लाइंट (मेरे संकलित प्रोग्राम का उपयोग करके) अपने जावा पर कहीं भी इस जावा फ़ाइल (जो मेरा इंटरफेस एक्स्प्लेम बढ़ाता है) को बचा सके, मेरे प्रोग्राम को संकलित करें (कहने के बिना "प्रतीक नहीं ढूंढ सकता: इंटरफेसएक्स नमूना" ) फिर इसे लोड करें और doSomething () विधि को कॉल करें?

मैं प्रतिबिंब या क्लासलोडर का उपयोग करके क्यू एंड ए का उपयोग करता रहता हूं और जिसने लगभग इसे संकलित करने का वर्णन किया है, लेकिन मेरे लिए कोई भी पर्याप्त विस्तृत नहीं है / मैं उन्हें पूरी तरह से समझ नहीं पा रहा हूं।


मैं जावा रनटाइम कंपाइलर लाइब्रेरी का उपयोग करने का सुझाव देता हूं। आप इसे स्मृति में एक स्ट्रिंग दे सकते हैं और यह कक्षा को वर्तमान वर्ग लोडर (या आपकी पसंद में से एक) में संकलित और लोड कर देगा और कक्षा को लोड कर देगा। नेस्टेड कक्षाएं भी लोड की जाती हैं। नोट: यह डिफ़ॉल्ट रूप से स्मृति में पूरी तरह से काम करता है।

जैसे

 // dynamically you can call
 String className = "mypackage.MyClass";
 String javaCode = "package mypackage;\n" +
                  "public class MyClass implements Runnable {\n" +
                  "    public void run() {\n" +
                  "        System.out.println(\"Hello World\");\n" +
                  "    }\n" +
                  "}\n";
 Class aClass = CompilerUtils.CACHED_COMPILER.loadFromJava(className, javaCode);
 Runnable runner = (Runnable) aClass.newInstance();
 runner.run();

JavaCompiler पर एक नज़र JavaCompiler

निम्नलिखित JavaDocs में दिए गए उदाहरण पर आधारित है

यह testcompile निर्देशिका में एक File को सहेज testcompile ( package नाम आवश्यकताओं के आधार पर) और File को जावा क्लास में संकलित करें ...

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

public class InlineCompiler {

    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder(64);
        sb.append("package testcompile;\n");
        sb.append("public class HelloWorld implements inlinecompiler.InlineCompiler.DoStuff {\n");
        sb.append("    public void doStuff() {\n");
        sb.append("        System.out.println(\"Hello world\");\n");
        sb.append("    }\n");
        sb.append("}\n");

        File helloWorldJava = new File("testcompile/HelloWorld.java");
        if (helloWorldJava.getParentFile().exists() || helloWorldJava.getParentFile().mkdirs()) {

            try {
                Writer writer = null;
                try {
                    writer = new FileWriter(helloWorldJava);
                    writer.write(sb.toString());
                    writer.flush();
                } finally {
                    try {
                        writer.close();
                    } catch (Exception e) {
                    }
                }

                /** Compilation Requirements *********************************************************************************************/
                DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
                JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
                StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);

                // This sets up the class path that the compiler will use.
                // I've added the .jar file that contains the DoStuff interface within in it...
                List<String> optionList = new ArrayList<String>();
                optionList.add("-classpath");
                optionList.add(System.getProperty("java.class.path") + ";dist/InlineCompiler.jar");

                Iterable<? extends JavaFileObject> compilationUnit
                        = fileManager.getJavaFileObjectsFromFiles(Arrays.asList(helloWorldJava));
                JavaCompiler.CompilationTask task = compiler.getTask(
                    null, 
                    fileManager, 
                    diagnostics, 
                    optionList, 
                    null, 
                    compilationUnit);
                /********************************************************************************************* Compilation Requirements **/
                if (task.call()) {
                    /** Load and execute *************************************************************************************************/
                    System.out.println("Yipe");
                    // Create a new custom class loader, pointing to the directory that contains the compiled
                    // classes, this should point to the top of the package structure!
                    URLClassLoader classLoader = new URLClassLoader(new URL[]{new File("./").toURI().toURL()});
                    // Load the class from the classloader by name....
                    Class<?> loadedClass = classLoader.loadClass("testcompile.HelloWorld");
                    // Create a new instance...
                    Object obj = loadedClass.newInstance();
                    // Santity check
                    if (obj instanceof DoStuff) {
                        // Cast to the DoStuff interface
                        DoStuff stuffToDo = (DoStuff)obj;
                        // Run it baby
                        stuffToDo.doStuff();
                    }
                    /************************************************************************************************* Load and execute **/
                } else {
                    for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
                        System.out.format("Error on line %d in %s%n",
                                diagnostic.getLineNumber(),
                                diagnostic.getSource().toUri());
                    }
                }
                fileManager.close();
            } catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException exp) {
                exp.printStackTrace();
            }
        }
    }

    public static interface DoStuff {

        public void doStuff();
    }

}

संकलित वर्ग के संकलक और लोडिंग और निष्पादन के लिए क्लासपाथ की आपूर्ति करने के लिए अब अपडेट किया गया है!





external