Daniel Sun created GROOVY-9144:
----------------------------------

             Summary: CLONE - CLONE - CLONE - Fix warning "An illegal 
reflective access operation has occurred"
                 Key: GROOVY-9144
                 URL: https://issues.apache.org/jira/browse/GROOVY-9144
             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 GROOVY-9081.

*?* means that we should discuss the case further as some breaking changes may 
be introduced.

{color:#d04437}*Case 2, 8, 9* are illegal access and have to be fixed by 
changing user's code(including the implementation of some AST 
Transformations){color}
h4. _{color:#d04437}2) Sub-class derives the {{protected}} members from public 
class,{color}_

{color:#d04437}*2.0) ?Invoke the members on the sub class instances(_Truely 
illegal access_), e.g.*{color}
 
[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}} 
, use {{Arrays.copyOf}} instead ( 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. -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}}

We can fix the case by filtering non-properties
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. _{color:#d04437}9) Avoid use {{java.math.BigInteger.multiply(long)}}, and 
use {{BigInteger.multiply(BigInteger)}} instead*(Truely illegal access)*, 
e.g.{color}_

[https://github.com/apache/groovy/blob/master/src/test/groovy/transform/stc/STCAssignmentTest.groovy#L692]
 *More examples:*
{code:java}
1G * 2 // illegal access
1G * 2G // append "G" to the number to represent BigInteger, no illegal access 
warnings
{code}
 



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to