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; + } + } +}
