This is an automated email from the ASF dual-hosted git repository.

struberg pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/openjpa.git


The following commit(s) were added to refs/heads/master by this push:
     new 60ccb2605 OPENJPA-2911 start removing Serp from PCDataGenerator
60ccb2605 is described below

commit 60ccb2605072307ddf123e499c458a34685d8e17
Author: Mark Struberg <strub...@apache.org>
AuthorDate: Sun Jul 23 18:36:46 2023 +0200

    OPENJPA-2911 start removing Serp from PCDataGenerator
    
    wip
---
 .../datacache/DataCachePCDataGenerator.java        |  60 ++-
 .../openjpa/enhance/DynamicStorageGenerator.java   | 467 ++++++++++++---------
 .../apache/openjpa/enhance/PCDataGenerator.java    | 422 +++++++++++--------
 .../org/apache/openjpa/util/InternalException.java |   4 +-
 .../org/apache/openjpa/util/OpenJPAException.java  |   3 +-
 .../apache/openjpa/util/asm/ClassNodeTracker.java  |   6 +-
 .../enhance/TestDynamicStorageGenerator.java       |   9 +-
 7 files changed, 585 insertions(+), 386 deletions(-)

diff --git 
a/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCachePCDataGenerator.java
 
b/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCachePCDataGenerator.java
index 6a962ea0e..3d560aa60 100644
--- 
a/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCachePCDataGenerator.java
+++ 
b/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCachePCDataGenerator.java
@@ -29,10 +29,13 @@ import org.apache.openjpa.enhance.PCDataGenerator;
 import org.apache.openjpa.kernel.AbstractPCData;
 import org.apache.openjpa.kernel.OpenJPAStateManager;
 import org.apache.openjpa.kernel.StoreContext;
+import org.apache.openjpa.lib.util.StringUtil;
 import org.apache.openjpa.meta.ClassMetaData;
 import org.apache.openjpa.meta.FieldMetaData;
 import org.apache.openjpa.meta.JavaTypes;
 import org.apache.openjpa.meta.ValueMetaData;
+import org.apache.openjpa.util.asm.AsmHelper;
+import org.apache.openjpa.util.asm.ClassNodeTracker;
 
 import serp.bytecode.BCClass;
 import serp.bytecode.BCField;
@@ -40,6 +43,7 @@ import serp.bytecode.BCMethod;
 import serp.bytecode.Code;
 import serp.bytecode.Instruction;
 import serp.bytecode.JumpInstruction;
