You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by rm...@apache.org on 2014/10/19 13:39:27 UTC

git commit: trying to use app loader and not API loader to define proxies to avoid to leak as much as possible + Closeables helper to close what needs in arquillian openejb embedded

Repository: tomee
Updated Branches:
  refs/heads/develop 2a38e3346 -> 0937a91bd


trying to use app loader and not API loader to define proxies to avoid to leak as much as possible + Closeables helper to close what needs in arquillian openejb embedded


Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/0937a91b
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/0937a91b
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/0937a91b

Branch: refs/heads/develop
Commit: 0937a91bdc483fa5c2c0e874a3c68f5cb3dcde1e
Parents: 2a38e33
Author: Romain Manni-Bucau <rm...@apache.org>
Authored: Sun Oct 19 13:39:08 2014 +0200
Committer: Romain Manni-Bucau <rm...@apache.org>
Committed: Sun Oct 19 13:39:08 2014 +0200

----------------------------------------------------------------------
 .../openejb/arquillian/openejb/Closeables.java  | 38 +++++++++++++
 .../openejb/OpenEJBArchiveProcessor.java        | 38 ++++++++-----
 .../openejb/OpenEJBDeployableContainer.java     | 39 +++++++++----
 .../arquillian/openejb/SWClassLoader.java       |  5 +-
 .../apache/openejb/dyni/DynamicSubclass.java    |  2 +-
 .../util/proxy/LocalBeanProxyFactory.java       |  7 ++-
 .../openejb/tck/cdi/embedded/GCListener.java    | 59 ++++++++++++++++++++
 tck/cdi-embedded/src/test/resources/passing.xml |  2 +
 8 files changed, 159 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tomee/blob/0937a91b/arquillian/arquillian-openejb-embedded-5/src/main/java/org/apache/openejb/arquillian/openejb/Closeables.java
----------------------------------------------------------------------
diff --git a/arquillian/arquillian-openejb-embedded-5/src/main/java/org/apache/openejb/arquillian/openejb/Closeables.java b/arquillian/arquillian-openejb-embedded-5/src/main/java/org/apache/openejb/arquillian/openejb/Closeables.java
new file mode 100644
index 0000000..5d093da
--- /dev/null
+++ b/arquillian/arquillian-openejb-embedded-5/src/main/java/org/apache/openejb/arquillian/openejb/Closeables.java
@@ -0,0 +1,38 @@
+/*
+ * 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.openejb.arquillian.openejb;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.LinkedList;
+
+public class Closeables implements Closeable {
+    private final Collection<Closeable> closeables = new LinkedList<>();
+
+    public synchronized void add(final Closeable closeable) {
+        closeables.add(closeable);
+    }
+
+    @Override
+    public synchronized void close() throws IOException {
+        for (final Closeable c : closeables) {
+            c.close();
+        }
+        closeables.clear();
+    }
+}

http://git-wip-us.apache.org/repos/asf/tomee/blob/0937a91b/arquillian/arquillian-openejb-embedded-5/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBArchiveProcessor.java
----------------------------------------------------------------------
diff --git a/arquillian/arquillian-openejb-embedded-5/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBArchiveProcessor.java b/arquillian/arquillian-openejb-embedded-5/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBArchiveProcessor.java
index 674a0dd..7982af7 100644
--- a/arquillian/arquillian-openejb-embedded-5/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBArchiveProcessor.java
+++ b/arquillian/arquillian-openejb-embedded-5/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBArchiveProcessor.java
@@ -91,7 +91,7 @@ public class OpenEJBArchiveProcessor {
     private static final String ENV_ENTRIES_PROPERTIES = "env-entries.properties";
     public static final String WEB_INF_CLASSES = "/WEB-INF/classes/";
 
-    public static AppModule createModule(final Archive<?> archive, final TestClass testClass) {
+    public static AppModule createModule(final Archive<?> archive, final TestClass testClass, final Closeables closeables) {
         final Class<?> javaClass;
         if (testClass != null) {
             javaClass = testClass.getJavaClass();
@@ -143,7 +143,7 @@ public class OpenEJBArchiveProcessor {
                 }
             }
         } else {
-            if (isEar) { // mainly for CDi TCKs
+            if (isEar) { // mainly for CDI TCKs
                 earMap = new HashMap<>();
                 final Map<ArchivePath, Node> jars = archive.getContent(new IncludeRegExpPaths("/.*\\.jar"));
                 final List<org.apache.xbean.finder.archive.Archive> archives = new ArrayList<>(jars.size());
@@ -183,13 +183,19 @@ public class OpenEJBArchiveProcessor {
 
         final URL[] urls = additionalPaths.toArray(new URL[additionalPaths.size()]);
 
-        final ClassLoader loader;
+        final SWClassLoader loader;
         if (!WEB_INF.equals(prefix)) {
-            loader = new SWClassLoader("", new URLClassLoader(urls, parent), archive);
+            final URLClassLoader swParent = new URLClassLoader(urls, parent);
+            closeables.add(swParent);
+            loader = new SWClassLoader("", swParent, archive);
         } else {
-            loader = new SWClassLoader(WEB_INF_CLASSES, new URLClassLoaderFirst(urls, parent), archive);
+            final URLClassLoaderFirst swParent = new URLClassLoaderFirst(urls, parent);
+            closeables.add(swParent);
+            loader = new SWClassLoader(WEB_INF_CLASSES, swParent, archive);
         }
+        closeables.add(loader);
         final URLClassLoader tempClassLoader = ClassLoaderUtil.createTempClassLoader(loader);
+        closeables.add(tempClassLoader);
 
         final AppModule appModule = new AppModule(loader, archive.getName());
         if (WEB_INF.equals(prefix)) {
@@ -199,8 +205,8 @@ public class OpenEJBArchiveProcessor {
             final WebModule webModule = new WebModule(new WebApp(), contextRoot(archive.getName()), loader, "", appModule.getModuleId());
             webModule.setUrls(additionalPaths);
             appModule.getWebModules().add(webModule);
-        } else if (isEar) { // mainly for CDi TCKs
-            final FinderFactory.OpenEJBAnnotationFinder earLibFinder = new FinderFactory.OpenEJBAnnotationFinder(new SimpleWebappAggregatedArchive(earArchive, earMap));
+        } else if (isEar) { // mainly for CDI TCKs
+            final FinderFactory.OpenEJBAnnotationFinder earLibFinder = new FinderFactory.OpenEJBAnnotationFinder(new SimpleWebappAggregatedArchive(tempClassLoader, earArchive, earMap));
             appModule.setEarLibFinder(earLibFinder);
 
             final EjbModule earCdiModule = new EjbModule(appModule.getClassLoader(), DeploymentLoader.EAR_SCOPED_CDI_BEANS + appModule.getModuleId(), new EjbJar(), new OpenejbJar());
@@ -218,9 +224,11 @@ public class OpenEJBArchiveProcessor {
                         final Map<ArchivePath, Node> libs = archive.getContent(new IncludeRegExpPaths("/WEB-INF/lib/.*\\.jar"));
                         */
 
