janino-compiler / janino

Janino is a super-small, super-fast Java™ compiler.
http://janino-compiler.github.io/janino
Other
1.21k stars 205 forks source link

can't import other package #219

Open HH904789360 opened 2 months ago

HH904789360 commented 2 months ago

Help! I want to compile some java code which is String format,like this

"import java.util.*;\n"+
"import xxxx.GsonUtils;\n"+
"\n" +
 "public class Script {\n" +
 "%s"+
 "}"

but I found when icompiler compile this code ,"java.util.*" is ok,but the second line GsonUtils which is a class in my own project,can't find this class when I call this :" compiler.compile()" method. Actually,it can run in my own pc, but when this code deploy on a production server , " compiler.compile()" method will throw exception ,can't find this class.

what can i do ! help!

Geolykt commented 2 months ago

it is best to know how the code is being compiled - that is how janino is being used. Especially the differences between your production server and your computer are relevant - differences in the classpath here are noteworthy here (but even if there are no differences, knowing the classpath should be important either way)

HH904789360 commented 2 months ago

I referred to this code in your home page https://janino-compiler.github.io/janino/#janino-as-a-command-line-java-compiler :

ICompiler compiler = compilerFactory.newCompiler();

// Store generated .class files in a Map:
Map<String, byte[]> classes = new HashMap<String, byte[]>();
compiler.setClassFileCreator(new MapResourceCreator(classes));

// Now compile two units from strings:
compiler.compile(new Resource[] {
    new StringResource(
        "pkg1/A.java",
        "package pkg1; public class A { public static int meth() { return pkg2.B.meth(); } }"
    ),
    new StringResource(
        "pkg2/B.java",
        "package pkg2; public class B { public static int meth() { return 77;            } }"
    ),
});

// Set up a class loader that uses the generated classes.
ClassLoader cl = new ResourceFinderClassLoader(
    new MapResourceFinder(classes),    // resourceFinder
    ClassLoader.getSystemClassLoader() // parent
);

and write my own code in this.Then found it can't import other package in production server ,can I add this compiler.setClassPath(new File[]{new File(".").getAbsoluteFile()}); to get setClassPath,then I can import some other package?

Geolykt commented 2 months ago

Yes, you'd need to configure the classpath in order to be able to use dependencies. I cannot quite remember how janino handles the classpath as it has been a while since I last used it, but I surmise that the file array you wish to use would include files which are jars to directories which contain raw class files. But in order to be sure I'd read the documentation of the method (https://github.com/janino-compiler/janino/blob/4db1b8117bda36056f4eeab2d29e1f524b21b13c/commons-compiler/src/main/java/org/codehaus/commons/compiler/ICompiler.java#L149-L154) which may provide more insight.

That being said, you don't need to include the source resources on the classpath. That is, for as long as you compile two (or more) classes together, you don't need to do anything if they depend on each other (but you can't easily compile them separately).

aunkrig commented 2 months ago

What exactly do you mean with "GsonUtils which is a class in my own project"? Is there a .class file with that name, or is that class on the classpath of the currently running JVM?

BTW, instead of concatenating Java code as in your code example, you should rather use new ScriptEvaluator(), which does what you (obviously) want to do.