+import serp.bytecode.Project;
 
 /**
  * A {@link PCDataGenerator} instance which generates properly
@@ -78,12 +82,18 @@ public class DataCachePCDataGenerator extends 
PCDataGenerator {
     }
 
     @Override
-    protected void decorate(BCClass bc, ClassMetaData meta) {
-        enhanceToData(bc);
-        enhanceToNestedData(bc);
-        replaceNewEmbeddedPCData(bc);
-        addSynchronization(bc);
-        addTimeout(bc);
+    protected void decorate(ClassNodeTracker cnt, ClassMetaData meta) {
+        //X TODO REMOVE
+        BCClass _bc = new 
Project().loadClass(cnt.getClassNode().name.replace("/", "."));
+        AsmHelper.readIntoBCClass(cnt, _bc);
+
+        enhanceToData(_bc);
+        enhanceToNestedData(_bc);
+        replaceNewEmbeddedPCData(_bc);
+        addSynchronization(_bc);
+        addTimeout(_bc);
+
+        cnt.setClassNode(AsmHelper.toClassNode(cnt.getProject(), 
_bc).getClassNode());
     }
 
     private void enhanceToData(BCClass bc) {
@@ -185,6 +195,44 @@ public class DataCachePCDataGenerator extends 
PCDataGenerator {
         code.calculateMaxStack();
     }
 
+    /**
+     * Add a bean field of the given name and type.
+     */
+    @Deprecated
+    private BCField addBeanField(BCClass bc, String name, Class type) {
+        if (name == null)
+            throw new IllegalArgumentException("name == null");
+
+        // private <type> <name>
+        BCField field = bc.declareField(name, type);
+        field.setAccessFlags(getFieldAccess());
+        name = StringUtil.capitalize(name);
+
+        // getter
+        String prefix = (type == boolean.class) ? "is" : "get";
+        BCMethod method = bc.declareMethod(prefix + name, type, null);
+        method.makePublic();
+        Code code = method.getCode(true);
+        code.aload().setThis();
+        code.getfield().setField(field);
+        code.xreturn().setType(type);
+        code.calculateMaxStack();
+        code.calculateMaxLocals();
+
+        // setter
+        method = bc.declareMethod("set" + name, void.class,
+                                  new Class[]{ type });
+        method.makePublic();
+        code = method.getCode(true);
+        code.aload().setThis();
+        code.xload().setParam(0).setType(type);
+        code.putfield().setField(field);
+        code.vreturn();
+        code.calculateMaxStack();
+        code.calculateMaxLocals();
+        return field;
+    }
+
     private void addTimeout(BCClass bc) {
         bc.declareInterface(DataCachePCData.class);
         bc.declareInterface(Timed.class);
diff --git 
a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/DynamicStorageGenerator.java
 
b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/DynamicStorageGenerator.java
index e1b2b85b1..02e7c6c99 100644
--- 
a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/DynamicStorageGenerator.java
+++ 
b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/DynamicStorageGenerator.java
@@ -19,30 +19,40 @@
 package org.apache.openjpa.enhance;
 
 import java.lang.reflect.Constructor;
-import java.security.AccessController;
 
-import org.apache.openjpa.lib.util.J2DoPrivHelper;
 import org.apache.openjpa.lib.util.StringUtil;
 import org.apache.openjpa.meta.JavaTypes;
 import org.apache.openjpa.util.InternalException;
+import org.apache.openjpa.util.asm.AsmHelper;
+import org.apache.openjpa.util.asm.ClassNodeTracker;
+import org.apache.openjpa.util.asm.EnhancementClassLoader;
+import org.apache.openjpa.util.asm.EnhancementProject;
+import org.apache.xbean.asm9.Opcodes;
+import org.apache.xbean.asm9.Type;
+import org.apache.xbean.asm9.tree.ClassNode;
+import org.apache.xbean.asm9.tree.FieldInsnNode;
+import org.apache.xbean.asm9.tree.FieldNode;
+import org.apache.xbean.asm9.tree.InsnList;
+import org.apache.xbean.asm9.tree.InsnNode;
+import org.apache.xbean.asm9.tree.JumpInsnNode;
+import org.apache.xbean.asm9.tree.LabelNode;
+import org.apache.xbean.asm9.tree.MethodInsnNode;
+import org.apache.xbean.asm9.tree.MethodNode;
+import org.apache.xbean.asm9.tree.TableSwitchInsnNode;
+import org.apache.xbean.asm9.tree.TypeInsnNode;
+import org.apache.xbean.asm9.tree.VarInsnNode;
 
-import serp.bytecode.BCClass;
-import serp.bytecode.BCClassLoader;
-import serp.bytecode.BCField;
-import serp.bytecode.BCMethod;
 import serp.bytecode.Code;
 import serp.bytecode.Constants;
 import serp.bytecode.Instruction;
-import serp.bytecode.JumpInstruction;
-import serp.bytecode.LoadInstruction;
-import serp.bytecode.Project;
-import serp.bytecode.TableSwitchInstruction;
+
 
 /**
  * Factory for creating new {@link DynamicStorage} classes. Can be
  * extended to decorate/modify the generated instances behavior.
  *
  * @author Steve Kim
+ * @author Mark Struberg rework to ASM
  * @since 0.3.2.0
  */
 public class DynamicStorageGenerator {
@@ -95,11 +105,8 @@ public class DynamicStorageGenerator {
     };
 
     // the project/classloader for the classes.
-    private final Project _project = new Project();
-    private final BCClassLoader _loader =
-        AccessController.doPrivileged(SerpPrivacyHelper.newBCClassLoaderAction(
-            _project, AccessController.doPrivileged(J2DoPrivHelper
-                .getClassLoaderAction(DynamicStorage.class))));
+    private final EnhancementProject _project = new EnhancementProject();
+    private final EnhancementClassLoader _loader = new 
EnhancementClassLoader(_project, DynamicStorage.class.getClassLoader());
 
     /**
      * Generate a generic {@link DynamicStorage} instance with the given
@@ -111,9 +118,9 @@ public class DynamicStorageGenerator {
             return null;
 
         String name = getClassName(obj);
-        BCClass bc = _project.loadClass(name);
+        ClassNodeTracker bc = _project.loadClass(name);
         declareClasses(bc);
-        bc.addDefaultConstructor().makePublic();
+        addDefaultConstructor(bc);
 
         int objectCount = declareFields(types, bc);
         addFactoryMethod(bc);
@@ -125,6 +132,26 @@ public class DynamicStorageGenerator {
         return createFactory(bc);
     }
 
+    private void addDefaultConstructor(ClassNodeTracker cnt) {
+        ClassNode classNode = cnt.getClassNode();
+        // find the default constructor
+        final boolean hasDefaultCt = classNode.methods.stream()
+                .anyMatch(m -> m.name.equals("<init>") && 
m.desc.equals("()V"));
+        if (!hasDefaultCt) {
+            MethodNode ctNode = new MethodNode(Opcodes.ACC_PUBLIC,
+                                               "<init>",
+                                               
Type.getMethodDescriptor(Type.VOID_TYPE),
+                                               null, null);
+            ctNode.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
+            ctNode.instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, 
classNode.superName,
+                                                       "<init>", "()V"));
+            ctNode.instructions.add(new InsnNode(Opcodes.RETURN));
+            classNode.methods.add(ctNode);
+        }
+    }
+
+
+
     /**
      * Return a class name to use for the given user key. By default,
      * returns the stringified key prefixed by PREFIX.
@@ -138,7 +165,7 @@ public class DynamicStorageGenerator {
      * {@link Constants}.
      */
     protected int getFieldAccess() {
-        return Constants.ACCESS_PRIVATE;
+        return Opcodes.ACC_PRIVATE;
     }
 
     /**
@@ -159,18 +186,17 @@ public class DynamicStorageGenerator {
     /**
      * Decorate the generated class.
      */
-    protected void decorate(Object obj, BCClass cls, int[] types) {
+    protected void decorate(Object obj, ClassNodeTracker cls, int[] types) {
     }
 
     /**
      * Create a stub factory instance for the given class.
      */
-    protected DynamicStorage createFactory(BCClass bc) {
+    protected DynamicStorage createFactory(ClassNodeTracker bc) {
         try {
-            Class cls = Class.forName(bc.getName(), false, _loader);
+            Class cls = Class.forName(bc.getClassNode().name.replace("/", 
"."), false, _loader);
             Constructor cons = cls.getConstructor((Class[]) null);
-            DynamicStorage data = (DynamicStorage) cons.newInstance
-                ((Object[]) null);
+            DynamicStorage data = (DynamicStorage) cons.newInstance((Object[]) 
null);
             _project.clear(); // remove old refs
             return data;
         } catch (Throwable t) {
@@ -181,74 +207,90 @@ public class DynamicStorageGenerator {
     /**
      * Add interface or superclass declarations to the generated class.
      */
-    protected void declareClasses(BCClass bc) {
+    protected void declareClasses(ClassNodeTracker bc) {
         bc.declareInterface(DynamicStorage.class);
     }
 
     /**
      * Implement the newInstance method.
      */
-    private void addFactoryMethod(BCClass bc) {
-        BCMethod method = bc.declareMethod("newInstance",
-            DynamicStorage.class, null);
-        Code code = method.getCode(true);
-        code.anew().setType(bc);
-        code.dup();
-        code.invokespecial().setMethod(bc.getName(), "<init>", "void", null);
-        code.areturn();
-        code.calculateMaxLocals();
-        code.calculateMaxStack();
+    private void addFactoryMethod(ClassNodeTracker bc) {
+        final ClassNode classNode = bc.getClassNode();
+        MethodNode method = new MethodNode(Opcodes.ACC_PUBLIC,
+                                           "newInstance",
+                                           
Type.getMethodDescriptor(Type.getType(DynamicStorage.class)),
+                                           null, null);
+        classNode.methods.add(method);
+        InsnList instructions = method.instructions;
+        instructions.add(new TypeInsnNode(Opcodes.NEW, classNode.name));
+        instructions.add(new InsnNode(Opcodes.DUP));
+        instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL,
+                                            classNode.name,
+                                            "<init>",
+                                            
Type.getMethodDescriptor(Type.VOID_TYPE)));
+        instructions.add(new InsnNode(Opcodes.ARETURN));
     }
 
     /**
      * Implement getFieldCount/getObjectCount.
      */
-    private void addFieldCount(BCClass bc, int[] types, int objectCount) {
-        BCMethod method = bc.declareMethod("getFieldCount", int.class, null);
-        Code code = method.getCode(true);
-        code.constant().setValue(types.length);
-        code.ireturn();
-        code.calculateMaxLocals();
-        code.calculateMaxStack();
-
-        method = bc.declareMethod("getObjectCount", int.class, null);
-        code = method.getCode(true);
-        code.constant().setValue(objectCount);
-        code.ireturn();
-        code.calculateMaxLocals();
-        code.calculateMaxStack();
+    private void addFieldCount(ClassNodeTracker bc, int[] types, int 
objectCount) {
+        final ClassNode classNode = bc.getClassNode();
+        MethodNode getFc = new MethodNode(Opcodes.ACC_PUBLIC,
+                                           "getFieldCount",
+                                           
Type.getMethodDescriptor(Type.INT_TYPE),
+                                           null, null);
+        classNode.methods.add(getFc);
+        getFc.instructions.add(AsmHelper.getLoadConstantInsn(types.length));
+        getFc.instructions.add(new InsnNode(Opcodes.IRETURN));
+
+        MethodNode getOc = new MethodNode(Opcodes.ACC_PUBLIC,
+                                          "getObjectCount",
+                                          
Type.getMethodDescriptor(Type.INT_TYPE),
+                                          null, null);
+        classNode.methods.add(getOc);
+        getOc.instructions.add(AsmHelper.getLoadConstantInsn(objectCount));
+        getOc.instructions.add(new InsnNode(Opcodes.IRETURN));
     }
 
     /**
      * Implement initialize.
      */
-    private void addInitialize(BCClass bc, int objectCount) {
-        BCMethod meth = bc.declareMethod("initialize", void.class, null);
-        Code code = meth.getCode(true);
-        JumpInstruction ifins = null;
+    private void addInitialize(ClassNodeTracker bc, int objectCount) {
+        final ClassNode classNode = bc.getClassNode();
+        MethodNode initMeth = new MethodNode(Opcodes.ACC_PUBLIC,
+                                          "initialize",
+                                          
Type.getMethodDescriptor(Type.VOID_TYPE),
+                                          null, null);
+        classNode.methods.add(initMeth);
+        InsnList instructions = initMeth.instructions;
+
+        LabelNode lblEndIf = null;
         if (objectCount > 0) {
             // if (objects == null)
             //                 objects = new Object[objectCount];
-            code.aload().setThis();
-            code.getfield().setField("objects", Object[].class);
-            ifins = code.ifnonnull();
-            code.aload().setThis();
-            code.constant().setValue(objectCount);
-            code.anewarray().setType(Object.class);
-            code.putfield().setField("objects", Object[].class);
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+            instructions.add(new FieldInsnNode(Opcodes.GETFIELD, 
classNode.name, "objects", Type.getDescriptor(Object[].class)));
+            lblEndIf = new LabelNode();
+            instructions.add(new JumpInsnNode(Opcodes.IFNONNULL, lblEndIf));
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+            instructions.add(AsmHelper.getLoadConstantInsn(objectCount));
+            instructions.add(new TypeInsnNode(Opcodes.ANEWARRAY, 
Type.getInternalName(Object.class)));
+            instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, 
classNode.name, "objects", Type.getDescriptor(Object[].class)));
+        }
+
+        if (lblEndIf != null) {
+            instructions.add(lblEndIf);
         }
-        Instruction ins = code.vreturn();
-        if (ifins != null)
-            ifins.setTarget(ins);
-        code.calculateMaxLocals();
-        code.calculateMaxStack();
+        instructions.add(new InsnNode(Opcodes.RETURN));
     }
 
     /**
      * Declare the primitive fields and the object field.
      */
-    private int declareFields(int[] types, BCClass bc) {
-        bc.declareField("objects", Object[].class).makePrivate();
+    private int declareFields(int[] types, ClassNodeTracker bc) {
+        ClassNode classNode = bc.getClassNode();
+        classNode.fields.add(new FieldNode(Opcodes.ACC_PRIVATE, "objects", 
Type.getDescriptor(Object[].class), null, null));
 
         int objectCount = 0;
         Class type;
@@ -257,8 +299,7 @@ public class DynamicStorageGenerator {
             if (type == Object.class)
                 objectCount++;
             else {
-                BCField field = bc.declareField(getFieldName(i), type);
-                field.setAccessFlags(getFieldAccess());
+                classNode.fields.add(new FieldNode(Opcodes.ACC_PRIVATE, 
getFieldName(i), Type.getDescriptor(type), null, null));
             }
         }
         return objectCount;
@@ -267,7 +308,7 @@ public class DynamicStorageGenerator {
     /**
      * Add all the typed set by index method.
      */
-    private void addSetMethods(BCClass bc, int[] types, int totalObjects) {
+    private void addSetMethods(ClassNodeTracker bc, int[] types, int 
totalObjects) {
         for (int type : TYPES) {
             addSetMethod(type, bc, types, totalObjects);
         }
@@ -276,77 +317,104 @@ public class DynamicStorageGenerator {
     /**
      * Add the typed set by index method.
      */
-    private void addSetMethod(int typeCode, BCClass bc, int[] types,
-        int totalObjects) {
+    private void addSetMethod(int typeCode, ClassNodeTracker bc, int[] types, 
int totalObjects) {
         int handle = getCreateFieldMethods(typeCode);
-        if (handle == POLICY_EMPTY)
+        if (handle == POLICY_EMPTY) {
             return;
+        }
+
         Class type = forType(typeCode);
+
         // public void set<Type> (int field, <type> val)
         String name = Object.class.equals(type) ? "Object" : 
StringUtil.capitalize(type.getName());
         name = "set" + name;
-        BCMethod method = bc.declareMethod(name, void.class,
-            new Class[]{ int.class, type });
-        method.makePublic();
-        Code code = method.getCode(true);
+
+        ClassNode classNode = bc.getClassNode();
+        MethodNode method = new MethodNode(Opcodes.ACC_PUBLIC,
+                                           name,
+                                           
Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE, Type.getType(type)),
+                                           null, null);
+        classNode.methods.add(method);
+        InsnList instructions = method.instructions;
+
         // switch (field)
-        code.aload().setParam(0);
-        TableSwitchInstruction tabins = code.tableswitch();
-        tabins.setLow(0);
-        tabins.setHigh(types.length - 1);
-        Instruction defaultIns;
-        if (handle == POLICY_SILENT) {
-            defaultIns = code.vreturn();
-        }
-        else {
-            defaultIns = throwException(code, IllegalArgumentException.class);
-        }
-        tabins.setDefaultTarget(defaultIns);
+        instructions.add(new VarInsnNode(Opcodes.ILOAD, 1)); // switch on 
first parameter which is an int
+
+        LabelNode defLbl = new LabelNode();
+        TableSwitchInsnNode switchNd = new TableSwitchInsnNode(0, types.length 
- 1, defLbl);
+        instructions.add(switchNd);
+
+
         int objectCount = 0;
         for (int i = 0; i < types.length; i++) {
             // default: throw new IllegalArgumentException
             if (!isCompatible(types[i], typeCode)) {
-                tabins.addTarget(tabins.getDefaultTarget());
+                LabelNode caseLbl = new LabelNode();
+                switchNd.labels.add(caseLbl);
+                instructions.add(caseLbl);
+                instructions.add(getDefaultSetInstructions(handle));
                 continue;
             }
 
-            tabins.addTarget(code.aload().setThis());
+            LabelNode caseLbl = new LabelNode();
+            switchNd.labels.add(caseLbl);
+            instructions.add(caseLbl);
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+
             if (typeCode >= JavaTypes.OBJECT) {
                 // if (objects == null)
                 //             objects = new Object[totalObjects];
-                code.aload().setThis();
-                code.getfield().setField("objects", Object[].class);
-                JumpInstruction ifins = code.ifnonnull();
-                code.aload().setThis();
-                code.constant().setValue(totalObjects);
-                code.anewarray().setType(Object.class);
-                code.putfield().setField("objects", Object[].class);
+                instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+                instructions.add(new FieldInsnNode(Opcodes.GETFIELD, 
classNode.name, "objects", Type.getDescriptor(Object[].class)));
+
+                LabelNode lblEndNonNull = new LabelNode();
+                instructions.add(new JumpInsnNode(Opcodes.IFNONNULL, 
lblEndNonNull));
+                instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+                instructions.add(AsmHelper.getLoadConstantInsn(totalObjects));
+                instructions.add(new TypeInsnNode(Opcodes.ANEWARRAY, 
Type.getInternalName(Object.class)));
+                instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, 
classNode.name, "objects", Type.getDescriptor(Object[].class)));
+
+                instructions.add(lblEndNonNull);
 
                 // objects[objectCount] = val;
-                ifins.setTarget(code.aload().setThis());
-                code.getfield().setField("objects", Object[].class);
-                code.constant().setValue(objectCount);
-                code.aload().setParam(1);
-                code.aastore();
+                instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+                instructions.add(new FieldInsnNode(Opcodes.GETFIELD, 
classNode.name, "objects", Type.getDescriptor(Object[].class)));
+                instructions.add(AsmHelper.getLoadConstantInsn(objectCount));
+                instructions.add(new VarInsnNode(Opcodes.ALOAD, 2)); // 2nd 
param
+                instructions.add(new InsnNode(Opcodes.AASTORE));
+
                 objectCount++;
             } else {
                 // case i: fieldi = val;
-                LoadInstruction load = code.xload();
-                load.setType(type);
-                load.setParam(1);
-                code.putfield().setField("field" + i, type);
+                instructions.add(new VarInsnNode(AsmHelper.getLoadInsn(type), 
2)); // 2nd param is primitive
+                instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, 
classNode.name, "field" + i, Type.getInternalName(type)));
             }
             // return
-            code.vreturn();
+            instructions.add(new InsnNode(Opcodes.RETURN));
         }
-        code.calculateMaxLocals();
-        code.calculateMaxStack();
+
+
+        // default:
+        instructions.add(defLbl);
+        instructions.add(getDefaultSetInstructions(handle));
+    }
+
+    private static InsnList getDefaultSetInstructions(int handle) {
+        InsnList defaultInsns;
+        if (handle == POLICY_SILENT) {
+            defaultInsns = new InsnList();
+            defaultInsns.add(new InsnNode(Opcodes.RETURN));
+        }
+        else {
+            defaultInsns = 
AsmHelper.throwException(IllegalArgumentException.class);
+        }
+        return defaultInsns;
     }
 
     /**
      * Add all typed get by index method for the given fields.
      */
-    private void addGetMethods(BCClass bc, int[] types) {
+    private void addGetMethods(ClassNodeTracker bc, int[] types) {
         for (int type : TYPES) {
             addGetMethod(type, bc, types);
         }
@@ -355,121 +423,139 @@ public class DynamicStorageGenerator {
     /**
      * Add typed get by index method.
      */
-    private void addGetMethod(int typeCode, BCClass bc, int[] types) {
+    private void addGetMethod(int typeCode, ClassNodeTracker bc, int[] types) {
         int handle = getCreateFieldMethods(typeCode);
-        if (handle == POLICY_EMPTY)
+        if (handle == POLICY_EMPTY) {
             return;
+        }
         Class type = forType(typeCode);
+
         // public <type> get<Type>Field (int field)
-        String name = Object.class.equals(type) ? "Object" :
-            StringUtil.capitalize(type.getName());
-        name = "get" + name;
-        BCMethod method = bc.declareMethod(name, type,
-            new Class[]{ int.class });
-        method.makePublic();
-        Code code = method.getCode(true);
+        String name = "get" + (Object.class.equals(type) ? "Object" : 
StringUtil.capitalize(type.getName()));
+
+        ClassNode classNode = bc.getClassNode();
+        MethodNode meth = new MethodNode(Opcodes.ACC_PUBLIC,
+                                         name,
+                                         
Type.getMethodDescriptor(Type.getType(type), Type.INT_TYPE),
+                                         null, null);
+        classNode.methods.add(meth);
+        InsnList instructions = meth.instructions;
+
         // switch (field)
-        code.aload().setParam(0);
-        TableSwitchInstruction tabins = code.tableswitch();
-        tabins.setLow(0);
-        tabins.setHigh(types.length - 1);
-        Instruction defaultIns = null;
-        if (typeCode == JavaTypes.OBJECT && handle == POLICY_SILENT) {
-            defaultIns = code.constant().setNull();
-            code.areturn();
-        } else
-            defaultIns = throwException
-                (code, IllegalArgumentException.class);
-        tabins.setDefaultTarget(defaultIns);
+        instructions.add(new VarInsnNode(Opcodes.ILOAD, 1)); // switch on 
first parameter which is an int
+
+        LabelNode defLbl = new LabelNode();
+        TableSwitchInsnNode switchNd = new TableSwitchInsnNode(0, types.length 
- 1, defLbl);
+        instructions.add(switchNd);
+
+
         int objectCount = 0;
         for (int i = 0; i < types.length; i++) {
             // default: throw new IllegalArgumentException
             if (!isCompatible(types[i], typeCode)) {
-                tabins.addTarget(tabins.getDefaultTarget());
+                LabelNode caseLbl = new LabelNode();
+                switchNd.labels.add(caseLbl);
+                instructions.add(caseLbl);
+                instructions.add(getDefaultGetInstructions(typeCode, handle));
                 continue;
             }
 
-            tabins.addTarget(code.aload().setThis());
+            LabelNode caseLbl = new LabelNode();
+            switchNd.labels.add(caseLbl);
+            instructions.add(caseLbl);
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
             if (typeCode >= JavaTypes.OBJECT) {
                 // if (objects == null)
                 //             return null;
                 // return objects[objectCount];
-                code.aload().setThis();
-                code.getfield().setField("objects", Object[].class);
-                JumpInstruction ifins = code.ifnonnull();
-                code.constant().setNull();
-                code.areturn();
-                ifins.setTarget(code.aload().setThis());
-                code.getfield().setField("objects", Object[].class);
-                code.constant().setValue(objectCount);
-                code.aaload();
-                code.areturn();
+                instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+                instructions.add(new FieldInsnNode(Opcodes.GETFIELD, 
classNode.name, "objects", Type.getDescriptor(Object[].class)));
+
+                LabelNode lblEndNonNull = new LabelNode();
+                instructions.add(new JumpInsnNode(Opcodes.IFNONNULL, 
lblEndNonNull));
+                instructions.add(new InsnNode(Opcodes.ACONST_NULL));
+                instructions.add(new InsnNode(Opcodes.ARETURN));
+
+                instructions.add(lblEndNonNull);
+                instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+                instructions.add(new FieldInsnNode(Opcodes.GETFIELD, 
classNode.name, "objects", Type.getDescriptor(Object[].class)));
+                instructions.add(AsmHelper.getLoadConstantInsn(objectCount));
+                instructions.add(new InsnNode(Opcodes.AALOAD));
+                instructions.add(new InsnNode(Opcodes.ARETURN));
+
                 objectCount++;
             } else {
                 // case i: return fieldi;
-                code.getfield().setField("field" + i, type);
-                code.xreturn().setType(type);
+                instructions.add(new FieldInsnNode(Opcodes.GETFIELD, 
classNode.name, "field" + i, Type.getInternalName(type)));
+                instructions.add(new InsnNode(AsmHelper.getReturnInsn(type)));
             }
         }
-        code.calculateMaxLocals();
-        code.calculateMaxStack();
+
+        // default:
+        instructions.add(defLbl);
+        instructions.add(getDefaultGetInstructions(typeCode, handle));
+    }
+
+    private static InsnList getDefaultGetInstructions(int typeCode, int 
handle) {
+        InsnList defaultInsns;
+        if (typeCode == JavaTypes.OBJECT && handle == POLICY_SILENT) {
+            defaultInsns = new InsnList();
+            defaultInsns.add(new InsnNode(Opcodes.ACONST_NULL));
+            defaultInsns.add(new InsnNode(Opcodes.ARETURN));
+        }
+        else {
+            defaultInsns = 
AsmHelper.throwException(IllegalArgumentException.class);
+        }
+        return defaultInsns;
     }
 
     /////////////
     // Utilities
     /////////////
 
-    /**
-     * Clear code associated with the given method signature, and return
-     * the empty code. Will return null if the method should be empty.
-     */
-    protected Code replaceMethod(BCClass bc, String name, Class retType,
-        Class[] args, boolean remove) {
-        bc.removeDeclaredMethod(name, args);
-        BCMethod meth = bc.declareMethod(name, retType, args);
-        Code code = meth.getCode(true);
-        if (!remove)
-            return code;
-        code.xreturn().setType(retType);
-        code.calculateMaxStack();
-        code.calculateMaxLocals();
-        return null;
-    }
-
     /**
      * Add a bean field of the given name and type.
      */
-    protected BCField addBeanField(BCClass bc, String name, Class type) {
-        if (name == null)
+    protected FieldNode addBeanField(ClassNodeTracker bc, String name, Class 
type) {
+        if (name == null) {
             throw new IllegalArgumentException("name == null");
+        }
+
+        ClassNode classNode = bc.getClassNode();
 
         // private <type> <name>
-        BCField field = bc.declareField(name, type);
-        field.setAccessFlags(getFieldAccess());
+        FieldNode field = new FieldNode(getFieldAccess(), name, 
Type.getDescriptor(type), null, null);
+        classNode.fields.add(field);
+
         name = StringUtil.capitalize(name);
 
         // getter
-        String prefix = (type == boolean.class) ? "is" : "get";
-        BCMethod method = bc.declareMethod(prefix + name, type, null);
-        method.makePublic();
-        Code code = method.getCode(true);
-        code.aload().setThis();
-        code.getfield().setField(field);
-        code.xreturn().setType(type);
-        code.calculateMaxStack();
-        code.calculateMaxLocals();
+        {
+            String prefix = (type == boolean.class) ? "is" : "get";
+            MethodNode meth = new MethodNode(Opcodes.ACC_PUBLIC,
+                                             prefix + name,
+                                             
Type.getMethodDescriptor(Type.getType(type)),
+                                             null, null);
+            classNode.methods.add(meth);
+            meth.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+            meth.instructions.add(new FieldInsnNode(Opcodes.GETFIELD, 
classNode.name, field.name, Type.getDescriptor(type)));
+            meth.instructions.add(new InsnNode(AsmHelper.getReturnInsn(type)));
+        }
 
         // setter
-        method = bc.declareMethod("set" + name, void.class,
-            new Class[]{ type });
-        method.makePublic();
-        code = method.getCode(true);
-        code.aload().setThis();
-        code.xload().setParam(0).setType(type);
-        code.putfield().setField(field);
-        code.vreturn();
-        code.calculateMaxStack();
-        code.calculateMaxLocals();
+        {
+            MethodNode meth = new MethodNode(Opcodes.ACC_PUBLIC,
+                                             "set" + name,
+                                             
Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(type)),
+                                             null, null);
+            classNode.methods.add(meth);
+
+            meth.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+            meth.instructions.add(new VarInsnNode(AsmHelper.getLoadInsn(type), 
1)); // value parameter
+            meth.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, 
classNode.name, field.name, Type.getDescriptor(type)));
+            meth.instructions.add(new InsnNode(Opcodes.RETURN));
+
+        }
         return field;
     }
 
@@ -530,9 +616,10 @@ public class DynamicStorageGenerator {
      */
     protected Class getWrapper(Class c) {
         for (Class[] wrapper : WRAPPERS) {
-            if (wrapper[0].equals(c))
+            if (wrapper[0].equals(c)) {
                 return wrapper[1];
+            }
         }
-               return c;
-       }
+        return c;
+    }
 }
diff --git 
a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCDataGenerator.java 
b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCDataGenerator.java
index 450b3a088..86ebf6c72 100644
--- 
a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCDataGenerator.java
+++ 
b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCDataGenerator.java
@@ -37,16 +37,31 @@ import org.apache.openjpa.meta.ClassMetaData;
 import org.apache.openjpa.meta.FieldMetaData;
 import org.apache.openjpa.meta.JavaTypes;
 import org.apache.openjpa.util.InternalException;
+import org.apache.openjpa.util.asm.AsmHelper;
+import org.apache.openjpa.util.asm.ClassNodeTracker;
+import org.apache.xbean.asm9.Opcodes;
+import org.apache.xbean.asm9.Type;
+import org.apache.xbean.asm9.tree.ClassNode;
+import org.apache.xbean.asm9.tree.FieldInsnNode;
+import org.apache.xbean.asm9.tree.FieldNode;
+import org.apache.xbean.asm9.tree.InsnList;
+import org.apache.xbean.asm9.tree.InsnNode;
+import org.apache.xbean.asm9.tree.JumpInsnNode;
+import org.apache.xbean.asm9.tree.LabelNode;
+import org.apache.xbean.asm9.tree.MethodInsnNode;
+import org.apache.xbean.asm9.tree.MethodNode;
+import org.apache.xbean.asm9.tree.TypeInsnNode;
+import org.apache.xbean.asm9.tree.VarInsnNode;
 
 import serp.bytecode.BCClass;
 import serp.bytecode.BCField;
 import serp.bytecode.BCMethod;
 import serp.bytecode.Code;
 import serp.bytecode.Constants;
-import serp.bytecode.ExceptionHandler;
 import serp.bytecode.Instruction;
 import serp.bytecode.JumpInstruction;
 import serp.bytecode.LookupSwitchInstruction;
+import serp.bytecode.Project;
 
 /**
  * Generates {@link PCData} instances which avoid primitive wrappers
@@ -54,10 +69,10 @@ import serp.bytecode.LookupSwitchInstruction;
  * startup time.
  *
  * @author Steve Kim
+ * @author Mark Struberg rework to ASM
  * @since 0.3.2
  */
-public class PCDataGenerator
-    extends DynamicStorageGenerator {
+public class PCDataGenerator extends DynamicStorageGenerator {
 
     private static final Localizer _loc = Localizer.forPackage
         (PCDataGenerator.class);
@@ -130,10 +145,10 @@ public class PCDataGenerator
     }
 
     @Override
-    protected void declareClasses(BCClass bc) {
+    protected void declareClasses(ClassNodeTracker bc) {
         super.declareClasses(bc);
         bc.declareInterface(DynamicPCData.class);
-        bc.setSuperclass(AbstractPCData.class);
+        bc.getClassNode().superName = 
Type.getInternalName(AbstractPCData.class);
     }
 
     @Override
@@ -149,52 +164,66 @@ public class PCDataGenerator
     }
 
     @Override
-    protected final void decorate(Object obj, BCClass bc, int[] types) {
+    protected final void decorate(Object obj, ClassNodeTracker bc, int[] 
types) {
         super.decorate(obj, bc, types);
         ClassMetaData meta = (ClassMetaData) obj;
 
         enhanceConstructor(bc);
         addBaseFields(bc);
         addImplDataMethods(bc, meta);
-        addFieldImplDataMethods(bc, meta);
-        addVersionMethods(bc);
         addGetType(bc, meta);
-        addLoadMethod(bc, meta);
-        addLoadWithFieldsMethod(bc, meta);
-        addStoreMethods(bc, meta);
-        addNewEmbedded(bc);
-        addGetData(bc);
+        addVersionMethods(bc);
+
+        BCClass _bc = new 
Project().loadClass(bc.getClassNode().name.replace("/", "."));
+        AsmHelper.readIntoBCClass(bc, _bc);
+
+        addFieldImplDataMethods(_bc, meta);
+        addLoadMethod(_bc, meta);
+        addLoadWithFieldsMethod(_bc, meta);
+        addStoreMethods(_bc, meta);
+        addNewEmbedded(_bc);
+        addGetData(_bc);
+
+        bc = AsmHelper.toClassNode(bc.getProject(), _bc);
+
         decorate(bc, meta);
     }
 
     /**
      * Apply additional decoration to generated class.
      */
-    protected void decorate(BCClass bc, ClassMetaData meta) {
+    protected void decorate(ClassNodeTracker bc, ClassMetaData meta) {
     }
 
     /**
      * Enhance constructor to initialize fields
      */
-    private void enhanceConstructor(BCClass bc) {
-        BCMethod cons = bc.getDeclaredMethod("<init>", (String[]) null);
-        Code code = cons.getCode(false);
-        code.afterLast();
-        code.previous();
+    private void enhanceConstructor(ClassNodeTracker bc) {
+        ClassNode classNode = bc.getClassNode();
 
-        // private BitSet loaded = new BitSet();
-        BCField loaded = addBeanField(bc, "loaded", BitSet.class);
-        loaded.setFinal(true);
-        code.aload().setThis();
-        code.anew().setType(BitSet.class);
-        code.dup();
-        code.constant().setValue(bc.getFields().length);
-        code.invokespecial().setMethod(BitSet.class, "<init>", void.class,
-            new Class[]{ int.class });
-        code.putfield().setField(loaded);
+        // find the default constructor
+        MethodNode defaultCt = classNode.methods.stream()
+                .filter(m -> m.name.equals("<init>") && m.desc.equals("()V"))
+                .findFirst()
+                .get();
 
-        code.calculateMaxStack();
-        code.calculateMaxLocals();
+        InsnList instructions = new InsnList();
+
+
+        // private BitSet loaded = new BitSet();
+        FieldNode loaded = addBeanField(bc, "loaded", BitSet.class);
+
+        instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+        instructions.add(new TypeInsnNode(Opcodes.NEW, 
Type.getInternalName(BitSet.class)));
+        instructions.add(new InsnNode(Opcodes.DUP));
+        
instructions.add(AsmHelper.getLoadConstantInsn(classNode.fields.size()));
+        instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL,
+                                            Type.getInternalName(BitSet.class),
+                                            "<init>",
+                                            
Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE)));
+        instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, classNode.name, 
loaded.name, loaded.desc));
+
+        defaultCt.instructions.insertBefore(defaultCt.instructions.getLast(), 
instructions);
     }
 
     /**
@@ -202,123 +231,143 @@ public class PCDataGenerator
      * same classloader (i.e. rar vs. ear). The context classloader
      * (i.e. the user app classloader) should be fine.
      */
-    private void addGetType(BCClass bc, ClassMetaData meta) {
-        BCField type = bc.declareField("type", Class.class);
-        type.setStatic(true);
-        type.makePrivate();
+    private void addGetType(ClassNodeTracker bc, ClassMetaData meta) {
+        ClassNode classNode = bc.getClassNode();
+        FieldNode typeField = new FieldNode(Opcodes.ACC_PRIVATE | 
Opcodes.ACC_STATIC, "type", Type.getDescriptor(Class.class), null, null);
+        classNode.fields.add(typeField);
+
         // public Class getType() {
-        BCMethod getter = bc.declareMethod("getType", Class.class, null);
-        getter.makePublic();
-        Code code = getter.getCode(true);
+        MethodNode getter = new MethodNode(Opcodes.ACC_PUBLIC,
+                                           "getType",
+                                           
Type.getMethodDescriptor(Type.getType(Class.class)),
+                                           null, null);
+        classNode.methods.add(getter);
+
+        InsnList instructions = getter.instructions;
+
+        // use name as constant filled with meta.getDescribedType().getName()
         // if (type == null) {
-        //             try {
-        //                     type = Class.forName
-        //                 (meta.getDescribedType().getName(), true,
-        //                 Thread.currentThread().getContextClassLoader());
-        //             } catch (ClassNotFoundException cnfe) {
-        //                     throw new InternalException();
-        //             }
+        //     type = PCDataGenerator.getType(name)
         // }
-        code.getstatic().setField(type);
-
-        Collection<Instruction> jumps = new LinkedList<>();
-        jumps.add(code.ifnonnull());
-        ExceptionHandler handler = code.addExceptionHandler();
-
-        handler.setTryStart(code.constant().setValue
-            (meta.getDescribedType().getName()));
-        code.constant().setValue(true);
-        code.invokestatic().setMethod(Thread.class, "currentThread",
-            Thread.class, null);
-        code.invokevirtual().setMethod(Thread.class, "getContextClassLoader",
-            ClassLoader.class, null);
-        code.invokestatic().setMethod(Class.class, "forName", Class.class,
-            new Class[]{ String.class, boolean.class, ClassLoader.class });
-        code.putstatic().setField(type);
-        Instruction go2 = code.go2();
-        jumps.add(go2);
-        handler.setTryEnd(go2);
-        handler.setCatch(ClassNotFoundException.class);
-        handler.setHandlerStart(throwException
-            (code, InternalException.class));
-        setTarget(code.getstatic().setField(type), jumps);
-        code.areturn();
+        instructions.add(new FieldInsnNode(Opcodes.GETSTATIC, classNode.name, 
typeField.name, typeField.desc));
+
+        LabelNode lblEndIfNN = new LabelNode();
+        instructions.add(new JumpInsnNode(Opcodes.IFNONNULL, lblEndIfNN));
+
+        // actual type = PCDataGenerator.getType(name)
+        
instructions.add(AsmHelper.getLoadConstantInsn(meta.getDescribedType().getName()));
+        instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
+                                            
Type.getInternalName(PCDataGenerator.class),
+                                            "getType",
+                                            
Type.getMethodDescriptor(Type.getType(Class.class), 
Type.getType(String.class))));
+        instructions.add(new FieldInsnNode(Opcodes.PUTSTATIC, classNode.name, 
typeField.name, typeField.desc));
+
+        instructions.add(lblEndIfNN);
+        instructions.add(new FieldInsnNode(Opcodes.GETSTATIC, classNode.name, 
typeField.name, typeField.desc));
+        instructions.add(new InsnNode(Opcodes.ARETURN));
+    }
 
-        code.calculateMaxStack();
-        code.calculateMaxLocals();
+    public static Class<?> getType(String className) {
+        try {
+            return Class.forName(className, true, 
Thread.currentThread().getContextClassLoader());
+        }
+        catch (ClassNotFoundException cnfe) {
+            throw new InternalException();
+        }
     }
 
     /**
      * Declare standard dynamic pcdata fields.
      */
-    private void addBaseFields(BCClass bc) {
+    private void addBaseFields(ClassNodeTracker bc) {
         addBeanField(bc, "id", Object.class);
-        BCField field = addBeanField(bc, "storageGenerator",
-            PCDataGenerator.class);
-        field.setAccessFlags(field.getAccessFlags()
-            | Constants.ACCESS_TRANSIENT);
+        FieldNode field = addBeanField(bc, "storageGenerator", 
PCDataGenerator.class);
+        field.access |= Constants.ACCESS_TRANSIENT;
     }
 
     /**
      * Add methods for loading and storing class-level impl data.
      */
-    private void addImplDataMethods(BCClass bc, ClassMetaData meta) {
-        // void storeImplData(OpenJPAStateManager);
-        BCMethod meth = bc.declareMethod("storeImplData", void.class,
-            new Class[]{ OpenJPAStateManager.class });
-        Code code = meth.getCode(true);
+    private void addImplDataMethods(ClassNodeTracker bc, ClassMetaData meta) {
+        ClassNode classNode = bc.getClassNode();
 
-        BCField impl = null;
-        if (!usesImplData(meta))
-            code.vreturn();
+        // void storeImplData(OpenJPAStateManager);
+        MethodNode storeM = new MethodNode(Opcodes.ACC_PUBLIC,
+                                         "storeImplData",
+                                         
Type.getMethodDescriptor(Type.VOID_TYPE, 
Type.getType(OpenJPAStateManager.class)),
+                                         null, null);
+        classNode.methods.add(storeM);
+        InsnList instructions = storeM.instructions;
+
+        FieldNode impl = null;
+        if (!usesImplData(meta)) {
+            instructions.add(new InsnNode(Opcodes.RETURN));
+        }
         else {
             // if (sm.isImplDataCacheable())
-            //                 setImplData(sm.getImplData());
+            //         setImplData(sm.getImplData());
             impl = addBeanField(bc, "implData", Object.class);
-            code.aload().setParam(0);
-            code.invokeinterface().setMethod(OpenJPAStateManager.class,
-                "isImplDataCacheable", boolean.class, null);
-            JumpInstruction ifins = code.ifeq();
-            code.aload().setThis();
-            code.aload().setParam(0);
-            code.invokeinterface().setMethod(OpenJPAStateManager.class,
-                "getImplData", Object.class, null);
-            code.invokevirtual().setMethod("setImplData", void.class,
-                new Class[]{ Object.class });
-            ifins.setTarget(code.vreturn());
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); // 1st param
+            instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE,
+                                                
Type.getInternalName(OpenJPAStateManager.class),
+                                                "isImplDataCacheable",
+                                                
Type.getMethodDescriptor(Type.BOOLEAN_TYPE)));
+            LabelNode lblEndIfEq = new LabelNode();
+            instructions.add(new JumpInsnNode(Opcodes.IFEQ, lblEndIfEq));
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); // 1st param
+            instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE,
+                                                
Type.getInternalName(OpenJPAStateManager.class),
+                                                "getImplData",
+                                                
Type.getMethodDescriptor(Type.getType(Object.class))));
+
+            instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
+                                                classNode.name,
+                                                "setImplData",
+                                                
Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Object.class))));
+
+            instructions.add(lblEndIfEq);
+            instructions.add(new InsnNode(Opcodes.RETURN));
         }
-        code.calculateMaxStack();
-        code.calculateMaxLocals();
 
         // void loadImplData(OpenJPAStateManager);
-        meth = bc.declareMethod("loadImplData", void.class,
-            new Class[]{ OpenJPAStateManager.class });
-        code = meth.getCode(true);
-        if (!usesImplData(meta))
-            code.vreturn();
+        MethodNode loadM = new MethodNode(Opcodes.ACC_PUBLIC,
+                                           "loadImplData",
+                                           
Type.getMethodDescriptor(Type.VOID_TYPE, 
Type.getType(OpenJPAStateManager.class)),
+                                           null, null);
+        classNode.methods.add(loadM);
+        instructions = loadM.instructions;
+
+        if (!usesImplData(meta)) {
+            instructions.add(new InsnNode(Opcodes.RETURN));
+        }
         else {
             // if (sm.getImplData() == null && implData != null)
-            //                 sm.setImplData(impl, true);
-            code.aload().setParam(0);
-            code.invokeinterface().setMethod(OpenJPAStateManager.class,
-                "getImplData", Object.class, null);
-            JumpInstruction ifins = code.ifnonnull();
-            code.aload().setThis();
-            code.getfield().setField(impl);
-            JumpInstruction ifins2 = code.ifnull();
-            code.aload().setParam(0);
-            code.aload().setThis();
-            code.getfield().setField(impl);
-            code.constant().setValue(true);
-            code.invokeinterface().setMethod(OpenJPAStateManager.class,
-                "setImplData", void.class,
-                new Class[]{ Object.class, boolean.class });
-            Instruction ins = code.vreturn();
-            ifins.setTarget(ins);
-            ifins2.setTarget(ins);
+            //         sm.setImplData(impl, true);
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); // 1st param
+            instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE,
+                                                
Type.getInternalName(OpenJPAStateManager.class),
+                                                "getImplData",
+                                                
Type.getMethodDescriptor(Type.getType(Object.class))));
+            LabelNode lblEndIf = new LabelNode();
+            instructions.add(new JumpInsnNode(Opcodes.IFNONNULL, lblEndIf));
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+            instructions.add(new FieldInsnNode(Opcodes.GETFIELD, 
classNode.name, impl.name, impl.desc));
+
+            LabelNode lblEndIf2 = new LabelNode();
+            instructions.add(new JumpInsnNode(Opcodes.IFNULL, lblEndIf2));
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); // 1st param
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+            instructions.add(new FieldInsnNode(Opcodes.GETFIELD, 
classNode.name, impl.name, impl.desc));
+            instructions.add(AsmHelper.getLoadConstantInsn(true));
+            instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE,
+                                                
Type.getInternalName(OpenJPAStateManager.class),
+                                                "setImplData",
+                                                
Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Object.class), 
Type.BOOLEAN_TYPE)));
+            instructions.add(lblEndIf);
+            instructions.add(lblEndIf2);
+            instructions.add(new InsnNode(Opcodes.RETURN));
         }
