Is there a way to add (or extend existing) classes at runtime in java. I'm stuck on a problem, in which I have to extend an existing class at runtime and add this to the classpath, so that this new class get picked up.
thanks,
There are a number of ways you could do this.
Compile source code at runtime using the javax.tools package and then load them using a ClassLoader.
If you are writing to interfaces, you can decorate classes with a Proxy.
Take the more complicated route of bytecode manipulation/generation using a technology like BCEL or ASM (the latter has more up-to-date support for language features, like annotations) and then load the class with a ClassLoader.
I imagine there are other options.
You might want to look at BCEL. Without any more information about what you need to do, it's tricky to give a more specific answer.
You should definitely write why you need this feature.
If you attempt to add or replace logic at runtime you might want to have a look at the scripting API and some actual implementations.
Related
I'm looking for different ways to prevent internals leaking into an API. This is a huge problem because once these internals leak into the API; you can run either into unexpected incompatibility issues or into frozen internals.
One of the simplest ways to do so is just make use of different Maven modules; one module with API and one module with implementation. This way it is impossible to expose the implementation from the API.
Unfortunately not everyone agrees this is the best approach; But are there other alternatives? E.g using checkstyle or other 'architecture checking' tools?
PS: Java 9 for us is not usable, since we are about to upgrade to Java 8 and this will be the lowest supporting version for quite some time to come.
Following your checkstyle idea, it should be possible to set up rules which examine import statements in source files.
Checkstyle has built-in support for that, specifically the IllegalImport and ImportControl rules.
This of course works best if public and internal classes can be easily separated by package names.
The idea for IllegalImport would be that you configure a TreeWalker in checkstyle which only looks at your API-sources, and which excludes imports from internal packages.
With the ImportControl rule on the other hand you can define very detailed access rules for the whole application/module in a separate XML file.
It is standard in Java to define an API using interfaces and implement them using classes. That way you can change the "internals" however you want and nothing changes for the user(s) of the API.
One alternative is to have one module (Jar file) for API and implementation (but then again, is it an API or just any kind of library?). Inside one separates classes and interfaces by using packages, e.g. com.acme.stuff.api and com.acme.stuff.impl. It is important to make classes inside the latter package protected or just package-protected.
Not only does the package name show the consuming developer "hey, this is the implementation", it is also not possible to use anything inside (let's omit reflections at this point for the sake of simplicity).
But again: This is against the idea of an API, because usually the implementation can be changed. With this approach one cannot separate API from implementation, because both are inside the same module.
If it is only about hiding internals of a library, then this is one (not the one) feasible approach.
And just in case you meant a library instead of an API, which only exposes its "frontend" (by using interfaces or abstract classes and such), use different package names, e.g. com.acme.stuff and com.acme.stuff.internal. The same visibility rules apply of course.
Also: This way one does not need Checkstyle and other burdens.
Here is a good start : http://wiki.netbeans.org/API_Design
Key point : Do not expose more than you want Obviously the less of the implementation is expressed in the API, the more flexibility one can have in future. There are some tricks that one can use to hide the implementation, but still deliver the desired functionality
I think you don't need any checkstyle or anything like that, just a good old solid design and architecture should be enough. Polymorphism is all you need here.
One of the simplest ways to do so is just make use of different Maven
modules; one module with API and one module with implementation. This
way it is impossible to expose the implementation from the API.
Yes, I totally agree, hide as much as possible, separate your interface in a standalone project.
I'm making a tool to perform several checks in runtime (this is going to be runned in the CI server) and one of the things that I need it's too change implementations of some classes to give the data that I need (basically, I need to know when some specific changes happen in some classes).
This is an OSGi application (I don't know if that's the right name) and I'm using AspectJ to make this information capturing, but AspectJ doesn't change JDK classes and, while I can solve my problem with some classes like LinkedList (not final class with non-final methods), I have to do the same with classes like StringTokenizer or StringBuilder (which I can't inherit or inject code with aspects).
After a few searches I have many questions about HotSwap, custom classloaders and a few other solutions that I've found and I don't know if they're going to satisfy my needs.
I'm using Eclipse Indigo (if it's a solution that will just work on the IDE will be fine too) with Java 6
Look at Apache BCEL to manipulate the bytecode of Java Final classes in a convenient way. This way, you can create your own custom classloader, load the class, manipulate the bytecode to include your own checks and then pass the modified class on to your runtime program.
http://commons.apache.org/proper/commons-bcel/
I want to create a one .java from the Java program. When I run the program, automatically one Java file will created in my project, and also create some run time (dynamic) variable in that file. How can I do this?
I know for this I have to use a Reflection API like Class and Method, but what are the methods in Class and Method to do this?
You cannot create new classes or methods using the reflection APIs. They are not designed for this. (The Class and Method APIs are for performing operations on object instances in a dynamic fashion.)
If you want to create new code on the fly, there are two basic approaches to doing this:
Generate Java source code, write it to a file, use the Java compiler to compile it to a bytecode file, and then load the bytecodes. (There are standard APIs for running the Java compiler within the JVM of a running application.)
Use BCEL or equivalent to construct a bytecode file from scratch, and then load the bytecodes.
Both approaches are tricky and computationally expensive. The BCEL approach is particularly tricky because you need to understand a lot about the JVM to do the job.
Apparently you want to create a new class at Runtime and use it. You can sure create a .javafile, compile it and load it from a custom class loader but that's probably not the best/easiest thing to do. Here are a bunch of solutions:
First of all if you want to extend an interface, you can use the Proxy from the Java Reflection API.
It you want to extend a class rather than implements an interface or create a class out of the blue you need to use a library to create bytecode. You can find a bunch of them on http://www.java-opensource.com/open-source/bytecode-libraries.html. Among these libraries I like javassist mainly because it is the only library to my knowledge letting you enter Java code directly rather than bytecode.
A last solution should be to use a framework like Groovy or BSH to interpret pseudo-java code.
No, you can't generate new .java files using Reflection. You could perhaps create a new class, and use this class, in runtime, but you can't write that class out to file in the form of a .java source file.
Have a look at the JustAdd framework for instance. This framework solves this type of problems IIRC.
Java is a strongly typed language( As opposed to a weakly typed language). Simply put you need to have a Class (prototype) to create a instance of object. What you are trying to do is not natural in java (or any strongly typed language).
If you have to have this functionality in java, you need to use groovy. Groovy is a dynamic language that can run in Java JVM. You need to check Expandos in groovy.(ofcourse it still will not create a .java file).
I'm looking for some ideas on how to compile Java code with some other pieces of code missing (method calls). I am fully aware that javac will not allow you to compile Java files if cannot find all dependencies. But maybe there is some way how to bypass it, something like force compile.
My bytecode knowledge is not so good but I think some method invoke is just full package definition of class and method name with parameters. So if compiler just puts this data to class file and assume in running process dependency will be available (if not simple NoSuchMethodExp).
Only workaround so far I found is to create empty missing class files with empty methods to "cheat" compiler. Works perfectly but there should be easier way :)
Any ideas?
Use Interfaces.
Create the interfaces that have the methods you need. At runtime, inject (Spring, Guice, etc.) or generate (cglib ...) classes that implement the interface.
If you're modifying a jar, you can extract the class files you are not modifying to another directory and include that in the classpath. That way they will be available to the compiler.
Bad luck! Probably all you can do is to create mock objects for missing parts of code just to compile your code (empty methods, so the compiler can find it).
Another question - if you miss some classes, how will you execute that code?
UPDATED according to information provided:
Well, there is another option to modify classes in jar, you can use AOP, and to make it done read about AspectJ - actually for me this is the easiest option (typically you need to spend time mocking objects, writing empty methods, so I would contribute that time to study new technology, which will help you many times ;)
And btw the easiest way to implement it, if you use Eclipse, is:
install AJDT
create aspect project
create aspect which modifies code (depending on what you need to change)
add jar file you want to modify
immediately get modified code in
another already packed jar file
Sounds magically :)
In this case you don't need any dependencies in classpath, except for libraries which are needed for new code you add!
Methods aren't dependencies. They are part of the class definition. The only places the java runtime looks for method definitions is in the class def that was compiled at compile time and in its parent classes. If you're problem is that a super class is incomplete, I don't think I can help you.
If not, you could define some of these methods as abstract and than have a child class implement them.
What kind of code is missing? Normally this happens if you refer to libraries your compiler can't find. Maybe you simply need to extend the classpath the compiler is searching for classes.
If you really refer to code that is not available yet you need to implement at least those methods you refer to. But that sounds strange... maybe you can clear things up.
I have a functionality that I wish to provide to a customer for a software mockup that we are preparing - and I want to know if it's
possible
intelligent (a.k.a. not stupid)
the best thing
I want the customer to be able to write a java class that implements my Computable interface and stick it in some predetermined folder. This folder will contain the .java files rather than .class files. Then, at runtime, I want my program to search that folder and extract all of the Computables from that folder and store them in a map from the name of the Computable to the Computable object. The Computable should only have a default constructor and the it interface will only have one method called compute which maps an array of Object to an Object.
The Java Compiler API introduced in Java SE 6 should give you what you need.
You may find Google Reflections useful to find classes implementing/extending a certain interface/superclass in the classpath. It's then as straightforward as
Reflections reflections = new Reflections("my.project.prefix");
Set<Class<? extends SomeClassOrInterface>> subTypes = reflections.getSubTypesOf(SomeClassOrInterface.class);
Then, to test if it indeed has a no-arg default constructor, just check for each if Class#newInstance() doesn't throw any exception.
There are several suggestions provided as answers to this question.
Here too On-the-fly, in-memory java code compilation for Java 5 and Java 6
If it's easy enough to compile at runtime that would be fine.
You can use javax.tools to do the compilation as needed. Create dynamic applications with javax.tools may help, too. It's also possible to do it in memory.
One caveat: using the compiler creates a dependency on the JDK; the JRE alone is insufficient.
take a look: Find Java classes implementing an interface
I think this would be simpler if you allowed your customer to type in a code declaration using something like Groovy, which is Java-ish enough, and easy to execute at runtime from a String value.
It's easy enough to iterate through the list of files in a folder. Someone mentioned that it's possible to call the Java compiler from Java (if you re-distribute the JDK, which I think is a point whose legality needs checking!!) That's much of the battle.
You seem to have a fixed model in your mind where only files fulfilling a certain interface are extracted from the folder. I think this is where your method needs to give a little. The sensible way (IMO) to do this would be to compile all files in that folder, and then with their classes stashed away somewhere, you can load and reflect them and then determine which of them "do" the interface and which don't. Those that don't will have been needlessly loaded into your JVM, but unless it's intentionally very space-wasteful, code you don't execute can't harm your program.
Having determined which ones do the computable thing, you can then store those classes (or instances thereof) in a Collection and do whatever you like with them. You simply ignore the other ones.
You could use BeanShell. This library is small and doesn't require the JDK. It is used in a number of IDE and web servers. The latest version appears to have the support you need loading .java files from the class path. (Still in beta)