Dynamic code execution - java

Similar to dynamic SQL, wherein a String is executed as an SQL at runtime, can we have Java code run dynamically? Like I return a String which is a Java code and then I execute at runtime. Is this possible?

For real Java code, this is possible using the JavaCompiler interface. However, it's very inconvenient to use since it's just an interface to a real Java compiler that expects to compile entire class definitions found in files.
The easiest way to execute code supplied at runtime would be to use the Rhino JavaScript engine.
Both of these options have been only in Java 6, though I believe the scripting interface existed before, so you could use Rhino in an earlier JRE if you download and add it to the classpath.

Javassist
You would need to use a bytecode manipulation library such as Javassist (Wikipedia), in order to run an arbitrary string that is provided at runtime. Javassist allows you to create a CtClass based on a string representing source code; and can then turn this into compiled Class object via a particular classloader, so that the class is then available to your application. Other libraries would need to do something similar to these two steps in order to achieve the same thing.
So it is possible, but it's very heavyweight and is likely to make your application very hard to reason about. If at all possible, consider designing a very flexible class statically, and having it accept parameters that control its behaviour.

If you want to do more than invoke an existing method dynamically, you may need to compile your String into bytecode. An easy way to do this is to include the Eclipse/JDT compiler jar in your classpath, and then you can use that to compile your String into a Class, which can then be loaded.
This type of dynamic code generation and execution is used to convert JSP files into Servlets and is used in other packages such as JasperReports to turn a report specification into a Class that is then invoked.
Remember that just as with SQL you must be careful to prevent code injection security problems if any of the String contains user-specified data.

You also may want to look at Java 6 scripting support:
http://download.oracle.com/javase/6/docs/technotes/guides/scripting/programmer_guide/index.htm
Here is a version of hello world that creates array of strings and prints a first one:
import javax.script.*;
public class EvalScript {
public static void main(String[] args) throws Exception {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
engine.eval("var a=java.lang.reflect.Array.newInstance(java.lang.String, 1);a[0]='Hello World';print(a[0])");
}
}

Yes it is possible. Look at the Java Compiler API. Have a look here:
http://download.oracle.com/javase/6/docs/api/javax/tools/JavaCompiler.html

Have a look at Beanshell. It provides an interpreter with java like syntax.

Related

Java: runtime reflection or type introspection?

Is the following code considered to be runtime reflection or is it type introspection?
Class c = java.util.ArrayList.class;
String className = c.getName();
I want to use this in the compilation phase, and do not want to use any resources (including time) in runtime. Does it use any runtime resource?
It is both, as #StephenC already points out correctly.
To your request for a compile-time solution: There is a solution, but you'd need to implement your own Builder for that.
First off, some standard-Java implementations:
Because implementing and including your own Builder might be a lot of work for very little effect, here's a much easier answer: class initialization.
public class CompileTimeInit {
// option 1
static public final String ARRAYLIST_CLASS_NAME = java.util.ArrayList.class.getName();
// option 2
static public final String ARRAYLIST_CLASS_NAME_INIT_BLOCK;
static {
ARRAYLIST_CLASS_NAME_INIT_BLOCK = java.util.ArrayList.class.getName();
}
public static void main(final String[] args) {
System.out.println("1:\t" + ARRAYLIST_CLASS_NAME);
System.out.println("2:\t" + ARRAYLIST_CLASS_NAME_INIT_BLOCK);
// option 3
final Class c = java.util.ArrayList.class;
final String className = c.getName();
System.out.println("3:\t" + className);
}
}
static initialization will take its (very minimal) time in class intialization. This is part of the runtime, but it will only take place once a class is referenced/metnioned in some code that gets executed. This initialization will only be done once (per classloader loaded class) and is considered really fast.
Now, to the real compile-time implementations:
You can have really advanced builders implemented, like Project Lombok does, along with integration into IDEs, compilers, build tools, platforms. Check out their page, top menu, "Install", to see the options available.
You can write your own builder and include it into the build cycle of your build cycle. The best way to do it is via an Annotaion "Pre"-Processor.
The third option is to write a complete standalone application. This means you have to implement:
opening .java source files
scanning for your Interfaces or Annotations
replacing the code with the calculated contents
saving .java source files
let the compilation phase continue
and include that into you build cycle. This is also partially described in the article above
I would have said that it is BOTH runtime reflection AND type introspection.
Note that the [introspection] tag defines introspection as:
"A capability of some object-oriented programming languages to determine the type of an object at runtime."
You could also say that your example uses (runtime) reflection to perform type introspection.
I want to use this in the compilation phase.
It is possible to examine types at compile time in an annotation processor. However, I suspect that the effort involved in doing that would be prohibitive. You need to be able to spot a specific pattern in two statements and then replace the statements with something else.
(Have you benchmarked the class name lookup to see how much time it actually takes? I would have thought it was just a few nanoseconds. Not enough to be significant.)

Can I convert a string to a java code [duplicate]

