BUG-4764: resolve serializer body before javassist callout 39/31439/2
authorRobert Varga <rovarga@cisco.com>
Wed, 16 Dec 2015 15:08:50 +0000 (16:08 +0100)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 16 Dec 2015 15:52:11 +0000 (15:52 +0000)
This moves the body generation phase out of the javassist lock, so that
it can perform cache lookups without the risk of hitting an AB-BA
deadlock.

Change-Id: I40d0237fef100f90bed9e91e3825a4121e4c503d
Signed-off-by: Robert Varga <rovarga@cisco.com>
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/AbstractStreamWriterGenerator.java

index 8efdc87ba5d3a5d304a78982b3b3a3d3bca14bc8..e41c4f8594320b92febe52fb1b212ee387642062 100644 (file)
@@ -188,22 +188,27 @@ abstract class AbstractStreamWriterGenerator extends AbstractGenerator implement
 
     private CtClass generateEmitter0(final Class<?> type, final DataObjectSerializerSource source, final String serializerName) {
         final CtClass product;
+
+        /*
+         * getSerializerBody() has side effects, such as loading classes and codecs, it should be run in model class
+         * loader in order to correctly reference load child classes.
+         *
+         * Furthermore the fact that getSerializedBody() can trigger other code generation to happen, we need to take
+         * care of this before calling instantiatePrototype(), as that will call our customizer with the lock held,
+         * hence any code generation will end up being blocked on the javassist lock.
+         */
+        final String body = ClassLoaderUtils.withClassLoader(type.getClassLoader(), new Supplier<String>() {
+                @Override
+                public String get() {
+                    return source.getSerializerBody().toString();
+                }
+            }
+        );
+
         try {
             product = javassist.instantiatePrototype(DataObjectSerializerPrototype.class.getName(), serializerName, new ClassCustomizer() {
                 @Override
                 public void customizeClass(final CtClass cls) throws CannotCompileException, NotFoundException {
-                    /* getSerializerBody() has side effects, such as loading classes
-                     * and codecs, it should be run in model class loader in order to
-                     * correctly reference load child classes
-                     */
-                    final String body = ClassLoaderUtils.withClassLoader(type.getClassLoader(), new Supplier<String>() {
-                            @Override
-                            public String get() {
-                                return source.getSerializerBody().toString();
-                            }
-                        }
-                    );
-
                     // Generate any static fields
                     for (final StaticConstantDefinition def : source.getStaticConstants()) {
                         final CtField field = new CtField(javassist.asCtClass(def.getType()), def.getName(), cls);