Bug 559847 - Null-safety cleanup in OT/Equinox implementation

- set version to 1.8, upgrade o.e.j.annotation to v 2.2.0
- adjust annotations for arrays & qualified names
- avoid references to implementations HashMap & ArrayList (less .eea)
- remove workarounds
- add a few necessary checks
- remaining warnings concern the interface to otre / otredyn
diff --git a/plugins/org.eclipse.objectteams.otequinox.turbo/.classpath b/plugins/org.eclipse.objectteams.otequinox.turbo/.classpath
index 098194c..eca7bdb 100644
--- a/plugins/org.eclipse.objectteams.otequinox.turbo/.classpath
+++ b/plugins/org.eclipse.objectteams.otequinox.turbo/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="output" path="bin"/>
diff --git a/plugins/org.eclipse.objectteams.otequinox.turbo/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.objectteams.otequinox.turbo/.settings/org.eclipse.jdt.core.prefs
index c2a6c9e..272543b 100644
--- a/plugins/org.eclipse.objectteams.otequinox.turbo/.settings/org.eclipse.jdt.core.prefs
+++ b/plugins/org.eclipse.objectteams.otequinox.turbo/.settings/org.eclipse.jdt.core.prefs
@@ -6,8 +6,13 @@
 org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
 org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
 org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
@@ -18,6 +23,7 @@
 org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
 org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
 org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
 org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
 org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
 org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
@@ -61,6 +67,7 @@
 org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
 org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
 org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
 org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
 org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
 org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
@@ -92,5 +99,6 @@
 org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.release=disabled
+org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.objectteams.otdt.compiler.option.pure_java=enabled
diff --git a/plugins/org.eclipse.objectteams.otequinox.turbo/META-INF/MANIFEST.MF b/plugins/org.eclipse.objectteams.otequinox.turbo/META-INF/MANIFEST.MF
index 3e305cf..28b6582 100644
--- a/plugins/org.eclipse.objectteams.otequinox.turbo/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.objectteams.otequinox.turbo/META-INF/MANIFEST.MF
@@ -3,8 +3,8 @@
 Bundle-Name: OT/Equinox Turbo
 Bundle-SymbolicName: org.eclipse.objectteams.otequinox.turbo
 Automatic-Module-Name: org.eclipse.objectteams.otequinox.turbo
-Bundle-Version: 2.4.0.qualifier
+Bundle-Version: 2.8.0.qualifier
 Bundle-Vendor: Eclipse.org - Object Teams
-Fragment-Host: org.eclipse.osgi;bundle-version="[3.10.0,4.0.0)"
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Fragment-Host: org.eclipse.osgi;bundle-version="[3.15.0,4.0.0)"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Export-Package: org.eclipse.objectteams.otequinox.turbo
diff --git a/plugins/org.eclipse.objectteams.otequinox.turbo/build.properties b/plugins/org.eclipse.objectteams.otequinox.turbo/build.properties
index 40a1314..ea7c440 100644
--- a/plugins/org.eclipse.objectteams.otequinox.turbo/build.properties
+++ b/plugins/org.eclipse.objectteams.otequinox.turbo/build.properties
@@ -3,3 +3,4 @@
 bin.includes = META-INF/,\
                .,\
                hookconfigurators.properties
+additional.bundles = org.eclipse.jdt.annotation
diff --git a/plugins/org.eclipse.objectteams.otequinox.turbo/src/org/eclipse/objectteams/otequinox/turbo/ForcedExportsRegistry.java b/plugins/org.eclipse.objectteams.otequinox.turbo/src/org/eclipse/objectteams/otequinox/turbo/ForcedExportsRegistry.java
index eb67a16..902fbdb 100644
--- a/plugins/org.eclipse.objectteams.otequinox.turbo/src/org/eclipse/objectteams/otequinox/turbo/ForcedExportsRegistry.java
+++ b/plugins/org.eclipse.objectteams.otequinox.turbo/src/org/eclipse/objectteams/otequinox/turbo/ForcedExportsRegistry.java
@@ -28,6 +28,8 @@
 import org.eclipse.osgi.framework.log.FrameworkLog;
 import org.eclipse.osgi.framework.log.FrameworkLogEntry;
 
+import org.eclipse.jdt.annotation.NonNull;
+
 /**
  * Reads forced exports from various locations (granted/denied).
  * 
@@ -237,7 +239,7 @@
 	 * @param the permission we are asking for
 	 * @return list of pairs (baseBundleId x packageName)
 	 */ 