Similar to dynamic SQL, wherein a String is executed as an SQL at runtime, can we have Java code run dynamically? Like I return a String which is a Java code and then I execute at runtime. Is this possible?
For real Java code, this is possible using the JavaCompiler interface. However, it's very inconvenient to use since it's just an interface to a real Java compiler that expects to compile entire class definitions found in files.
The easiest way to execute code supplied at runtime would be to use the Rhino JavaScript engine.
Both of these options have been only in Java 6, though I believe the scripting interface existed before, so you could use Rhino in an earlier JRE if you download and add it to the classpath.
Javassist
You would need to use a bytecode manipulation library such as Javassist (Wikipedia), in order to run an arbitrary string that is provided at runtime. Javassist allows you to create a CtClass based on a string representing source code; and can then turn this into compiled Class object via a particular classloader, so that the class is then available to your application. Other libraries would need to do something similar to these two steps in order to achieve the same thing.
So it is possible, but it's very heavyweight and is likely to make your application very hard to reason about. If at all possible, consider designing a very flexible class statically, and having it accept parameters that control its behaviour.
If you want to do more than invoke an existing method dynamically, you may need to compile your String into bytecode. An easy way to do this is to include the Eclipse/JDT compiler jar in your classpath, and then you can use that to compile your String into a Class, which can then be loaded.
This type of dynamic code generation and execution is used to convert JSP files into Servlets and is used in other packages such as JasperReports to turn a report specification into a Class that is then invoked.
Remember that just as with SQL you must be careful to prevent code injection security problems if any of the String contains user-specified data.
You also may want to look at Java 6 scripting support:
http://download.oracle.com/javase/6/docs/technotes/guides/scripting/programmer_guide/index.htm
Here is a version of hello world that creates array of strings and prints a first one:
import javax.script.*;
public class EvalScript {
public static void main(String[] args) throws Exception {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
engine.eval("var a=java.lang.reflect.Array.newInstance(java.lang.String, 1);a[0]='Hello World';print(a[0])");
}
}
Yes it is possible. Look at the Java Compiler API. Have a look here:
http://download.oracle.com/javase/6/docs/api/javax/tools/JavaCompiler.html
Have a look at Beanshell. It provides an interpreter with java like syntax.

Can reflection bind a class to a new name?

I am trying to let users of my program rename classes and methods in the class. The new names can be read in and configured at run time and they will call these classes and methods in a scripting language using Java Script Engine. I need a way to bind their new names to the real names of the classes and methods. I have been looking at Reflection but I do not think this can provide me with the capability I need, or is this even possible?
Ex:
public class RealName {
public void printHello() {
System.out.println("Hello");
}
}
Then in maybe Paython say
obj = new NewName()
obj.hello()
Tell me if this is impossible please!
You can not change the method names, but you can bind an instance of an object to a given name and inject that into the context of the scripting language.
This would only work for that instance of the class, not for instantiating new instances.
If you really want this you may be able to generate sub classes with the new name and method names in the target scripting language and inject them into to the context to get the effect you are looking for.
Having said all that I can't really come up with a good reason to do any of this.
To answer my question from what I've found no you cannot use reflection to bind a class to a new name. In fact I found no easy way to do dynamic renaming.
What I did to overcome this was to write code from a string to a file, save that file with extension .java, compile that file, then use it with reflection or better yet use it inside a script using the Java ScriptEngine API (that way you can avoid the ugly reflection code and actually have everything dynamic and on the fly).
Here's a starting point for creating the file,
Dynamic in-memory compilation
And here's something for scripting Java,
Scripting for Java

Any risk using a single dollar sign `$` as a java class name?

