You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by ti...@apache.org on 2011/11/04 20:12:30 UTC
svn commit: r1197720 - in /aries/trunk/proxy/proxy-impl/src:
main/java/org/apache/aries/proxy/impl/common/
test/java/org/apache/aries/blueprint/proxy/
Author: timothyjward
Date: Fri Nov 4 19:12:30 2011
New Revision: 1197720
URL: http://svn.apache.org/viewvc?rev=1197720&view=rev
Log:
ARIES-775: Fix ClassCircularityError seen on Mac VMs when locating no-args constructors.
Added:
aries/trunk/proxy/proxy-impl/src/main/java/org/apache/aries/proxy/impl/common/ConstructorFinder.java
aries/trunk/proxy/proxy-impl/src/test/java/org/apache/aries/blueprint/proxy/ProxyTestClassStaticInitOfChild.java
aries/trunk/proxy/proxy-impl/src/test/java/org/apache/aries/blueprint/proxy/ProxyTestClassStaticInitOfChildParent.java
Modified:
aries/trunk/proxy/proxy-impl/src/main/java/org/apache/aries/proxy/impl/common/AbstractWovenProxyAdapter.java
aries/trunk/proxy/proxy-impl/src/test/java/org/apache/aries/blueprint/proxy/WovenProxyGeneratorTest.java
Modified: aries/trunk/proxy/proxy-impl/src/main/java/org/apache/aries/proxy/impl/common/AbstractWovenProxyAdapter.java
URL: http://svn.apache.org/viewvc/aries/trunk/proxy/proxy-impl/src/main/java/org/apache/aries/proxy/impl/common/AbstractWovenProxyAdapter.java?rev=1197720&r1=1197719&r2=1197720&view=diff
==============================================================================
--- aries/trunk/proxy/proxy-impl/src/main/java/org/apache/aries/proxy/impl/common/AbstractWovenProxyAdapter.java (original)
+++ aries/trunk/proxy/proxy-impl/src/main/java/org/apache/aries/proxy/impl/common/AbstractWovenProxyAdapter.java Fri Nov 4 19:12:30 2011
@@ -19,6 +19,7 @@
package org.apache.aries.proxy.impl.common;
import java.io.IOException;
+import java.io.InputStream;
import java.io.Serializable;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
@@ -241,13 +242,9 @@ public abstract class AbstractWovenProxy
nonObjectSupers.add(nextSuper);
nextSuper = nextSuper.getSuperclass();
}
- try {
- superHasNoArgsConstructor = (superClass.getDeclaredConstructor().
- getModifiers() & Modifier.PRIVATE) == 0;
- } catch (NoSuchMethodException nsme) {
- // This is a no-op here, but means we need to add a no-Args that
- // delegates to Object#<init>() yuck :(
- }
+ //Don't use reflection - it can be dangerous
+ superHasNoArgsConstructor = superHasNoArgsConstructor(superName, name);
+
} else {
superHasNoArgsConstructor = true;
}
@@ -274,6 +271,31 @@ public abstract class AbstractWovenProxy
}
}
+ /**
+ * This method allows us to determine whether a superclass has a
+ * non-private no-args constructor without causing it to initialize.
+ * This avoids a potential ClassCircularityError on Mac VMs if the
+ * initialization references the subclass being woven. Odd, but seen
+ * in the wild!
+ */
+ private final boolean superHasNoArgsConstructor(String superName, String name) {
+
+ ConstructorFinder cf = new ConstructorFinder();
+
+ try {
+ InputStream is = loader.getResourceAsStream(superName +".class");
+
+ if(is == null)
+ throw new IOException();
+
+ new ClassReader(is).accept(cf, ClassReader.SKIP_FRAMES + ClassReader.SKIP_DEBUG + ClassReader.SKIP_CODE);
+ } catch (IOException ioe) {
+ UnableToProxyException u = new UnableToProxyException(name, ioe);
+ throw new RuntimeException(NLS.MESSAGES.getMessage("cannot.load.superclass", superName.replace('/', '.'), typeBeingWoven.getClassName()), u);
+ }
+ return cf.hasNoArgsConstructor();
+ }
+
private boolean checkInterfacesForSerializability(String[] interfaces) throws ClassNotFoundException {
for(String iface : interfaces)
{
Added: aries/trunk/proxy/proxy-impl/src/main/java/org/apache/aries/proxy/impl/common/ConstructorFinder.java
URL: http://svn.apache.org/viewvc/aries/trunk/proxy/proxy-impl/src/main/java/org/apache/aries/proxy/impl/common/ConstructorFinder.java?rev=1197720&view=auto
==============================================================================
--- aries/trunk/proxy/proxy-impl/src/main/java/org/apache/aries/proxy/impl/common/ConstructorFinder.java (added)
+++ aries/trunk/proxy/proxy-impl/src/main/java/org/apache/aries/proxy/impl/common/ConstructorFinder.java Fri Nov 4 19:12:30 2011
@@ -0,0 +1,53 @@
+/*
+ * 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 org.apache.aries.proxy.impl.common;
+
+import org.objectweb.asm.ClassAdapter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.commons.EmptyVisitor;
+
+import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
+
+public class ConstructorFinder extends ClassAdapter
+{
+
+ private boolean hasNoArgsConstructor = false;
+
+ public boolean hasNoArgsConstructor()
+ {
+ return hasNoArgsConstructor;
+ }
+
+ public ConstructorFinder()
+ {
+ super(new EmptyVisitor());
+ }
+
+ @Override
+ public MethodVisitor visitMethod(int access, String name, String desc, String signature,
+ String[] exceptions)
+ {
+ if("<init>".equals(name)) {
+ if(Type.getArgumentTypes(desc).length == 0 && (access & ACC_PRIVATE) == 0)
+ hasNoArgsConstructor = true;
+ }
+ return null;
+ }
+}
Added: aries/trunk/proxy/proxy-impl/src/test/java/org/apache/aries/blueprint/proxy/ProxyTestClassStaticInitOfChild.java
URL: http://svn.apache.org/viewvc/aries/trunk/proxy/proxy-impl/src/test/java/org/apache/aries/blueprint/proxy/ProxyTestClassStaticInitOfChild.java?rev=1197720&view=auto
==============================================================================
--- aries/trunk/proxy/proxy-impl/src/test/java/org/apache/aries/blueprint/proxy/ProxyTestClassStaticInitOfChild.java (added)
+++ aries/trunk/proxy/proxy-impl/src/test/java/org/apache/aries/blueprint/proxy/ProxyTestClassStaticInitOfChild.java Fri Nov 4 19:12:30 2011
@@ -0,0 +1,28 @@
+/*
+ * 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 org.apache.aries.blueprint.proxy;
+
+public class ProxyTestClassStaticInitOfChild extends ProxyTestClassStaticInitOfChildParent
+{
+
+ public ProxyTestClassStaticInitOfChild(){
+ super("test");
+ }
+
+}
Added: aries/trunk/proxy/proxy-impl/src/test/java/org/apache/aries/blueprint/proxy/ProxyTestClassStaticInitOfChildParent.java
URL: http://svn.apache.org/viewvc/aries/trunk/proxy/proxy-impl/src/test/java/org/apache/aries/blueprint/proxy/ProxyTestClassStaticInitOfChildParent.java?rev=1197720&view=auto
==============================================================================
--- aries/trunk/proxy/proxy-impl/src/test/java/org/apache/aries/blueprint/proxy/ProxyTestClassStaticInitOfChildParent.java (added)
+++ aries/trunk/proxy/proxy-impl/src/test/java/org/apache/aries/blueprint/proxy/ProxyTestClassStaticInitOfChildParent.java Fri Nov 4 19:12:30 2011
@@ -0,0 +1,34 @@
+/*
+ * 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 org.apache.aries.blueprint.proxy;
+
+public class ProxyTestClassStaticInitOfChildParent
+{
+
+ private static final ProxyTestClassStaticInitOfChildParent child = new ProxyTestClassStaticInitOfChild();
+
+ public static void doStuff() {
+ //Do silly stuff;
+ child.toString();
+ }
+
+ public ProxyTestClassStaticInitOfChildParent(String s){
+
+ }
+}
Modified: aries/trunk/proxy/proxy-impl/src/test/java/org/apache/aries/blueprint/proxy/WovenProxyGeneratorTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/proxy/proxy-impl/src/test/java/org/apache/aries/blueprint/proxy/WovenProxyGeneratorTest.java?rev=1197720&r1=1197719&r2=1197720&view=diff
==============================================================================
--- aries/trunk/proxy/proxy-impl/src/test/java/org/apache/aries/blueprint/proxy/WovenProxyGeneratorTest.java (original)
+++ aries/trunk/proxy/proxy-impl/src/test/java/org/apache/aries/blueprint/proxy/WovenProxyGeneratorTest.java Fri Nov 4 19:12:30 2011
@@ -30,6 +30,7 @@ import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -70,7 +71,7 @@ public class WovenProxyGeneratorTest ext
}
/** An array of classes that will be woven - note no UnweavableParents should be in here! */
- private static final Class<?>[] CLASSES = new Class<?>[]{TEST_CLASS, ProxyTestClassSuper.class,
+ private static final List<Class<?>> CLASSES = Arrays.asList(new Class<?>[]{TEST_CLASS, ProxyTestClassSuper.class,
ProxyTestClassFinalMethod.class, ProxyTestClassFinal.class, ProxyTestClassGeneric.class,
ProxyTestClassGenericSuper.class, ProxyTestClassCovariant.class, ProxyTestClassCovariantOverride.class,
ProxyTestClassUnweavableChild.class, ProxyTestClassUnweavableSibling.class, ProxyTestClassInner.class,
@@ -78,7 +79,11 @@ public class WovenProxyGeneratorTest ext
ProxyTestClassUnweavableChildWithFinalMethodParent.class,
ProxyTestClassUnweavableChildWithDefaultMethodWrongPackageParent.class,
ProxyTestClassSerializable.class, ProxyTestClassSerializableWithSVUID.class,
- ProxyTestClassSerializableChild.class, ProxyTestClassSerializableInterface.class};
+ ProxyTestClassSerializableChild.class, ProxyTestClassSerializableInterface.class,
+ ProxyTestClassStaticInitOfChild.class});
+
+ /** An array of classes that are loaded by the WeavingLoader, but not actually woven **/
+ private static final List<Class<?>> OTHER_CLASSES = Arrays.asList(new Class<?>[] {ProxyTestClassStaticInitOfChildParent.class});
private static final Map<String, byte[]> rawClasses = new HashMap<String, byte[]>();
@@ -101,7 +106,16 @@ public class WovenProxyGeneratorTest ext
if(bytes == null)
return super.loadClass(className, b);
- bytes = WovenProxyGenerator.getWovenProxy(bytes, className, this);
+ boolean weave = false;
+
+ for(Class<?> c : CLASSES) {
+ if(c.getName().equals(className)) {
+ weave = true;
+ break;
+ }
+ }
+ if(weave)
+ bytes = WovenProxyGenerator.getWovenProxy(bytes, className, this);
return defineClass(className, bytes, 0, bytes.length);
}
@@ -117,7 +131,12 @@ public class WovenProxyGeneratorTest ext
@BeforeClass
public static void setUp() throws Exception
{
- for(Class<?> clazz : CLASSES) {
+ List<Class<?>> classes = new ArrayList(CLASSES.size() + OTHER_CLASSES.size());
+
+ classes.addAll(CLASSES);
+ classes.addAll(OTHER_CLASSES);
+
+ for(Class<?> clazz : classes) {
InputStream is = clazz.getClassLoader().getResourceAsStream(
clazz.getName().replace('.', '/') + ".class");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -383,6 +402,19 @@ public class WovenProxyGeneratorTest ext
assertFalse(woven.getDeclaredField("serialVersionUID").isSynthetic());
}
+ /**
+ * This test covers a weird case on Mac VMs where we sometimes
+ * get a ClassCircularityError if a static initializer in a
+ * non-woven superclass references a subclass that's being
+ * woven, and gets triggered by the weaving process. Not known
+ * to fail on IBM or Sun/Oracle VMs
+ */
+ @Test
+ public void testSuperStaticInitOfChild() throws Exception {
+ Class<?> parent = weavingLoader.loadClass(ProxyTestClassStaticInitOfChildParent.class.getName());
+ parent.getMethod("doStuff").invoke(null);
+ }
+
@Override
protected Object getProxyInstance(Class<?> proxyClass) {
try {