Daniel Sun created GROOVY-9103:
----------------------------------
Summary: CLONE - CLONE - Fix warning "An illegal reflective access
operation has occurred"
Key: GROOVY-9103
URL: https://issues.apache.org/jira/browse/GROOVY-9103
Project: Groovy
Issue Type: Improvement
Components: groovy-jdk
Affects Versions: 2.4.11, 2.4.15
Environment: >gradle --version
Gradle 4.2
Build time: 2017-09-20 14:48:23 UTC
Revision: 5ba503cc17748671c83ce35d7da1cffd6e24dfbd
Groovy: 2.4.11
Ant: Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM: 9 (Oracle Corporation 9+181)
OS: Windows 10 10.0 amd64
Reporter: Benjamin Roedell
This cloned issue is to cover the rest part of case ② as mentioned in
GROOVY-8339.
*?* means that we should discuss the case further as some breaking changes may
be introduced.
h4. 1) Sub-class derives the public members from {{package-private}} class, but
invoke the members on the sub class instances, e.g.
*-1.0) Non-category-*
[https://github.com/apache/groovy/blob/master/subprojects/groovy-groovysh/src/main/groovy/org/codehaus/groovy/tools/shell/Groovysh.groovy#L532]
*-1.1) Category-*
[https://github.com/apache/groovy/blob/master/src/spec/test/TraitsSpecificationTest.groovy#L835]
h4. 2) Sub-class derives the {{protected}} members from public class,
*2.0) ?Invoke the members on the sub class instances, e.g.*
[https://github.com/apache/groovy/blob/master/subprojects/groovy-swing/src/test/groovy/groovy/beans/BindableSwingTest.groovy#L31-L40]
We are considering to generate stub/bridge methods automatically.
{color:#d04437}_*2.1) Clone array via {{clone}} method of {{java.lang.Object}}
( Note: the method is {{protected}}, truely illegal access, we should fix our
code), e.g.*_{color}
[https://github.com/apache/groovy/blob/master/src/test/org/codehaus/groovy/transform/ImmutableTransformTest.groovy#L163-L180]
As we can see, {{groovy.transform.Immutable}} will generate the code to invoke
{{clone}} on array object:
{code:java}
@groovy.transform.Generated
public HasList(java.util.Map args) {
metaClass = /*BytecodeExpression*/
if ( args == null) {
args = [:]
}
org.codehaus.groovy.transform.ImmutableASTTransformation.checkPropNames(this,
args)
if ( args .letters == null) {
this .letters = null
} else {
this .letters =
((org.codehaus.groovy.runtime.ReflectionMethodInvoker.invoke( args .letters,
'clone', new java.lang.Object[][])) as java.lang.String[])
}
if ( args .nums == null) {
this .nums = null
} else {
if ( args .nums instanceof java.lang.Cloneable) {
this .nums =
((((org.codehaus.groovy.runtime.ReflectionMethodInvoker.invoke( args .nums,
'clone', new java.lang.Object[][])) as java.lang.Object) instanceof
java.util.SortedSet ?
org.codehaus.groovy.runtime.DefaultGroovyMethods.asImmutable((((org.codehaus.groovy.runtime.ReflectionMethodInvoker.invoke(
args .nums, 'clone', new java.lang.Object[][])) as java.lang.Object)) as
java.util.SortedSet<E extends java.lang.Object>) :
((org.codehaus.groovy.runtime.ReflectionMethodInvoker.invoke( args .nums,
'clone', new java.lang.Object[][])) as java.lang.Object) instanceof
java.util.SortedMap ?
org.codehaus.groovy.runtime.DefaultGroovyMethods.asImmutable((((org.codehaus.groovy.runtime.ReflectionMethodInvoker.invoke(
args .nums, 'clone', new java.lang.Object[][])) as java.lang.Object)) as
java.util.SortedMap<K extends java.lang.Object, V extends java.lang.Object>) :
((org.codehaus.groovy.runtime.ReflectionMethodInvoker.invoke( args .nums,
'clone', new java.lang.Object[][])) as java.lang.Object) instanceof
java.util.Set ?
org.codehaus.groovy.runtime.DefaultGroovyMethods.asImmutable((((org.codehaus.groovy.runtime.ReflectionMethodInvoker.invoke(
args .nums, 'clone', new java.lang.Object[][])) as java.lang.Object)) as
java.util.Set<E extends java.lang.Object>) :
((org.codehaus.groovy.runtime.ReflectionMethodInvoker.invoke( args .nums,
'clone', new java.lang.Object[][])) as java.lang.Object) instanceof
java.util.Map ?
org.codehaus.groovy.runtime.DefaultGroovyMethods.asImmutable((((org.codehaus.groovy.runtime.ReflectionMethodInvoker.invoke(
args .nums, 'clone', new java.lang.Object[][])) as java.lang.Object)) as
java.util.Map<K extends java.lang.Object, V extends java.lang.Object>) :
((org.codehaus.groovy.runtime.ReflectionMethodInvoker.invoke( args .nums,
'clone', new java.lang.Object[][])) as java.lang.Object) instanceof
java.util.List ?
org.codehaus.groovy.runtime.DefaultGroovyMethods.asImmutable((((org.codehaus.groovy.runtime.ReflectionMethodInvoker.invoke(
args .nums, 'clone', new java.lang.Object[][])) as java.lang.Object)) as
java.util.List<E extends java.lang.Object>) :
org.codehaus.groovy.runtime.DefaultGroovyMethods.asImmutable((((org.codehaus.groovy.runtime.ReflectionMethodInvoker.invoke(
args .nums, 'clone', new java.lang.Object[][])) as java.lang.Object)) as
java.util.Collection)) as java.lang.Object)
} else {
this .nums = (( args .nums instanceof java.util.SortedSet ?
org.codehaus.groovy.runtime.DefaultGroovyMethods.asImmutable(( args .nums) as
java.util.SortedSet<E extends java.lang.Object>) : args .nums instanceof
java.util.SortedMap ?
org.codehaus.groovy.runtime.DefaultGroovyMethods.asImmutable(( args .nums) as
java.util.SortedMap<K extends java.lang.Object, V extends java.lang.Object>) :
args .nums instanceof java.util.Set ?
org.codehaus.groovy.runtime.DefaultGroovyMethods.asImmutable(( args .nums) as
java.util.Set<E extends java.lang.Object>) : args .nums instanceof
java.util.Map ? org.codehaus.groovy.runtime.DefaultGroovyMethods.asImmutable((
args .nums) as java.util.Map<K extends java.lang.Object, V extends
java.lang.Object>) : args .nums instanceof java.util.List ?
org.codehaus.groovy.runtime.DefaultGroovyMethods.asImmutable(( args .nums) as
java.util.List<E extends java.lang.Object>) :
org.codehaus.groovy.runtime.DefaultGroovyMethods.asImmutable(( args .nums) as
java.util.Collection)) as java.lang.Object)
}
}
}
{code}
{color:#d04437}_*2.2) Access the overrided {{protected}} method of
sub-class(Truely illegal access, we should fix our code), e.g.*_{color}
[https://github.com/apache/groovy/blob/master/src/test/org/codehaus/groovy/transform/classloading/TransformsAndCustomClassLoadersTest.groovy#L124]
{{AppClassLoader}} derives {{ClassLoader}}, but {{Class<?> loadClass(String
cn, boolean resolve)}} of {{AppClassLoader}} is still {{protected}}, we should
not access it if we do not want warnings.
{color:#d04437}_*2.3) Access the {{protected final}} method(Truely illegal
access, we should fix our code), e.g.*_{color}
[https://github.com/apache/groovy/blob/master/src/test/org/codehaus/groovy/reflection/SecurityTest.java#L243-L258]
{{protected final Class<?> defineClass(String name, java.nio.ByteBuffer b,
ProtectionDomain protectionDomain)}} of {{ClassLoader}}
h4. -3) Access {{public}} members of {{private}} class, e.g.-
[https://github.com/apache/groovy/blob/master/subprojects/groovy-console/src/main/groovy/groovy/inspect/swingui/ScriptToTreeNodeAdapter.groovy#L235]
{{java.util.Collections.UnmodifiableMap::toString}}
We should try to find the overrided member of its base class and
access(virtual invocation will happen eventually)
h4. -4) Access {{public}} members of {{package-private}} class, e.g.-
[https://github.com/apache/groovy/blob/master/src/spec/test/gdk/WorkingWithIOSpecTest.groovy#L355]
{{java.lang.ProcessImpl::waitFor}}
We should try to find the overrided member of its base class and
access(virtual invocation will happen eventually)
h4. -5) Favor the method with more accurate parameter type even if it is not
visible, e.g. {{EnumMap::equals(EnumMap<?,?>)}}-
[https://github.com/apache/groovy/blob/master/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/util/ASTComparatorCategory.groovy#L271]
When comparing two {{ClassNode}} instances, {{ClassNode.transformInstances}}
will be compared, their type is {{EnumMap}}
h4. 6) ?Get {{properties}} of objects(including {{private}} methods)
[https://github.com/apache/groovy/blob/master/src/test/org/codehaus/groovy/classgen/asm/sc/ArraysAndCollectionsStaticCompileTest.groovy#L68]
{{''.properties}} will access {{java.lang.String.isLatin1}}, which is
{{private}}
h4. -7) Access non-visible constructor when {{as}} type, e.g.-
[https://github.com/apache/groovy/blob/master/src/test/groovy/lang/MapOfClosureTest.groovy#L57]
The constructor of {{TimerTask}} is {{protected}}
h4. {color:#d04437}_8) Access invisible members or explicitly invoke
{{setAccessible}} (Truely illegal access, we should fix our code), e.g._{color}
[https://github.com/apache/groovy/blob/master/src/test/groovy/transform/ThreadInterruptTest.groovy#L65]
h4. 9) ?Avoid use {{java.math.BigInteger.multiply(long)}}, and use
{{BigInteger.multiply(BigInteger)}} instead, e.g.
[https://github.com/apache/groovy/blob/master/src/test/groovy/transform/stc/STCAssignmentTest.groovy#L692]
We should make groovy a bit smarter
--
This message was sent by Atlassian JIRA
(v7.6.3#76005)