Discussion:
why is modularity changing the rules of inheritance?
Bernard Amade
2018-03-13 09:23:52 UTC
Permalink
Hello all (OOps! wrote "Hell all" )

just curious to read about the rationale behind this behaviour:
if you have a code in moduleB that inherits from code in moduleA, modularity wise the inherited methods behave as if they were invoked from moduleA (not from moduleB). see an example at the end of this post.
Naïvely found this behaviour *very bad* but I suppose that if it were not the case then the situation could be worse... so I would like to read the rationale behind this.

thanks

code of a service definition in moduleA:
-----------------------------------------------
public abstract class PropertiesProvider {
public Properties get(String domain) {
Class clazz =this.getClass();
System.out.println(" CLASS " +clazz);
try {
Object obj = clazz.getConstructor().newInstance();
System.out.println("Object " + obj);

} catch (Exception exc) {
exc.printStackTrace();
}
InputStream is = clazz.getResourceAsStream(domain) ;
if (is != null) {
Properties props = new Properties();
try {
props.load(is);
return props;
} catch (IOException e) {
System.getLogger("").log(System.Logger.Level.WARNING,e) ;
}

}
and so on ...
now if in module B you just create a Service by inheriting from this class:
- the className is correct (an instance of the class has been created for the service)
- you can't invoke newInstance from that very class!(if the class is not opened or exported)
- you can't get the Resource (or other files) unless they are explicilty opened.
if you copy this code in the class implementing the service everything just works fine
so there is a difference between the same code being explicitly in the class or inherited!
(got a headache trying to find something to say for people learning Java)
Alan Bateman
2018-03-13 10:12:22 UTC
Permalink
Post by Bernard Amade
- the className is correct (an instance of the class has been created for the service)
- you can't invoke newInstance from that very class!(if the class is not opened or exported)
Constructor::newInstance has always been caller sensitive. If I read the
example correctly, you've got code in class A trying to create an
instance of class B. B is not accessible to A, it doesn't matter that B
extends A. The issue you are running into isn't new with modules -
you'll see the same IllegalAccessException with the class path for the
case that B is not public (and in a different package to A).
Post by Bernard Amade
- you can't get the Resource (or other files) unless they are explicilty opened.
if you copy this code in the class implementing the service everything just works fine
so there is a difference between the same code being explicitly in the class or inherited!
The Class.getResourceXXX methods are also caller sensitive so the
example is code in class A trying to locate a resource in its own
module. If you maintain both A and B then it would be simpler if B were
to call the method in the super class with a connection or URL to the
resource.

-Alan.
Gregg Wonderly
2018-03-13 16:32:22 UTC
Permalink
This is pretty much what was lamented about on the list as the project proceeded. In the end, the restrictions you see are because all the system classes in the Java VM implementation need to be protected in this way to provide the opportunity for evolution of the implementations underlying the JVM. Rather than implementing some customization of visibility “into” specific system classes, we all get to deal with having visibility changes that break existing code which uses introspection for IoC etc.

Practically, Jigsaw feels like too little too late for Java improvement over all. It’s way past the time when people would be satisfied to see Java fixed in places where underlying APIs were not sufficient and so introspection based fixes ended up being made, or base JVM classes replaced with bootclasspath.

There seems to be an honest effort to try and fix things in the base of Java by this work, but the cloud environment is being overrun by .Net, just because of the number of developers being trained there, vs the J2EE disaster. .Net is not an attractive solution for stability reasons however.

Additionally, the desktop environment is so overrun by other platforms due to the lack of focus on media support and fixes to Swing/AWT problems, that Java on the desktop is probably not as interesting as it once was.

Swift, Go, .Net and a few other platforms have much more productivity for creating usable applications, and are being taught and used much more prolifically than Java. Apple pulled away from Java completely as Swift came flying into view. That was a pretty good number of nails into the coffin.

Oracle has a bad name in many places because of “Android”, “Jenkins”, “MySQL” and other Oracle things around open source arguments. People are standing at a distance from anything that Oracle is doing because they tire of the argumentative and restrictive control that is constantly changing for the worse.

It’s really a sad state of affairs given the opportunity for unification of programming language/platform that Java once offered…

Gregg
Post by Bernard Amade
Hello all (OOps! wrote "Hell all" )
if you have a code in moduleB that inherits from code in moduleA, modularity wise the inherited methods behave as if they were invoked from moduleA (not from moduleB). see an example at the end of this post.
Naïvely found this behaviour *very bad* but I suppose that if it were not the case then the situation could be worse... so I would like to read the rationale behind this.
thanks
-----------------------------------------------
public abstract class PropertiesProvider {
public Properties get(String domain) {
Class clazz =this.getClass();
System.out.println(" CLASS " +clazz);
try {
Object obj = clazz.getConstructor().newInstance();
System.out.println("Object " + obj);
} catch (Exception exc) {
exc.printStackTrace();
}
InputStream is = clazz.getResourceAsStream(domain) ;
if (is != null) {
Properties props = new Properties();
try {
props.load(is);
return props;
} catch (IOException e) {
System.getLogger("").log(System.Logger.Level.WARNING,e) ;
}
}
and so on ...
- the className is correct (an instance of the class has been created for the service)
- you can't invoke newInstance from that very class!(if the class is not opened or exported)
- you can't get the Resource (or other files) unless they are explicilty opened.
if you copy this code in the class implementing the service everything just works fine
so there is a difference between the same code being explicitly in the class or inherited!
(got a headache trying to find something to say for people learning Java)
Loading...