On 13 July 2016 at 22:47,  <mark.reinh...@oracle.com> wrote:
> To put what Alex wrote in a somewhat different way, I'd say that the
> tension here is between explicit configuration (as one finds today in,
> e.g., the Maven world) and implicit configuration (IoC).  Both approaches
> are important.  The former is typical of standalone Java SE applications
> while the latter is typical of Java EE applications, though the two
> approaches are often intermixed.

I would caution against simplistic use cases for reflection and
setAccessible. Both are widely used, and I would argue are one of the
cornerstones of the success of Java. ie. Java provides a nice safe
world for most developers, but provides the ability to step down and
access the internals if necessary.

Looking through the code currently in my IDE I see reflection and
setAccessible used for:

- access Unsafe, for which alternatives are being provided (lots)
- access beans for command line setting (JCommander)
- access bean properties (Joda-Beans)
- access beans for XML/JSON/binary serialization (Joda-Beans)
- access Types.newParameterizedType() in Guava (Joda-Convert)
- access Thread.inheritableThreadLocals (Guava)
- set final fields during deserialization (Guava)
- deliver messages to annotated subscriber methods (Guava)
- set private fields during configuration (BoneCP)
- find enum-like constants declared in a class (Strata-Collect)
- access beans (Sleepycat)
- set field to workaround bug in HttpURLConnection (Jersey)
- access and invoke annotated fields/methods (Jersey)
- access ClassLoader.defineClass to create class from bytecode (Jersey)
- access JAXB element name by creating an instance to call API (Jersey)
- access methods for expression language walking (JUEL)
- invoke task started/finished API in Ant (Groovy)
- creating bytecode and querying generated proxies (Javassist)
- create bean instance and bind to fields/methods (EHCache)
- query all fields to determine object size (EHCache)
- expression language (EHCache)
- obtain an instance for testing (Terracotta)
- access field/method for parsing (Antlr)
- produce a toString() based on fields (ActiveMQ)
- access beans (Commons-BeanUtils)
- access fields/methods (Commons-Lang)
- delayed deserialization of large matrix, setting field (Commons-Math)
- merge two objects, setting non-public field (Apache Shiro)
- produce a toString() based on fields (KahaDB)
- create an instance of a failure in JUnit (AssertJ)
- inject from JNDI into a bean field/setter (Jetty)
- invoke a lifecycle method (Jetty)
- access ClassLoader.defineClass to create class from bytecode (Hawt-Dispatch)
- produce a toString() based on fields (Hawt-Dispatch)
- access beans for ORM query/update (HIbernate)
- access beans for ORM code generation (HIbernate)
- access beans for JSON serialization (Jolokia)
- spy on fields/methods (Mockito)
- access Java deserialization internals (Objenesis)
- access SqlMapConfigParser.state in iBATIS (Spring)
- expression language (StringTemplate)
- create and run tests (TestNG)
(this doesn't list every use, just some key/obvious ones)

Looking through this list (obtained by manually examining uses of
setAccessible) there are some repeating patterns, but other use cases
are unique. The common ones are:

- beans and properties (includes config, serialization, ORM and
expression language)
- reflection-based toString() - related to beans/properties
- accessing something in another project that should have been public
- accessing something in another project to workaround a bug
- access Unsafe

I did this to ensure that me expectation was correct - that reflection
is used absolutely everywhere in Java. It will simply not be possible
for developer to restrict the packages they expose to prevent
reflection. (The use cases where reflection really must be prevented
are very few AFAICT)

I'd also note that a large portion of the problem is due to the
terrible Java beans approach (and the unwillingness of the team
maintaining Java to address the problem of beans/properties over many
years). Sadly my effort [1] has not gone anywhere, but a new API is
really needed in this area to avoid all this ad-hoc and incompatible
reflection of beans/properties.

In summary, restricting reflection/setAccessible would effectively be
signing the death warrant of Java, and there is IMO no choice but for
all packages to be exported at runtime given the current ecosystem.

Stephen

[1] https://github.com/jodastephen/property-alliance

Reply via email to