2010-01-28 8 views
6

के साथ उपयोगकर्ता कोड संकलित और चल रहा है मैं जावा सीखने के लिए वेब ऐप लिख रहा हूं। कौन से उपयोगकर्ता मेरे कोड को अपने कोड पर संकलित कर सकते हैं + उस कोड को चलाएं। संकलन JavaCompiler करना आसान है:JavaCompiler और ClassLoader

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 
    DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>(); 
    CompilationTask task = compiler.getTask(null, null, diagnostics, null, null, prepareFile(nazwa, content)); 

    task.call(); 

    List<String> returnErrors = new ArrayList<String>(); 
    String tmp = new String(); 
    for (Diagnostic diagnostic : diagnostics.getDiagnostics()) { 
     tmp = String.valueOf(diagnostic.getLineNumber()); 
     tmp += " msg: " + diagnostic.getMessage(null); 
     returnErrors.add(tmp.replaceAll("\n", " ")); 
    } 

मैं कोड के साथ वर्ग लोड करने के लिए प्रबंधन:

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 
    StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null); 

    try { 
     URL[] urls = {new URL("file:///root/"), new URL("file://C:\\serv\\Apache Tomcat 6.0.20\\bin\\")}; 
     ClassLoader cl_old = Thread.currentThread().getContextClassLoader(); 
     ClassLoader cl_new = new URLClassLoader(urls, cl_old); 
     Class compiledClass = cl_new.loadClass(CLASS_NAME); 
     Method myMethod = compiledClass.getMethod(METHOD_NAME); 
     Object tmp = myMethod.invoke(null); 
    } catch (Exception ex) { 
     Logger.getLogger(ITaskCompile.class.getName()).log(Level.SEVERE, null, ex); 
    } 

मैं अंतहीन लूप, और बुराई छात्रों से मेरे ऐप की रक्षा कैसे कर सकते हैं;)

  1. क्या जीवन भर के साथ उस कोड को चलाने का कोई तरीका है?
  2. मेमोरी लीक के साथ कोई जोखिम है, और मैं इसे ठीक करने के लिए क्या कर सकता हूं।
  3. यह अच्छा समाधान है, या आप कुछ बेहतर सुझाव दे सकते हैं?

thx। Tzim

उत्तर

2

मैं कैसे अंतहीन लूप से मेरे एप्लिकेशन, और बुराई छात्रों की रक्षा कर सकते हैं;)

आप कर सकते हैं एक JVM में नहीं। बुराई छात्रों को विशेष रूप से निपटना मुश्किल होता है क्योंकि स्मार्ट लोग आपके नियंत्रण तंत्र को हटाने के लिए कुछ रास्ता समझेंगे।

1) क्या जीवनकाल के साथ उस कोड को चलाने का कोई तरीका है?

नहीं, जब तक कि आप इसे एक अलग JVM में नहीं चलाते।

2) क्या स्मृति रिसाव के साथ कोई जोखिम है, और मैं इसे ठीक करने के लिए क्या कर सकता हूं।

हां वहाँ है, और इसके बारे में आप कुछ भी नहीं कर सकते हैं (अलग जेवीएम के अलावा)। असल में, यह एक समस्या होगी भले ही आप छात्र कार्यक्रमों को मार सकते हैं जो लूप में फंस जाते हैं, आदि। ऐसे कई तरीके हैं जिनसे एप्लिकेशन जावा क्लास लाइब्रेरी को स्मृति/संसाधनों को रिसाव करने का कारण बन सकता है ... आवेदन के बाद भी खुद खत्म हो गया है और जीसीड किया गया है।

3) क्या यह अच्छा समाधान है, या आप कुछ बेहतर सुझाव दे सकते हैं?

प्रत्येक छात्र एप्लिकेशन को एक अलग JVM में चलाएं जिसे आपने Process और मित्रों का उपयोग करके अपने सर्वर से लॉन्च किया है। निष्पादन समय सीमा निर्धारित करने के लिए, और डेडलॉक के छात्र अनुप्रयोगों को मारने के लिए आपको होस्ट ऑपरेटिंग सिस्टम विशिष्ट सामग्री लिखनी होगी। इसके अलावा आपको यह सुनिश्चित करने के सभी प्रकार के मुद्दे मिल गए हैं कि आप बहुत से JVMs को फायर करके मेजबान मशीन प्रदर्शन को गलती से मिटा नहीं देते हैं।

एक बेहतर जवाब प्रत्येक छात्र को डेस्कटॉप कंप्यूटर या वर्चुअल मशीन प्रदान करना है और उन्हें अपनी खुद की चीज़ देना है।

+0

+1: लेकिन चेतावनी के साथ कि आप एक सुरक्षा प्रबंधक को सैंड-बॉक्स में छात्र कोड, यहां तक ​​कि उसी JVM में भी उपयोग करने में सक्षम होना चाहिए। लेकिन आप इस नीति का उपयोग करना चाहेंगे: सभी को ब्लॉक करें, फिर चयनित कार्रवाइयों की अनुमति दें। –

+0

Thx। हे सबसे बुरा हिस्सा यह है कि मुझे इसे एक सर्वर के साथ करना होगा। मैं प्रक्रिया का उपयोग करने की कोशिश करूंगा। जवाब देने के लिए धन्यवाद। – tzim

1

क्या जीवन भर के साथ कोड चलाने के लिए कोई तरीका है?

ऐसी प्रक्रिया बनाएं जो बाल प्रक्रियाओं पर नज़र रखता है और इसे बहुत लंबा लगता है।

