On Fri, Apr 13, 2018 at 2:24 PM, Mark Raynsford <list+org.o...@io7m.com> wrote:
> On 2018-04-13T12:11:41 +0100 > Neil Bartlett <njbartl...@gmail.com> wrote: > > > > To be clear, I'm not convinced OSGi would ever want to do this. If we > did, > > we would likely invert the default from "closed" to "open". Closing off a > > bundle to ALL access, even reflectively, seems like an extreme measure > that > > would only be necessary in fairly unusual circumstances, so I believe > that > > JPMS has the default the wrong way around. It's useful to compare with > Java > > classes, which can be made final but are not final by default. > > I'm not sure if we're talking about the same thing. It also seems a > little strange to hear that: For me one of the main attractions about > OSGi is that I get to state what's visible to the outside world and > what isn't. This gives me the freedom to change things without breaking > consumers. For the sake of the discussion, we could assume that bundles > in the new magic OSGi container are all open for reflective access (but > that the non-exported parts are still inaccessible, as with JPMS > modules). > It's definitely possible that we're talking about different things, but let me explain myself a little more. In OSGi today, private packages are not ordinarily visible to other bundles. That means I cannot just write plain code that depends on a private type and have OSGi load that type for me. However I can load classes, including classes that exist in private packages, from any bundle using Bundle.loadClass(). Actually if Java security is enabled then we can restrict the permissions around that, which gets very close to the isolation that JPMS offers, but apparently nobody ever uses Java security so here we are... This is the equivalent of an "open module" in JPMS parlance, and I argue that it is the better default. It makes bundles accessible to frameworks such as dependency injectors, marshallers, ORM mappers, etc. I still have the freedom to change my internals though: by not exporting a package I have given a clear indication to other developers that the package is private. If they go ahead and use reflection to work around the visibility protections, then they cannot call foul when I change my internals and break them. Therefore I believe that the strong isolation offered by "closed" modules in JPMS is only needed for security-critical code. > > Mainly what I'm referring to is that I'd want the VM to believe that > any assumptions that it can make about a JPMS module, for optimization > purposes, it could also make those same assumptions about a bundle in > our container. The same goes for assumptions that javac can make (but > this is less interesting because it's easy to make something that's > both an OSGi bundle and a JPMS module at compile time). > Yes I agree that's an additional benefit, but I'm not clear on what those optimizations might be. > > There was a recent thread on the amber-experts list, for example, that > talked about modifying the exhaustiveness check for switches over enum > values based on whether the enum type is the same module as the switch > or not. I got the feeling that this idea was rejected, but the > point is that there's this looming possibility that language features > will depend on module boundaries sooner or later, and so we should > probably want to allow OSGi bundles to be treated as equals to JPMS > modules, and for the VM and JIT to see them as the same thing. > That's an interesting use case, but surely it would only be useful where an enum is private to a module? If it's exported then you cannot check switch statements in modules that haven't been written yet. And if it's private to the module/bundle then we can check all switch statements using existing tools. Java language features already do depend on the concept of accessibility: e.g. the compiler can optimize access to a private field because it knows all the places where the field is used, and potentially remove a redundant volatile modifier or synchronization block. JPMS creates a new level of accessibility applied to public types. I believe that any techniques the compiler applies based on module membership could also be used when the compiler can call my proposed checkAccess method... SO LONG AS the same checkAccess is used at both compile and runtime. Admittedly this complicates matters, and might require putting information into the module metadata about the compile time checks that were used. However I think that compile-time optimizations that depend on module boundaries are a long way in the future, if they ever come. As long as the module system is optional, you will be able to take a module and put it on the classpath, invalidating all the assumptions the compiler made about accessibility. > > > > > > > Let's assume that, for the perspective of someone using this magic new > > > OSGi container, the goal is to have it behave pretty much like an OSGi > > > container already behaves (modulo the R7 java.* changes): An OSGi > > > bundle can only depend on OSGi bundles, > > > > Note quite true. OSGi bundles depend on capabilities... > > Yes, agreed. I phrased it poorly. My point was more that you depend on > something that is almost certainly provided by a bundle (perhaps via > the system bundle exporting packages from a JPMS module). For the sake > of limiting the scope a bit, I introduced the notion that "bundles > depend on bundles" so that people wouldn't think I was talking about > bundles being able to depend on arbitrary JPMS modules outside of the > container without anything special being done by the container to make > this work. > Granted. > > > > What additions to the JPMS APIs would be needed to make this a reality > > > today? > > > > > > > I think the starting point is as simple as a callback interface along > these > > lines: > > > > void checkAccess(Class from, Class to) throws > IllegalAccessException; > > > > The JVM would call this each time it needs to check whether "from" is > > allowed to access "to". It would be able to cache the answer because when > > an OSGi bundle is updated we get a new ClassLoader and a new Class > > identity. The JVM would also have some built-in checks before invoking > this > > method, to allow it to lock out the application layer from JVM internals. > > > > The above should work at runtime for both OSGi and JPMS. To implement > > compile-time checks you need something else to stand in for the > identities > > or locations of the two input types. > > Would you intend this to be a fundamental primitive such that the JPMS > would be reimplemented in terms of this callback? How and where would > one implement this callback? If I have multiple OSGi containers in the > same JVM, along with modules in a separate JPMS system... How many > implementations of it are there, and which one "wins" (if any)? > I think that JPMS *could* be implemented on top of this as a fundamental primitive, but it's very unlikely to happen. These are obviously details that require careful consideration. My initial thoughts are that the callback could be implemented as a service that is configured once in the JVM, probably via a command line switch. In order to support things like multiple OSGi frameworks, you could have a composite implementation that delegates to child or sibling frameworks. At this point I'm happy to wave my hands and say "a solution exists" without spending too much time working out that solution. Given the improbability of this going anywhere, any such effort feels like it would be wasted. Neil > > -- > Mark Raynsford | http://www.io7m.com > >
_______________________________________________ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev