On 29.12.2016 18:24, Rafael Winterhalter wrote:
Hei Jochen, thank you for your feedback. I must have missed your posting, I regularly fail to follow up on the things discussed on the mailing list and its not easy to seatch for topics, sorry for that.
don“t worry, my complaints have not been ignored, but did not change anything either.
In Byte Buddy, I created an option to use subclassing by creating dedicated class loaders for proxy classes. There is however a row of disadvantages: 1. Class loaders are not cheap objects, they require some memory and the performance cost of creating dedicated class loaders is significant. I have benchmarked this, as well and it costs you about three times the time to create such "wrapper class loaders" rather than injecting.
agreed
2. It is close to impossible to define a good life-cycle for classes loaded by such wrapper class loaders. You need to keep a reference to the proxy class to prohibit its collection which in turn keeps a reference to the original class loader making it uncollectable. Using soft or weak references is less then ideal, too and the only option would be to use ephemerons which are not supported by Java. With injection, it is as easy as looking up a previously created class from the proxied class's class loader which dies and lives with this class loader.
A ClassValue is no ephemeron, but letting it keep a SoftReference to the proxy class may work. It means there will be situations in which the class will be recreated, but thanks to the SoftReference both classes and loaders should still be garbage collectable.
3. Java packages define their identity by name and class loader at runtime. Many developers use anonymous classes or nested classes which are package-private and cannot be subclassed by creating a new class loader but which must live in the same class loader.
package-private is another story... I would be happy enough to have a generic solution for protected.
and 4. if the loader is defined by a module you will have fun with creating layers and export/read edges
Those are the main issues that lead us to strongly prefer injection, especially in a testing library like Mockito and there are some more complications that we would like to avoid.
the reply will most probably be about asking why these classes are not made public. They can be exported to only the framework module and all that.
I am however especially concerned about upgrading. Esepcially with mature and wide-spread libraries like Mockito or Hibernate, even minor changes can cause really big, hard-to-debug issues for our users.
been there and I agree. But it is unlikely that something like the implementation of strong encapsulation will be done without trouble for bigger projects. Will this lower adoption of Java9? Sure.
Switching from injection to subclassing would be much more than a minor change. The JVM developers surely know this, otherwise they would not keep classes like Stack around or fix quirks in classes like ByteBuffer. Too much code was written on top of these classes and their expected inner working. If we were however forced to change our APIs that drastically, I think the real consequences would be much more drastic than the mentioned changes. At the moment, as a library author, I do however feel like there are few options to avoid this.
On the other hand... if you think it has to be done at some point, then why delay it? Of course the question of if it has to be done is questionable in itself, especially since the slim advantages of the module system turn into the negative, if weighted against "other solutions", the work you will have with it and the limitations it imposes.
bye Jochen