-	public static /*@NonNull*/ List<String[]> getForcedExportsByAspect(String aspectBundleId, int perm) 
+	public static @NonNull List<@NonNull String[]> getForcedExportsByAspect(String aspectBundleId, int perm) 
 	{
 		// can be queried before we had a chance to initialize our data structures
 		synchronized (OTStorageHook.class) {
diff --git a/plugins/org.eclipse.objectteams.otequinox/.classpath b/plugins/org.eclipse.objectteams.otequinox/.classpath
index 7e70cf8..bef925c 100644
--- a/plugins/org.eclipse.objectteams.otequinox/.classpath
+++ b/plugins/org.eclipse.objectteams.otequinox/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
 		<attributes>
 			<attribute name="annotationpath" value="/org.eclipse.objectteams.otequinox/annotations/jre"/>
 		</attributes>
diff --git a/plugins/org.eclipse.objectteams.otequinox/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.objectteams.otequinox/.settings/org.eclipse.jdt.core.prefs
index 3a4c56d..155789e 100644
--- a/plugins/org.eclipse.objectteams.otequinox/.settings/org.eclipse.jdt.core.prefs
+++ b/plugins/org.eclipse.objectteams.otequinox/.settings/org.eclipse.jdt.core.prefs
@@ -6,9 +6,10 @@
 org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
 org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -22,6 +23,7 @@
 org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
 org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
 org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
 org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
 org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=warning
 org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
@@ -65,6 +67,7 @@
 org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
 org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
 org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
 org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
 org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
 org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=enabled
@@ -96,5 +99,6 @@
 org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
 org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
 org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.release=disabled
+org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.objectteams.otdt.compiler.option.pure_java=enabled
diff --git a/plugins/org.eclipse.objectteams.otequinox/META-INF/MANIFEST.MF b/plugins/org.eclipse.objectteams.otequinox/META-INF/MANIFEST.MF
index c470289..dd91c83 100644
--- a/plugins/org.eclipse.objectteams.otequinox/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.objectteams.otequinox/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.objectteams.otequinox;singleton:=true
 Automatic-Module-Name: org.eclipse.objectteams.otequinox
-Bundle-Version: 2.7.7.qualifier
+Bundle-Version: 2.8.0.qualifier
 Bundle-Activator: org.eclipse.objectteams.otequinox.TransformerPlugin
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
@@ -12,8 +12,8 @@
  org.eclipse.objectteams.otre;bundle-version="[2.5.0,3.0.0)",
  org.eclipse.objectteams.otredyn;bundle-version="[1.3.1,2.0.0)",
  org.eclipse.osgi;bundle-version="[3.10.0,4.0.0)",
- org.eclipse.jdt.annotation;bundle-version="[1.1.0,2.0.0)";resolution:=optional,
+ org.eclipse.jdt.annotation;bundle-version="[2.2.0,3.0.0)";resolution:=optional,
  org.objectweb.asm;bundle-version="[7.0.0,8.0.0)"
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Bundle-ActivationPolicy: lazy
 Export-Package: org.eclipse.objectteams.otequinox
diff --git a/plugins/org.eclipse.objectteams.otequinox/about.ini b/plugins/org.eclipse.objectteams.otequinox/about.ini
index 0938d54..e4f7cae 100644
--- a/plugins/org.eclipse.objectteams.otequinox/about.ini
+++ b/plugins/org.eclipse.objectteams.otequinox/about.ini
@@ -1,6 +1,6 @@
 aboutText=Object Teams -- Equinox integration (OT/Equinox)\n\
 \n\
-Version: 2.7.7\n\
+Version: 2.8.0\n\
 \n\
 Part of Eclipse SimRel 2020-03\n\
 \n\
diff --git a/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/lang/String.eea b/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/lang/String.eea
index 2178297..fd4e3a4 100644
--- a/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/lang/String.eea
+++ b/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/lang/String.eea
@@ -1,5 +1,11 @@
 class java/lang/String
 
+split
+ (Ljava/lang/String;)[Ljava/lang/String;
+ (Ljava/lang/String;)[L1java/lang/String;
+substring
+ (II)Ljava/lang/String;
+ (II)L1java/lang/String;
 trim
  ()Ljava/lang/String;
  ()L1java/lang/String;
diff --git a/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/net/URL.eea b/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/net/URL.eea
new file mode 100644
index 0000000..9badd15
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/net/URL.eea
@@ -0,0 +1,7 @@
+class java/net/URL
+getFile
+ ()Ljava/lang/String;
+ ()L1java/lang/String;
+openStream
+ ()Ljava/io/InputStream;
+ ()L1java/io/InputStream;
diff --git a/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/util/Collections.eea b/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/util/Collections.eea
index 9da7b53..c981a77 100644
--- a/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/util/Collections.eea
+++ b/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/util/Collections.eea
@@ -3,4 +3,7 @@
 emptyList
  <T:Ljava/lang/Object;>()Ljava/util/List<TT;>;
  <T:Ljava/lang/Object;>()L1java/util/List<TT;>;
- 
\ No newline at end of file
+ 
+singleton
+ <T:Ljava/lang/Object;>(TT;)Ljava/util/Set<TT;>;
+ <1T:Ljava/lang/Object;>(TT;)L1java/util/Set<TT;>;
diff --git a/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/util/EnumSet.eea b/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/util/EnumSet.eea
new file mode 100644
index 0000000..75476f1
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/util/EnumSet.eea
@@ -0,0 +1,7 @@
+class java/util/EnumSet
+allOf
+ <E:Ljava/lang/Enum<TE;>;>(Ljava/lang/Class<TE;>;)Ljava/util/EnumSet<TE;>;
+ <E:Ljava/lang/Enum<TE;>;>(Ljava/lang/Class<TE;>;)L1java/util/EnumSet<T1E;>;
+of
+ <E:Ljava/lang/Enum<TE;>;>(TE;)Ljava/util/EnumSet<TE;>;
+ <E:Ljava/lang/Enum<TE;>;>(TE;)L1java/util/EnumSet<T1E;>;
diff --git a/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/util/List.eea b/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/util/List.eea
new file mode 100644
index 0000000..9724fd1
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/util/List.eea
@@ -0,0 +1 @@
+class java/util/List -- we trust the parametric nullness of this type
diff --git a/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/util/Map$Entry.eea b/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/util/Map$Entry.eea
new file mode 100644
index 0000000..3ad81ae
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/util/Map$Entry.eea
@@ -0,0 +1 @@
+class java/util/Map$Entry -- we trust the parametric nullness of this type
diff --git a/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/util/Map.eea b/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/util/Map.eea
new file mode 100644
index 0000000..97ab712
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/util/Map.eea
@@ -0,0 +1,7 @@
+class java/util/Map
+get
+ (Ljava/lang/Object;)TV;
+ (Ljava/lang/Object;)T0V;
+remove
+ (Ljava/lang/Object;)TV;
+ (Ljava/lang/Object;)T0V;
diff --git a/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/util/StringTokenizer.eea b/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/util/StringTokenizer.eea
new file mode 100644
index 0000000..eca8fda
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otequinox/annotations/jre/java/util/StringTokenizer.eea
@@ -0,0 +1,4 @@
+class java/util/StringTokenizer
+nextToken
+ ()Ljava/lang/String;
+ ()L1java/lang/String;
diff --git a/plugins/org.eclipse.objectteams.otequinox/annotations/plugins/org/osgi/framework/BundleContext.eea b/plugins/org.eclipse.objectteams.otequinox/annotations/plugins/org/osgi/framework/BundleContext.eea
index 6f9f3e3..89462d9 100644
--- a/plugins/org.eclipse.objectteams.otequinox/annotations/plugins/org/osgi/framework/BundleContext.eea
+++ b/plugins/org.eclipse.objectteams.otequinox/annotations/plugins/org/osgi/framework/BundleContext.eea
@@ -4,6 +4,9 @@
  ()Lorg/osgi/framework/Bundle;
  ()L1org/osgi/framework/Bundle;
 
+getService
+ <S:Ljava/lang/Object;>(Lorg/osgi/framework/ServiceReference<TS;>;)TS;
+ <S:Ljava/lang/Object;>(Lorg/osgi/framework/ServiceReference<TS;>;)T0S;
 registerService
  ([Ljava/lang/String;Ljava/lang/Object;Ljava/util/Dictionary<Ljava/lang/String;*>;)Lorg/osgi/framework/ServiceRegistration<*>;
  ([Ljava/lang/String;Ljava/lang/Object;Ljava/util/Dictionary<Ljava/lang/String;*>;)L1org/osgi/framework/ServiceRegistration<*>;
diff --git a/plugins/org.eclipse.objectteams.otequinox/annotations/plugins/org/osgi/framework/hooks/weaving/WeavingHook.eea b/plugins/org.eclipse.objectteams.otequinox/annotations/plugins/org/osgi/framework/hooks/weaving/WeavingHook.eea
new file mode 100644
index 0000000..562a7c4
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otequinox/annotations/plugins/org/osgi/framework/hooks/weaving/WeavingHook.eea
@@ -0,0 +1,4 @@
+class org/osgi/framework/hooks/weaving/WeavingHook
+weave
+ (Lorg/osgi/framework/hooks/weaving/WovenClass;)V
+ (L1org/osgi/framework/hooks/weaving/WovenClass;)V
diff --git a/plugins/org.eclipse.objectteams.otequinox/annotations/plugins/org/osgi/framework/hooks/weaving/WovenClass.eea b/plugins/org.eclipse.objectteams.otequinox/annotations/plugins/org/osgi/framework/hooks/weaving/WovenClass.eea
index ea820c2..1224357 100644
--- a/plugins/org.eclipse.objectteams.otequinox/annotations/plugins/org/osgi/framework/hooks/weaving/WovenClass.eea
+++ b/plugins/org.eclipse.objectteams.otequinox/annotations/plugins/org/osgi/framework/hooks/weaving/WovenClass.eea
@@ -1,6 +1,17 @@
 class org/osgi/framework/hooks/weaving/WovenClass
 
+getBundleWiring
+ ()Lorg/osgi/framework/wiring/BundleWiring;
+ ()L1org/osgi/framework/wiring/BundleWiring;
+
+getBytes
+ ()[B
+ ()[1B
+
 getClassName
  ()Ljava/lang/String;
  ()L1java/lang/String;
- 
\ No newline at end of file
+ 
+getDynamicImports
+ ()Ljava/util/List<Ljava/lang/String;>;
+ ()Ljava/util/List<L1java/lang/String;>;
diff --git a/plugins/org.eclipse.objectteams.otequinox/annotations/plugins/org/osgi/framework/hooks/weaving/WovenClassListener.eea b/plugins/org.eclipse.objectteams.otequinox/annotations/plugins/org/osgi/framework/hooks/weaving/WovenClassListener.eea
new file mode 100644
index 0000000..3b1c1ee
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otequinox/annotations/plugins/org/osgi/framework/hooks/weaving/WovenClassListener.eea
@@ -0,0 +1,4 @@
+class org/osgi/framework/hooks/weaving/WovenClassListener
+modified
+ (Lorg/osgi/framework/hooks/weaving/WovenClass;)V
+ (L1org/osgi/framework/hooks/weaving/WovenClass;)V
diff --git a/plugins/org.eclipse.objectteams.otequinox/annotations/plugins/org/osgi/framework/wiring/BundleWiring.eea b/plugins/org.eclipse.objectteams.otequinox/annotations/plugins/org/osgi/framework/wiring/BundleWiring.eea
new file mode 100644
index 0000000..bf88918
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otequinox/annotations/plugins/org/osgi/framework/wiring/BundleWiring.eea
@@ -0,0 +1,4 @@
+class org/osgi/framework/wiring/BundleWiring
+getClassLoader
+ ()Ljava/lang/ClassLoader;
+ ()L0java/lang/ClassLoader;
diff --git a/plugins/org.eclipse.objectteams.otequinox/annotations/plugins/org/osgi/util/tracker/ServiceTracker.eea b/plugins/org.eclipse.objectteams.otequinox/annotations/plugins/org/osgi/util/tracker/ServiceTracker.eea
new file mode 100644
index 0000000..e619605
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otequinox/annotations/plugins/org/osgi/util/tracker/ServiceTracker.eea
@@ -0,0 +1,4 @@
+class org/osgi/util/tracker/ServiceTracker
+getService
+ ()TT;
+ ()T0T;
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/AspectBinding.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/AspectBinding.java
index ccf3830..d6fda74 100644
--- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/AspectBinding.java
+++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/AspectBinding.java
@@ -164,7 +164,7 @@
 				checkExported: {
 					List<String> imports = baseClass.getDynamicImports();
 					Bundle aspectBundle = AspectBinding.this.aspectBundle;
-					BundleRevision bundleRevision = aspectBundle != null ? aspectBundle.adapt(BundleRevision.class) : null;
+					@Nullable BundleRevision bundleRevision = aspectBundle != null ? aspectBundle.adapt(BundleRevision.class) : null;
 					if (bundleRevision != null) { // catch uninstalled state
 						for (Capability capability : bundleRevision.getCapabilities(PackageNamespace.PACKAGE_NAMESPACE)) {
 							Object exported = capability.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE);
@@ -262,7 +262,7 @@
 	static class BaseBundle {
 		String bundleName;
 		/** Team classes indexed by base classes that should trigger activating the team. */
-		final HashMap<String, Set<TeamBinding>> teamsPerBase = new HashMap<>();
+		final Map<String, Set<TeamBinding>> teamsPerBase = new HashMap<>();
 
 		public BaseBundle(String bundleName) {
 			this.bundleName = bundleName;
@@ -314,8 +314,11 @@
 		Bundle bundle = this.aspectBundle;
 		if (bundle == null)
 			return;
-		BundleWiring wiring = bundle.adapt(BundleWiring.class);
-		try (InputStream classStream = wiring.getClassLoader().getResourceAsStream(className.replace('.', '/')+".class")) {
+		@Nullable BundleWiring wiring = bundle.adapt(BundleWiring.class);
+		ClassLoader classLoader = wiring.getClassLoader();
+		if (classLoader == null)
+			return;
+		try (InputStream classStream = classLoader.getResourceAsStream(className.replace('.', '/')+".class")) {
 			this.weavingScheme = ASMByteCodeAnalyzer.determineWeavingScheme(classStream, className);
 			if (OTWeavingHook.DEFAULT_WEAVING_SCHEME == WeavingScheme.Unknown) {
 				OTWeavingHook.DEFAULT_WEAVING_SCHEME = this.weavingScheme;
@@ -379,7 +382,7 @@
 		long time = 0;
 		if (Util.PROFILE) time= System.nanoTime();
 		ClassScanner scanner = new ClassScanner();
-		for (@SuppressWarnings("null")@NonNull TeamBinding team : getAllTeamBindings()) {
+		for (TeamBinding team : getAllTeamBindings()) {
 			if (team.hasScannedBases) { // not a surprise for members of equivalentSet or classes already processed by weave()
 				if (!team.hasScannedRoles) { // weave() only scans bases, not roles!
 					team.hasScannedRoles = true;
@@ -408,10 +411,13 @@
 
 	private List<TeamBinding> getAllTeamBindings() {
 		List<TeamBinding> all = new ArrayList<>();
-		for (TeamBinding team : teams) all.add(team);
+		for (TeamBinding team : teams)
+			if (team != null)
+				all.add(team);
 		for (int i = 0; i < teams.length; i++) {
-			if (teams[i].superTeam != null)
-				all.add(teams[i].superTeam);
+			TeamBinding superTeam = teams[i].superTeam;
+			if (superTeam != null)
+				all.add(superTeam);
 			all.addAll(teams[i].subTeams);
 		}
 		return all;
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/AspectBindingRegistry.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/AspectBindingRegistry.java
index 769768e..2af38fc 100644
--- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/AspectBindingRegistry.java
+++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/AspectBindingRegistry.java
@@ -70,10 +70,10 @@
 		KNOWN_OTDT_ASPECTS.add("org.eclipse.objectteams.otdt.samples");
 	}
 	/** main internal registry of aspect bindings. */
-	private static HashMap<String, ArrayList<AspectBinding>> aspectBindingsByBasePlugin = 
-			   new HashMap<String, ArrayList<AspectBinding>>();
-	private static HashMap<String, ArrayList<AspectBinding>> aspectBindingsByAspectPlugin = 
-		       new HashMap<String, ArrayList<AspectBinding>>();
+	private static Map<String, ArrayList<AspectBinding>> aspectBindingsByBasePlugin = 
+		   new HashMap<String, ArrayList<AspectBinding>>();
+	private static Map<String, ArrayList<AspectBinding>> aspectBindingsByAspectPlugin = 
+		   new HashMap<String, ArrayList<AspectBinding>>();
 	private Map<String, BaseBundle> baseBundleLookup = new HashMap<>();
 
 	private Set<String> selfAdaptingAspects= new HashSet<String>(); // TODO, never read / evaluated
@@ -89,7 +89,7 @@
 	/* Load extensions for org.eclipse.objectteams.otequinox.aspectBindings and check aspect permissions. */
 	public void loadAspectBindings(
 			IExtensionRegistry extensionRegistry,
-			@SuppressWarnings("deprecation") @Nullable org.osgi.service.packageadmin.PackageAdmin packageAdmin,
+			@SuppressWarnings("deprecation") org.osgi.service.packageadmin.@Nullable PackageAdmin packageAdmin,
 			OTWeavingHook hook) throws OTAgentNotInstalled 
 	{
 		IConfigurationElement[] aspectBindingConfigs = extensionRegistry
@@ -162,7 +162,9 @@
 					for (@NonNull IConfigurationElement superBase : teams[j].getChildren(SUPER_BASE)) {
 						AspectBinding superBaseBinding = addSuperBase(superBase, aspectBundleId, aspectBundle, baseBundle, team, packageAdmin, hook);
 						bindings.add(superBaseBinding);
-						teamSet.add(superBaseBinding.teams[0]);
+						@SuppressWarnings("null") // addSuperBase ensures a valid teams[0]
+						@NonNull TeamBinding superBaseTeam = superBaseBinding.teams[0];
+						teamSet.add(superBaseTeam);
 					}
 				}
 				
@@ -183,7 +185,8 @@
 				if (baseBundles == null || baseBundles.length == 0 || (baseBundles[0].getState() < Bundle.RESOLVED)) {
 					log(IStatus.ERROR, "base bundle "+baseBundleId+" is not resolved - weaving may be incomplete.");
 				} else {
-					BundleWiring baseBundleWiring = baseBundles[0].adapt(BundleWiring.class);
+					@Nullable BundleWiring baseBundleWiring = baseBundles[0].adapt(BundleWiring.class);
+					assert baseBundleWiring != null : "Bundle should adapt to BundleWiring";
 					Collection<String> boundBases = binding.scanTeamClasses(aspectBundle, DelegatingTransformer.newTransformer(binding.weavingScheme, hook, baseBundleWiring));
 					addBoundBaseClasses(boundBases);
 				}
@@ -197,11 +200,12 @@
 
 	private AspectBinding addSuperBase(IConfigurationElement superBase, String aspectBundleId, @Nullable Bundle aspectBundle,
 			BaseBundle baseBundle, TeamBinding teamBinding,
-			@SuppressWarnings("deprecation") @Nullable org.osgi.service.packageadmin.PackageAdmin packageAdmin,
+			@SuppressWarnings("deprecation") org.osgi.service.packageadmin.@Nullable PackageAdmin packageAdmin,
 			OTWeavingHook hook) throws OTAgentNotInstalled
 	{
 		String superBaseClass = superBase.getAttribute(SUPER_BASE_CLASS);
 		String superBasePlugin = superBase.getAttribute(SUPER_BASE_PLUGIN);
+		if (superBaseClass == null) throw new IllegalArgumentException("superBase element must define 'class'");
 		BaseBundle superBaseBundle;
 		if (superBasePlugin == null) {
 			superBasePlugin = baseBundle.bundleName;
@@ -224,7 +228,7 @@
 
 	@SuppressWarnings("deprecation") // multiple uses of deprecated but still recommended class PackageAdmin
 	private boolean checkRequiredFragments(String aspectBundleId, String baseBundleId, IConfigurationElement[] fragments, 
-			@Nullable org.osgi.service.packageadmin.PackageAdmin packageAdmin) 
+			org.osgi.service.packageadmin.@Nullable PackageAdmin packageAdmin) 
 	{
 		// checking only, no real action needed.
 		boolean hasError = false;
@@ -297,8 +301,8 @@
 	 * Given a potential aspect bundle, answer the symbolic names of all base bundles
 	 * adapted by the aspect bundle.
 	 */
-	public @Nullable String[] getAdaptedBasePlugins(Bundle aspectBundle) {
-		ArrayList<AspectBinding> bindings = aspectBindingsByAspectPlugin.get(aspectBundle.getSymbolicName());
+	public String @Nullable[] getAdaptedBasePlugins(Bundle aspectBundle) {
+		List<AspectBinding> bindings = aspectBindingsByAspectPlugin.get(aspectBundle.getSymbolicName());
 		if (bindings == null) return null;
 		String[] basePlugins = new String[bindings.size()];
 		for (int i=0; i<basePlugins.length; i++) {
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/AspectPermissionManager.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/AspectPermissionManager.java
index 68f9006..aa73416 100644
--- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/AspectPermissionManager.java
+++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/AspectPermissionManager.java
@@ -100,12 +100,12 @@
 	
 	// collect all forced exports (denied/granted), granted should balance to an empty structure.
 	// structure is: aspect-id -> (base bundle x base package)*
-	private HashMap<String, List<String[]>> deniedForcedExportsByAspect= new HashMap<String, List<String[]>>();
-	private HashMap<String, List<String[]>> grantedForcedExportsByAspect= new HashMap<String, List<String[]>>();
+	private Map<String, List<@NonNull String[]>> deniedForcedExportsByAspect= new HashMap<>();
+	private Map<String, List<@NonNull String[]>> grantedForcedExportsByAspect= new HashMap<>();
 	
 	// key is aspectId+"->"+baseId, value is array of team names
-	private HashMap<String, Set<String>> deniedTeamsByAspectBinding = new HashMap<String, Set<String>>();
-	private HashMap<String, Set<String>> grantedTeamsByAspectBinding = new HashMap<String, Set<String>>();
+	private Map<String, Set<String>> deniedTeamsByAspectBinding = new HashMap<String, Set<String>>();
+	private Map<String, Set<String>> grantedTeamsByAspectBinding = new HashMap<String, Set<String>>();
 
 	// the workspace directory for storing the state of this plugin
 	@Nullable private IPath otequinoxState;
@@ -113,12 +113,12 @@
 	private Bundle transformerBundle;
 	// helper instance needed to stop bundles by name
 	@SuppressWarnings("deprecation")
-	@Nullable private org.osgi.service.packageadmin.PackageAdmin packageAdmin;
+	private org.osgi.service.packageadmin.@Nullable PackageAdmin packageAdmin;
 	
 	private ForcedExportsDelegate forcedExportsDelegate;
 	
 	public AspectPermissionManager(Bundle bundle, 
-			@SuppressWarnings("deprecation") @Nullable org.osgi.service.packageadmin.PackageAdmin packageAdmin)
+			@SuppressWarnings("deprecation") org.osgi.service.packageadmin.@Nullable PackageAdmin packageAdmin)
 	{
 		this.transformerBundle = bundle;
 		this.packageAdmin = packageAdmin;
@@ -226,7 +226,7 @@
 			String forcedExportsRequest = forcedExport.getValue();
 			if (forcedExportsRequest == null)
 				continue;
-			for (@SuppressWarnings("null")@NonNull String singleForcedExportRequest : forcedExportsRequest.split(","))
+			for (@NonNull String singleForcedExportRequest : forcedExportsRequest.split(","))
 			{
 				singleForcedExportRequest = singleForcedExportRequest.trim();
 
@@ -312,11 +312,11 @@
 	 * @param map		in/out param for storing results from OTStorageHook
 	 * @return		 	list of pairs (base bundle x base package)
 	 */
-	private List<String[]> getConfiguredForcedExports( String                          aspectId, 
+	private List<@NonNull String[]> getConfiguredForcedExports( String                          aspectId, 
 														AspectPermission 				perm, 
-														HashMap<String, List<String[]>> map)
+														Map<String, List<@NonNull String[]>> map)
     {
-		List<String[]> forcedExports= map.get(aspectId);
+		List<@NonNull String[]> forcedExports= map.get(aspectId);
 		if (forcedExports == null) {
 			// fetch declarations from config.ini or other locations.
 			forcedExports= forcedExportsDelegate.getForcedExportsByAspect(aspectId, perm);
@@ -325,7 +325,7 @@
 		return forcedExports;
 	}
 
-	private @Nullable String[] findRequestInList(String baseBundleId, String basePackage, List<String[]> list) {
+	private String @Nullable[] findRequestInList(String baseBundleId, String basePackage, List<String[]> list) {
 		for (String[] singleExport : list)
 			if (   singleExport[0].equals(baseBundleId)
 				&& singleExport[1].equals(basePackage))
@@ -540,7 +540,9 @@
 									teamInstance.deactivate(Team.ALL_THREADS);
 							// could also check if roles are present already ...
 						}
-						bundlesToStop.add(teamClass.getAspectBinding().aspectBundle);
+						Bundle aspectBundle = teamClass.getAspectBinding().aspectBundle;
+						if (aspectBundle != null)
+							bundlesToStop.add(aspectBundle);
 					}
 					for (Bundle bundle : bundlesToStop) {
 						if ((bundle.getState() & (Bundle.STARTING|Bundle.ACTIVE)) != 0) {
@@ -662,12 +664,12 @@
 		log(IStatus.INFO, "Created aspect binding defaults file "+configFile.getCanonicalPath());
 	}
 
-	private void parseTeamPermissionFile(HashMap<String, Set<String>> teamsByAspectBinding, File configFile) {
+	private void parseTeamPermissionFile(Map<String, Set<String>> teamsByAspectBinding, File configFile) {
 		try (BufferedReader reader = new BufferedReader(new FileReader(configFile))) {
 			String line;
 			while ((line = reader.readLine()) != null) {
 				if (line.length() > 0 && line.charAt(0) == '#') continue;
-				String[] parts = line.split("=");
+				@NonNull String[] parts = line.split("=");
 				if (parts.length == 2) {
 					Set<String> teams = new HashSet<String>();
 					StringTokenizer teamToks = new StringTokenizer(parts[1], ",");
@@ -685,7 +687,7 @@
 	{
 		IPath state = this.otequinoxState;
 		if (state != null) {
-			HashMap<String, Set<String>> teamsByAspect = null;
+			Map<String, Set<String>> teamsByAspect = null;
 			IPath configFilePath = null;
 			switch (negotiatedPermission) {
 			case GRANT:
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/BaseBundleLoadTrigger.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/BaseBundleLoadTrigger.java
index 8f3bac2..346611c 100644
--- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/BaseBundleLoadTrigger.java
+++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/BaseBundleLoadTrigger.java
@@ -41,14 +41,14 @@
 
 	private AspectBindingRegistry aspectBindingRegistry;
 	@SuppressWarnings("deprecation")
-	private @Nullable org.osgi.service.packageadmin.PackageAdmin admin;
+	private org.osgi.service.packageadmin.@Nullable PackageAdmin admin;
 
 	private String baseBundleName;	
 	@Nullable private BaseBundle baseBundle; // null when representing an aspectBundle with SELF-adapting teams
 	private List<AspectBinding> aspectBindings = new ArrayList<>();
 
 	public BaseBundleLoadTrigger(String bundleSymbolicName, @Nullable BaseBundle baseBundle, AspectBindingRegistry aspectBindingRegistry, 
-			@SuppressWarnings("deprecation") @Nullable org.osgi.service.packageadmin.PackageAdmin admin) 
+			@SuppressWarnings("deprecation") org.osgi.service.packageadmin.@Nullable PackageAdmin admin) 
 	{
 		this.baseBundleName = bundleSymbolicName;
 		this.baseBundle = baseBundle;
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/ClassScanner.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/ClassScanner.java
index 4a7fd39..be997c4 100644
--- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/ClassScanner.java
+++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/ClassScanner.java
@@ -25,6 +25,7 @@
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.jdt.annotation.NonNull;
@@ -50,10 +51,10 @@
 	// collect class names recorded by readOTAttributes:
 	
 	//   * this version used by the MasterTeamLoader.loadTeams:
-	HashMap<String,ArrayList<String>> baseClassNamesByTeam = new HashMap<String, ArrayList<String>>();
+	Map<String,ArrayList<String>> baseClassNamesByTeam = new HashMap<String, ArrayList<String>>();
 	//   * these fields used by TransformerHook.processClass (collected over multiple readOTAttributes):
-	ArrayList<String> allBaseClassNames = new ArrayList<String>();
-	ArrayList<String> roleClassNames = new ArrayList<String>();
+	List<String> allBaseClassNames = new ArrayList<String>();
+	List<String> roleClassNames = new ArrayList<String>();
 
 
 	/** 
@@ -134,7 +135,7 @@
 	{
 		List<String> roles = CallinBindingManager.getRolePerTeam(className);
 		if (roles != null) {
-			for (@SuppressWarnings("null")@NonNull String roleName: roles) {
+			for (@NonNull String roleName: roles) {
 				log(IStatus.OK, "scanning role "+roleName);
 				try {
 					this.roleClassNames.add(roleName);
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/DelegatingTransformer.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/DelegatingTransformer.java
index b340308..db2b6b1 100644
--- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/DelegatingTransformer.java
+++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/DelegatingTransformer.java
@@ -27,6 +27,7 @@
 import java.util.EnumSet;
 
 import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.objectteams.internal.osgi.weaving.ASMByteCodeAnalyzer.ClassInformation;
 import org.eclipse.objectteams.internal.osgi.weaving.OTWeavingHook.WeavingReason;
 import org.eclipse.objectteams.internal.osgi.weaving.OTWeavingHook.WeavingScheme;
@@ -65,7 +66,7 @@
 	}
 
 	/** Factory method for a fresh transformer. */
-	static @NonNull DelegatingTransformer newTransformer(WeavingScheme weavingScheme, OTWeavingHook hook, BundleWiring wiring) {
+	static @NonNull DelegatingTransformer newTransformer(WeavingScheme weavingScheme, @NonNull OTWeavingHook hook, @NonNull BundleWiring wiring) {
 		switch (weavingScheme) {
 			case OTDRE:
 				return new OTDRETransformer(getWeavingContext(hook, wiring));
@@ -79,10 +80,10 @@
 	private static class OTRETransformer extends DelegatingTransformer {
 		org.eclipse.objectteams.otre.jplis.ObjectTeamsTransformer transformer = new org.eclipse.objectteams.otre.jplis.ObjectTeamsTransformer();
 		@Override
-		public void readOTAttributes(String className, InputStream inputStream, String fileName, Bundle bundle) throws ClassFormatError, IOException {
+		public void readOTAttributes(@NonNull String className, @NonNull InputStream inputStream, @NonNull String fileName, Bundle bundle) throws ClassFormatError, IOException {
 			this.transformer.readOTAttributes(inputStream, fileName, bundle);
 		}
-		public Collection<String> fetchAdaptedBases() {
+		public Collection<@NonNull String> fetchAdaptedBases() {
 			return this.transformer.fetchAdaptedBases();
 		}
 		public byte[] transform(Bundle bundle, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] bytes)
@@ -99,11 +100,11 @@
 			transformer = new org.eclipse.objectteams.otredyn.transformer.jplis.ObjectTeamsTransformer(weavingContext);
 		}
 		@Override
-		public void readOTAttributes(String className, InputStream inputStream, String fileName, Bundle bundle) throws ClassFormatError, IOException {
+		public void readOTAttributes(@NonNull String className, @NonNull InputStream inputStream, @NonNull String fileName, Bundle bundle) throws ClassFormatError, IOException {
 			// TODO provide classID
 			this.transformer.readOTAttributes(className, className.replace('.', '/'), inputStream, getBundleLoader(bundle));
 		}
-		public Collection<String> fetchAdaptedBases() {
+		public Collection<@NonNull String> fetchAdaptedBases() {
 			return transformer.fetchAdaptedBases();
 		}
 		public byte[] transform(final Bundle bundle, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] bytes) throws IllegalClassFormatException {
@@ -156,7 +157,8 @@
 		}
 	}
 
-	static ClassLoader getBundleLoader(final Bundle bundle) {
+	static @Nullable ClassLoader getBundleLoader(final @Nullable Bundle bundle) {
+		if (bundle == null) return null;
 		return new ClassLoader() {
 			@Override
 			public Class<?> loadClass(String name) throws ClassNotFoundException {
@@ -169,29 +171,30 @@
 		};
 	}
 
-	static IWeavingContext getWeavingContext(final OTWeavingHook hook, final BundleWiring bundleWiring) {
+	static IWeavingContext getWeavingContext(final @NonNull OTWeavingHook hook, final @NonNull BundleWiring bundleWiring) {
 		return new IWeavingContext() {
 			@Override
 			public boolean isWeavable(String className, boolean considerSupers, boolean allWeavingReasons) {
 				if (className == null)
 					return false;
 				// boolean allWeavingReasons is used in the signature, because IWeavingContext cannot see WeavingReaons:
-				EnumSet<WeavingReason> reasons = allWeavingReasons ? EnumSet.allOf(WeavingReason.class) : EnumSet.of(WeavingReason.Base);
+				EnumSet<@NonNull WeavingReason> reasons = allWeavingReasons ? EnumSet.allOf(WeavingReason.class) : EnumSet.of(WeavingReason.Base);
 				WeavingReason reason = hook.requiresWeaving(bundleWiring, className, null, considerSupers, reasons);
 				return reason != WeavingReason.None;
 			}
 			
 			@Override
-			public boolean scheduleReweaving(String className, IReweavingTask task) {
+			public boolean scheduleReweaving(String className, /*@NonNull*/ IReweavingTask task) {
 				return hook.scheduleReweaving(className, task);
 			}
 		};
 	}
 	
-	public abstract void readOTAttributes(String className, InputStream inputStream, String fileName, Bundle bundle) throws ClassFormatError, IOException;
+	// FIXME: it's unclear if we can tollerate @Nullable Bundle
+	public abstract void readOTAttributes(@NonNull String className, @NonNull InputStream inputStream, @NonNull String fileName, Bundle bundle) throws ClassFormatError, IOException;
 	
 	public abstract byte[] transform(Bundle bundle, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] bytes)
 			throws IllegalClassFormatException;
 
-	public abstract Collection<String> fetchAdaptedBases();
+	public abstract Collection<@NonNull String> fetchAdaptedBases();
 }
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/ForcedExportsDelegate.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/ForcedExportsDelegate.java
index 9581a68..5635c1b 100644
--- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/ForcedExportsDelegate.java
+++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/ForcedExportsDelegate.java
@@ -22,6 +22,7 @@
 import java.util.List;
 
 import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.objectteams.otequinox.AspectPermission;
 import org.eclipse.objectteams.otequinox.TransformerPlugin;
 
@@ -46,11 +47,12 @@
 		return registryClass != null;
 	}
 
-	public @NonNull List<String[]> getForcedExportsByAspect(String aspectBundleId, AspectPermission perm) {
+	@NonNullByDefault
+	public List<@NonNull String[]> getForcedExportsByAspect(String aspectBundleId, AspectPermission perm) {
 		if (getForcedExportsByAspect != null) {
 			try {
 				@SuppressWarnings({ "unchecked", "null" })@NonNull // reflection knows nothing about nullness, nor generics
-				List<String[]> result = (List<String[]>) getForcedExportsByAspect.invoke(null, new Object[] {aspectBundleId, perm.ordinal()});
+				List<@NonNull String[]> result = (List<String[]>) getForcedExportsByAspect.invoke(null, new Object[] {aspectBundleId, perm.ordinal()});
 				return result;
 			} catch (SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
 				TransformerPlugin.log(e, "Failed to access forced exports");
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/OTWeavingHook.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/OTWeavingHook.java
index 91303ab..5fc4204 100644
--- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/OTWeavingHook.java
+++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/OTWeavingHook.java
@@ -39,6 +39,7 @@
 import org.eclipse.core.runtime.IExtensionRegistry;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.objectteams.internal.osgi.weaving.ASMByteCodeAnalyzer.ClassInformation;
 import org.eclipse.objectteams.internal.osgi.weaving.AspectBinding.BaseBundle;
@@ -74,9 +75,10 @@
  * re-attempt instantiating the dependent team(s).</li>
  * </ul>
  */
+@NonNullByDefault
 public class OTWeavingHook implements WeavingHook, WovenClassListener {
 
-	static @NonNull WeavingScheme DEFAULT_WEAVING_SCHEME = WeavingScheme.Unknown;
+	static WeavingScheme DEFAULT_WEAVING_SCHEME = WeavingScheme.Unknown;
 	enum WeavingScheme { Unknown, OTRE, OTDRE };
 
 	static final ThreadWeaving WEAVE_THREAD_NOTIFICATION;
@@ -122,30 +124,30 @@
 	enum WeavingReason { None, Aspect, Base, Thread }
 	
 	/** Interface to data about aspectBinding extensions. */
-	private @NonNull AspectBindingRegistry aspectBindingRegistry = new AspectBindingRegistry();
+	private AspectBindingRegistry aspectBindingRegistry = new AspectBindingRegistry();
 	
 	/** Map of trip wires to be fired when a particular base bundle is loaded. */
-	private @NonNull HashMap<String, BaseBundleLoadTrigger> baseTripWires = new HashMap<>();
+	private Map<String, BaseBundleLoadTrigger> baseTripWires = new HashMap<>();
 
 	/** Set of classes for which processing has started but which are not yet defined in the class loader. */
-	private @NonNull Set<String> beingDefined = new HashSet<>();
+	private Set<String> beingDefined = new HashSet<>();
 
 	/** Map of tasks per qualified class name: reweaving requested during defineClass(). */
-	private @NonNull Map<String, IReweavingTask> pendingReweavingTasks = new HashMap<>();
+	private Map<String, IReweavingTask> pendingReweavingTasks = new HashMap<>();
 
 	/** Records of teams that have been deferred due to unresolved class dependencies: */
-	private @NonNull List<WaitingTeamRecord> deferredTeams = new ArrayList<>();
+	private List<WaitingTeamRecord> deferredTeams = new ArrayList<>();
 
-	private @NonNull ASMByteCodeAnalyzer byteCodeAnalyzer = new ASMByteCodeAnalyzer();
+	private ASMByteCodeAnalyzer byteCodeAnalyzer = new ASMByteCodeAnalyzer();
 
-	private AspectPermissionManager permissionManager;
+	private @Nullable AspectPermissionManager permissionManager;
 
 	/** A registered lifting participant is directly handled by us. */
 	private @Nullable IConfigurationElement liftingParticipantConfig;
 	private @Nullable Class<?> ooTeam;
 
 	/** Call-back once the extension registry is up and running. */
-	public void activate(@NonNull BundleContext bundleContext, ServiceReference<IExtensionRegistry> serviceReference) throws OTAgentNotInstalled {
+	public void activate(BundleContext bundleContext, @Nullable ServiceReference<IExtensionRegistry> serviceReference) throws OTAgentNotInstalled {
 		loadAspectBindingRegistry(bundleContext, serviceReference);
 		TransformerPlugin.initialize(bundleContext, this.aspectBindingRegistry, this.permissionManager);
 	}
@@ -153,7 +155,7 @@
 	// ====== Aspect Bindings & Permissions: ======
 
 	@SuppressWarnings("deprecation")
-	private void loadAspectBindingRegistry(BundleContext context, ServiceReference<IExtensionRegistry> serviceReference) throws OTAgentNotInstalled {
+	private void loadAspectBindingRegistry(BundleContext context, @Nullable ServiceReference<IExtensionRegistry> serviceReference) throws OTAgentNotInstalled {
 		org.osgi.service.packageadmin.PackageAdmin packageAdmin = null;
 		
 		ServiceReference<?> ref= context.getServiceReference(org.osgi.service.packageadmin.PackageAdmin.class.getName());
@@ -167,8 +169,9 @@
 		if (extensionRegistry == null) {
 			log(IStatus.ERROR, "Failed to acquire ExtensionRegistry service, cannot load aspect bindings.");
 		} else {
-			permissionManager = new AspectPermissionManager(context.getBundle(), packageAdmin);
-			permissionManager.loadAspectBindingNegotiators(extensionRegistry);
+			AspectPermissionManager manager = new AspectPermissionManager(context.getBundle(), packageAdmin);
+			manager.loadAspectBindingNegotiators(extensionRegistry);
+			permissionManager = manager;
 
 			aspectBindingRegistry.loadAspectBindings(extensionRegistry, packageAdmin, this);
 
@@ -176,7 +179,7 @@
 		}
 	}
 
-	public @NonNull AspectPermissionManager getAspectPermissionManager() {
+	public AspectPermissionManager getAspectPermissionManager() {
 		AspectPermissionManager manager = this.permissionManager;
 		if (manager == null)
 			throw new NullPointerException("Missing AspectPermissionManager");
@@ -218,8 +221,8 @@
 	 * Callback during AspectBindingRegistry#loadAspectBindings():
 	 * Set-up a trip wire to fire when the mentioned base bundle is loaded.
 	 */
-	void setBaseTripWire(@SuppressWarnings("deprecation") @Nullable org.osgi.service.packageadmin.PackageAdmin packageAdmin,
-			@NonNull String baseBundleId, BaseBundle baseBundle) 
+	void setBaseTripWire(@SuppressWarnings("deprecation") org.osgi.service.packageadmin.@Nullable PackageAdmin packageAdmin,
+			String baseBundleId, BaseBundle baseBundle) 
 	{
 		if (!baseTripWires.containsKey(baseBundleId))
 			baseTripWires.put(baseBundleId, new BaseBundleLoadTrigger(baseBundleId, baseBundle, aspectBindingRegistry, packageAdmin));
@@ -229,7 +232,7 @@
 	 * Check if the given base bundle / base class mandate any loading/instantiation/activation of teams.
 	 * @return true if all involved aspect bindings have been denied (permissions).
 	 */
-	boolean triggerBaseTripWires(@Nullable String bundleName, @NonNull WovenClass baseClass) {
+	boolean triggerBaseTripWires(@Nullable String bundleName, WovenClass baseClass) {
 		BaseBundleLoadTrigger activation = baseTripWires.get(bundleName);
 		if (activation != null) {
 			activation.fire(baseClass, beingDefined, this);
@@ -336,7 +339,7 @@
 		return false;
 	}
 
-	WeavingReason requiresWeaving(BundleWiring bundleWiring, @NonNull String className, byte[] bytes,
+	WeavingReason requiresWeaving(BundleWiring bundleWiring, String className, byte @Nullable[] bytes,
 			boolean considerSupers, EnumSet<WeavingReason> considerReasons) {
 		
 		// 1. consult the aspect binding registry (for per-bundle info):
@@ -393,7 +396,7 @@
 	/** check need for weaving by finding an aspect binding affecting this exact base class or one of its supers. 
 	 * @param searchSupers controls whether super classes should be considered, too.
 	 */
-	boolean isAdaptedBaseClass(List<AspectBinding> aspectBindings, String className, boolean searchSupers, byte[] bytes, ClassLoader resourceLoader) {
+	boolean isAdaptedBaseClass(List<AspectBinding> aspectBindings, String className, boolean searchSupers, byte @Nullable[] bytes, @Nullable ClassLoader resourceLoader) {
 		if (skipBaseClassCheck) return true; // have aspect bindings, flag requests to transform *all* classes in this base bundle
 		
 		if ("java.lang.Object".equals(className))
@@ -412,6 +415,8 @@
 			if (bytes != null) {
 				classInfo = this.byteCodeAnalyzer.getClassInformation(bytes, className);
 			} else {
+				if (resourceLoader == null)
+					return false; // no chance to analyse (happens with fragments)
 				try (InputStream is = resourceLoader.getResourceAsStream(className.replace('.', '/')+".class")) {
 					if (is != null)
 						classInfo = this.byteCodeAnalyzer.getClassInformation(is, className);
@@ -433,7 +438,7 @@
 		}
 	}
 
-	private void recordBaseClasses(DelegatingTransformer transformer, @NonNull String aspectBundle, String className) {
+	private void recordBaseClasses(DelegatingTransformer transformer, String aspectBundle, String className) {
 		Collection<String> adaptedBases = transformer.fetchAdaptedBases();
 		if (adaptedBases == null || adaptedBases.isEmpty()) return;
 		aspectBindingRegistry.addBoundBaseClasses(adaptedBases);
@@ -536,7 +541,7 @@
 	
 	}
 
-	private boolean needsThreadNotificationCode(String className, byte[] bytes, ClassLoader resourceLoader, boolean isBaseBundle) {
+	private boolean needsThreadNotificationCode(String className, byte @Nullable[] bytes, @Nullable ClassLoader resourceLoader, boolean isBaseBundle) {
 
 		if ("java.lang.Object".equals(className))
 			return false; // shortcut, have no super
@@ -553,6 +558,8 @@
 			if (bytes != null) {
 				classInfo = this.byteCodeAnalyzer.getClassInformation(bytes, className);
 			} else {
+				if (resourceLoader == null)
+					return false; // happens for fragments
 				try (InputStream is = resourceLoader.getResourceAsStream(className.replace('.', '/')+".class")) {
 					if (is != null) {
 						classInfo = this.byteCodeAnalyzer.getClassInformation(is, className);
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 7e1f4dc..40a4bff 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
@@ -267,7 +267,7 @@
 	
 	private @Nullable String findUnloadableBaseClass(TeamBinding team) {
 		// easy tests first:
-		for (@SuppressWarnings("null")@NonNull String baseclass : team.baseClassNames) {
+		for (String baseclass : team.baseClassNames) {
 			if (this.beingDefined.contains(baseclass))
 				return baseclass;
 		}
@@ -277,7 +277,7 @@
 			// 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 (String baseclass : team.baseClassNames) { 
 				Boolean previous = ObjectTeamsTransformer.initiatedByThrowAwayLoader.get();
 				try {
 					ObjectTeamsTransformer.initiatedByThrowAwayLoader.set(Boolean.TRUE);
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/Util.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/Util.java
index 8778bf2..13c194c 100644
--- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/Util.java
+++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/internal/osgi/weaving/Util.java
@@ -20,8 +20,6 @@
  **********************************************************************/
 package org.eclipse.objectteams.internal.osgi.weaving;
 
-import static org.eclipse.objectteams.otequinox.TransformerPlugin.doLog;
-
 import static org.eclipse.core.runtime.IStatus.*;
 
 public class Util 
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/IAspectRegistry.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/IAspectRegistry.java
index d891a94..f32e88c 100644
--- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/IAspectRegistry.java
+++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/IAspectRegistry.java
@@ -49,7 +49,7 @@
 	 *  @param aspectBundle potential aspect plugin
 	 *  @return array of base plugin IDs or null.
 	 */
-	public @Nullable String[] getAdaptedBasePlugins(Bundle aspectBundle);
+	public String @Nullable[] getAdaptedBasePlugins(Bundle aspectBundle);
 
 	/**
 	 * Does `bundle' have internal teams, i.e., teams that adapt classes from their
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/TransformerPlugin.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/TransformerPlugin.java
index 2727ef2..cbb5bef 100644
--- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/TransformerPlugin.java
+++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/TransformerPlugin.java
@@ -102,7 +102,7 @@
 		}
 
 		@Override
-		public @Nullable String[] getAdaptedBasePlugins(Bundle aspectBundle) {
+		public String @Nullable[] getAdaptedBasePlugins(Bundle aspectBundle) {
 			return this.aspectBindingRegistry.getAdaptedBasePlugins(aspectBundle);
 		}
 
@@ -206,6 +206,7 @@
 				= new ServiceTracker<ExtendedLogService,ExtendedLogService>(bundleContext, ExtendedLogService.class, null);
 		tracker.open();
 		ExtendedLogService logService = tracker.getService();
+		if (logService == null) throw new IllegalStateException("no log service available"); // give up :(
 		Bundle bundle = bundleContext.getBundle();
 		Logger logger = logService.getLogger(bundle, OTEQUINOX_LOGGER_NAME);
 
@@ -213,19 +214,20 @@
 				= new ServiceTracker<ExtendedLogReaderService,ExtendedLogReaderService>(bundleContext, ExtendedLogReaderService.class.getName(), null);
 		logReaderTracker.open();
 		ExtendedLogReaderService logReader = logReaderTracker.getService();
+		if (logReader == null) throw new IllegalStateException("no log reader available"); // give up :(
 
 		final Logger equinoxLogger = logService.getLogger(bundle, LoggerBridge.EQUINOX_LOGGER_NAME);
 
 		// listen to log events from our logger and asynchronously dispatch them to the equinox logger
 		logReader.addLogListener(
 			new LogListener() {
-				@Override @NonNullByDefault(false)
+				@Override @NonNullByDefault({})
 				public void logged(LogEntry entry) {
 					equinoxLogger.log(entry.getLevel(), entry.getMessage(), entry.getException());
 				}
 			},
 			new LogFilter() {
-				@Override @NonNullByDefault(false)
+				@Override @NonNullByDefault({})
 				public boolean isLoggable(Bundle bundle, String loggerName, int logLevel) {
 					return OTEQUINOX_LOGGER_NAME.equals(loggerName);
 				}
@@ -245,7 +247,9 @@
 		ServiceTracker<LoggerAdmin,LoggerAdmin> adminTracker
 					= new ServiceTracker<LoggerAdmin,LoggerAdmin>(bundleContext, LoggerAdmin.class, null);
 		adminTracker.open();
-		adminTracker.getService().getLoggerContext(bundleSymbolicName).setLogLevels(levels);
+		LoggerAdmin service = adminTracker.getService();
+		if (service != null)
+			service.getLoggerContext(bundleSymbolicName).setLogLevels(levels);
 	}
 
 	private void OTREInit() {
@@ -394,7 +398,7 @@
 	}
 
 	@Override
-	public @Nullable String[] getAdaptedBasePlugins(Bundle aspectBundle) {
+	public String @Nullable[] getAdaptedBasePlugins(Bundle aspectBundle) {
 		throw notInitialized();
 	}