将.java文件动态编译为.class

时间:2015-06-02 09:40:16

标签: java android

我的项目的目标是从移动设备执行用户输入的Java代码。

到目前为止,我已经能够从EditText中获取用户输入的代码,并将其插入到设备的数据/文件夹中的.java文件中。

我现在坚持将.java文件从设备中编译成.class,然后我可以将.cl​​ass转换为.dex并执行包含用户代码的方法。

这是我用来创建.java文件的代码。对于此示例,我创建了一个表示用户输入的字符串,但在应用程序中,它将从EditText框中获取:

writeJavaFile("public class UserClass{public void userMethod(){\n\n\n\n}}");
insertUserCode("System.out.println(\"This is a print\")");

private void insertUserCode(String userData){

    try{

        File file = new File(getFilesDir(),"TestClass.java");

        BufferedReader br = new BufferedReader(new FileReader(file));

        StringBuilder text = new StringBuilder();
        String line;

        int counter = 0;

        while((line = br.readLine()) != null) {

            if(counter == 2){
                text.append(userData);
            }else{
                text.append(line);
            }
            counter++;
        }
        br.close();

        writeJavaFile(text.toString());

    }catch(Exception e){
        e.printStackTrace();
    }

}


private void writeJavaFile(String stringToInsert) {
    try{
        FileOutputStream fOut = openFileOutput("TestClass.java", MODE_PRIVATE);

        OutputStreamWriter osw = new OutputStreamWriter(fOut);

        osw.write(stringToInsert);

        osw.flush();
        osw.close();

    }catch(Exception e){
        e.printStackTrace();
    }
}

2 个答案:

答案 0 :(得分:3)

无法在移动设备/ Android设备中编译java文件,因为移动设备没有用于将.java文件转换为.class文件的JDK。

另外,android没有JDK它有DVM(Dalvik虚拟机)或ART(Android运行时),负责将.dex文件转换为机器相关代码。

要实现这一点,您必须在应用程序中实现JDK,并且由于JDK / JVM是依赖于平台的,因此您必须编写自己的JDK代码才能在您的应用程序中工作。

我建议您查看 JRE (Java运行时环境)和 JDK (Java开发工具包)。

答案 1 :(得分:1)

我使用groovy。了解更多详情。您可以动态运行。

import groovy.lang.GroovyShell;
import groovy.lang.Script;

public class Test {
    public static void main(String[] args) throws Exception{
        String input = "public int calculate() { " +
                        " return 5 + 10;" + 
                        "}";
        Script groovyShell = new GroovyShell().parse(input);
        int result = (Integer)groovyShell.invokeMethod("calculate", null);
        System.out.println("Result : " + result);
    }
}

<强>更新

以下是我的Web应用程序的示例动态输入。 用户从UI输入此脚本/ java代码。我们有经常变化的计算。这就是我们思考动态计算方式的原因。

我的程序是动态运行的

以下script/java code来自UI输入..

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;
import com.java.groovy.DateUtils;
import com.java.groovy.ParamConstant;
import com.java.groovy.CalcConstant;
import com.java.groovy.CalcResult;

    public Map<String, BigDecimal> calculate(Map<Object, Object> map) {
        def script = new GroovyScriptEngine('resources/').with {loadScriptByName('CalculatorUtils.groovy')};
        this.metaClass.mixin script;
        BigDecimal oldPremium = map.get(ParamConstant.OLD_PREMIUM);
        Date startDate = map.get(ParamConstant.START_DATE);
        Date endDate = map.get(ParamConstant.END_DATE);
        Date endorsementDate = map.get(ParamConstant.ENDORSEMENT_DATE);
        BigDecimal actRate = map.get(ParamConstant.ACTUAL_RATE);

        int year = DateUtils.getPeriodOfYears(startDate, endDate);
        int term = 0;
        if (year >= 1) {
            term = DateUtils.getPeriodOfDays(startDate, endDate);
        } else {
            term = DateUtils.getPeriodOfDays(startDate, endDate) + 1;
        }

        int passedDays = DateUtils.getPeriodOfDays(startDate, endorsementDate) + 1;
        int restDays = DateUtils.getPeriodOfDays(endorsementDate, endDate) + 1;

        Map<String, BigDecimal> result = new HashMap<String, BigDecimal>();

        // Calculate Short Period Rate
        BigDecimal shortPeriodRate = new BigDecimal(calcMotorShortPeriodRate(startDate, endDate));
        BigDecimal newPremium = actRate.multiply(shortPeriodRate);

        // Pro-Rata Rate with old vehicle
        BigDecimal oldVehProRataRate = calcMotorProRataRate(passedDays, oldPremium.doubleValue(), term);
        // Pro-Rata Rate with new vehicle
        BigDecimal newVehProRataRate = calcMotorProRataRate(restDays, newPremium.doubleValue(), term);

        BigDecimal balanceAmountWithOldPremium = (oldPremium.subtract(oldVehProRataRate));
        BigDecimal endorseAmount = (newVehProRataRate.subtract(balanceAmountWithOldPremium));
        newPremium = newPremium.setScale(CalcConstant.RESULT_DECIMAL_LIMIT, RoundingMode.HALF_UP);
        result.put(CalcResult.PREMIUM, newPremium);
        endorseAmount = endorseAmount.setScale(CalcConstant.RESULT_DECIMAL_LIMIT, RoundingMode.HALF_UP);
        result.put(CalcResult.ENDORSEMENT_AMOUNT, endorseAmount);
        return result;
    }