I have a scenario where I need to load classes from unknown sources and instantiate them for mocking - I don't need the code to run, but methods and properties must be in the resulting instance. I also need the class's name to remain unchanged, so its instance can be assigned to fields from that type of other already loaded classes. Sometimes a class instantiation fails due to an ExceptionInInitializerError
, leaving the class in an invalid state which is impossible to recover. I do not know which class will fail beforehand.
Consider this:
class A {
static {
// Throws exception, resulting in 'A' changing to an error state
}
}
class B {
// In case 'A' could not be instantiated properly, I wish to mock
// it so it can be assigned to this field
private A someField;
}
The following is what I came up with:
- Create a subclass of the failing class using ByteBuddy - fails with
NoClassDefFoundError
, probably because the superclass is in an error state. - Modify the class's static initializer and wrap it in try-catch statements while it is loaded using a ByteBuddy's agent - this seems rather complicated to accomplish in a portable manner.
- Load a class in a separate temporary class loader and identify the initialization failure; if an
ExceptionInInitializerError
has been thrown, redefine that class and remove its static initializer. This also appears very complex to achieve and results in various linkage and circularity errors.
Am I missing something? Is there a simpler way to achieve what I'm looking for?
Aucun commentaire:
Enregistrer un commentaire