Java - prevent field assignment using reflection on instantiation? - java

I have a java class in a 3rd party lib with a private member which is assigned at class instantiation.
public class CacheLookupUtil extends AbstractCacheLookupUtil<InvocationContext> {
#Inject
private BeanManagerUtil beanManagerUtil;
private CacheKeyGenerator defaultCacheKeyGenerator = new DefaultCacheKeyGenerator();
private CacheResolverFactory defaultCacheResolverFactory = new DefaultCacheResolverFactory();
...
...
}
My problem is that the assignment of defaultCacheResolverFactory is causing an exception due to the wrong constructor having been chosen.
If I try to subclass CacheLookupUtil, this assignment is still done in the parent class, so I'm no further ahead.
Is there any mechanism I can use in Java reflection that would allow me to construct/instantiate the object, but prevent the assignment of defaultCacheResolverFactory, and allowing me to set the value via reflection?
I know this is an ugly solution, but to be honest, I cannot visualize any other way to proceed.

Is DefaultCacheResolverFactory part of your libraries jar?
If not I would guess that this is a version problem.
Otherwise you should lookout for a bugfix version of your library or open a ticket.
Last but not least you could use AspectJ Load-Time Weaving to manipulate the bytecode at class loading time. But this requires that you always start your code with Load-Time Weaving. See Load-Time Weaving.
So I personally would prefer option 1 or 2.

Check the version of library that contains CacheLookupUtil (I understand that its a thirdparty class). For example, let it be jar-A.
Then check the version of jar that contains DefaultCacheResolverFactory. If its also jar-A, this effectively means that this library doesn't work at this version, so you should upgrade.
If its in some jar-B, then check pom.xml of jar-A itself, what version of dependency on jar-B is required, probably you override the version of this jar.
Then adjust the version so that jar-A's expectations from the version of jar-B will match :)
For me its the best solution.
Now as for dirty tricks. One trick can be to create your own copy of CacheLookupUtil and put it into the same package, depending on class-loaders policy (you haven't specified in which environment do you run, so I assume plain java) it might load first and effectively "substitute" CacheLookupUtil from the jar.
Of course the same can be done with DefaultCacheResolverFactory (so that you could fix the no-op constructor there)
If you believe its a real bug, an another option to consider is to fork from the "buggy" library and create your own version of it with a fix. Of course you better make the developers of the original library to fix this bug so that eventually you could get back to the official version, in the world of open source, sometimes solutions like this work as long as the licencing permits doing so.
If it doesn't help, then Byte Code manipulation is the only way to fix as #PowerStat already mentioned. this I believe, Java Agent, class loading patching, AspectJ, and so forth. Hopefully you won't get there only because of this issue :)

Related

How to inherit/replace a java final class?

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/

Overriding single classes from rt.jar

I'm looking for a neat way to override a class from the bootstrap class path, rt.jar.
The reason is OpenJDK7 bug http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7104625
The fix for this bug is a trivial (see linked mailing list post) change to sun.awt.X11.XComponentPeer. So I was wondering if there is an easy way to override just this one affected class on my classpath, without having to repack/rebuild rt.jar (so the fix isn't lost on the next automatic update of OpenJDK).
Ideally, it would also affect Eclipse...
I assume that java -Djava.system.class.loader=myClassLoader would work? Is there any other way to override a single class with such a "hotfix"? (Note: not used in my own code, but deep in Java AWT code)
You can use the VM parameter -Xbootclasspath/p to prepend your own JAR file with the patched class to the boot class path.
I believe the only supported way of doing this is to "patch" rt.jar by replacing the desired *.class file. 7-Zip can help you easily do this.
This is exactly how Oracle supplied their double-parsing bug fix with their FPUpdater tool, which was essentially a script that did just this. (Some history.)
I think you can try to use javaagent
You must intercept event, when JVM loads system class and swap it to yours
I think #ziesemer is correct, but you may be able to use the classloader to replace the offending class when your app is bootstrapping. This may be cleaner if you don't want to worry about the JDK updating underneath you, though you'd have to stick this bootstrapping classloader code into every app you are working on.

Retro-actively add Java annotations to methods?

Is there a way to modify .class files in order to add Java annotations to certain methods? Basically I want to traverse methods of each class file in a jar file and annotate certain ones. Note that this is not at run-time while using the jar file. Rather, after I'm done I want to have modified class files with the annotations.
I do have access to the source code, so if there's an automatic source code modifier, that would work as well...
I'm assuming I'll need a tool such as Javassist or ASM. If so, which one should I use and how would I go about it?
Actually, this is a classic use case for AspectJ:
declare #method : public * BankAccount+.*(..) : #Secured(role="supervisor")
While I will grant you that direct byte code manipulation is more powerful, AspectJ is much more user-friendly, and it immediately gives you compiler warnings when you are doing something wrong.
Also, if you use Load Time Weaving, you can leave the original library jar unchanged, because the weaving happens at class-load time.
Reference:
Declare Annotation
AspectJ in Action (book)
Googling for an hour or so turned this article up which seems to completely answer my question: use ASM. To write class files using the changed bytecode, use ClassWriter.
Well, time to get to work then, I guess. :)

Compile Java class with missing code parts

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.

Finding new Java class at runtime

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)

Categories

Resources