Skip to content
Advertisement

Java Proxy.newProxyInstance IllegalArgumentException

I define an interface follow

JavaScript

then I define a abstract class implement the interface

JavaScript

then I has a class extends the abstract class

JavaScript

now I want to generate a proxy for the instance field of the BaseCore class,I do this

JavaScript

but I receive the exception

JavaScript

who can help me explain the excetion and how I can solve the problem? thanks

Advertisement

Answer

Your code has serious style issues, and it is broken. And we haven’t even gotten to the error you’re asking about yet. I suggest you skip the actual answer and instead read why you’re barking up the wrong tree and need to rethink this code, making the actual answer irrelevant for you.

The actual answer

Proxy will make a new instance of a proxy class (that’s where that $Proxy2 thing is coming from). Proxy cannot make an object that is an instance of that actual class: That’s just not how java works. Thus, you have an instance of an unknown, effectively irrelevant class. However, that $Proxy2 class does implement whatever interfaces you want it to. It can’t extend anything (other than, obviously, java.lang.Object). No final classes, no normal classes, not even abstract classes. That’s just how it works: If you want a proxy that extends something specific, you’re out of luck.

Thus: You can only proxy interfaces.

Had the field been:

JavaScript

instead, it would have worked fine; That $Proxy2 class is a class made on the fly by the Proxy.newProxyInstance call, and this class implements all the interface you passed in.

But, as I said, do not just start changing things, you need to rethink this code more fundamentally.

The more significant issues with your code

  • Your BaseCore class has a field of type Core, eliminating any point or purpose in the class hierarchy of it. Its type should possible be BaseCore, or the ‘singleton holder’ field should be in Core. Generally fields should have the least specific type that you want to use, e.g. we write List x = new ArrayList – because List is less specific. You’ve gone the other way, and made the field the most specific type you could find (Core, which is more specific than BaseCore, which is more specific than SdkInterface). If that static field’s type is SdkInterface, you can assign a proxy object to it. But if the type of that field is a class (other than java.lang.Object), then that is impossible – as proxies implement whatever interfaces you want, but extend j.l.Object and can’t be made to extend anything else.
  • Double checked locking does not work, so don’t do it. Your getInstance() method is broken in a really nasty way: It is broken, but, most tests do not catch it. It requires a specific combination of hardware, android version, and phase of the moon for it to fail. There are only 2 sane ways to ‘load’ singletons: Generally, just initialize the field (and make it final), because java lazy loads; the only benefit to having an actual method that loads it only when you invoke .getInstance() or whatnot, is when it is plausible you will ‘touch’ the class (load a class that has a field of type Core, for example), but never actually need the instance. This happens, but it is rare. If it doesn’t apply to you, there is no point to any of this, and you can just write public static final Core INSTANCE = new Core(); and be done with it all. If you really do need the getSingleton method, use the java classloader which is extremely good at efficient locking – at least as good as anything you can write in java and possibly better:
JavaScript

This works because java doesn’t load classes until it is needed, and nothing ‘touches’ CoreSingletonHolder (causing it to be loaded), except invoking the get() method. Hence, new Core() is executed exactly once, and only once, as per JVM guarantees, using ClassLoader’s own locking mechanism, which is very efficient. It’s efficient because java has to do this with every single last class your app ever loads. If it wasn’t efficient, java/android would be dog slow, and we know it isn’t, QED.

  • Your intended singleton instance is public and non-final; anything can overwrite it. The above strategies fix these issues; given that all access needs to go through get() in order to ensure its initialized, why make it public?
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement