A way to opt out of access restrictions on non-exported members.

Remi Forax forax at univ-mlv.fr
Mon Nov 16 22:12:04 UTC 2015

Hi Stephen,

----- Mail original -----
> De: "Stephen Colebourne" <scolebourne at joda.org>
> À: "jigsaw-dev" <jigsaw-dev at openjdk.java.net>
> Envoyé: Lundi 16 Novembre 2015 13:28:22
> Objet: Re: A way to opt out of access restrictions on non-exported members.
> Access to private members of classes by reflection is indeed very,
> very common. I agree that JDK 9 needs to be cautious around this.
> For me, I'm not yet sure I'm comfortable with setAccessible(true) no
> longer being sufficient to access them.
> I did wonder if perhaps a change could be made such that any instance
> of 'Class' passed into a module would automatically be granted the
> necessary enhanced module readability. Unfortunately, I don't think it
> will be enough for most serialization frameworks, as they traverse a
> graph of objects.

We discuss something like this at Devoxx,
add a read edge between the current module and the module of the declaring class when you do a setAccessible on a member of that class.

This will not solved all the issues, frameworks will still not be able to call setAccessible on a non exported class but i think it will fix most of the issues if (and it's a big if) creators of modules do not allow non-exported classes to leak. 

> I do think that there may need to be separate JDK 8 and 9 versions of
> many OSS libraries (for which the multi-version jar file is one
> option). This will certainly slow adoption.
> Stephen


> On 15 November 2015 at 11:03, Reinier Zwitserloot
> <reinier at zwitserloot.com> wrote:
> > TL;DR: There are rather a lot of libraries out there that access private
> > members via reflection. I posit that almost all such libraries break
> > without an easy way to fix the problem, if there is no way to use
> > reflection to access non-exported members.
> >
> >
> >
> > setAccessible(true) doesn't let you opt out of module access rules. There
> > are ways to effectively 'read' everything (and if not, there's addRead),
> > but that still doesn't help if you need to reflectively access a member
> > that isn't exported. According to the questions at the end of the J1
> > session 'Advanced Modular Development (CON6821)', by Mark Reinhold, Alex
> > Buckley, and Alex Bateman, there is no way to in-process get around the
> > JVM-enforced access restriction.
> >
> > Now, under normal circumstances you shouldn't be accessing such classes /
> > methods / fields / constructors in the first place, but that exact same
> > line of reasoning can be used to defend not including setAccessible,
> > getDeclaredMethod(s), getDeclaredField(s), and all the other ways the
> > reflection API can be used to access (in JDK1-JDK8, at least) protected,
> > package private, and private elements. Those things were never designed to
> > be accessed either, and yet, accessing private members of existing stuff
> > occurs in lots of libraries, usually for:
> >
> > * Dependency injection (guice and company)
> >
> > * Debugging tools (not all of these use JVMTI; sometimes you just have a
> > utility method that dumps some information to a log that includes private
> > members just because that seems like it'll help debug an exotic condition
> > that you can't quite put your finger on).
> >
> > * Code automation tools (apache has a few utilities that return a useful
> > hashCode, which work by inspecting your instance's fields).
> >
> > * Serialization libraries. I'm pretty sure a number of core JDK devs have
> > gone on record not liking the built in serialization mechanism
> > (java.io.Serializable and co), but third party solutions access private
> > members all the time to do their job.
> >
> > * Workarounds. This one is a perhaps controversial, but as the saying goes,
> > java is a 'blue collar' programming language. Sometimes you use access to
> > private members to work around a bug or to get access to functionality that
> > optimally speaking should be done differently or should be accomodated with
> > an update to the library to make that part designed for public access.
> >
> > What are such libraries to do? They could provide the user with ways to use
> > command line switches to hack in the required exports, but this is the kind
> > of hassle that is going to reflect badly on JDK9 and slow adoption rates. I
> > propose some mechanism to get around the restriction is added, with all due
> > warnings in the documentation that this should be considered a hacky
> > workaround. (interestingly, such commentary is not part of the javadoc on
> > .setAccessible!)
> >
> > Alternatively, there are 3 ways this can go:
> >
> > * The authors of these libraries, or the help forums associated with such
> > libraries, start espousing the principle that you should just export
> > everything from your modules, or 'things might break'. This doesn't sound
> > like a desirable outcome for the jigsaw project. It certainly doesn't sound
> > desirable to me.
> >
> > * The authors of these libraries, or the help forums associated with this
> > libraries, start espousing the principle that upgrading to JDK9 is an
> > arduous slog, and that it is better to just stick with JDK8 for the
> > foreseeable future. Certainly, not a desirable outcome.
> >
> > * The heavens part, ponies and rainbows for all, and everyone takes the
> > time to update their serialized data structures or whatnot to make sense in
> > a 'these are exported, these are not' world. I'm not sure this is even
> > possible; it would make sense to have a public interface, and then 2
> > (non-exported!) classes that are implementations of this. How would a
> > no-hassle serialization library ever get this done without a way to dodge
> > the rules? A module can export _TO_ a serialization library, but this
> > breaks encapsulation: Now the author of framework A needs to know that the
> > user of said framework so happens to have a desire to serialize the stuff
> > from framework A using serialization library X. In practice you'd have to
> > export everything to all the serialization frameworks out there, and now no
> > new framework can ever be created because all these libraries failed to
> > export their internals to them. In any case this boils down to 'just export
> > every package to this subset of tools',  and that's the best case scenario,
> > which doesn't sound desirable either.
> >
> > I guess option 4 is: "Surely it won't be that bad", but that's a bit of a
> > gamble to make, given that the stakes are serious lack of adoption of JDK9,
> > or widespread misconfiguration of exports clauses.
> >
> > NB1: Note also that JDK9 has taken its time (and rightly so) to fix its
> > ball-o-twine dependency mess. However, once JDK9 is unleashed upon the
> > masses, a 'quick fix' to make libraries at least workable with JDK9
> > probably require such hacks. If it's not possible to do it, then libraries
> > won't be JDK9 ready for years. Perhaps other projects aren't as messy as
> > JDK pre-9 was, but let's not make that assumption.
> >
> > NB2: The module system already has a larger impact on adoption (compared to
> > 6, 7, or 8) simply because of the unavoidable differences inherent in what
> > jigsaw is doing (I bet a bunch of command line scripts are going to end up
> > breaking, for example, or at least will be obsolete). Adding more barriers
> > to adoption is something that should, in my opinion, by taken particularly
> > seriously for this release.
> >
> >  --Reinier Zwitserloot

More information about the jigsaw-dev mailing list