aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Lippert2012-04-26 15:14:49 (EDT)
committerMartin Lippert2012-04-26 15:15:04 (EDT)
commita16e79f4c31488011ef9a45e22c58d7a7b25fff9 (patch)
tree5e4f5339b428fed5cfb14d52f1f67c48ca11d7dd
parenta193f94ec1e690835c1cb93363c0b33848424d54 (diff)
downloadrt.equinox.bundles-a16e79f4c31488011ef9a45e22c58d7a7b25fff9.zip
rt.equinox.bundles-a16e79f4c31488011ef9a45e22c58d7a7b25fff9.tar.gz
rt.equinox.bundles-a16e79f4c31488011ef9a45e22c58d7a7b25fff9.tar.bz2
Bug 377740 - avoid parallel execution of aspectj weaving for the same bundle
-rw-r--r--bundles/org.eclipse.equinox.weaving.aspectj/META-INF/MANIFEST.MF3
-rw-r--r--bundles/org.eclipse.equinox.weaving.aspectj/src/org/eclipse/equinox/weaving/aspectj/loadtime/OSGiWeavingAdaptor.java130
2 files changed, 130 insertions, 3 deletions
diff --git a/bundles/org.eclipse.equinox.weaving.aspectj/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.weaving.aspectj/META-INF/MANIFEST.MF
index ea5cd43..1403096 100644
--- a/bundles/org.eclipse.equinox.weaving.aspectj/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.weaving.aspectj/META-INF/MANIFEST.MF
@@ -2,12 +2,13 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: WeavingService Plug-in (Incubation)
Bundle-SymbolicName: org.eclipse.equinox.weaving.aspectj
-Bundle-Version: 1.0.1.qualifier
+Bundle-Version: 1.0.2.qualifier
Bundle-Activator: org.eclipse.equinox.weaving.aspectj.AspectJWeavingActivator
Import-Package: org.aspectj.weaver;version="1.6.3";resolution:=optional,
org.aspectj.weaver.loadtime;version="1.6.3";resolution:=optional,
org.aspectj.weaver.loadtime.definition;version="1.6.3";resolution:=optional,
org.aspectj.weaver.tools;version="1.6.3";resolution:=optional,
+ org.aspectj.weaver.bcel;version="1.6.3";resolution:=optional,
org.eclipse.equinox.service.weaving,
org.eclipse.osgi.service.debug,
org.eclipse.osgi.service.resolver,
diff --git a/bundles/org.eclipse.equinox.weaving.aspectj/src/org/eclipse/equinox/weaving/aspectj/loadtime/OSGiWeavingAdaptor.java b/bundles/org.eclipse.equinox.weaving.aspectj/src/org/eclipse/equinox/weaving/aspectj/loadtime/OSGiWeavingAdaptor.java
index 6dcff7f..fcd1691 100644
--- a/bundles/org.eclipse.equinox.weaving.aspectj/src/org/eclipse/equinox/weaving/aspectj/loadtime/OSGiWeavingAdaptor.java
+++ b/bundles/org.eclipse.equinox.weaving.aspectj/src/org/eclipse/equinox/weaving/aspectj/loadtime/OSGiWeavingAdaptor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2009 IBM Corporation and others.
+ * Copyright (c) 2006, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -12,17 +12,25 @@
* Martin Lippert minor changes and bugfixes
* Martin Lippert reworked
* Martin Lippert caching of generated classes
+ * Martin Lippert added locking for weaving
*******************************************************************************/
package org.eclipse.equinox.weaving.aspectj.loadtime;
import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
+import java.util.concurrent.ConcurrentLinkedQueue;
import org.aspectj.weaver.IUnwovenClassFile;
+import org.aspectj.weaver.bcel.BcelWeakClassLoaderReference;
import org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor;
+import org.aspectj.weaver.tools.GeneratedClassHandler;
+import org.aspectj.weaver.tools.Trace;
+import org.aspectj.weaver.tools.TraceFactory;
import org.eclipse.equinox.weaving.aspectj.AspectJWeavingStarter;
/**
@@ -31,8 +39,80 @@ import org.eclipse.equinox.weaving.aspectj.AspectJWeavingStarter;
*/
public class OSGiWeavingAdaptor extends ClassLoaderWeavingAdaptor {
+ /**
+ * internal class to collect generated classes (produced by the weaving) to
+ * define then after the weaving itself
+ */
+ class GeneratedClass {
+
+ private final byte[] bytes;
+
+ private final String name;
+
+ public GeneratedClass(final String name, final byte[] bytes) {
+ this.name = name;
+ this.bytes = bytes;
+ }
+
+ public byte[] getBytes() {
+ return bytes;
+ }
+
+ public String getName() {
+ return name;
+ }
+ }
+
+ /**
+ * generated class handler to collect generated classes (produced by the
+ * weaving) to define then after the weaving itself
+ */
+ class OSGiGeneratedClassHandler implements GeneratedClassHandler {
+
+ private final ConcurrentLinkedQueue<GeneratedClass> classesToBeDefined;
+
+ private final BcelWeakClassLoaderReference loaderRef;
+
+ public OSGiGeneratedClassHandler(final ClassLoader loader) {
+ loaderRef = new BcelWeakClassLoaderReference(loader);
+ classesToBeDefined = new ConcurrentLinkedQueue<GeneratedClass>();
+ }
+
+ /**
+ * Callback when we need to define a generated class in the JVM
+ */
+ public void acceptClass(final String name, final byte[] bytes) {
+ try {
+ if (shouldDump(name.replace('/', '.'), false)) {
+ dump(name, bytes, false);
+ }
+ } catch (final Throwable throwable) {
+ throwable.printStackTrace();
+ }
+ classesToBeDefined.offer(new GeneratedClass(name, bytes));
+ }
+
+ public void defineGeneratedClasses() {
+ while (!classesToBeDefined.isEmpty()) {
+ final GeneratedClass generatedClass = classesToBeDefined.poll();
+ if (generatedClass != null) {
+ defineClass(loaderRef.getClassLoader(),
+ generatedClass.getName(), generatedClass.getBytes());
+ } else {
+ break;
+ }
+ }
+ }
+
+ }
+
+ private static Trace trace = TraceFactory.getTraceFactory().getTrace(
+ ClassLoaderWeavingAdaptor.class);
+
private final ClassLoader classLoader;
+ private Method defineClassMethod;
+
private boolean initialized;
private boolean initializing;
@@ -59,6 +139,42 @@ public class OSGiWeavingAdaptor extends ClassLoaderWeavingAdaptor {
this.namespace = namespace;
}
+ private void defineClass(final ClassLoader loader, final String name,
+ final byte[] bytes) {
+ if (trace.isTraceEnabled()) {
+ trace.enter("defineClass", this,
+ new Object[] { loader, name, bytes });
+ }
+ Object clazz = null;
+ debug("generating class '" + name + "'");
+
+ try {
+ if (defineClassMethod == null) {
+ defineClassMethod = ClassLoader.class.getDeclaredMethod(
+ "defineClass",
+ new Class[] { String.class, bytes.getClass(),
+ int.class, int.class });
+ }
+ defineClassMethod.setAccessible(true);
+ clazz = defineClassMethod.invoke(loader, new Object[] { name,
+ bytes, new Integer(0), new Integer(bytes.length) });
+ } catch (final InvocationTargetException e) {
+ if (e.getTargetException() instanceof LinkageError) {
+ warn("define generated class failed", e.getTargetException());
+ // is already defined (happens for X$ajcMightHaveAspect interfaces since aspects are reweaved)
+ // TODO maw I don't think this is OK and
+ } else {
+ warn("define generated class failed", e.getTargetException());
+ }
+ } catch (final Exception e) {
+ warn("define generated class failed", e);
+ }
+
+ if (trace.isTraceEnabled()) {
+ trace.exit("defineClass", clazz);
+ }
+ }
+
/**
* In some situations the weaving creates new classes on the fly that are
* not part of the original bundle. This is the case when the weaver needs
@@ -107,6 +223,8 @@ public class OSGiWeavingAdaptor extends ClassLoaderWeavingAdaptor {
if (!initialized) {
initializing = true;
super.initialize(classLoader, weavingContext);
+ this.generatedClassHandler = new OSGiGeneratedClassHandler(
+ classLoader);
initialized = true;
initializing = false;
@@ -139,10 +257,18 @@ public class OSGiWeavingAdaptor extends ClassLoaderWeavingAdaptor {
if (!initialized) {
initializing = true;
super.initialize(classLoader, weavingContext);
+ this.generatedClassHandler = new OSGiGeneratedClassHandler(
+ classLoader);
initialized = true;
initializing = false;
}
- bytes = super.weaveClass(name, bytes, mustWeave);
+
+ synchronized (this) {
+ bytes = super.weaveClass(name, bytes, mustWeave);
+ }
+
+ ((OSGiGeneratedClassHandler) this.generatedClassHandler)
+ .defineGeneratedClasses();
}
return bytes;
}