janino-compiler / janino Goto Github PK
View Code? Open in Web Editor NEWJanino is a super-small, super-fast Java™ compiler.
Home Page: http://janino-compiler.github.io/janino
License: Other
Janino is a super-small, super-fast Java™ compiler.
Home Page: http://janino-compiler.github.io/janino
License: Other
Thanks a lot for creating janino - helps a lot prototyping some cool ideas in the area of route planning :) !
I'm currently seeking for the best approach to make dozens of helper variables available for a dynamic script like
edge.get(helperVariable1) * 0.9
The only parameter that changes per call is edge
. But the helperVariable1 is not just a constant, it is an instance of an "accessor" class which is already available at creation (or "cook") time. E.g. we can write edge.get(surface)
and an integer value is returned. So basically these helper variables are known up front (and there could be a lot of them), but we can't just replace them with int or double values up front.
Now, when I use createFastEvaluator
with 25 parameters I get a nice fast evaluation (in my case 0.06ms/call). (E.g. this is faster compared to "cook&evaluate" with 0.1ms/call, also with 25 params). But the method of the interface gets really lengthy and is not really customizable. (or is there a trick?)
Is there a better and still fast approach like creating a class with all the helper variables (ClassBodyEvaluator?) as local variables and then make only one method scriptable for the end user?
For example something like this:
public class MyClass {
HelperParam helperVariable1;
public MyClass() {
// init helperParam
}
public double run(OtherParam otherParam) {
// USER SCRIPT HERE
// that uses one or more helper variables
}
}
If this is the way to go. Would I use ClassBodyEvaluator and string manipulation to inject the user script or is there a cleaner method?
I hope this is a bit understandable. Can give more examples if necessary.
Edit: Here is the current working snippet with this approach:
public ScriptWeighting createScriptWeighting(FlexModel model) {
String script = model.getScript();
for (String chars : Arrays.asList("{", "}", "import", "static", "file"))
if (script.contains(chars))
throw new IllegalArgumentException("Script contains illegal character " + chars);
if (!script.contains("return"))
script = "return " + script;
if (!script.endsWith(";"))
script = script + ";";
try {
IClassBodyEvaluator cbe = CompilerFactoryFactory.getDefaultCompilerFactory().newClassBodyEvaluator();
cbe.setNoPermissions();
cbe.setImplementedInterfaces(new Class[]{ScriptInterface.class});
cbe.setDefaultImports(new String[]{"com.graphhopper.util.EdgeIteratorState",
"com.graphhopper.routing.profiles.*"});
cbe.setClassName("MyRunner");
cbe.cook("public EnumEncodedValue road_class;\n"
+ " public EnumEncodedValue road_environment;\n"
+ " public IntEncodedValue toll;\n"
+ " public double getMillisFactor(EdgeIteratorState edge, boolean reverse) {\n"
+ script
+ " }");
Class<?> c = cbe.getClazz();
return new ScriptWeighting(model.getBase(), model.getMaxSpeed(), (ScriptInterface) c.newInstance());
} catch (Exception ex) {
throw new IllegalArgumentException(ex);
}
}
But it looks a bit looks a bit hacky.
Hi,
Apache Calcite uses Janino 2.7.6 for compiling code which is used for handling different kinds of query metadata. All was working fine before bumping up Java version in maven-compiler-plugin to 1.8. After this, some tests failed with compile exceptions for generated code. The same issue is observed with Janino 3.0.7.
I have reproduced it on the current Janino master.
When Java version 1.8 is specified in janino-parent/pom.xml
maven-compiler-plugin
for both source
and target
, the next test placed into CompilerTest.java
is failed:
public interface A {
A theFirstMethod();
}
public interface B extends A {
B theFirstMethod();
Object theSecondMethod();
}
@Test
public void testInterfaceWithOverriddenMethod() throws Exception {
SimpleCompiler s = new SimpleCompiler();
s.setDebuggingInformation(true, true, true);
s.cook("package pkg;\n"
+ "public class D {\n"
+ " public java.lang.Object one(org.codehaus.janino.tests.CompilerTest.B b) { \n"
+ " return b.theFirstMethod().theSecondMethod();\n"
+ " }\n"
+ "}\n");
s.getClassLoader().loadClass("pkg.D");
}
Error message and stacktrace:
org.codehaus.commons.compiler.CompileException: Line 4, Column 50: A method named "theSecondMethod" is not declared in any enclosing class nor any supertype, nor through a static import
at org.codehaus.janino.UnitCompiler.compileError(UnitCompiler.java:12063)
at org.codehaus.janino.UnitCompiler.findIMethod(UnitCompiler.java:8955)
at org.codehaus.janino.UnitCompiler.compileGet2(UnitCompiler.java:5018)
at org.codehaus.janino.UnitCompiler.access$9100(UnitCompiler.java:215)
at org.codehaus.janino.UnitCompiler$16.visitMethodInvocation(UnitCompiler.java:4378)
at org.codehaus.janino.UnitCompiler$16.visitMethodInvocation(UnitCompiler.java:4351)
at org.codehaus.janino.Java$MethodInvocation.accept(Java.java:5051)
at org.codehaus.janino.UnitCompiler.compileGet(UnitCompiler.java:4351)
at org.codehaus.janino.UnitCompiler.compileGetValue(UnitCompiler.java:5533)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:2649)
at org.codehaus.janino.UnitCompiler.access$2800(UnitCompiler.java:215)
at org.codehaus.janino.UnitCompiler$6.visitReturnStatement(UnitCompiler.java:1504)
at org.codehaus.janino.UnitCompiler$6.visitReturnStatement(UnitCompiler.java:1487)
at org.codehaus.janino.Java$ReturnStatement.accept(Java.java:3541)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:1487)
at org.codehaus.janino.UnitCompiler.compileStatements(UnitCompiler.java:1567)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:3356)
at org.codehaus.janino.UnitCompiler.compileDeclaredMethods(UnitCompiler.java:1357)
at org.codehaus.janino.UnitCompiler.compileDeclaredMethods(UnitCompiler.java:1330)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:822)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:432)
at org.codehaus.janino.UnitCompiler.access$400(UnitCompiler.java:215)
at org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:411)
at org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:406)
at org.codehaus.janino.Java$PackageMemberClassDeclaration.accept(Java.java:1406)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:406)
at org.codehaus.janino.UnitCompiler.compileUnit(UnitCompiler.java:378)
at org.codehaus.janino.SimpleCompiler.cook(SimpleCompiler.java:237)
at org.codehaus.janino.SimpleCompiler.compileToClassLoader(SimpleCompiler.java:465)
at org.codehaus.janino.SimpleCompiler.cook(SimpleCompiler.java:216)
at org.codehaus.janino.SimpleCompiler.cook(SimpleCompiler.java:207)
at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:80)
at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:75)
at org.codehaus.janino.tests.CompilerTest.testInterfaceWithOverriddenMethod(CompilerTest.java:440)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
It looks like the overridden method A theFirstMethod()
from the parent interface A
was chosen instead of the method from interface B
when b.theFirstMethod()
was executed.
Also, I have noticed that with Java 8 the next code:
Method[] declaredMethods = Class.forName("org.codehaus.janino.tests.CompilerTest$B").getDeclaredMethods();
for (Method m : declaredMethods) {
System.out.println(m);
}
returns
public abstract org.codehaus.janino.tests.CompilerTest$B org.codehaus.janino.tests.CompilerTest$B.theFirstMethod()
public default org.codehaus.janino.tests.CompilerTest$A org.codehaus.janino.tests.CompilerTest$B.theFirstMethod()
public abstract java.lang.Object org.codehaus.janino.tests.CompilerTest$B.theSecondMethod()
So perhaps in our case that default
method was chosen instead of the correct one.
EDIT:
Please, remove this post - I have solved my problem differently so it is no more a problem, sorry for bothering...
As of version 3.0.2, OSGi manifest entries are no longer present.
Hi,
We are reaching out to you to check Java 11 compatibility of the library commons-compiler.
Could you help us by answering the following questions:
Appreciate your response by 19.08.2018.
Thanks,
Krzysztof Dragan,
PTC Inc. Contractor
Hello,
In the documentation you say that Janino supports strings in switch statements (Java 7 language features).
However, the following simple test:
@Test
public void testSwitch() throws CompileException, InvocationTargetException {
ScriptEvaluator se = new ScriptEvaluator();
se.setReturnType(String.class);
se.cook("switch(\"1\") { case \"1\": return \"42\"; default: return null; }");
assertEquals("42", se.evaluate(new Object[0]));
}
throws the following:
org.codehaus.commons.compiler.CompileException: Line 1, Column 7: Assignment conversion not possible from type "java.lang.String" to type "int"
at org.codehaus.janino.UnitCompiler.compileError(UnitCompiler.java:11523)
at org.codehaus.janino.UnitCompiler.assignmentConversion(UnitCompiler.java:10379)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:1881)
at org.codehaus.janino.UnitCompiler.access$2300(UnitCompiler.java:209)
at org.codehaus.janino.UnitCompiler$6.visitSwitchStatement(UnitCompiler.java:1451)
at org.codehaus.janino.UnitCompiler$6.visitSwitchStatement(UnitCompiler.java:1438)
at org.codehaus.janino.Java$SwitchStatement.accept(Java.java:3220)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:1438)
at org.codehaus.janino.UnitCompiler.compileStatements(UnitCompiler.java:1518)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:2950)
at org.codehaus.janino.UnitCompiler.compileDeclaredMethods(UnitCompiler.java:1308)
at org.codehaus.janino.UnitCompiler.compileDeclaredMethods(UnitCompiler.java:1281)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:780)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:431)
at org.codehaus.janino.UnitCompiler.access$400(UnitCompiler.java:209)
at org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:385)
at org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:380)
at org.codehaus.janino.Java$PackageMemberClassDeclaration.accept(Java.java:1405)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:380)
at org.codehaus.janino.UnitCompiler.compileUnit(UnitCompiler.java:354)
at org.codehaus.janino.SimpleCompiler.compileToClassLoader(SimpleCompiler.java:413)
at org.codehaus.janino.ClassBodyEvaluator.compileToClass(ClassBodyEvaluator.java:318)
at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:597)
at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:489)
at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:422)
at org.codehaus.janino.SimpleCompiler.cook(SimpleCompiler.java:200)
at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:76)
at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:71)
Whereas it works perfectly with a simple switch on int:
@Test
public void testSwitch() throws CompileException, InvocationTargetException {
ScriptEvaluator se = new ScriptEvaluator();
se.setReturnType(String.class);
se.cook("switch(1) { case 1: return \"42\"; default: return null; }");
assertEquals("42", se.evaluate(new Object[0]));
}
For information, I'm using the latest version of Janino:
<dependency>
<groupId>org.codehaus.janino</groupId>
<artifactId>janino</artifactId>
<version>3.0.6</version>
</dependency>
Am I doing something wrong?
Many thanks for your help!
Laurent
When a variable with "default" access modifier is accessed from outside the declaring file, we get this error.
It'd be clearer if the error message include the name of the field.
Caused by: org.codehaus.commons.compiler.CompileException: File 'Unknown', Line -1, Column -1: Member with "/*default*/" access cannot be accessed from type "com.exampl.MyApp"
at org.codehaus.janino.UnitCompiler.compileError(UnitCompiler.java:11004)
at org.codehaus.janino.UnitCompiler.checkAccessible(UnitCompiler.java:6464)
at org.codehaus.janino.UnitCompiler.checkAccessible(UnitCompiler.java:6440)
at org.codehaus.janino.UnitCompiler.compileGet2(UnitCompiler.java:3828)
at org.codehaus.janino.UnitCompiler.access$8800(UnitCompiler.java:206)
at org.codehaus.janino.UnitCompiler$12.visitFieldAccess(UnitCompiler.java:3793)
at org.codehaus.janino.UnitCompiler$12.visitFieldAccess(UnitCompiler.java:3762)
at org.codehaus.janino.Java$FieldAccess.accept(Java.java:3709)
at org.codehaus.janino.Java$Lvalue.accept(Java.java:3563)
at org.codehaus.janino.UnitCompiler.compileGet(UnitCompiler.java:3762)
at org.codehaus.janino.UnitCompiler.compileGet2(UnitCompiler.java:4270)
at org.codehaus.janino.UnitCompiler.access$8900(UnitCompiler.java:206)
at org.codehaus.janino.UnitCompiler$12.visitFieldAccessExpression(UnitCompiler.java:3794)
at org.codehaus.janino.UnitCompiler$12.visitFieldAccessExpression(UnitCompiler.java:3762)
at org.codehaus.janino.Java$FieldAccessExpression.accept(Java.java:3975)
at org.codehaus.janino.Java$Lvalue.accept(Java.java:3563)
at org.codehaus.janino.UnitCompiler.compileGet(UnitCompiler.java:3762)
at org.codehaus.janino.UnitCompiler.compileGetValue(UnitCompiler.java:4933)
at org.codehaus.janino.UnitCompiler.compileGet2(UnitCompiler.java:4476)
at org.codehaus.janino.UnitCompiler.access$7500(UnitCompiler.java:206)
at org.codehaus.janino.UnitCompiler$12.visitMethodInvocation(UnitCompiler.java:3774)
at org.codehaus.janino.UnitCompiler$12.visitMethodInvocation(UnitCompiler.java:3762)
at org.codehaus.janino.Java$MethodInvocation.accept(Java.java:4328)
at org.codehaus.janino.UnitCompiler.compileGet(UnitCompiler.java:3762)
at org.codehaus.janino.UnitCompiler.compileGetValue(UnitCompiler.java:4933)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:3180)
at org.codehaus.janino.UnitCompiler.access$5000(UnitCompiler.java:206)
at org.codehaus.janino.UnitCompiler$9.visitMethodInvocation(UnitCompiler.java:3151)
at org.codehaus.janino.UnitCompiler$9.visitMethodInvocation(UnitCompiler.java:3139)
at org.codehaus.janino.Java$MethodInvocation.accept(Java.java:4328)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:3139)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:2112)
at org.codehaus.janino.UnitCompiler.access$1700(UnitCompiler.java:206)
at org.codehaus.janino.UnitCompiler$6.visitExpressionStatement(UnitCompiler.java:1377)
at org.codehaus.janino.UnitCompiler$6.visitExpressionStatement(UnitCompiler.java:1370)
at org.codehaus.janino.Java$ExpressionStatement.accept(Java.java:2558)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:1370)
at org.codehaus.janino.UnitCompiler.compileStatements(UnitCompiler.java:1450)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:1436)
at org.codehaus.janino.UnitCompiler.access$1600(UnitCompiler.java:206)
at org.codehaus.janino.UnitCompiler$6.visitBlock(UnitCompiler.java:1376)
at org.codehaus.janino.UnitCompiler$6.visitBlock(UnitCompiler.java:1370)
at org.codehaus.janino.Java$Block.accept(Java.java:2471)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:1370)
at org.codehaus.janino.UnitCompiler.compileStatements(UnitCompiler.java:1450)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:1436)
at org.codehaus.janino.UnitCompiler.access$1600(UnitCompiler.java:206)
at org.codehaus.janino.UnitCompiler$6.visitBlock(UnitCompiler.java:1376)
at org.codehaus.janino.UnitCompiler$6.visitBlock(UnitCompiler.java:1370)
at org.codehaus.janino.Java$Block.accept(Java.java:2471)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:1370)
at org.codehaus.janino.UnitCompiler.compileStatements(UnitCompiler.java:1450)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:1436)
at org.codehaus.janino.UnitCompiler.access$1600(UnitCompiler.java:206)
at org.codehaus.janino.UnitCompiler$6.visitBlock(UnitCompiler.java:1376)
at org.codehaus.janino.UnitCompiler$6.visitBlock(UnitCompiler.java:1370)
at org.codehaus.janino.Java$Block.accept(Java.java:2471)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:1370)
at org.codehaus.janino.UnitCompiler.compileStatements(UnitCompiler.java:1450)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:2811)
at org.codehaus.janino.UnitCompiler.compileDeclaredMethods(UnitCompiler.java:1262)
at org.codehaus.janino.UnitCompiler.compileDeclaredMethods(UnitCompiler.java:1234)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:538)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:420)
at org.codehaus.janino.UnitCompiler.access$400(UnitCompiler.java:206)
at org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:374)
at org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:369)
at org.codehaus.janino.Java$AbstractPackageMemberClassDeclaration.accept(Java.java:1309)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:369)
at org.codehaus.janino.UnitCompiler.compileUnit(UnitCompiler.java:345)
at com.streambase.sb.codegen.JaninoCompiler.compile(JaninoCompiler.java:88)
at com.streambase.sb.codegen.CGCompiler.generateBinaryClasses(CGCompiler.java:201)
at com.streambase.sb.codegen.CompilationUnit.compile(CompilationUnit.java:176)
... 7 more
Thanks for your library!
Regarding security the documentation says:
JANINO has full access to the JRE, security problems can arise if the expression, script, class body or compilation being compiled and executed contains user input.
I can imagine that the input is very often a user input and then defaults should be something like 'let access only to helper classes', e.g. just allow mathematical operations, Math.* and a list of allowed classes.
The docs says that this can be fixed with de.unkrig.commons.lang.security.Sandboxcode. Wouldn't it make sense to provide this inbuilt maybe as the default option? Or with a simple config call
new ScriptEvaluator(restrictedEnvironment=true)
? Or how would I configure the sandbox for this very restricted environment? Is there some more documentation about this than the javadocs?
They reason I ask this is that I'm considering to include this library in a project (due to its simplicity) but have heard that e.g. ElasticSearch had lots of security problems due to its powerful scripting. So they moved from mvel to groovy and then finally moved to some handwritten expression library Painless with 'proper' security.
Hi,
I am getting an exception as
_Exception in thread "main" java.lang.ClassFormatError: Too many arguments in method signature in class file SC
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
at org.codehaus.janino.ByteArrayClassLoader.findClass(ByteArrayClassLoader.java:81)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
at org.codehaus.janino.ClassBodyEvaluator.compileToClass(ClassBodyEvaluator.java:319)
at org.codehaus.janino.ScriptEvaluator.cook2(ScriptEvaluator.java:609)
at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:598)
at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:534)
at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:503)
at org.codehaus.janino.SimpleCompiler.cook(SimpleCompiler.java:204)
at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:80)
at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:75)
at org.codehaus.janino.ScriptEvaluator.(ScriptEvaluator.java:165)
at ScriptComplier.main(ScriptComplier.java:23)
I am using scriptEvaluator(block,returntype,parametername,parametertype) to which I am passing two arrays parametername and parametertype both of the size 1000.And script String length 74324.
I have attached the sample code file. Please guide me on this. Is there any other way to achieve this
The javadocs say:
/**
* Same as {@link #cook(String)}, but for multiple scripts.
*/
But when I use the latest master and I do:
ExpressionEvaluator ee = new ExpressionEvaluator();
ee.setStaticMethod(false);//without this there is no error
ee.cook("9*3;7+1".split(";"));
I get
! java.lang.IllegalArgumentException: null
! at org.codehaus.janino.ScriptEvaluator.array(ScriptEvaluator.java:775)
! at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:550)
! at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:535)
! at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:500)
! at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:473)
! at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:466)
And how would I define a variable? The following does not work:
ee.cook("int tmp = 3;tmp*7+1".split(";"));
First and foremost, thanks a ton for Janino. I've been using it to run in-class examples for my introductory programming course and it's working brilliantly.
I'm confused, however, as to why the following works:
class Test {
private int value;
}
Test t = new Test();
t.value = 5;
System.out.println(t.value);
Is there a way to get the visibility modifiers to work in examples like this? Note that I'm currently disabling almost all permissions—with the exception of RuntimePermission("getProtectionDomain")
which I needed to enable to get class loading to work at all. Perhaps I'm disabling a permission that is causing this work work incorrectly?
FWIW, the code for Janini (my script runner web service) is available here.
This is the same as issue #6 in the old repository
When we pass the following code piece to Janino, Janino throws the following exception because the max height of Java operand stack for foo()
is more than 254.
This issue was revealed by the JIRA entry
Program
double test(double d0, double d1, ..., double d126) { return 1.0D; }
double foo() {
boolean b = false
double d = b ? 0.0D : test(0, 0, .... 0); // @kiszk corrected this line on July 1, 2016
return d;
}
Exception
org.codehaus.janino.JaninoRuntimeException: org.apache.spark.sql.catalyst.expressions.GeneratedClass$SpecificSafeProjection.apply(java.lang.Object _i): Operand stack overflow at offset ...
The example for using the ScriptEvaluator from the website:
ScriptEvaluator se = new ScriptEvaluator();
se.cook(
""
+ "static void method1() {\n"
+ " System.out.println(1);\n"
+ "}\n"
+ "\n"
+ "method1();\n"
+ "method2();\n"
+ "\n"
+ "static void method2() {\n"
+ " System.out.println(2);\n"
+ "}\n"
);
fails with the exception:
org.codehaus.commons.compiler.CompileException: Line 1, Column 7: Unexpected token "static" in primary
https://github.com/apache/drill/branches/1.14.0/exec/java-exec/src/main/java/org/apache/drill/exec/compile/bytecode/AloadPopRemover.java
correctly reports that Janino doesn't optimize this case:
localVariable.staticMethod();
The code generated by Janino retrieves the local variable value and immediately discards it.
Hello,
I'm in the context of a tomcat 6 webapp, using janino 3.0.7
My code is much like the documented code in the security section
What happens is a stackoverflow originated by
SecurityMamanger.checkRead calling the SandBox.checkPermission
In my case here is the loop created
SecurityMamanger.checkRead:888
code : checkPermission(new FilePermission(file,SecurityConstants.FILE_READ_ACTION));
SandBox$1.checkPermission:82
code : acc = Sandbox.CONFINED_CLASS_LOADERS.get(clasS.getClassLoader());
Class.getClassLoader:683
ClassLoader.checkClassLoaderPermission:1528
who again call : SandBox$1.checkPermission:82
And so we are from here stuck in a loop which lead to a S.O.
Dear Janino developers,
I am developing a free java program for life scientists and would be very interested in a fast java compiler like janino.
Some Java classes are quite big and take several seconds to compile with Oracle javac.
This makes code-editing / recompilation cumbersome. Therefore janino would help a lot.
For final compilation I would probably still trust Oracle Javac but for rapid error fixing and developing
I would prefer janino.
Unfortunately, janino does not compile many of my Java-files. I would need to change too many lines of code
for example explicit casting the results of Map#get and Collection#get.
Is there a chance to get these issues resolved in janino?
I guess, that there are only very few syntactical constructs which are not yet supported in janino.
Many thanks for developing this nice software
Cheers
Christoph
Is it possible to cook multiple strings using the Janino SimpleCompiler
? I tried something like this:
for (String source : sources) {
simpleCompiler.cook(new ByteArrayInputStream(source.getBytes(StandardCharsets.UTF_8)));
simpleCompiler.setParentClassLoader(simpleCompiler.getClassLoader());
}
This works fine as long as the dependencies are in the correct order, but fails if they are not. In contrast, feeding in one string with both class definitions works regardless of in which order the classes are defined.
An obvious approach is to try and concatenate the files together and feed them all in at once, but that fails if there are imports at the top of each class file.
Overall I'd like to be able to take a request containing multiple strings each containing a Java class file with imports, compile them all and then run something. It seems like Janino is really close to being able to do that...
Question like this https://stackoverflow.com/questions/9368764
Get Instrumentation is not easy, if janino can compile the code, is it possible to tell me the object memory size ?
After the recent addition of try-with-resources support, the newly added VariableAccessResource
seems to be suffering from some copy-and-paste error:
(from org.codehaus.janino.Java.TryStatement.VariableAccessResource#VariableAccessResource
)
/**
* @param modifiers Only {@code final} allowed
*/
public
VariableAccessResource(Location location, Rvalue variableAccess) {
super(location);
this.variableAccess = variableAccess;
}
I'm a newbie, I'd read the tutorial. I need on-memory compiling and run for heavy task.
so the function I need is, load source code as String java heap object, return java.lang.Class on memory.
I wrote the following code. but exception occured. and I don't know this method is suitable for performance. please help.
successException in thread "main"
java.lang.AbstractMethodError: junk.JaninoTest.task()D
at junk.Janino.main(Janino.java:38)
package junk;
import org.codehaus.commons.compiler.*;
import org.codehaus.janino.*;
public class Janino {
public static void main(String[] args) throws Exception {
String srcName = "junk.JaninoTest";
String crlf = System.lineSeparator();
SimpleCompiler sc = new SimpleCompiler();
sc.cook("package junk;" + crlf + "import junk.Janino.*;" + crlf
+ "public class JaninoTest implements TestI{" + crlf
+ "public double task(){" + "double r = 0;" + crlf
+ "for(double i=0;i<1000*1000*10;i++){" + crlf
+ "r += i*(i+r)/r%r*r;" + crlf
+ "if(Double.isNaN(r)){" + crlf
+ "r = 38297;" + crlf
+"}" + crlf
+ "}" + crlf + "return r;" + crlf
+ "}" + crlf + "}" + crlf);
sc.setCompileErrorHandler(new ErrorHandler() {
@Override
public void handleError(String message, Location optionalLocation)
throws CompileException {
System.out.println(message);
}
});
Class<?> clazz = sc.getClassLoader().loadClass(srcName);
Object o = clazz.getDeclaredConstructor().newInstance();
if (o instanceof TestI) {
System.out.println("success");
TestI t = (TestI) o;
//comparison of janino and jdk
long start = System.currentTimeMillis();
double d = t.task();
System.out.println(d);
System.out.println("by janino "+(System.currentTimeMillis() - start) + "ms");
start = System.currentTimeMillis();
d = task();
System.out.println(d);
System.out.println("by jdk "+(System.currentTimeMillis() - start) + "ms");
} else {
System.out.println("failure");
}
}
public static double task() {
double r = 0;
for (double i = 0; i < 1000 * 1000 * 10; i++) {
r += i * (i + r) / r % r * r;
if(Double.isNaN(r)){
r = 38297;
}
}
return r;
}
public interface TestI {
double task();
}
}
Hello,
Apache Drill widely uses Janino for code compilation, rewriting source code of user-defined functions to be able to use it in generated classes and for some other things.
The main modification which we are doing with user-defined functions is wrapping methods code into the block with the label and replacing all return statements in this method by break ones with mentioned above labels.
We use a class, extended from Unparser
for this goal, but some of its methods are private, and some of them call visitors.
It would be great if Unparser.unparseMethodDeclarator()
and Unparser.unparseStatements()
methods became protected and logic from Unparser.blockStatementUnparser.visitReturnStatement()
method is moved to protected method in Unparser
which will be called from Unparser.blockStatementUnparser.visitReturnStatement()
, so inheritors will be able to extend its logic (similar to the Unparser.blockStatementUnparser
).
Janino: 3.0.8
Java: 1.8
Currently unable to compile enums.
We're generating Java code and compiling it at runtime. Currently I'm unable to get Janino to compile enums generated. Nothing particularly special about the enums. The one thing I can think of is that we can have the same enum generated in different packages.
Example of actual enums that fail:
public enum Gender {
MALE,
FEMALE,
OTHER,
RATHER_NOT_SAY;
}
public enum HttpMethod {
GET,
PUT,
POST,
DELETE,
PATCH,
OPTIONS,
HEAD,
TRACE,
CONNECT;
}
For now, I'm going to swap out code gen of enums for ints but I'd like to use enums.
The compiler stacktrace is:
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.ClassFormatError: Duplicate field name "ENUM$VALUES" with signature "[Lcore.HttpMethod;" in class file core/HttpMethod
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1006)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:877)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:71)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:166)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:133)
at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:165)
at hypi.davil.AppSubmissionTest.emptyPostResultsInArror(AppSubmissionTest.java:65)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.ClassFormatError: Duplicate field name "ENUM$VALUES" with signature "[Lcore.HttpMethod;" in class file core/HttpMethod
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at org.codehaus.janino.JavaSourceClassLoader.defineBytecode(JavaSourceClassLoader.java:246)
at org.codehaus.janino.JavaSourceClassLoader.findClass(JavaSourceClassLoader.java:198)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at hypi.davil.gql.ModelCtx.lambda$compileJava$0(ModelCtx.java:119)
at java.util.HashMap$KeySet.forEach(HashMap.java:933)
at hypi.davil.gql.ModelCtx.compileJava(ModelCtx.java:117)
at hypi.davil.gql.ModelCtx.traverseModel(ModelCtx.java:86)
at hypi.davil.handlers.GQLHandler.graphql(GQLHandler.java:76)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
... 42 more
I will try to get some time soon to reproduce this in isolation and attach a a reproducer project if the above isn't enough to go on.
I get the feeling that enums are being shared somehow across the packages.
I'm finding the documentation on permissions hard to follow. Is it true that if I don't call setPermissions
then all permissions are enabled by default? If I call setPermissions
with a permission list, only those permissions are enabled. Is it possible to approach from the other angle and disallow certain permissions?
When I compiled the simple program using janinoc
with janino 3.0.7, I realized that the compiled java bytecode does not use sipush
java bytecode, but it uses ldc
java bytecode. While it functionally works correctly, the generated java bytecode consumes an additional constant pool entry.
When I compiled this program using javac
in OpenJDK8, the generated java bytecode uses sipush
.
public class CP2 {
static public void main(String[] argv) {
int i = 32767;
}
}
Classfile /home/ishizaki/Spark/PR/lsof/spark/CP2.class
Last modified Nov 24, 2017; size 263 bytes
MD5 checksum 8759300e8265dce5114c34a53ae853d0
Compiled from "CP2.java"
public class CP2
minor version: 0
major version: 49
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Utf8 CP2
#2 = Class #1 // CP2
#3 = Utf8 java/lang/Object
#4 = Class #3 // java/lang/Object
#5 = Utf8 SourceFile
#6 = Utf8 CP2.java
#7 = Utf8 main
#8 = Utf8 ([Ljava/lang/String;)V
#9 = Integer 32767
#10 = Utf8 LineNumberTable
#11 = Utf8 Code
#12 = Utf8 <init>
#13 = Utf8 ()V
#14 = NameAndType #12:#13 // "<init>":()V
#15 = Methodref #4.#14 // java/lang/Object."<init>":()V
{
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=2, args_size=1
0: ldc #9 // int 32767
2: istore_1
3: return
LineNumberTable:
line 3: 0
line 2: 3
public CP2();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #15 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 1: 0
}
Digging into this runtime error from a Logback configurator, I discovered that janino has an undeclared runtime dependency on de.unkrig.jdiasm:
java.lang.ClassNotFoundException: de.unkrig.jdisasm.Disassembler
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at org.codehaus.janino.UnitCompiler.disassembleToStdout(UnitCompiler.java:11913)
at org.codehaus.janino.UnitCompiler.addClassFile(UnitCompiler.java:847)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:841)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:431)
at org.codehaus.janino.UnitCompiler.access$400(UnitCompiler.java:209)
at org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:385)
at org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:380)
at org.codehaus.janino.Java$PackageMemberClassDeclaration.accept(Java.java:1405)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:380)
at org.codehaus.janino.UnitCompiler.compileUnit(UnitCompiler.java:354)
at org.codehaus.janino.SimpleCompiler.compileToClassLoader(SimpleCompiler.java:413)
at org.codehaus.janino.ClassBodyEvaluator.compileToClass(ClassBodyEvaluator.java:318)
at org.codehaus.janino.ClassBodyEvaluator.cook(ClassBodyEvaluator.java:235)
at org.codehaus.janino.SimpleCompiler.cook(SimpleCompiler.java:200)
at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:76)
at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:71)
at ch.qos.logback.core.joran.conditional.PropertyEvalScriptBuilder.build(PropertyEvalScriptBuilder.java:47)
at ch.qos.logback.core.joran.conditional.IfAction.begin(IfAction.java:65)
at ch.qos.logback.core.joran.spi.Interpreter.callBeginAction(Interpreter.java:269)
at ch.qos.logback.core.joran.spi.Interpreter.startElement(Interpreter.java:145)
at ch.qos.logback.core.joran.spi.Interpreter.startElement(Interpreter.java:128)
at ch.qos.logback.core.joran.spi.EventPlayer.play(EventPlayer.java:50)
at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:158)
at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:145)
at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:103)
at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:53)
at play.api.libs.logback.LogbackLoggerConfigurator.configure(LogbackLoggerConfigurator.scala:94)
Which is right there in the code but it's not in the pom:
Please add a runtime
dependency to your pom.xml to make this explicit so that it will show up properly in dependency management tools.
Should do a quick check to make sure janino will run on java 9
Hi,
The following exception is printed to the console when I execute a simple evaluation:
java.lang.ClassNotFoundException: de.unkrig.jdisasm.Disassembler
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at org.codehaus.janino.UnitCompiler.disassembleToStdout(UnitCompiler.java:11913)
at org.codehaus.janino.UnitCompiler.addClassFile(UnitCompiler.java:847)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:841)
at org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:431)
at org.codehaus.janino.UnitCompiler.access$400(UnitCompiler.java:209)
at org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:385)
at org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:380)
at org.codehaus.janino.Java$PackageMemberClassDeclaration.accept(Java.java:1405)
at org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:380)
at org.codehaus.janino.UnitCompiler.compileUnit(UnitCompiler.java:354)
at org.codehaus.janino.SimpleCompiler.compileToClassLoader(SimpleCompiler.java:413)
at org.codehaus.janino.ClassBodyEvaluator.compileToClass(ClassBodyEvaluator.java:318)
at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:597)
at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:489)
at org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:422)
at org.codehaus.janino.SimpleCompiler.cook(SimpleCompiler.java:200)
at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:76)
at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:71)
at com.ohua.engine.flowgraph.elements.operator.CallArrayConstruction$C
The code is not failing but I don't want this log output. It seems that the logger is per-default set to log level FINEST. Is that necessary?
JaninoRuntimeException: Code attribute in class "xxx" grows beyond 64 KB Fragment.
org.codehaus.commons.compiler.CompileException: File './target/1473454439101-0/test.java', Line 1078, Column 31: Assignment conversion not possible from type "java.lang.Object" to type "boolean"
the code line looks like:
this.boolean = method(someObject, someBoolean);
method signature is:
T method(Object obj, T someBool)
This is with janino 3.0.1
How should Janino be cited in an academic paper? Specifically, I need something to fill into the author field. Should I use "Janino Compiler Project"?
I am using Janino library to evaluate expressions fed by user dynamically. Sometimes values passed to expression can be null, while executing expression get following exception:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.janino.ScriptEvaluator.evaluate(ScriptEvaluator.java:929) at org.codehaus.janino.ScriptEvaluator.evaluate(ScriptEvaluator.java:349)
..
..
..
Caused by: java.lang.NullPointerException
at SC.eval0(Unknown Source)
... 9 more
Expression: (a != null && a.equals("MATCH"))?true:false
Wile executing sometimes values of a can be null, but expression doesn't get executed since a is null. How could we get this working?
I just discovered Janino's ability to use the built-in javax.tools
compiler. You have no idea how much time that has saved me—thanks so much for that. (And of course it exposes how much faster Janino is... wow.)
Are there plans to get this working with more recent versions of Java: 9 or 10? Note that I don't mean adding support for these new features to Janino's compiler—I understand how much work that would be. Hopefully supporting the javax.tools compiler would be simpler.
I accidentally experimented with this today as I had my IntelliJ configured to use Java 9. So I can confirm that it does not work. But the problem looked like it was asking the SimpleCompiler
class whether a given option was supported which triggered an exception that caused everything to fail. I can reproduce with more details if it's helpful. But I was wondering if just ignoring that option request or returning false
would allow things to move forward.
Anyway, thanks again for all of your hard work on this project. I have an unrelated question that I'll open separately.
17/04/06 17:04:55 WARN [org.apache.spark.sql.catalyst.expressions.codegen.CodeGenerator(87) -- main]: Error calculating stats of compiled class.
java.lang.IllegalArgumentException: Can not set final [B field org.codehaus.janino.util.ClassFile$CodeAttribute.code to org.codehaus.janino.util.ClassFile$CodeAttribute
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:55)
at sun.reflect.UnsafeQualifiedObjectFieldAccessorImpl.get(UnsafeQualifiedObjectFieldAccessorImpl.java:38)
at java.lang.reflect.Field.get(Field.java:379)
at org.apache.spark.sql.catalyst.expressions.codegen.CodeGenerator$$anonfun$recordCompilationStats$1$$anonfun$apply$4$$anonfun$apply$5.apply(CodeGenerator.scala:997)
at org.apache.spark.sql.catalyst.expressions.codegen.CodeGenerator$$anonfun$recordCompilationStats$1$$anonfun$apply$4$$anonfun$apply$5.apply(CodeGenerator.scala:984)
at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33)
at scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:186)
at org.apache.spark.sql.catalyst.expressions.codegen.CodeGenerator$$anonfun$recordCompilationStats$1$$anonfun$apply$4.apply(CodeGenerator.scala:984)
at org.apache.spark.sql.catalyst.expressions.codegen.CodeGenerator$$anonfun$recordCompilationStats$1$$anonfun$apply$4.apply(CodeGenerator.scala:983)
at scala.collection.Iterator$class.foreach(Iterator.scala:893)
at scala.collection.AbstractIterator.foreach(Iterator.scala:1336)
at scala.collection.IterableLike$class.foreach(IterableLike.scala:72)
Since v3.0.2., using of getLineNumber() ends up in compilation error:
Caused by: java.lang.NoSuchMethodError: org.codehaus.commons.compiler.Location.getLineNumber()S
I think, maybe the error occurs in Location.java:
...
public static final Location NOWHERE = new Location("<internally generated location>", **(short)** -1, **(short)** -1);
@Nullable private final String optionalFileName;
private final int lineNumber;
private final int columnNumber;
...
public
Location(@Nullable String optionalFileName, **int** lineNumber, **int** columnNumber) {
this.optionalFileName = optionalFileName;
this.lineNumber = lineNumber;
this.columnNumber = columnNumber;
}
Greetings,
Patrick
Hi,
I created a new language proposal at https://github.com/ONorg/Javon, which focusing on Context-sensitive and simple(maybe should say super simple:) syntax.
Is there of some interests from you?
Cheers
Lyrachord
I get the below exception very often, I am evaluating using janio for expression evaluation. I have expression like this ((5<=(264+(2.0*0.0)))), that needs to be evaluated, I am using janio within apache storm, where a bolt does the evaluation, I don't get this exception for every message, but it fail for a large number of message.
I don't see these exception when i try to debug with expression it failed for, looks like this happens when there are lot of thread running, like it always does with apache storm.
ee = new ExpressionEvaluator(); ee.cook("((5<=(264+(2.0*0.0))))"); passed = (boolean) ee.evaluate(null);
This is the piece of code with a bolt that does the evaluation, i pass null to evaluate because all the value in the expression are already there.
Any help on this, would be great.
"error": "org.codehaus.commons.compiler.CompileException: Line 1, Column 21: Assignment conversion not possible from type "java.lang.Boolean" to type "java.lang.Object"\n\tat org.codehaus.janino.UnitCompiler.compileError(UnitCompiler.java:10062)\n\tat org.codehaus.janino.UnitCompiler.assignmentConversion(UnitCompiler.java:8988)\n\tat org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:1903)\n\tat org.codehaus.janino.UnitCompiler.access$2100(UnitCompiler.java:182)\n\tat org.codehaus.janino.UnitCompiler$4.visitReturnStatement(UnitCompiler.java:946)\n\tat org.codehaus.janino.Java$ReturnStatement.accept(Java.java:2541)\n\tat org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:958)\n\tat org.codehaus.janino.UnitCompiler.compileStatements(UnitCompiler.java:999)\n\tat org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:2284)\n\tat org.codehaus.janino.UnitCompiler.compileDeclaredMethods(UnitCompiler.java:822)\n\tat org.codehaus.janino.UnitCompiler.compileDeclaredMethods(UnitCompiler.java:794)\n\tat org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:504)\n\tat org.codehaus.janino.UnitCompiler.compile2(UnitCompiler.java:390)\n\tat org.codehaus.janino.UnitCompiler.access$400(UnitCompiler.java:182)\n\tat org.codehaus.janino.UnitCompiler$2.visitPackageMemberClassDeclaration(UnitCompiler.java:344)\n\tat org.codehaus.janino.Java$PackageMemberClassDeclaration.accept(Java.java:1136)\n\tat org.codehaus.janino.UnitCompiler.compile(UnitCompiler.java:351)\n\tat org.codehaus.janino.UnitCompiler.compileUnit(UnitCompiler.java:319)\n\tat org.codehaus.janino.SimpleCompiler.compileToClassLoader(SimpleCompiler.java:358)\n\tat org.codehaus.janino.ClassBodyEvaluator.compileToClass(ClassBodyEvaluator.java:315)\n\tat org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:573)\n\tat org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:471)\n\tat org.codehaus.janino.ScriptEvaluator.cook(ScriptEvaluator.java:383)\n\tat org.codehaus.janino.SimpleCompiler.cook(SimpleCompiler.java:192)\n\tat org.codehaus.commons.compiler.Cookable.cook(Cookable.java:84)\n\tat org.codehaus.commons.compiler.Cookable.cook(Cookable.java:77)\n\tat com.tgt.wlm.workgen.bolts.RuleEvaluatorBolt.evaluateEpressionsFast(RuleEvaluatorBolt.java:75)\n\tat com.tgt.wlm.workgen.bolts.RuleEvaluatorBolt.execute(RuleEvaluatorBolt.java:53)\n\tat org.apache.storm.daemon.executor$fn__7953$tuple_action_fn__7955.invoke(executor.clj:728)\n\tat org.apache.storm.daemon.executor$mk_task_receiver$fn__7874.invoke(executor.clj:461)\n\tat org.apache.storm.disruptor$clojure_handler$reify__7390.onEvent(disruptor.clj:40)\n\tat org.apache.storm.utils.DisruptorQueue.consumeBatchToCursor(DisruptorQueue.java:439)\n\tat org.apache.storm.utils.DisruptorQueue.consumeBatchWhenAvailable(DisruptorQueue.java:418)\n\tat org.apache.storm.disruptor$consume_batch_when_available.invoke(disruptor.clj:73)\n\tat org.apache.storm.daemon.executor$fn__7953$fn__7966$fn__8019.invoke(executor.clj:847)\n\tat org.apache.storm.util$async_loop$fn__625.invoke(util.clj:484)\n\tat clojure.lang.AFn.run(AFn.java:22)\n\tat java.lang.Thread.run(Thread.java:745)\n"
Not sure of the exact problem and it's difficult to post an example unfortunately, but I can try if this is an unknown issue. I seem to be getting a compile error when trying to reference a class that is full of static items. The import is correct but the compiler says it's an error.
The class being references is like this:
public class MyStaticClass {
public static final SomeOtherClass ITEM1;
static {
ITEM1 = new SomeOtherClass("abc");
}
}
Then I reference that static item from my code that I am loading with SimpleCompiler:
public void someMethod() {
SomeOtherClass c1 = MyStaticClass.ITEM1;
}
Error text just points to the line number and position in someMethod().
I apologize for the lack of actual code example but let me know if this is not a known issue and i'll try to provide more information. The actual error is being caused within a Minecraft mod and their code undergoes deobfuscation etc. so a bit hard to provide an example.
java.lang.StackOverflowError
at org.codehaus.janino.Java$NormalAnnotation.setEnclosingScope(Java.java:389)
at org.codehaus.janino.Java$NormalAnnotation.setEnclosingScope(Java.java:389)
at org.codehaus.janino.Java$NormalAnnotation.setEnclosingScope(Java.java:389)
at org.codehaus.janino.Java$NormalAnnotation.setEnclosingScope(Java.java:389)
at org.codehaus.janino.Java$NormalAnnotation.setEnclosingScope(Java.java:389)
looking at the code, it looks like a infinite loop:
@Override public void
setEnclosingScope(Scope enclosingScope) { this.setEnclosingScope(enclosingScope); }
Findbugs would complain about it....
I am using janino 2.7.8
Please create/add tags for downloadable source tarballs/zipfiles under releases. Thank you!
can i separate the compile and load, and get the bytecode after compile process?
I use a Oracle JDK compile the Java source(the code size 2000 rows), and find it excute faster than Janino . (may be fast 60 s) , does Janino has limit on the size of Java source? thanks.
First and foremost, Janino is really cool. I'm using it for in-class in-browser examples for an intro programming class and it's a lot of fun.
That said, the following doesn't seem to work properly:
int i;
System.out.println(i);
I suppose it is up to the compiler to initialize uninitialized values appropriately, and apparently Janino decides to fail rather than follow the common behavior of setting i to zero. But it would be nice if it matched the behavior of more standard (and slower) compilers.
In order to analyse user generated code, some additional accessors would be helpful.
I would like to check method usage through ConstantMethodrefInfo but the data I need is not publicly exposed:
Is this deliberate? Would it be possible to add more getters?
Excuse me, where can I find the test code? It seems different with other open source projects which have lots of unit tests.
I'm on 3.0.8. Compiling a small JPA class file with three annotations fails:
@Id
@GeneratedValue(strategy=IDENTITY)
@Column(nullable=false)
private java.lang.Integer id;
If I remove the @GeneratedValue
annotation, everything works fine.
The input code compiles with JDK7-8.
Error:
Exception in thread "main" java.lang.StackOverflowError
at org.codehaus.janino.UnitCompiler.reclassifyName(UnitCompiler.java:8222)
at org.codehaus.janino.UnitCompiler.reclassifyName(UnitCompiler.java:8119)
at org.codehaus.janino.UnitCompiler.reclassify(UnitCompiler.java:7986)
at org.codehaus.janino.UnitCompiler.access$1000(UnitCompiler.java:212)
at org.codehaus.janino.UnitCompiler$22$2.visitRvalue(UnitCompiler.java:8058)
at org.codehaus.janino.Java$Rvalue.accept(Java.java:3855)
at org.codehaus.janino.UnitCompiler$22.toObject(UnitCompiler.java:8051)
at org.codehaus.janino.UnitCompiler$22.toIAnnotation(UnitCompiler.java:8027)
at org.codehaus.janino.UnitCompiler$22.visitNormalAnnotation(UnitCompiler.java:8019)
at org.codehaus.janino.UnitCompiler$22.visitNormalAnnotation(UnitCompiler.java:8002)
at org.codehaus.janino.Java$NormalAnnotation.accept(Java.java:477)
at org.codehaus.janino.UnitCompiler.toIAnnotation(UnitCompiler.java:8001)
at org.codehaus.janino.UnitCompiler.toIAnnotations(UnitCompiler.java:7993)
at org.codehaus.janino.UnitCompiler.compileField(UnitCompiler.java:7895)
at org.codehaus.janino.UnitCompiler.compileFields(UnitCompiler.java:7860)
at org.codehaus.janino.UnitCompiler.access$17600(UnitCompiler.java:212)
at org.codehaus.janino.UnitCompiler$30.getDeclaredIFields2(UnitCompiler.java:9532)
at org.codehaus.janino.IClass.getDeclaredIFieldsCache(IClass.java:345)
at org.codehaus.janino.IClass.getDeclaredIField(IClass.java:358)
at org.codehaus.janino.UnitCompiler.findIField(UnitCompiler.java:11725)
at org.codehaus.janino.UnitCompiler.reclassifyName(UnitCompiler.java:8321)
at org.codehaus.janino.UnitCompiler.reclassifyName(UnitCompiler.java:8119)
at org.codehaus.janino.UnitCompiler.reclassify(UnitCompiler.java:7986)
at org.codehaus.janino.UnitCompiler.access$1000(UnitCompiler.java:212)
at org.codehaus.janino.UnitCompiler$22$2.visitRvalue(UnitCompiler.java:8058)
at org.codehaus.janino.Java$Rvalue.accept(Java.java:3855)
at org.codehaus.janino.UnitCompiler$22.toObject(UnitCompiler.java:8051)
at org.codehaus.janino.UnitCompiler$22.toIAnnotation(UnitCompiler.java:8027)
at org.codehaus.janino.UnitCompiler$22.visitNormalAnnotation(UnitCompiler.java:8019)
at org.codehaus.janino.UnitCompiler$22.visitNormalAnnotation(UnitCompiler.java:8002)
at org.codehaus.janino.Java$NormalAnnotation.accept(Java.java:477)
. . .
Another question: Are there any build instructions for Janino and the commons-compiler jars?
Janino trips over when compiling a negation on minimal values of int
and long
. e.g. for the following code snippet:
long value = -(-9223372036854775808L);
Janino would throw an exception saying Invalid integer literal "9223372036854775808L"
, while javac compiles it fine.
This code causes an error in Janino v3.0.6 when running on Google AppEngine (although not in their development server):
import java.util.Scanner;
public class T1
{
public static void main(String[] args)
{
Scanner scnr = new Scanner(System.in);
}
}
The error is this:
Compiling "T1": "findIClass()" returned "Lcom/google/apphosting/runtime/security/shared/stub/java/nio/file/Path;" instead of "Ljava/nio/file/Path;"
The source seems to be this code in org.codehaus.janino.IClassLoader
(lines 305-313):
if (!result.getDescriptor().equalsIgnoreCase(fieldDescriptor)) {
throw new JaninoRuntimeException(
"\"findIClass()\" returned \""
+ result.getDescriptor()
+ "\" instead of \""
+ fieldDescriptor
+ "\""
);
}
Would it be possible to have some kind of compile-time or run-time switch that would go around this code when compiling for, or running in, Google App Engine?
Thanks,
Jon
Here is the scope:
(org.codehaus.janino.Java$FieldDeclaration) public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{"type":"enum","name":"requiredEnum","namespace":"test","symbols":["a","b"]}");
I am not sure what Janino does not like here...
This problem was originally reported by Matthias Boehm from IBM:
We recently ran into race conditions of multi-threaded
compilation and loading of classes with the same class name. We fixed it
by simply synchronizing the code path for code generation in Spark
executors. However, it might be an indicator of unwanted side effects
because the APIs of isolated SimpleCompilerinstances would suggest
thread-safeness. The intermittent failures we got were puzzling as the
related code works just fine:
- Operand stack underrun at offset 91
- No applicable constructor/method found for actual parameters
- Binary numeric promotion not possible on types "java.lang.Object" and
"double"
There's a pattern of integer overflow issues in the ClassFile
read path.
/**
* u2 attributes_count, attributes[attributes_count]
*/
private List<AttributeInfo>
loadAttributes(DataInputStream dis) throws IOException {
short attributesCount = dis.readShort();
List<AttributeInfo> attributes = new ArrayList<AttributeInfo>(attributesCount);
for (int i = 0; i < attributesCount; ++i) attributes.add(this.loadAttribute(dis));
return attributes;
}
The Class file format says the attribute_count is a u2
, but it's read here with dis.readShort()
so that's reading as a signed short
.
In some Class files that Spark generates, various sizes/counts can be really big, above the signed ranges of the corresponding integer types, so when Janino reads in such files, they're subject to weird exceptions like:
java.io.EOFException
at java.io.DataInputStream.readFully(DataInputStream.java:197)
at java.io.DataInputStream.readFully(DataInputStream.java:169)
at org.codehaus.janino.util.ClassFile.loadAttribute(ClassFile.java:1808)
at org.codehaus.janino.util.ClassFile.loadAttributes(ClassFile.java:698)
at org.codehaus.janino.util.ClassFile.loadFields(ClassFile.java:673)
at org.codehaus.janino.util.ClassFile.<init>(ClassFile.java:299)
at org.apache.spark.sql.catalyst.expressions.codegen.CodeGenerator$$anonfun$29.apply(CodeGenerator.scala:1674)
...
In one such cases, the constant pool had a lot of entries:
...
#49449 = Utf8 <init>
#49450 = Utf8 (Lorg/apache/spark/sql/catalyst/expressions/GeneratedClass$SpecificMutableProjection;)V
#49451 = Utf8 ()V
#49452 = NameAndType #49449:#49451 // "<init>":()V
#49453 = Methodref #4.#49452 // java/lang/Object."<init>":()V
{
(short)49453
interpreted as a signed short is -16083
, which probably overflows the following code:
https://github.com/janino-compiler/janino/blob/master/janino/src/main/java/org/codehaus/janino/util/ClassFile.java#L664
short constantPoolCount = dis.readShort(); // constant_pool_count
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.