This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch GROOVY_2_5_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit d33a332ef9814d7d3850ef6e002f6b7296cc5245
Author: Daniel.Sun <[email protected]>
AuthorDate: Tue Mar 31 19:00:15 2020 +0800

    GROOVY-9487: Update and check if initialized via same field of metaclass
    
    2_5_X backport
---
 src/main/groovy/groovy/lang/ExpandoMetaClass.java  | 10 ++--
 src/main/groovy/groovy/lang/MetaClassImpl.java     |  6 ++-
 .../groovy/runtime/metaclass/ClosureMetaClass.java | 10 +++-
 src/test/groovy/bugs/Groovy9487.groovy             | 55 ++++++++++++++++++++++
 4 files changed, 74 insertions(+), 7 deletions(-)

diff --git a/src/main/groovy/groovy/lang/ExpandoMetaClass.java 
b/src/main/groovy/groovy/lang/ExpandoMetaClass.java
index 93dc584d4c..b7cb439ae8 100644
--- a/src/main/groovy/groovy/lang/ExpandoMetaClass.java
+++ b/src/main/groovy/groovy/lang/ExpandoMetaClass.java
@@ -273,7 +273,7 @@ public class ExpandoMetaClass extends MetaClassImpl 
implements GroovyObject {
     // These two properties are used when no ExpandoMetaClassCreationHandle is 
present
 
     private MetaClass myMetaClass;
-    private boolean initialized;
+    private volatile boolean initialized;
     private volatile boolean modified;
 
     private boolean initCalled;
@@ -479,10 +479,10 @@ public class ExpandoMetaClass extends MetaClassImpl 
implements GroovyObject {
         ExpandoMetaClassCreationHandle.disable();
     }
 
-    /* (non-Javadoc)
-     * @see groovy.lang.MetaClassImpl#initialize()
+    /**
+     * {@inheritDoc}
      */
-
+    @Override
     public void initialize() {
         try {
             writeLock.lock();
@@ -503,6 +503,7 @@ public class ExpandoMetaClass extends MetaClassImpl 
implements GroovyObject {
      * Checks if the meta class is initialized.
      * @see groovy.lang.MetaClassImpl#isInitialized()
      */
+    @Override
     protected boolean isInitialized() {
         try {
             readLock.lock();
@@ -512,6 +513,7 @@ public class ExpandoMetaClass extends MetaClassImpl 
implements GroovyObject {
         }
     }
 
+    @Override
     protected void setInitialized(boolean b) {
         this.initialized = b;
     }
diff --git a/src/main/groovy/groovy/lang/MetaClassImpl.java 
b/src/main/groovy/groovy/lang/MetaClassImpl.java
index c097c1a8a7..9db05aebed 100644
--- a/src/main/groovy/groovy/lang/MetaClassImpl.java
+++ b/src/main/groovy/groovy/lang/MetaClassImpl.java
@@ -3077,6 +3077,10 @@ public class MetaClassImpl implements MetaClass, 
MutableMetaClass {
         return initialized;
     }
 
+    protected void setInitialized(boolean initialized) {
+        this.initialized = initialized;
+    }
+
     /**
      * return false: add method
      *        null:  ignore method
@@ -3336,7 +3340,7 @@ public class MetaClassImpl implements MetaClass, 
MutableMetaClass {
                 // Introspection failure...
                 // May happen in Android
             }
-            initialized = true;
+            setInitialized(true);
         }
     }
 
diff --git 
a/src/main/java/org/codehaus/groovy/runtime/metaclass/ClosureMetaClass.java 
b/src/main/java/org/codehaus/groovy/runtime/metaclass/ClosureMetaClass.java
index bdf8c8df41..ac487f956b 100644
--- a/src/main/java/org/codehaus/groovy/runtime/metaclass/ClosureMetaClass.java
+++ b/src/main/java/org/codehaus/groovy/runtime/metaclass/ClosureMetaClass.java
@@ -436,6 +436,7 @@ public final class ClosureMetaClass extends MetaClassImpl {
         attributeInitDone = !attributes.isEmpty();
     }
 
+    @Override
     public synchronized void initialize() {
         if (!isInitialized()) {
             CachedMethod[] methodArray = theCachedClass.getMethods();
@@ -446,8 +447,7 @@ public final class ClosureMetaClass extends MetaClassImpl {
                 }
             }
             assignMethodChooser();
-
-            initialized = true;
+            setInitialized(true);
         }
     }
 
@@ -585,10 +585,16 @@ public final class ClosureMetaClass extends MetaClassImpl 
{
         return null;
     }
 
+    @Override
     protected boolean isInitialized() {
         return initialized;
     }
 
+    @Override
+    protected void setInitialized(boolean initialized) {
+        this.initialized = initialized;
+    }
+
     public MetaMethod getStaticMetaMethod(String name, Object[] args) {
         return CLOSURE_METACLASS.getStaticMetaMethod(name, args);
     }
diff --git a/src/test/groovy/bugs/Groovy9487.groovy 
b/src/test/groovy/bugs/Groovy9487.groovy
new file mode 100644
index 0000000000..80c6e17317
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy9487.groovy
@@ -0,0 +1,55 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.bugs
+
+import org.junit.Test
+
+final class Groovy9487 {
+
+    @Test
+    void testInitializedFlagSetProperly() {
+        def mc = new MyMetaClass(HelloWorld)
+        mc.initialize()
+
+        assert mc.initialized
+        assert mc.invokeStaticMethod(HelloWorld, 'hello') == 'Hello, world'
+    }
+
+    static class HelloWorld {
+        static String hello() { 'Hello, world' }
+    }
+
+    static class MyMetaClass extends MetaClassImpl {
+        private boolean initialized
+
+        MyMetaClass(Class theClass) {
+            super(theClass)
+        }
+
+        @Override
+        protected boolean isInitialized() {
+            return this.initialized;
+        }
+
+        @Override
+        protected void setInitialized(boolean initialized) {
+            this.initialized = initialized;
+        }
+    }
+}

Reply via email to