Bug 549282 - [otdre] avoid logging CNFE below
TeamLoader.findUnloadableBaseClass()
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/TeamLoader.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/TeamLoader.java
index 85da45e..7e1f4dc 100644
--- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/TeamLoader.java
+++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/TeamLoader.java
@@ -32,6 +32,7 @@
import org.eclipse.objectteams.internal.osgi.weaving.Util.ProfileKind;
import org.eclipse.objectteams.otequinox.ActivationKind;
import org.eclipse.objectteams.otredyn.runtime.TeamManager;
+import org.eclipse.objectteams.otredyn.transformer.jplis.ObjectTeamsTransformer;
import org.objectteams.Team;
import org.osgi.framework.Bundle;
import org.osgi.framework.hooks.weaving.WovenClass;
@@ -276,12 +277,17 @@
// use a throw-away class loader so we have a fresh chance to load any failed classes later
// (only initiating class loader remembers the failure, if this is discarded, the slate is clean):
ClassLoader tryLoader = new ClassLoader(teamClass.getClassLoader()) {};
- for (@SuppressWarnings("null")@NonNull String baseclass : team.baseClassNames)
+ for (@SuppressWarnings("null")@NonNull String baseclass : team.baseClassNames) {
+ Boolean previous = ObjectTeamsTransformer.initiatedByThrowAwayLoader.get();
try {
+ ObjectTeamsTransformer.initiatedByThrowAwayLoader.set(Boolean.TRUE);
tryLoader.loadClass(baseclass);
} catch (Throwable t) {
return baseclass;
+ } finally {
+ ObjectTeamsTransformer.initiatedByThrowAwayLoader.set(previous);
}
+ }
}
return null;
}
diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmWritableBoundClass.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmWritableBoundClass.java
index bab8ecc..4cf30cf 100644
--- a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmWritableBoundClass.java
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmWritableBoundClass.java
@@ -30,6 +30,7 @@
import org.eclipse.objectteams.otredyn.bytecode.RedefineStrategyFactory;
import org.eclipse.objectteams.otredyn.bytecode.asm.verify.OTCheckClassAdapter;
import org.eclipse.objectteams.otredyn.runtime.TeamManager;
+import org.eclipse.objectteams.otredyn.transformer.jplis.ObjectTeamsTransformer;
import org.eclipse.objectteams.otredyn.transformer.names.ClassNames;
import org.eclipse.objectteams.otredyn.transformer.names.ConstantMembers;
import org.eclipse.objectteams.runtime.IReweavingTask;
@@ -193,26 +194,16 @@
try {
redefine(definedClass);
} catch (ClassNotFoundException cnfe) {
- throw new RuntimeException("OTDRE: Failed to redefine class: "+this.getName(), cnfe);
+ if (ObjectTeamsTransformer.initiatedByThrowAwayLoader.get() == Boolean.TRUE) {
+ scheduleRetry(definedClass);
+ return;
+ } else {
+ throw new RuntimeException("OTDRE: Failed to redefine class: "+this.getName(), cnfe);
+ }
} catch (Throwable t) {
// t.printStackTrace(System.out);
// if redefinition failed (ClassCircularity?) install a runnable for deferred redefinition:
- final Runnable previousTask = TeamManager.pendingTasks.get();
- TeamManager.pendingTasks.set(new Runnable() {
- public void run() {
- if (previousTask != null)
- previousTask.run();
- try {
- redefine(definedClass);
- } catch (ClassNotFoundException e) {
- e.printStackTrace(); // should never get here, since we expect CNFE already on the first attempt
- }
- }
- @Override
- public String toString() {
- return "Retry "+AsmWritableBoundClass.this.toString();
- }
- });
+ scheduleRetry(definedClass);
return;
}
}
@@ -229,6 +220,25 @@
}
}
+ private void scheduleRetry(final Class<?> definedClass) {
+ final Runnable previousTask = TeamManager.pendingTasks.get();
+ TeamManager.pendingTasks.set(new Runnable() {
+ public void run() {
+ if (previousTask != null)
+ previousTask.run();
+ try {
+ redefine(definedClass);
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace(); // should never get here, since we expect CNFE already on the first attempt
+ }
+ }
+ @Override
+ public String toString() {
+ return "Retry "+AsmWritableBoundClass.this.toString();
+ }
+ });
+ }
+
protected void superTransformation(Class<?> definedClass) throws IllegalClassFormatException {
AbstractTeam mySuper = getSuperclass();
if (mySuper != null && mySuper.isLoaded()) {
diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/transformer/jplis/ObjectTeamsTransformer.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/transformer/jplis/ObjectTeamsTransformer.java
index d600924..2ea7e2b 100644
--- a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/transformer/jplis/ObjectTeamsTransformer.java
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/transformer/jplis/ObjectTeamsTransformer.java
@@ -38,6 +38,12 @@
*/
public class ObjectTeamsTransformer implements ClassFileTransformer {
+ /**
+ * API for OT/Equinox, to signal when class loading is initiaed by a throw-away loader,
+ * which implies that ClassNotFoundException should not be regarded as fatal.
+ */
+ public static final ThreadLocal<Boolean> initiatedByThrowAwayLoader = new ThreadLocal<Boolean>();
+
private IWeavingContext weavingContext;
private Set<String> boundBaseClassNames = new HashSet<String>();