-        code.calculateMaxStack();
-        code.calculateMaxLocals();
     }
 
     /**
@@ -448,7 +497,7 @@ public class PCDataGenerator
             code.ifnull().setTarget(nullTarget);
 
             // if (fieldImpl == null)
-            //                 fieldImpl = new Object[fields];
+            //         fieldImpl = new Object[fields];
             code.aload().setThis();
             code.getfield().setField(impl);
             ifins = code.ifnonnull();
@@ -467,7 +516,7 @@ public class PCDataGenerator
             code.vreturn();
 
             // if (fieldImpl != null)
-            //                 fieldImpl[index] = null;
+            //         fieldImpl[index] = null;
             code.next(); // step over nullTarget
             code.getfield().setField(impl);
             ifins = code.ifnonnull();
@@ -486,49 +535,67 @@ public class PCDataGenerator
     /**
      * Add methods for loading and storing version data.
      */
-    protected void addVersionMethods(BCClass bc) {
-        // void storeVersion(OpenJPAStateManager sm);
-        addBeanField(bc, "version", Object.class);
-        BCMethod meth = bc.declareMethod("storeVersion", void.class,
-            new Class[]{ OpenJPAStateManager.class });
-        Code code = meth.getCode(true);
+    protected void addVersionMethods(ClassNodeTracker bc) {
+        ClassNode classNode = bc.getClassNode();
 
-        // version = sm.getVersion();
-        code.aload().setThis();
-        code.aload().setParam(0);
-        code.invokeinterface()
-            .setMethod(OpenJPAStateManager.class, "getVersion",
-                Object.class, null);
-        code.putfield().setField("version", Object.class);
-        code.vreturn();
-        code.calculateMaxStack();
-        code.calculateMaxLocals();
+        final FieldNode versionField = addBeanField(bc, "version", 
Object.class);
 
-        // void loadVersion(OpenJPAStateManager sm)
-        meth = bc.declareMethod("loadVersion", void.class,
-            new Class[]{ OpenJPAStateManager.class });
-        code = meth.getCode(true);
+        // void storeVersion(OpenJPAStateManager sm);
+        {
+            MethodNode storeMeth = new MethodNode(Opcodes.ACC_PUBLIC,
+                                                  "storeVersion",
+                                                  
Type.getMethodDescriptor(Type.VOID_TYPE, 
Type.getType(OpenJPAStateManager.class)),
+                                                  null, null);
+            classNode.methods.add(storeMeth);
+            InsnList instructions = storeMeth.instructions;
+
+
+            // version = sm.getVersion();
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); // 1st param
+            instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE,
+                                                
Type.getInternalName(OpenJPAStateManager.class),
+                                                "getVersion",
+                                                
Type.getMethodDescriptor(Type.getType(Object.class))));
+            instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, 
classNode.name, versionField.name, versionField.desc));
+            instructions.add(new InsnNode(Opcodes.RETURN));
+        }
 