-                        final Map<String, Object> altDD = new HashMap<String, Object>();
+                        final Map<String, Object> altDD = new HashMap<>();
                         final Node beansXml = findBeansXml(webArchive, new ArrayList<AssetSource>(), WEB_INF, altDD);
                         final SWClassLoader webLoader = new SWClassLoader(WEB_INF_CLASSES, parent, webArchive);
+                        closeables.add(webLoader);
+
                         final FinderFactory.OpenEJBAnnotationFinder finder = new FinderFactory.OpenEJBAnnotationFinder(
                                 finderArchive(beansXml, webArchive, webLoader, Collections.<URL>emptyList()));
 
@@ -442,11 +450,11 @@ public class OpenEJBArchiveProcessor {
             }
         }
 
-        final Map<URL, List<String>> classesByUrl = new HashMap<URL, List<String>>();
+        final Map<URL, List<String>> classesByUrl = new HashMap<>();
 
-        final List<org.apache.xbean.finder.archive.Archive> archives = new ArrayList<org.apache.xbean.finder.archive.Archive>();
+        final List<org.apache.xbean.finder.archive.Archive> archives = new ArrayList<>();
         for (final URL url : DeploymentLoader.filterWebappUrls(additionalPaths.toArray(new URL[additionalPaths.size()]), null)) {
-            final List<String> currentClasses = new ArrayList<String>();
+            final List<String> currentClasses = new ArrayList<>();
             final org.apache.xbean.finder.archive.Archive newArchive = new FilteredArchive(new JarArchive(cl, url), new WebappAggregatedArchive.ScanXmlSaverFilter(false, null, currentClasses));
             classesByUrl.put(url, currentClasses);
             archives.add(newArchive);
@@ -454,7 +462,7 @@ public class OpenEJBArchiveProcessor {
 
         archives.add(new ClassesArchive(classes));
         if (beansXml != null) {
-            final List<String> mainClasses = new ArrayList<String>();
+            final List<String> mainClasses = new ArrayList<>();
             for (final Class<?> clazz : classes) {
                 mainClasses.add(clazz.getName());
             }
@@ -467,7 +475,7 @@ public class OpenEJBArchiveProcessor {
             }
         }
 
-        return new SimpleWebappAggregatedArchive(new CompositeArchive(archives), classesByUrl);
+        return new SimpleWebappAggregatedArchive(cl, new CompositeArchive(archives), classesByUrl);
     }
 
     private static boolean isExcluded(final String archiveName) {
@@ -503,8 +511,8 @@ public class OpenEJBArchiveProcessor {
         private final CompositeArchive delegate;
         private final Map<URL, List<String>> classesMap;
 
-        public SimpleWebappAggregatedArchive(final CompositeArchive archive, final Map<URL, List<String>> map) {
-            super(Thread.currentThread().getContextClassLoader(), new HashMap<String, Object>(), new ArrayList<URL>());
+        public SimpleWebappAggregatedArchive(final ClassLoader cl, final CompositeArchive archive, final Map<URL, List<String>> map) {
+            super(cl, new HashMap<String, Object>(), new ArrayList<URL>());
 
             delegate = archive;
             classesMap = map;

http://git-wip-us.apache.org/repos/asf/tomee/blob/0937a91b/arquillian/arquillian-openejb-embedded-5/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBDeployableContainer.java
----------------------------------------------------------------------
diff --git a/arquillian/arquillian-openejb-embedded-5/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBDeployableContainer.java b/arquillian/arquillian-openejb-embedded-5/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBDeployableContainer.java
index 6665024..00d1125 100644
--- a/arquillian/arquillian-openejb-embedded-5/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBDeployableContainer.java
+++ b/arquillian/arquillian-openejb-embedded-5/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBDeployableContainer.java
@@ -113,10 +113,17 @@ public class OpenEJBDeployableContainer implements DeployableContainer<OpenEJBCo
     private InstanceProducer<HttpSession> sessionProducer;
 
     @Inject
+    @DeploymentScoped
+    private InstanceProducer<Closeables> closeablesProducer;
+
+    @Inject
     @SuiteScoped
     private InstanceProducer<ClassLoader> classLoader;
 
     @Inject
+    private Instance<Closeables> closeables;
+
+    @Inject
     private Instance<ServletContext> servletContext;
 
     @Inject
@@ -178,9 +185,11 @@ public class OpenEJBDeployableContainer implements DeployableContainer<OpenEJBCo
         contextProducer.set(initialContext);
 
         containerArchives = ArquillianUtil.toDeploy(properties);
+        final Closeables globalScopeCloseables = new Closeables();
+        SystemInstance.get().setComponent(Closeables.class, globalScopeCloseables);
         for (final Archive<?> archive : containerArchives) {
             try {
-                quickDeploy(archive, testClass.get());
+                quickDeploy(archive, testClass.get(), globalScopeCloseables);
             } catch (final DeploymentException e) {
                 Logger.getLogger(OpenEJBDeployableContainer.class.getName()).log(Level.SEVERE, e.getMessage(), e);
             }
@@ -190,13 +199,16 @@ public class OpenEJBDeployableContainer implements DeployableContainer<OpenEJBCo
     @Override
     public ProtocolMetaData deploy(final Archive<?> archive) throws DeploymentException {
         try {
-            final DeploymentInfo info = quickDeploy(archive, testClass.get());
+            final Closeables cl = new Closeables();
+            closeablesProducer.set(cl);
+            final DeploymentInfo info = quickDeploy(archive, testClass.get(), cl);
 
             servletContextProducer.set(info.appServletContext);
             sessionProducer.set(info.appSession);
             appInfoProducer.set(info.appInfo);
             appContextProducer.set(info.appCtx);
-            classLoader.set(info.appCtx.getClassLoader());
+            final ClassLoader loader = info.appCtx.getWebContexts().isEmpty() ? info.appCtx.getClassLoader() : info.appCtx.getWebContexts().iterator().next().getClassLoader();
+            classLoader.set(loader == null ? info.appCtx.getClassLoader() : loader);
         } catch (final Exception e) {
             throw new DeploymentException("can't deploy " + archive.getName(), e);
         }
@@ -211,9 +223,9 @@ public class OpenEJBDeployableContainer implements DeployableContainer<OpenEJBCo
         return new ProtocolMetaData();
     }
 
-    private DeploymentInfo quickDeploy(final Archive<?> archive, final TestClass testClass) throws DeploymentException {
+    private DeploymentInfo quickDeploy(final Archive<?> archive, final TestClass testClass, final Closeables cls) throws DeploymentException {
         try {
-            final AppModule module = OpenEJBArchiveProcessor.createModule(archive, testClass);
+            final AppModule module = OpenEJBArchiveProcessor.createModule(archive, testClass, cls);
             final AppInfo appInfo = configurationFactory.configureApplication(module);
             final AppContext appCtx = assembler.createApplication(appInfo, module.getClassLoader());
 
@@ -230,6 +242,15 @@ public class OpenEJBDeployableContainer implements DeployableContainer<OpenEJBCo
 
     @Override
     public void undeploy(final Archive<?> archive) throws DeploymentException {
+        final Closeables cl = closeables.get();
+        if (cl != null) {
+            try {
+                cl.close();
+            } catch (final IOException e) {
+                // no-op
+            }
+        }
+
         // reset classloader for next text
         // otherwise if it was closed something can fail
         classLoader.set(OpenEJBDeployableContainer.class.getClassLoader());
@@ -238,11 +259,6 @@ public class OpenEJBDeployableContainer implements DeployableContainer<OpenEJBCo
             return;
         }
 
-        final ClassLoader cl = appContext.get().getClassLoader();
-        if (SWClassLoader.class.isInstance(cl)) {
-            SWClassLoader.class.cast(cl).close();
-        }
-
         try {
             assembler.destroyApplication(info.get().path);
             stopContexts(appContext.get().getWebBeansContext().getContextsService(), servletContext.get(), session.get());
@@ -259,8 +275,11 @@ public class OpenEJBDeployableContainer implements DeployableContainer<OpenEJBCo
             if (initialContext != null) {
                 initialContext.close();
             }
+            SystemInstance.get().getComponent(Closeables.class).close();
         } catch (final NamingException e) {
             throw new LifecycleException("can't close the OpenEJB container", e);
+        } catch (final IOException e) {
+            // no-op: close() of classloaders, not a big deal at this moment
         } finally {
             OpenEJB.destroy();
         }

http://git-wip-us.apache.org/repos/asf/tomee/blob/0937a91b/arquillian/arquillian-openejb-embedded-5/src/main/java/org/apache/openejb/arquillian/openejb/SWClassLoader.java
----------------------------------------------------------------------
diff --git a/arquillian/arquillian-openejb-embedded-5/src/main/java/org/apache/openejb/arquillian/openejb/SWClassLoader.java b/arquillian/arquillian-openejb-embedded-5/src/main/java/org/apache/openejb/arquillian/openejb/SWClassLoader.java
index 168ce79..4f35da8 100644
--- a/arquillian/arquillian-openejb-embedded-5/src/main/java/org/apache/openejb/arquillian/openejb/SWClassLoader.java
+++ b/arquillian/arquillian-openejb-embedded-5/src/main/java/org/apache/openejb/arquillian/openejb/SWClassLoader.java
@@ -44,7 +44,7 @@ import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.Map;
 
-public class SWClassLoader extends ClassLoader {
+public class SWClassLoader extends ClassLoader implements Closeable {
     static {
         try {
             final Field handler = URL.class.getDeclaredField("handlers");
@@ -197,7 +197,8 @@ public class SWClassLoader extends ClassLoader {
         }
     }
 
-    public void close() {
+    @Override
+    public void close() throws IOException {
         ArchiveStreamHandler.reset(archive.getName());
         for (final Closeable cl : closeables) {
             try {

http://git-wip-us.apache.org/repos/asf/tomee/blob/0937a91b/container/openejb-core/src/main/java/org/apache/openejb/dyni/DynamicSubclass.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/dyni/DynamicSubclass.java b/container/openejb-core/src/main/java/org/apache/openejb/dyni/DynamicSubclass.java
index d231290..64b4a0a 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/dyni/DynamicSubclass.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/dyni/DynamicSubclass.java
@@ -79,7 +79,7 @@ public class DynamicSubclass implements Opcodes {
                 // no-op
             }
 
-            return LocalBeanProxyFactory.Unsafe.defineClass(abstractClass, proxyName, generateBytes(abstractClass));
+            return LocalBeanProxyFactory.Unsafe.defineClass(cl, abstractClass, proxyName, generateBytes(abstractClass));
 
         } catch (final Exception e) {
             throw new InternalError(DynamicSubclass.class.getSimpleName() + ".createSubclass: " + Debug.printStackTrace(e));

http://git-wip-us.apache.org/repos/asf/tomee/blob/0937a91b/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/LocalBeanProxyFactory.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/LocalBeanProxyFactory.java b/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/LocalBeanProxyFactory.java
index 37b63f4..cd9cb7e 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/LocalBeanProxyFactory.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/LocalBeanProxyFactory.java
@@ -134,7 +134,7 @@ public class LocalBeanProxyFactory implements Opcodes {
             }
 
             final byte[] proxyBytes = generateProxy(classToProxy, classFileName, interfaces);
-            return Unsafe.defineClass(classToProxy, proxyName, proxyBytes);
+            return Unsafe.defineClass(cl, classToProxy, proxyName, proxyBytes);
 
         } catch (final Exception e) {
             throw new InternalError("LocalBeanProxyFactory.createProxy: " + Debug.printStackTrace(e));
@@ -814,8 +814,9 @@ public class LocalBeanProxyFactory implements Opcodes {
             }
         }
 
-        public static Class defineClass(final Class<?> clsToProxy, final String proxyName, final byte[] proxyBytes) throws IllegalAccessException, InvocationTargetException {
-            return (Class<?>) defineClass.invoke(unsafe, proxyName, proxyBytes, 0, proxyBytes.length, clsToProxy.getClassLoader(), clsToProxy.getProtectionDomain());
+        // it is super important to pass a classloader as first parameter otherwise if API class is in a "permanent" classloader then it will leak
+        public static Class defineClass(final ClassLoader loader, final Class<?> clsToProxy, final String proxyName, final byte[] proxyBytes) throws IllegalAccessException, InvocationTargetException {
+            return (Class<?>) defineClass.invoke(unsafe, proxyName, proxyBytes, 0, proxyBytes.length, loader, clsToProxy.getProtectionDomain());
         }
     }
 

http://git-wip-us.apache.org/repos/asf/tomee/blob/0937a91b/tck/cdi-embedded/src/test/java/org/apache/openejb/tck/cdi/embedded/GCListener.java
----------------------------------------------------------------------
diff --git a/tck/cdi-embedded/src/test/java/org/apache/openejb/tck/cdi/embedded/GCListener.java b/tck/cdi-embedded/src/test/java/org/apache/openejb/tck/cdi/embedded/GCListener.java
new file mode 100644
index 0000000..72a5680
--- /dev/null
+++ b/tck/cdi-embedded/src/test/java/org/apache/openejb/tck/cdi/embedded/GCListener.java
@@ -0,0 +1,59 @@
+/*
+ * 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.openejb.tck.cdi.embedded;
+
+import org.testng.IInvokedMethod;
+import org.testng.IInvokedMethodListener2;
+import org.testng.ITestContext;
+import org.testng.ITestResult;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryMXBean;
+
+public class GCListener implements IInvokedMethodListener2 {
+    private final MemoryMXBean memory;
+
+    public GCListener() {
+        memory = ManagementFactory.getMemoryMXBean();
+    }
+
+    @Override
+    public void beforeInvocation(final IInvokedMethod iInvokedMethod, final ITestResult iTestResult, final ITestContext iTestContext) {
+        dump("b");
+    }
+
+    @Override
+    public void afterInvocation(final IInvokedMethod iInvokedMethod, final ITestResult iTestResult, final ITestContext iTestContext) {
+        dump("a");
+    }
+
+    private void dump(final String prefix) {
+        System.out.println(prefix + ">>> heap             : " + memory.getHeapMemoryUsage().toString());
+        System.out.println(prefix + ">>> non heap         : " + memory.getNonHeapMemoryUsage().toString());
+        System.out.println(prefix + ">>> pending instances: " + memory.getObjectPendingFinalizationCount());
+    }
+
+    @Override
+    public void beforeInvocation(final IInvokedMethod iInvokedMethod, final ITestResult iTestResult) {
+        // no-op
+    }
+
+    @Override
+    public void afterInvocation(final IInvokedMethod iInvokedMethod, final ITestResult iTestResult) {
+        // no-op
+    }
+}

http://git-wip-us.apache.org/repos/asf/tomee/blob/0937a91b/tck/cdi-embedded/src/test/resources/passing.xml
----------------------------------------------------------------------
diff --git a/tck/cdi-embedded/src/test/resources/passing.xml b/tck/cdi-embedded/src/test/resources/passing.xml
index edc63d2..00eb112 100644
--- a/tck/cdi-embedded/src/test/resources/passing.xml
+++ b/tck/cdi-embedded/src/test/resources/passing.xml
@@ -35,6 +35,8 @@
 <!-- OWB one ATM, remove exclude groups to be openejb ;) -->
 <suite name="JSR-346-TCK" verbose="2" configfailurepolicy="continue" >
   <listeners>
+    <!-- debug -->
+    <listener class-name="org.apache.openejb.tck.cdi.embedded.GCListener"/>
     <!-- Required - avoid randomly mixed test method execution -->
     <listener class-name="org.jboss.cdi.tck.impl.testng.SingleTestClassMethodInterceptor"/>
     <!-- Optional - intended for debug purpose only -->