Originally I was using the underscore _ as a class name. The new Java8 compiler complains that it "might not be supported after Java SE 8". I changed that to $, and there is no warning any more. However I remember that $ is used by Java to indicate an inner/embedded class in the byte code. I am wondering if there is any risk to use a dollar sign $ as a class name
Some background to this question. What I want to do is to overcome the fact that Java doesn't support pure function, and the _ or $ is to put an namespace to encapsulate some very generic concept (classes/static methods). and neither do I have a good name for this, nor do I want the lib user type too many things to reference that namespace. Here is the code showing what I am doing under the way: https://github.com/greenlaw110/java-tool/blob/master/src/main/java/org/osgl/_.java
It is bad style, and potentially risky to use $ in any identifier in Java. The reason it is risky is that the $ character is reserved for the use of the Java toolchain and third-party language tools.
It is used by Java compilers in "internal" class names for inner and nested classes.
It is used by Java compilers in the names of synthetic attributes.
It could be used by third-party code generators (e.g. annotation processors) for various purposes.
It could be used by other languages that target the JVM platform, and that might need to co-exist with your code.
You probably won't have technical issues with a plain $ classname at the moment (at least with respect to the standard Java toolchain). But there's always the possibility that this will change in the future:
They have (effectively) reserved the right to change this1.
There is a precedent for doing this in the _ example.
If you really, really need a one-character classname, it would be better to play it safe and use F or Z or something else that isn't reserved.
But to be honest, I think you'd be better off trying to implement (or just use) a real functional language than trying to shoe-horn a functional programming "system" into Java. Or maybe, just switch to Java 8 ahead of its official release. 'Cos I for one would refuse to read / maintain a Java codebase that looked like jquery.
I don't mean to create a functional lib for Java, just want to create a lib to maintain some common utilities I used. Again, I am a advocate of minimalism and feel suck with things like apache commons. The functional stuff is added to help me easier to manipulate collection(s).
If it is your code, you can do what you like. Make your own decisions. Act on your opinions. Be a "risk taker" ... :-). (Our advice on $, etcetera ... is moot.)
But if you are writing this code for a client or employer, or with the intention of creating a (viable) open source product, then you need to take account of other people's opinion. For example, your boss needs to have an informed opinion on how maintainable your code will be if you find a better paying job somewhere else. In general, will the next guy be able to figure it out, keep your code, fresh, etc ... or will it be consigned to the dustbin?
1 - JLS ยง3.8 states "The $ character should be used only in mechanically generated source code". That is saying "use it at your peril". The assumption is that folks who build their own source code generators can change them if the standard toolchain uses a bare $ ... but it is harder to change lots of hand written code, and that would be an impediment to upgrading.
Huh, you're right, using a $ in a classname works. Eclipse complains that it is against convention, but, if you are sure, you can do it.
The problem (conventionally) with using a $ is that the $ is used in the class hierarchy to indicate nested classes.... for example, the file A.java containing:
class A {
class SubA {
}
}
would get compiled to two files:
A.class
A$SubA.class
Which is why, even though $ works, it is ill advised because parsing the jars may be more difficult... and you run the risk of colliding two classes and causing other issues
EDIT, I have just done a test with the following two Java files (in the default package)
public class A {
private static final class SubA {
public String toString() {
return "I am initializing Nested SUBA";
}
}
private static final SubA sub = new SubA();
public A() {
System.out.println("What is " + sub.toString());
}
}
public class A$SubA {
#Override
public String toString() {
return "I am A$SubA";
}
}
public class MyMain {
public static void main(String[] args) {
System.out.println(new A());
System.out.println(new A$SubA());
}
}
And the code will not compile.....
Two problems, type A$SubA is already defined, and can't reference a nested class A$SubA by it's binary name.
Yes, to be pedantic about answering your question there is a risk. As some other folks have mentioned, it violates java naming conventions. So the risk is that with future versions of the JDK this may cause problems. But beyond that, and some issues if you try to use nested classes you should be fine.
I think you're trying to avoid ugly names like Util.andThen. Consider using static imports. That lets you import all the methods in the header import static org.ogsl.Util.*, so then you can simply use you andThen without any prefix at all.
The Selenide project does it. Just look at the top of this documentation:
https://selenide.org/documentation.html
Maybe it is a more acceptable thing to do only in test code.
API ref:
https://selenide.org/javadoc/current/com/codeborne/selenide/Selenide.html

Java: Static string localization

Are there any tool that will compile a java .properties file to a class which I can use in Java EE (tomcat) application? Similar to android where the eclipse plugin produces a static R.strings class.
I found this article:
http://www.techhui.com/profiles/blogs/localization-in-gwt-using
But it is dependant on GWT. Any help appreciated.
I have never heard about such tool. GWT has a great deferred-binding based technique but it is not the thing you are looking for. However I think it is possible to implement a basic code generator for such tasks.
But the answer to your question is: as far as I know there isn't.
To internationalize applications I implemented a Message Compiler, which creates the resource bundle files and constant definitions as Java enums or static final strings for the keys from one single source file. So the constants can be used in the Java source code, which is a much safer way than to use plain strings. In this case you also get a compile time error, when you use a key constant, that doesn't exist. The message compiler cannot only be used for Java. It creates also resource files and constants for Objective-C or Swift and can be extended for other programming environments.
What about ResourceBundle?
// refers to "src/config.properties"
ResourceBundle config = ResourceBundle.getBundle("config");
String property1 = config.getString("property1");
I think one could write a very simple grammar for properties files using ANTLR in a custom a maven plugin (or Ant task) that just generates the Java source before the compilation step.
How about storing your properties in a JSON file. The JSON object stored in the file should map to a Java class, use Jackson mapper to deserialize. With Jackson you can enforce that all fields must be non-null on deserialize.
You can also use GSON and write a custom deserializer that performs checks as strict as you want them. Example - you can enforce not null along with not empty for strings.
Compiler Assisted Localization (CAL10N) is not exactly what you asked, but may be of help.
Although it does not generate Java classes from .properties, using enums as message keys is still better than strings, as you get some help from the compiler.
Declare a enum, bind it to .properties with annotation and use enum values in message lookups. I have not tried it yet, though. See manual.

Categories

Resources