-        // if (sm.getVersion() == null)
-        //             sm.setVersion(version);
-        code.aload().setParam(0);
-        code.invokeinterface().setMethod(OpenJPAStateManager.class,
-            "getVersion", Object.class, null);
-        JumpInstruction ifins = code.ifnonnull();
-        code.aload().setParam(0);
-        code.aload().setThis();
-        code.getfield().setField("version", Object.class);
-        code.invokeinterface()
-            .setMethod(OpenJPAStateManager.class, "setVersion",
-                void.class, new Class[]{ Object.class });
-        ifins.setTarget(code.vreturn());
-        code.calculateMaxStack();
-        code.calculateMaxLocals();
+        // void loadVersion(OpenJPAStateManager sm)
+        {
+            MethodNode loadMeth = new MethodNode(Opcodes.ACC_PUBLIC,
+                                                 "loadVersion",
+                                                 
Type.getMethodDescriptor(Type.VOID_TYPE, 
Type.getType(OpenJPAStateManager.class)),
+                                                 null, null);
+            classNode.methods.add(loadMeth);
+            InsnList instructions = loadMeth.instructions;
+
+            // if (sm.getVersion() == null)
+            //         sm.setVersion(version);
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); // 1st param
+            instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE,
+                                                
Type.getInternalName(OpenJPAStateManager.class),
+                                                "getVersion",
+                                                
Type.getMethodDescriptor(Type.getType(Object.class))));
+
+            LabelNode lblEndIf = new LabelNode();
+            instructions.add(new JumpInsnNode(Opcodes.IFNONNULL, lblEndIf));
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); // 1st param
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+            instructions.add(new FieldInsnNode(Opcodes.GETFIELD, 
classNode.name, versionField.name, versionField.desc));
+            instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE,
+                                                
Type.getInternalName(OpenJPAStateManager.class),
+                                                "setVersion",
+                                                
Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Object.class))));
+
+            instructions.add(lblEndIf);
+            instructions.add(new InsnNode(Opcodes.RETURN));
+        }
     }
 
     private void addLoadMethod(BCClass bc, ClassMetaData meta) {
         // public void load(OpenJPAStateManager sm, FetchConfiguration fetch,
-        //             Object context)
+        //         Object context)
         Code code = addLoadMethod(bc, false);
         FieldMetaData[] fmds = meta.getFields();
         Collection<Instruction> jumps = new LinkedList<>();
@@ -584,7 +651,7 @@ public class PCDataGenerator
     private void addLoadWithFieldsMethod(BCClass bc, ClassMetaData meta) {
         Code code = addLoadMethod(bc, true);
         // public void load(OpenJPAStateManager sm, BitSet fields,
-        //             FetchConfiguration fetch, Object conn)
+        //         FetchConfiguration fetch, Object conn)
         FieldMetaData[] fmds = meta.getFields();
         Collection<Instruction> jumps = new LinkedList<>();
         Collection<Instruction> jumps2;
@@ -602,7 +669,7 @@ public class PCDataGenerator
             intermediate = usesIntermediate(fmds[i]);
             // if (fields.get(i))
             // {
-            //                 if (loaded.get(i))
+            //         if (loaded.get(i))
             setTarget(code.aload().setParam(1), jumps);
             code.constant().setValue(i);
             code.invokevirtual().setMethod(BitSet.class, "get",
@@ -706,7 +773,7 @@ public class PCDataGenerator
                 FieldMetaData.class, new Class[]{ int.class });
             code.astore().setLocal(local);
             // sm.storeField(i, toField(sm, fmd, objects[objectCount],
-            //                 fetch, context);
+            //         fetch, context);
             code.aload().setParam(0);
             code.constant().setValue(index);
             code.aload().setThis();
@@ -735,13 +802,13 @@ public class PCDataGenerator
     private Instruction addLoadIntermediate(Code code, int index,
         int objectCount, Collection<Instruction> jumps2, int inter) {
         // {
-        //             Object inter = objects[objectCount];
+        //         Object inter = objects[objectCount];
         Instruction first = code.aload().setThis();
         code.getfield().setField("objects", Object[].class);
         code.constant().setValue(objectCount);
         code.aaload();
         code.astore().setLocal(inter);
-        //             if (inter != null && !sm.getLoaded().get(index))
+        //         if (inter != null && !sm.getLoaded().get(index))
         code.aload().setLocal(inter);
         jumps2.add(code.ifnull());
         code.aload().setParam(0);
@@ -751,8 +818,8 @@ public class PCDataGenerator
         code.invokevirtual().setMethod(BitSet.class, "get",
             boolean.class, new Class[]{ int.class });
         jumps2.add(code.ifne());
-        //                     sm.setIntermediate(index, inter);
-        //     }  // end else
+        //            sm.setIntermediate(index, inter);
+        //    }  // end else
         code.aload().setParam(0);
         code.constant().setValue(index);
         code.aload().setLocal(inter);
@@ -769,8 +836,7 @@ public class PCDataGenerator
         addStoreMethod(bc, meta, false);
     }
 
-    private void addStoreMethod(BCClass bc, ClassMetaData meta,
-        boolean fields) {
+    private void addStoreMethod(BCClass bc, ClassMetaData meta, boolean 
fields) {
         BCMethod store;
         if (fields)
             store = bc.declareMethod("store", void.class,
@@ -832,7 +898,7 @@ public class PCDataGenerator
                 jumps.add(code.ifne());
                 // Object val = sm.getIntermediate(index);
                 // if (val != null)
-                //             objects[objectCount] = val;
+                //         objects[objectCount] = val;
                 code.aload().setParam(0);
                 code.constant().setValue(i);
                 code.invokeinterface().setMethod(OpenJPAStateManager.class,
@@ -876,7 +942,7 @@ public class PCDataGenerator
                 new Class[]{ int.class });
         } else {
             // Object val = toData(sm.getMetaData().getField(index),
-            //                 sm.fetchField(index, false), sm.getContext());
+            //         sm.fetchField(index, false), sm.getContext());
             int local = code.getNextLocalsIndex();
             code.aload().setThis();
             code.aload().setParam(0);
@@ -900,11 +966,11 @@ public class PCDataGenerator
             code.astore().setLocal(local);
 
             // if (val == NULL) {
-            //                 val = null;
-            //                 loaded.clear(index);
-            //         } else
-            //                 loaded.set(index);
-            //         objects[objectCount] = val;
+            //         val = null;
+            //         loaded.clear(index);
+            //     } else
+            //         loaded.set(index);
+            //     objects[objectCount] = val;
             code.aload().setLocal(local);
             code.getstatic().setField(AbstractPCData.class, "NULL",
                 Object.class);
@@ -950,7 +1016,7 @@ public class PCDataGenerator
             new Class[]{ OpenJPAStateManager.class });
         Code code = meth.getCode(true);
         // return getStorageGenerator().generatePCData
-        //             (sm.getId(), sm.getMetaData());
+        //         (sm.getId(), sm.getMetaData());
         code.aload().setThis();
         code.getfield().setField("storageGenerator", PCDataGenerator.class);
         code.aload().setParam(0);
diff --git 
a/openjpa-kernel/src/main/java/org/apache/openjpa/util/InternalException.java 
b/openjpa-kernel/src/main/java/org/apache/openjpa/util/InternalException.java
index 903566436..f30081599 100644
--- 
a/openjpa-kernel/src/main/java/org/apache/openjpa/util/InternalException.java
+++ 
b/openjpa-kernel/src/main/java/org/apache/openjpa/util/InternalException.java
@@ -26,10 +26,8 @@ import org.apache.openjpa.lib.util.Localizer.Message;
  * @author Abe White
  * @since 0.3.2
  */
-public class InternalException
-    extends OpenJPAException {
+public class InternalException extends OpenJPAException {
 
-    
     private static final long serialVersionUID = 1L;
 
     public InternalException() {
diff --git 
a/openjpa-kernel/src/main/java/org/apache/openjpa/util/OpenJPAException.java 
b/openjpa-kernel/src/main/java/org/apache/openjpa/util/OpenJPAException.java
index 15a89bd8d..8300d0788 100644
--- a/openjpa-kernel/src/main/java/org/apache/openjpa/util/OpenJPAException.java
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/util/OpenJPAException.java
@@ -35,8 +35,7 @@ import org.apache.openjpa.lib.util.Localizer.Message;
  * @author Abe White
  * @since 0.4.0
  */
-public abstract class OpenJPAException
-    extends RuntimeException
+public abstract class OpenJPAException extends RuntimeException
     implements Serializable, ExceptionInfo {
 
     private static final long serialVersionUID = 1L;
diff --git 
a/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/ClassNodeTracker.java
 
b/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/ClassNodeTracker.java
index acb615d7d..eb78edd02 100644
--- 
a/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/ClassNodeTracker.java
+++ 
b/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/ClassNodeTracker.java
@@ -27,7 +27,7 @@ import org.apache.xbean.asm9.tree.ClassNode;
  * @author <a href="mailto:strub...@apache.org";>Mark Struberg</a>
  */
 public class ClassNodeTracker {
-    private final ClassNode classNode;
+    private ClassNode classNode;
     private final ClassLoader cl;
     private final EnhancementProject project;
 
@@ -60,6 +60,10 @@ public class ClassNodeTracker {
         return classNode;
     }
 
+    public void setClassNode(ClassNode classNode) {
+        this.classNode = classNode;
+    }
+
     public ClassLoader getClassLoader() {
         return cl;
     }
diff --git 
a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/TestDynamicStorageGenerator.java
 
b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/TestDynamicStorageGenerator.java
index a07a5cdb0..ef99af94b 100644
--- 
a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/TestDynamicStorageGenerator.java
+++ 
b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/TestDynamicStorageGenerator.java
@@ -32,8 +32,7 @@ public class TestDynamicStorageGenerator
         super(s, "enhancecactusapp");
     }
 
-    public void testStorage()
-        throws Exception {
+    public void testStorage() throws Exception {
 
         DynamicStorageGenerator gen = new DynamicStorageGenerator();
         int[] types = new int[]{
@@ -48,8 +47,7 @@ public class TestDynamicStorageGenerator
             JavaTypes.STRING,
             JavaTypes.OBJECT
         };
-        DynamicStorage storage = gen.generateStorage(types,
-            "org.apache.openjpa.enhance.Test");
+        DynamicStorage storage = gen.generateStorage(types, 
"org.apache.openjpa.enhance.Test");
         storage = storage.newInstance();
 
         storage.setBoolean(0, true);
@@ -71,8 +69,7 @@ public class TestDynamicStorageGenerator
         assertEquals(4, storage.getShort(4));
         assertEquals(5, storage.getLong(5));
         assertTrue(6.59 < storage.getFloat(6) && 6.61 > storage.getFloat(6));
-        assertTrue(7.69 < storage.getDouble(7)
-            && 7.71 > storage.getDouble(7));
+        assertTrue(7.69 < storage.getDouble(7) && 7.71 > storage.getDouble(7));
         assertEquals("field8", storage.getObject(8));
         assertEquals(date, storage.getObject(9));
     }

Reply via email to