i'm very confused...
I have a class which directly implements an interface:
public class Device implements AutocompleteResult
{...}
Here is proof that I'm looking at the right variables:
Object match = ...;
log.debug(match.getClass()); // Outputs 'Device'
log.debug(match.getClass().getInterfaces()[0]); // Outputs 'AutocompleteResult'
Yet when I try to cast an instance of the class to the interface:
AutocompleteResult result = (AutocompleteResult) match;
I get a ClassCastException!
ClassCastException: Device cannot be cast to AutocompleteResult
Also, isAssignableFrom returns false and i'm not sure why:
log.debug(AutocompleteResult.class.isAssignableFrom(Device.class));
from the doc:
Determines if the class or interface represented by this Class object is either the same as, or is a superclass or superinterface of, the class or interface represented by the specified Class parameter.
Shouldn't I always be able to cast a object to an interface its class implements?
Thanks.
This can happen if two different classloaders load a class named AutocompleteResult.
These two classes are then treated as entirely different classes, even if they have the same package and name (and even implementation/fields/methods).
A common cause for this is if you use some kind of plugin system and both your base classes and the plugin classes provide the same class.
To check for this issue print the value returned by Class.getClassLoader() on both offending classes (i.e. the class of the interface implemented by Device and the result of AutocompleteResult.class).
AKA when Java apparently doesn't Java.
I hit this problem recently with Play Framework 2.6.3, what helped me was this:
https://www.playframework.com/documentation/2.6.x/ThreadPools#Application-class-loader
I leave this info here for the people that might have the same problem.
To make it clearer, what helps is:
Injecting Application on an Eager Singleton and then using its classloader to load the classes I was having issues with.
To make it clearer
public class Module {
#Override
public void configure {
bind(TheClassLoaderLoader.class).asEagerSingleton()
public static class TheClassLoaderLoader {
#Inject
public TheClassLoaderLoader( Application application) {
ClassLoader classloader = application.classloader();
Class<?> interfaceClass = classloader.loadClass(InterfaceClass.class.getName());
classloader.loadClass(ImplementsInterfaceClass.class.getName()).asSubclass(interfaceClass);
The example here https://playframework.com/documentation/2.6.x/JavaDependencyInjection#Configurable-bindings
That uses Environment often throws a frustrating ClassNotFoundException
Cheers
Related
I need to support two versions of a dependency, which have the same API but different package names.
How do I handle this without maintaining two versions of my code, with the only change being the import statement?
For local variables, I guess I could use reflection (ugly!), but I use the classes in question as method argument. If I don't want to pass around Object instances, what else can I do to abstract from the package name?
Is it maybe possible to apply a self-made interface - which is compatible to the API - to existing instances and pass them around as instance of this interface?
I am mostly actually using xtend for my code, if that changes the answer.
Since you're using Xtend, here's a solution that makes use of Xtend's #Delegate annotation. There might be better solutions that aren't based on Xtend though and this will only work for simple APIs that only consist of interfaces with exactly the same method signatures.
So assuming you have interfaces with exactly the same method signatures in different packages, e.g. like this:
package vendor.api1
interface Greeter {
def void sayHello(String name)
}
package vendor.api2
interface Greeter {
def void sayHello(String name)
}
Then you can combine both into a single interface and only use only this combined interface in your code.
package example.api
interface Greeter extends vendor.api1.Greeter, vendor.api2.Greeter {
}
This is also possible in Java so far but you would have to write a lot boilerplate for each interface method to make it work. In Xtend you can use #Delegate instead to automatically generate everything without having to care how many methods the interface has or what they look like:
package example.internal
import example.api.Greeter
import org.eclipse.xtend.lib.annotations.Delegate
import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
#FinalFieldsConstructor
class GreeterImpl implements Greeter {
#Delegate val Api delegate
}
#FinalFieldsConstructor
class Greeter1Wrapper implements Greeter {
#Delegate val vendor.api1.Greeter delegate
}
#FinalFieldsConstructor
class Greeter2Wrapper implements Greeter {
#Delegate val vendor.api2.Greeter delegate
}
Both Greeter1Wrapper and Greeter2Wrapper actually implement the interface of both packages here but since the signature is identical all methods are forwarded to the respective delegate instance. These wrappers are necessary because the delegate of GreeterImpl needs to implement the same interface as GreeterImpl (usually a single delegate would be enough if the packages were the same).
Now you can decide at run-time which version to use.
val vendor.api1.Greeter greeterApi1 = ... // get from vendor API
val vendor.api2.Greeter greeterApi2 = ... // get from vendor API
val apiWrapper = switch version {
case 1: new Greeter1Wrapper(greeterApi1)
case 2: new Greeter2Wrapper(greeterApi2)
}
val example.api.Greeter myGreeter = new GreeterImpl(apiWrapper)
myGreeter.sayHello("world")
This pattern can be repeated for all interfaces. You might be able to avoid even more boilerplate by implementing a custom active annotation processor that generates all of the required classes from a single annotation.
I have a Spring bean (ChildBean extends Parent) which is extending an abstract class (Parent implements Runnable).
public abstract class Parent implements Runnable {
public final void run() {
// some code
}
public int overridenFunct() {
// some code
}
}
Child bean class variant which causes ClassCastException:
#Transactional
#Scope("prototype")
#Service("beanName")
public class ChildBean extends Parent {
#Override
public int overridenFunct() {
// some diff code
}
}
Everything works fine until I override public non-abstract method from parent class in child bean. After that a ClassCastException is thrown when I'm trying to create an instance of that bean.
Parent p = (Parent) appContext.getBean("beanName");
Bean object returned by getBean() is a ChildBean class instance (checked with debugger). Why does casting ChildBean object to its abstract parent class Parent not work?
So, without an overridenFunct() implemented in ChildBean everything works fine.
Could someone please tell what is the problem here?
UPDATE:
Changing method overridingFunct() to protected fixes the issue. But what if I need to override a public method? Is that allowed? I'm using Spring 3.2.8
UPDATE2:
Well, I didn't get to the point why overriding public method in abstract parent causes ClassCastException. As the resolution I did the following: created an interface with all public methods with common logic, an abstract class, which implements that interface and all "common" methods. Then all the child beans are extended from that abstract class, implementing its specific logic.
For anyone that may encounter this error, the following may prove to be useful in debugging this. First and foremost, the problem can be caused by the ClassLoader loading two copies of a particular class due to dependency overinclusion.
Supply the following option to your JVM via IDE or via
java -verbose:class {rest of your args / options}
Then, monitor the console output for the particular Parent class. A chance exists that the class has made it into the ClassLoader twice, perhaps by including a particular dependency more than once. Pay particular attention to the time when the bean is retrieved from lookup.
I was able to solve an issue on 4/22/2022 by using the above strategy to track down an issue in our Gradle build script that caused extra files to make their way into a WAR.
The Problem with your code is, that appContext.getBean("beanName") does not return an object that inherits from the class Parent.
A common mistake regarding classes with names like Parent is a wrong import.
Check if you are importing from the correct package.
If this does not fix the issue, make sure that appContext.getBean("beanName") returns the object you think it does.
It might return a Bean Object, that does not inherit from the Parent class.
The context also might not even contain your ChildBean object yet. Make sure it is added to it beforehand.
I have an interface defined as follows:
public interface Cache {
}
Then an abstract class implementing the above:
public abstract class AbstractCache implements Cache {
}
Then a concrete class inheriting from above:
public class RealTimeCache extends AbstractCache {
}
Then another class defined as follows:
public class CacheProbe {
public static <T> T probe(T base) {
return (T) Proxy.newProxyInstance(
base.getClass().getClassLoader(),
new Class[]{Cache.class},
new MethodCountInvocationHandler(base) // I am not mentioning this class as it's irrelevant
);
}
}
I have a class as follows which is using all of the above:
public class CacheLoader<T extends Cache> {
public T load() {
T result = getResult(...);
CacheProbe x = new CacheProbe(result);
return x.probe();
}
}
Lastly, the lines causing the issue (located outside above classes):
final CacheLoader<RealTimeCache> cacheLoader = getNewLoader(); //Method of this method is irrelevant and unchangeable
RealTimeCache x = cacheLoader.load(); //This is the line which is causing a runtime issue
Problem is, at run time the following exception is thrown at the last line mentioned above:
java.lang.ClassCastException: com.sun.proxy.$Proxy57 cannot be cast to RealTimeCache
However I don't see how this is possible because the dynamic proxy class generated is based on Cache.
How do I fix this ?
Please note that I can only change CacheProbe class in order to fix this. Cache, AbstractCache, RealTimeCache, CacheLoader and those last two lines are unchangeable.
However I don't see how this is possible because the dynamic proxy class generated is based on Cache.
Yes, the docs for java.lang.reflect.Proxy say
Proxy provides static methods for creating dynamic proxy classes and instances, and it is also the superclass of all dynamic proxy classes created by those methods.
(emphasis added)
Thus, you cannot use Proxy to create (an instance of) a subclass of an arbitrary class of your choice.
How do I fix this ?
You can create an ordinary subclass of RealTimeCache, and return an instance of that. Proxy is meant primarily to serve for interfaces that are not known until runtime, and in that case the only way to interact with them anyway is the interface type. That's not your scenario.
If necessary, you can implement such a subclass in terms of a MethodCountInvocationHandler, just as your proxy class uses, but I'm sure it would be easier to implement whatever tooling that is supposed to provide directly.
For some special use-case I have a small utility to load Java classes from jars using a dynamic class loader DynamicClassLoader. This works fine for Java classes contained in jars. Loading Scala classes from a jar also works without problems. However, instantiating the loaded Scala class leads to the following exception. It looks like the Scala class has private default constructor? Note the compiled Scala class name ending with $
java.lang.IllegalAccessException: Class XXX can not access a member of class ScalaClassYYY$ with modifiers "private"
The snippet below illustrates the idea of what I'm trying to achieve and gives a bit more context. The exception happens at the annotated line:
// deploy and register the new code
byte[] jarBytes = (byte[]) ((Object) message.getAttachment("jar"));
String registerClassName = message.getAttachment("register");
logger.debug("the register is '" + registerClassName + "'");
DynamicClassLoader loader = new DynamicClassLoader(jarBytes);
Class<?> registerClass = loader.lookUp(registerClassName);
// ===> this is where the java.lang.IllegalAccessException happens
IRegisterExecutor registerExecutor = (IRegisterExecutor) registerClass.newInstance();
registerExecutor.register();
Any ideas how to fix?
Obviously, you need to make the default constructor public (it won't work for Java classes without a public default constructor either). E.g.
class ScalaClassYYY() {
...
}
or if you want primary constructor to take some arguments,
class ScalaClassYYY(arg1: Int) {
def this() = this(0)
}
But from
Note the compiled Scala class name ending with $
it seems like you are actually trying to instantiate a Scala object:
object ScalaClassYYY { ... }
In this case, you shouldn't create a new instance and instead use the existing one:
(IRegisterExecutor) registerClass.getField("MODULE$").get(null);
EDIT:
I don't see in your answer how you add a default public constructor to a Scala class that does NOT require any parameters.
A class (not an object) that doesn't require any parameters has a default public constructor already (my first example).
Actually in Java all classes by default offer a public default constructor
No. Only those classes which have no constructors which take arguments.
remove the "(it won't work for Java classes without a public default constructor either)" because it is wrong
The documentation for Class.newInstance() says
IllegalAccessException - if the class or its nullary constructor is not accessible.
So I am pretty sure it's right. If it does work for Java classes without a public default constructor, this seems to be a major bug in the class loader you use. You can test it with a Java class which looks like this:
public class TestClass implements IRegisterExecutor {
public TestClass(int dummy) {}
// some implementation for IRegisterExecutor methods to get it to compile
}
I made a Dynamic Proxy to be the middle man when handling specific methods in a class. I'm doing this to avoid having to override every single method in each of the interfaces that I need to take control of.
Waffley bit that nobody will understand or care about (but may add more context to the question):
In the example I am going to give, I've tried to make it generic so you can compile it to test and run yourself, but in the real situation, I have something like this:
interface CommandSender
interface ConsoleCommandSender extends CommandSender
interface Player extends CommandSender
If I were to make a proxy of a ConsoleCommandSender instance, the resulting proxy SHOULD be castable to a CommandSender. In reality, ConsoleCommandSender doesn't list all of its interfaces with getInterfaces() and this happens:
java.lang.ClassCastException: $Proxy18 cannot be cast to org.bukkit.command.CommandSender
The Player class does not have this issue, and is always castable to CommandSender.
The real question:
So, using the following code as a starting point, how can one successfully cast the proxy denoted by myProxy to the format desired without having to worry about the ClassCastException?
The following code will successfully compile and run, but hopefully you understand what I'm getting at by casting to a List rather than an ArrayList.
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
public class ProxyClass implements InvocationHandler {
private Object classProxy;
public static void main(String[] args) {
// Example declaration
// (I know the proxy should really be cast as an ArrayList
// but this is my point, it SHOULD work anyway)
ArrayList methodObject = new ArrayList<String>();
List<String> myProxy = (List<String>)ProxyClass.newInstance(methodObject, false);
// Example usage
myProxy.add("Hello World!");
System.out.println(myProxy.get(0));
}
public static Object newInstance(Object proxy, boolean silent) {
return Proxy.newProxyInstance(
proxy.getClass().getClassLoader(),
proxy.getClass().getInterfaces(),
new ProxyClass(proxy));
}
private ProxyClass(Object proxy) {
this.classProxy = proxy;
}
// Is called whenever a method is invoked
public Object invoke(Object p, Method m, Object[] args) throws Throwable {
return m.invoke(classProxy, args);
}
}
On another thread I made about the preliminary part of this issue, one guy commented saying I could use the <T> variable to add another valid interface to the list. I didn't really understand how to implement this though, but it seemed like a good start.
I am not 100% sure I admit I understood your question -
You want to be able to "directly" cast to ArrayList? I mean -
ArrayList<String> myProxy = (ArrayList<String>)ProxyClass.newInstance(methodObject, false);
This just won't work for you. The reason is that the generated object is not an instant of ArrayList. In a sense the behavior resembles decorator.
Is decorator an instance of the object it decorates? No, they conform to the same interface.
What you should do is consider using CGLIB.
CGLIB let's you create proxies (intercepted objects) for classes.
a Proxied object by CGBLib is indeed an instance of the proxied object.
If I remember correctly, Hibernate uses CGLib and ASM in order to proxy the entity objects,
You can see here a link to some experiments I did with CGLIB.