मेमोरी लीक के साथ कोई जोखिम है, और मैं इसे ठीक करने के लिए क्या कर सकता हूं।

वैसा करने के लिए, कुछ हद तक, को नियंत्रित करने के लिए कितना स्मृति आवंटित किया जाता है (सूर्य की JVM को -Xmx पैरामीटर की तरह) से सक्षम होना चाहिए।

यह अच्छा समाधान है, या आप कुछ बेहतर सुझाव दे सकते हैं?

मुझे यकीन नहीं है कि एक समाधान प्रस्तावित किया गया है, लेकिन यहां एक विचार है। एक SecurityManager स्थापित करें जो निष्पादित कोड क्या कर सकता है, जैसे कि फाइल सिस्टम, स्पॉन प्रक्रियाओं आदि का उपयोग करना बहुत सीमित करता है। एक प्रक्रिया के साथ जो टाइमआउट के लिए मॉनीटर करता है, आवंटित स्मृति को सीमित करता है, एप्लिकेशन को एक अलग उपयोगकर्ता खाते आदि के तहत चलाता है। , और मुझे लगता है कि आप कुछ काम करने योग्य हो सकते हैं।

जो आप खोज रहे हैं वह संभव है, लेकिन पूरी तरह से नहीं हो सकता है यदि आप केवल जावा तक ही सीमित हैं।

1

कालेब के उत्तर में जोड़ना, सख्त ढेर सीमा (जैसे। -Xmx16M) के साथ लक्षित JVM को चलाने के लिए सुनिश्चित रहें। और, ज़ाहिर है, आप चल रहे जेवीएम की संख्या को सीमित करना चाहते हैं।

1

मेरे वर्तमान समाधान है कि तरह लग रहा है:

रन कोड:

@RequestMapping("/student/runITask.action") 
public String student_runITask(@ModelAttribute(value = "program") ProgramToCompile program, ModelMap map) { 
    //1. code compile 
    ITaskCompile itcompile = new ITaskCompile(); 
    List<String> errorList = itcompile.compileTask(program.getClassname(), program.getProgram()); 
    Date tmp = new Date(); 
    this.setPathName(program.getClassname() + tmp.hashCode()); 
    //2. if compiled... 
    if (errorList.size() < 1) { 
     try { 
      String[] cmd = {"/bin/sh", "-c", "java -Xmx16M -Xms2M -cp /root/ " + program.getClassname() + "> " + getPathName() + ".data"}; 
      Runtime rt = Runtime.getRuntime(); 
      final Process proc = rt.exec(cmd); 
      Thread.sleep(1000); 
      proc.destroy(); 
      if (proc.exitValue() > 0) { 
       try { 
        killJavaProcesses(); 
        map.addAttribute("comment", "Endless LOOP!"); 
       } catch (Exception ex1) { 
        Logger.getLogger(CompileITaskControler.class.getName()).log(Level.SEVERE, null, ex1); 
       } 
      } else { 
       StringBuffer fileData = new StringBuffer(1000); 
       BufferedReader reader = new BufferedReader(new FileReader("/root/" + getPathName() + ".data")); 
       char[] buf = new char[1024]; 
       int numRead = 0; 
       while ((numRead = reader.read(buf)) != -1) { 
        fileData.append(buf, 0, numRead); 
       } 
       reader.close(); 
       map.addAttribute("comment","Output: <br/><br/><br/><pre>"+fileData.toString()+"</pre>"); 
      } 
     } catch (Exception ex) { 
      try { 
       killJavaProcesses(); 
       map.addAttribute("comment", "Endless LOOP!"); 
      } catch (Exception ex1) { 
       Logger.getLogger(CompileITaskControler.class.getName()).log(Level.SEVERE, null, ex1); 
      } 
     } 
    } else { 
     map.addAttribute("errorList", errorList); 
     map.addAttribute("comment", "PROGRAM NIE ZOSTAŁ URUCHOMIONY"); 

    } //3. return 
    return DISPLAY_COMP_MSG; 


} 

जहां killJavaProcesses() कि

public void killJavaProcesses() throws IOException, InterruptedException { 
    String[] getProcessList = {"/bin/sh", "-c", "ps | grep java"}; 
    String[] killProcessByIdList = {"/bin/sh", "-c", "kill -9 "}; 
    Runtime rt = Runtime.getRuntime(); 
    Process proc = rt.exec(getProcessList); 
    InputStream inputstream = proc.getInputStream(); 
    InputStreamReader inputstreamreader = new InputStreamReader(inputstream); 
    BufferedReader bufferedreader = new BufferedReader(inputstreamreader); 
    String line2; 
    String kill = new String(); 
    while ((line2 = bufferedreader.readLine()) != null) { 
     kill += line2 + "\n"; 
    } 
    proc.destroy(); 
    String arraykill[] = kill.split("\n"); 
    String element2kill = ""; 
    String[] tmp; 
    if (arraykill.length >= 1) { 
     element2kill = arraykill[arraykill.length - 1].trim().split(" ")[0]; 
    } 
    killProcessByIdList[2] += element2kill; 
    Process proc2 = rt.exec(killProcessByIdList); 
    proc2.waitFor(); 
} 

मैं इस प्रक्रिया अलग नहीं मार सकता है की तरह लग रहा है। Proc.destroy() का उपयोग उबंटू/विन XP मशीनों पर सही काम नहीं करता है। अब मैं कॉन्फ़िगर करने और SecurityManager का उपयोग करने का प्रयास करूंगा।

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