A way to opt out of access restrictions on non-exported members.
Stephen Colebourne
scolebourne at joda.org
Mon Nov 16 12:28:22 UTC 2015
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.
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
PS. I'm reminded of Java's missing "properties" feature again, cf.
http://jodastephen.github.io/property-alliance/
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