Hi Alan, I just tried to get an overview to answer what you have asked and some of the internal types being used are for example the specific JMX bean implementations rather than their interfaces to expose some additional metrics that someone at customer ops required at some time following the commit history. Those are part reflection, part hard-coded, mainly depending on a type's visibility. To be honest, the containing modules do not change much and are not recompiled often, I guess neither did people care too much as long as things worked. There is still a lot of "old" code that does not even use generics yet and there are compiler warnings all over the place. Unfortunaely, code migration jobs tend to surpass code segments that people do not often work with. To stop using internal types is not even the first thing I would like to see changed in this part of the code base.
About our own reflective code, here is a very common pattern of the application in question that I found especially problematic and which is one of the reasons I went for the "weak modules only approach". Consider the following code: package com.acme; interface Foo { Foo getInstance() { return new Bar(); } void qux(); } package com.acme.internal; class Bar implements Foo { public void qux() { /* something */ } } <rules-engine> <rule> <method>qux</method> </rule> </rules-engine> triggering in the following reflective invocation in the Java layer of the rule engine's module: Object foo = Foo.getInstance(); foo.getClass().getMethod("qux").invoke(foo); // Causes IllegalAccessError In the actual application, the type of Foo is of course not given at this point, this is a simpliciation. As the above reflection implicitly invokes "qux" on WorldImpl rather than World, this results in an IllegalAccessError. Neither is the Bar class supposed to be exposed from the module but when Java 4 came out and XML was still cool, this is what people went for. For this and many other reasons, as for this particular application, I do not believe it will ever make it past the "weak module" phase. A lot of code was built based on the assumption that reflection can just cut through. And while the hack with the agent is of course not show-casing my personal preference of how to structure an application, it is an easy work-around for us to make code work correctly that would be non-trivial to change or is contained in a third-party library. Probably, this solution will make the customer the happiest, too, considering how expensive development hours are. After making my first actual Java 9 experiences, I also want to add just one personal comment given my background in enterprise programming: Jigsaw is a great addition and I do really want to use modules. Having them feels very right and adding them immediately uncovers poorly structured Maven modules. I am sure, this will greatly influence application design of future Java applications. However, for the adoption process, I think it is crucial that non-modularized code behaves as it did before, i.e. that non-modularized code shows the same behavior when its run on a Java 9 VM. Given the enormous landscape of Java libraries and so many millions of code lines being written, I think this reflective access restriction will furstrate many users as it is difficult to make isolated changes that do not trigger global effects. In this context, it will always be the easiest to drop the module migration alltogether and it would be a shame if Jigsaw modules were not used as much as they should be only for this reason. Thanks for taking so much time giving feedback on my experience report. Best regards, Rafael 2016-10-01 21:29 GMT+02:00 Alan Bateman <alan.bate...@oracle.com>: > On 30/09/2016 16:16, Rafael Winterhalter wrote: > > > With the newest EA build, out of 7000 unit tests, only >>> 42 tests still fail and those are all because of using non-exported API >>> of >>> the JCL. >>> >> Just curious, what is "JCL" here? >> > > I mean "Java class library", the classes that are part of the JVM. > > Are there many JDK internal APIs bring used? Are all these usages using > core reflection (and so not found by jdeps). > > > > : > > I was using reflection for this functionality and offered a fallback or > offered a proper failure message. I did however manage to fix most of these > problems in the last hours by revisiting them. I am currently down to a > single failing unit test which relates to Class.forName(typeName, false, > classLoader) not returning its loaded classes if the class loader is an > instance of "DelegatingClassLoader". I worked around this by reading the > class containing vector for instances of this class loader and wrote a unit > tests that is no longer executable. As it only affects the test, this does > however not really matter. > > Is the DelegatingClassLoader that is used in the internal reflection > implementation or is it something else? > > > > : > > I hope this is clear now from my above clarification. I was trying out > explicit, "proper" modules and added dependent jars as automatic modules. > > Just on this, I'm interested to know if the modules names that were chosen > for the automatic modules work out okay? When you migrated automatic > modules to explicit modules then did you keep the module name? > > -Alan >