The Details
The Tutorial allows you to perfectly use Objenesis. However, if you want implementation details, tools and more power, you're at the right place.
Test your environment
Depending on your JVM and security manager, Objenesis might not be able to instantiate some of your classes. If that's the case, first, we are highly interested in knowing this limitation.
Then, to prevent this, we provide a TCK to run in your environment. You can find it on our download page. It will print a report to the standard output. Exceptions, if they occur, will be printed out to the standard error. Tests are run against ObjenesisStd and ObjenesisSerializer and are made of every kind of class types you might want to instantiate. So you can check if all of them or at least the kind you want are correctly instantiated.
To launch from the command line, just type
java -jar objenesis-3.4-tck.jar
Note that the Objenesis jar is bundled in the TCK so no special classpath is needed.
To launch from within an application server, the easiest is to bundle it in your application
and to call org.objenesis.tck.Main.main()
from your code.
Android
Objenesis also works on Dalvik, the Android VM. So a TCK is also provided for it in the form of an apk. You can also find it on download page. Just use the following command to install and run it.
adb install -r objenesis-tck-android-3.4.apk adb shell am instrument -w org.objenesis.tck.android/.TckInstrumentation
Exception Handling
If something wrong occurs using Objenesis, you will normally get an ObjenesisException wrapping the real exception. It is a RuntimeException so you don't have to catch it. Some reasons why it fails:
- Using ObjenesisSerializer with a class that isn't
Serializable
. - Using ObjenesisSerializer, the constructor of the first parent class that isn't
Serializable
throws an exception. - Your SecurityManager prevents Objenesis from working normally.
- Objenesis isn't able to work for some reason. Please tell us
ObjectInstantiator caching
ObjenesisBase provides a built-in cache that is activated by default. This cache keeps ObjectInstantiator instances per Class. This improves performance quite a lot when the same Class is frequently instantiated. For this reason, it is recommended to reuse Objenesis instances whenever possibly or to keep is as a singleton in your favorite dependency injection framework.
However, you can always disable the cache if needed.
Objenesis o = new ObjenesisStd(false); // cache disabled
The cache should behave correctly in an application server and not cause any memory leaks.
Use you own strategy
As you've seen in the Tutorial, Objenesis implementations are determining the best instantiator using a strategy. It might occurs that you need to implement your own strategy. Two possible reasons I can think of are that
- You want to specialize for a given JVM. Default strategies are
supporting all JVMs. This has a little performance cost so you might want to
provide a strategy that is optimized for your JVM.
public class Sun14Strategy implements InstantiatorStrategy { public ObjectInstantiator newInstantiatorOf(Class type) { // return sun dedicated instantiator return new SunReflectionFactoryInstantiator(type); } }
- Objenesis doesn't support your environment by default. In that case, we would be really happy to add this support in our next version and meanwhile, you can use your own strategy and instantiator to fix this.
From there, you can use this new strategy.
// Directly Objenesis o = new ObjenesisBase(new Sun14Strategy()); // Or inside your Objenesis own implementation public class ObjenesisSun14 extends ObjenesisBase { public ObjenesisSun14() { super(new Sun14Strategy()); } }
Also, if Objenesis can't find the right instantiator to use by itself, this doesn't mean it doesn't bundle an instantiator that works on your platform. To try to find one, we provide a nice tool that will run through all the instantiators and tell you which ones work
java -cp objenesis-3.4-tck.jar org.objenesis.tck.search.SearchWorkingInstantiator
Some culprits:
- Some instantiators are made to mimic the Java serialization. It means they will call the default constructor of the first non-serializable class
- Some instantiators only works if the class is serializable
- Some instantiators will in fact call the default constructor
- Depending on your security manager, classes coming from a low level class loader might not be instantiable
The Evil ObjenesisHelper
Static methods are considered a really bad practice. They can't be mocked or replace easily. Worst, if the class keep a static state, you will fell in class loading issues, memory leaks, module dependencies and so on. We strongly recommend you not to use them.
However, if for some reason that we prefer ignore, you still want to use Objenesis in a static way, you can do so. It's called ObjenesisHelper.
We prefer to provide it knowing that some of you will code it anyway. It a wrapper over an ObjenesisStd and ObjenesisSerializer instance which are kept statically.
It can't be more straightforward to use:
Object o1 = ObjenesisHelper.newInstance(MyClass.class); Object o2 = ObjenesisHelper.newSerializableInstance(MyClass.class); ObjectInstantiator o3 = ObjenesisHelper.getInstantiatorOf(MyClass.class); ObjectInstantiator o4 = ObjenesisHelper.getSerializableObjectInstantiatorOf(MyClass.class);
Serializing instantiator details
The instantiator returned by SerializingInstantiatorStrategy
will do the following.
- Fail is the class is not serializable
- Call the no-arg constructor of the first none serializable class. Just like the serialization would do
Externalizable
classes won't have a special treatment. If you want one, implement it yourself- No serializable specific method is called (e.g.
readResolve, readExternal, readObject, readObjectNoData
)