I need to call a bunch of Class.forName() s on third-party classes but this causes the static initializers to run of all the affected classes. This running of the static initializers is a undesired side effect that I want to avoid because the logic pulls in all sorts of other dependencies and other garbage.
Is there a way to prevent these from running? I need the class object, not just info I can get by hacking the class binaries.
I am aware that classes need to be properly initialized before methods should be invoked. I am not doing anything with the code of these classes, I want them frozen.
If you are dependent on the real class containing everything the class consists of, you are stuck with the static initializers unless you patch your virtual machine.
If you just need class meta-information (e.g. method names of the class, implemented interfaces) you can go with a library like Reflections.
Your suggestion to use Powermock/Mockito to suppress the static initialization would go in a similar direction as the Reflections library. Both Test frameworks change the bytecode of classes before loading, resulting in slightly different classes than the original one.
Without using any additional libraries, you can just do:
Class.forName(className, false, this.getClass().getClassLoader());
Where the second argument is initialize , to flag whether you want the class initialising.
The class is initialized only if the initialize parameter is true and if it has not been initialized earlier.
The single argument call to forName is just a convenience wrapper:
Returns the Class object associated with the class or interface with the given string name. Invoking this method is equivalent to:
Class.forName(className, true, currentLoader)
See: Class.forName documentation (Oracle Java SE7)
Related
Hello StackOverflow Community,
I recently discovered Java Instrumentation and what great things you can do with it, so I decided to write a small library for me that simplifies some of these things.
I have the following method (simplified):
public static void editClass(Class<*> clazz) {
...
}
It adds a transformer via Instrumentation that transforms the bytecode of loaded classes with the name of clazz.getName().
So in my premain method, I can say
editClass(Foo.class);
My problem is, by specifying the class via a reference to it (.class), this class gets loaded before the transformer is added, so after that, I have to retransform the class which prevents me from adding/removing methods and so on.
So, is there a way to not load the class when using this class reference? Or an other way to implement this? I know that I could just pass the class name as an argument, but I would really like to make this whole library type-safe and make refactoring easier.
Thanks in advance!
If you want to call the editClass method from premain only and we assume that the Java Agent itself does not use the class otherwise, so that the class literal inside the editClass call would be the only trigger, you can do the following:
provide both methods, editClass(Class<?> clazz) and editClass(String qualifiedName)
write the premain method (or agent classes in general) using editClass(Class<?>) and enjoy compile-time safety regarding the existence of the classes referenced via literals
perform a static code transformation of the agent classes, replacing all calls of editClass(Class<?>) with editClass(String)
This shouldn’t be too hard, as you only have to replace all sequences of ldc packagename/Foo.class, invokestatic (Ljava/lang/Class;)V with ldc "packagename.Foo", invokestatic (Ljava/lang/String;)V.
It may become even easier when the method editClass(String qualifiedName) can handle the internal class names (using slashes instead of dots).
Since you said you “recently discovered Java Instrumentation”, this might be a good exercise in class file transformations
Use the transformed Agent classes which have no references to the classes to transform anymore, to perform the load time transformations
I want to call a method in different class in a different package using the lines injected through javassist. Is there any other way to call those methods directly without making them public static and call using the fully qualified classname? In here it describes about a importPackage() method. But it looks like it can be used only with classpool object where we try to obtain the required class file.
Imports are compile time only. If you want to invoke non-static methods in another class, you will need some means of acquiring the correct object instances to invoke against, such as:
Instantiating them
Some sort of object finder
Implements a shared collection that can be accessed statically that contains the objects.
One of these would need to be injected into your class so you can get the instances, and then you can wire in the actual invocation.
It might be helpful if you provided some code samples, perhaps how the code is now, and how you would like it to be.
I am wondering if it would be possible to generate a class, via an annotation processor, that would be an inner class of a class to be compiled.
For instance, while compiling class A, generate class A$Foo. I wonder if there is a trick that could be used or not. I got the feeling that it might be possible to generate some source that will be compiled in the same byte code as an inner class would. And, at compile/runtime, the JVM would take it for an inner class, and allow accessing outer class private fields.
The idea behind that question, which is not a noobie question, though it may look more or less technical, is to be able to use the private visibility modifier for annotated fields like Dagger, ButterKnife, etc. The private modifier allowing to detect unused fields more easily, whereas package private protection hides them.
Or is there any workaround, any way to get the best of both words ?
Given your use case, no.
An inner class is a normal Java class, living in a different .class file. When compiled, a hidden constructor param is added to the inner class constructor. Private fields in the outer class are made accessible by adding hidden accessor methods in the outer class. All of this happens at compile time.
The JVM has nothing to do with that. If you generate a class that "looks like an inner class of another class", that won't make the outer class fields accessible.
Private visibility is really just a hint to compiler. There is no problem to access those fields at the runtime at all (like I do in my small dependency injector: https://github.com/ko5tik/andject)
And non-static inner classes on android are generally a bad idea as it used to have performance penalty.
At the compile time you could use source generation tool like xdoclet (though it became technically obsolete years ago, but still occasionally used) and generate all the sources you need in advance before compiling them.
I am writing code that adds functions to a 'mod' if it exists in the classpath (referenced by pixelmonPresent)
PixelHammerTool extends ItemHammer
, ItemHammer only exists if pixelmon is present
The issue im having is, if i do this in the class (same package)
if(Basemod.pixelmonPresent) {
rubyHammer = new PixelHammerTool(Basemod.RUBY, "pixelutilitys:RubyHammer", "rubyHammer");
}
It will cause a class not found on PixelHammerTool,
Why is this being called if the if statement is false and what can i do about it ?
The why is simple and straightforward: because when a class is loaded, all the classes referenced by it are loaded too. (In fact they are loaded first.)
Avoiding it isn't too complicated either, although the code won't look nice: you need to load the class with reflection, using Class.forName(), find the constructor you want from the array returned by Class.getConstructors() and then create an instance using Constructor.newInstance().
Note that while if it only happens a few times in your code, this solution is fine, if you find yourself doing this a lot then you should probably look for a dependency injection framework that will do the heavy lifting for you.
Under the Linking section in the specs, we see this:
For example, a Java Virtual Machine implementation may choose to resolve each symbolic reference in a class or interface individually when it is used ("lazy" or "late" resolution), or to resolve them all at once when the class is being verified ("eager" or "static" resolution). This means that the resolution process may continue, in some implementations, after a class or interface has been initialized. Whichever strategy is followed, any error detected during resolution must be thrown at a point in the program that (directly or indirectly) uses a symbolic reference to the class or interface.
So when the constant has to be defined is implementation-dependent, based on the class loader. The behavior you're seeing is consistent with the "eager" resolution mentioned: when you reference PixelHammerTool in your code, even if it's for a runtime path that will never be hit, the class loader tries to link in its definition, which does not exist.
This strategy causes the JVM to start slower but execute faster at runtime, which is generally the strategy taken in all the implementations I'm familiar with. Indeed, the default class loader is given the name "bootstrap class loader" because it has this behavior - load classes at JVM bootstrap time.
You can either instantiate the class via reflection, as biziclop suggested (the easier route), which forces linking at runtime, or find or create a class loader that instantiates classes lazily.
It is possible in plain Java to override a method of a class
programmatically at runtime (or even create a new method)?
I want to be able to do this even if I don't know the classes at compile time.
What I mean exactly by overriding at runtime:
abstract class MyClass{
public void myMethod();
}
class Overrider extends MyClass{
#Override
public void myMethod(){}
}
class Injector{
public static void myMethod(){ // STATIC !!!
// do actual stuff
}
}
// some magic code goes here
Overrider altered = doMagic(
MyClass.class, Overrider.class, Injector.class);
Now, this invocation...
altered.myMethod();
...would call Injector.myMethod() instead of Overrider.myMethod().
Injector.myMethod() is static, because, after doing "magic"
it is invoked from different class instance (it's the Overrider),
(so we prevent it from accessing local fields).
You can use something like cglib for generating code on-the-fly
In java6 has been added the possibility to transform any already loaded class. Take a look at the changes in the java.lang.instrument package
For interfaces there is java.lang.reflect.Proxy.
For classes you'll either need a third-party library or write a fair bit of code. Generally dynamically creating classes in this way is to create mocks for testing.
There is also the instrumentation API that allows modification of classes. You can also modify classes with a custom class loader or just the class files on disk.
I wrote an article for java.net about how to transparently add logging statements to a class when it is loaded by the classloader using a java agent.
It uses the Javassist library to manipulate the byte code, including using the Javassist compiler to generate extra bytecode which is then inserted in the appropriate place, and then the resulting class is provided to the classloader.
A refined version is available with the slf4j project.
If I got it right, the main problem that concerns you is how to pass a static method delegate (like in C#), through the instance interface method.
You can check this article: A Java Programmer Looks at C# Delegates (archived), which shows you how to get a reference to your static method and invoke it. You can then create a wrapper class which accepts the static method name in its constructor, and implements your base class to invoke the static method from the instance method.