I want to have one feature of Java 8 for Java 7: automatic interface implementation generation for method (to avoid performace deficiency due to reflection calls). I know that Java 8 provide the generation at compile time but I think it's not possible for Java 7 (without maintainance of metadata files). So I agree with implementation generation at runtime.
Example:
I have following interface:
public interface Extractor<E> {
public Object getProperty(E aSourceObject);
}
And a bean class (or interface)
public class Foo {
public int getProperty1();
public String getProperty2();
public boolean getProperty3();
}
I need for each property of Foo an implementation of Extractor interface. Something like Foo::getProperty1 for Java 8.
public class Foo1Extractor implements Extractor<Foo> {
public Object getProperty(Foo anObject) {
return anObject.getProperty1();
}
}
Should I use JavaCompiler (currently I have few interfaces to implement and can work with template classes) or you have better solutions?
The main requirement is the short bytecode generation time and LGPL compatibility (can be used in commercial product).
If possible, provide a little example for my case.
You may not see visible performance improvement if you replace reflection with generated classes unless your application is performing millions operation per second. Also the complexity of adding the dynamic code generation to the project (both in runtime and compile time) are quite high. So I'd recommend to go for it only if reflection is proved to be the real bottleneck.
Anyway, for the code generation in compile time in JDK 7 you can the use the annotation processing API, which is basically a plugin API for javac that you can combine it with some sort of template engine. Have a look at this project which uses the power of the annotation processing for doing quite good stuff.
Related
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.)
We have a small lightweight framework with around 20 classes, used by 50+ developers and semi-large code base. To keep the framework small, we've avoided creating too many interfaces, abstract classes, etc. This is a trade-off to speed up adaptation by new developers as well as keep code complexity low.
So we do not utilize internal/external interfaces or heavy use of factory classes. We rely on a few classes with public/private methods to define scope. However sometimes methods have to be public but only be accessible to the framework and not the developer.
Example:
public class Logger
public boolean isDebugEnabled() {...}
public void enableDebug() {...}
enableDebug is an "internal" framework method and is documented with "Do not use - Internal class". The method cannot be private nor at package scope due to framework structure.
Once in a while a developer will miss the javadoc and invoke an internal method which can produce unexpected results at runtime.
Example:
if (!Logger.isDebugEnabled) {
Logger.enableDebug(); // screw the javadoc - i'm enabling debug logging
}
The framework team is thinking the best approach is to name them following a certain convention. This will not introduce compile-time safety, but decrease error probability.
Example:
public void enableDebugInternal() or _enableDebug() or $enableDebug()
is more precise than
/**
* Internal method - do not use
*/
public void enableDebug()
Another option they are thinking is to wrap all internal methods into an internal class:
public class Logger
public boolean isDebugEnabled() {...}
public class Internal {
public void enableDebug() {...}
}
Can you recommend a better approach ?
Preferably something that provides compile-time safety
EDIT: Turns out what I am looking for is a design pattern for the keyword "internal" for C# in java:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/accessibility-levels
Well, you pretty much answered your own question. You can't change the access level, so you'll pretty much have to change the name of it. A bit hacky, but you could also deprecate the method. Hamcrest does something... err... interesting... with the Matcher interface to this effect.
If you want to enforce that it's not used outside of the package then you'll need to do some kind of static analysis as part of your build. If I had no other choice, I'd write a Maven plugin to look for usages.
Ultimately, it sounds like your design is wrong if you have a public method that needs to act as if it were package-private.
You shouldn't be writing your own logging facade anyway, especially if you're writing a framework. You should be using SLF4J.
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.
My problem is that I am trying to interop with a Java app whose jar file contains obfuscated byte code. The app releases updates ever month or so, and when they do a release, most of the class and method names change.
Thus, the method proposed here:
http://rickyclarkson.blogspot.com/2006/07/duck-typing-in-java-and-no-reflection.html
or
Simulating duck typing in Java
won't work in my solution because because I would have to update the interfaces by hand each time.
What I do have however is an automatically generated (for the most part) mapping from deobfuscated class name <-> obfuscated class name by means of parsing the class files for calls to debug logging calls in the form of:
logger.log(severity, "ClassName", "MethodName() has some error")
What I generate is something like this:
public final static String MyRealName = "someObfuscatedName".
public final static String MyRealName_myCoolMethod = "someMethodName".
I have a fairly decent solution for interacting with objects of "myRealName" via the reflection API and simply proxy objects that implement a subset of functionality of the object it is proxying. Somewhat like this:
class MyRealName {
private Object backingObject;
public MyRealName(Object o) { backingObject = o;}
public void myCoolMethod() {
return getFieldValue(backingObject
, DeobNames.MyRealName_myCoolMethod);
}
}
However, the problem arises when I want to test my code in the absence of the obfuscated app from running - startup time and setup could take several minutes whereas I want test verification to be a couple of seconds.
What I am looking for is some way of easily adapting my tests to accommodate the frequently changing class names that my code depends upon.
I was intrigued by the power of tools like JMockit, etc in that they were able to automatically generate mock objects for me, I'm hoping to be able to have some thin layer that will enable to still have the majority of my mocks generated quite easily vs having to manually write everything, every update.
If you are running the code from Java, I don't think this is possible.
However if you are running the code with Groovy then you can use Groovy's methodMissing
See: http://groovy.codehaus.org/Using+methodMissing+and+propertyMissing
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.