On 12/20/2024 12:48 PM, David Lloyd wrote:
A replacement library (or even an original library) might be
obligated to change one of *its* implementation dependencies (like a
utility library) due to security problems of this sort, and since it
is an implementation detail, it would not be natural to expect any
user to consider that the third library's having a different API/
package set could introduce some new hygiene problem. We've always
considered it to be a natural property of encapsulation for the
consumers of A to not have to worry about what's going on with C in
an A->B->C scenario (or its presence or absence).

We view _encapsulation_ as being achieved via _accessibility_: the ability of the JVM to prevent access to classes if either the accessing module does not consume (does not "read") the classes' module, or if the accessing module does consume ("read") the classes' module but the classes' module does not export the classes.

Let's talk about the A->B->C scenario.

Suppose a consumer of A, called M, obtains a reference to an object of a class defined in C. This can happen in innumerable ways, and the reference can have a variety of types: Object, Serializable, some interface defined by A, etc. Even if C exports the class, M does not consume (does not "read") C. So, no access for M's code to C's code. M's code cannot do anything interesting with the object it obtained.

This accessibility mechanism is orthogonal to class loaders. All the classes in M, A, B, and C could be defined by the same class loader.

M can easily arrange to consume C, via `requires` or addReads. If that happens, then C's predilection for exporting classes means that M's code can access C's code. Of course it can! If C didn't want arbitrary code to access its classes, then C should have qualified its exports.

When you say that M should "not have to worry about what's going on with C", I think you mean that _even if C exports all its classes and even if M arranges to consume C_, some additional mechanism should provide _isolation_ for C, such that M's code cannot access C's code.

Such isolation would open the door to replacing C by D -- a module with different bits, and different dependencies, but the same name and exports as C. D and all of its dependencies would be outside the worry range of M, just as C was.

Alex

Reply via email to