Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

94
LINES

< > BotCompany Repo | #1034314 // ClassMaker [BCEL helper]

JavaX fragment (include) [tags: use-pretranspiled]

Transpiled version (12720L) is out of date.

!include once #1019934 // BCEL

// A = interface we are implementing
sclass ClassMaker<A> {
  gettable S className;
  gettable ClassGen cg;
  JavaClass baked;
  InMemoryClassLoader classLoader;
  Class loadedClass;
  settable bool printDisassembly;
  settable S superClassName = "java.lang.Object";
  settable S fileName;
  
  *(S className) {
    this(className, null);
  }
  
  *(S *className, S *superClassName, S[] interfaces) {
    setClassGen(new ClassGen(className, superClassName, fileName,
      Const.ACC_PUBLIC, interfaces));
  }
  
  *(S *className, S[] interfaces) {
    setClassGen(new ClassGen(className, superClassName, fileName,
      Const.ACC_PUBLIC, interfaces));
  }
  
  *(Class<A> interfaceToImplement) {
    className = randomClassName();
    setClassGen(new ClassGen(className, "java.lang.Object", null,
      Const.ACC_PUBLIC, new S[] { main className(interfaceToImplement) }));
      
    addDefaultConstructor();
  }
  
  void addDefaultConstructor {
    cg.addEmptyConstructor(Const.ACC_PUBLIC);
  }
  
  void setClassGen(ClassGen cg) {
    this.cg = cg;
    
    // up the byte code version so we can do ldc of class objects (e.g.)
    cg.setMajor(50); // JDK 6
    //cg.setMajor(55); // JDK 11. can't use yet because StackMapTable became mandatory in JDK 8 and BCEL doesn't generate that
    cg.setMinor(0);
  }
  
  JavaClass bake() {
    if (baked == null) {
      baked = cg.getJavaClass();
      if (printDisassembly)
        printClassWithMethods();
    }
    ret baked;
  }
  
  // tabs can look bad in JTextArea, so we're using tabToSingleSpace
  void printClassWithMethods() {
    // print class overview
    print_tabToSingleSpace(bake());
    
    // print the methods
    for (method : baked.getMethods()) {
      print_tabToSingleSpace("\n" + method);
      print_tabToSingleSpace(method.getCode());
    }
  }
  
  simplyCached byte[] toBytes aka getBytes() {
    ret bake().getBytes();
  }
  
  Class<A> load() {
    if (loadedClass == null) {
      var bytes = toBytes();
      classLoader = new InMemoryClassLoader(myClassLoader());
      loadedClass = (Class) classLoader.defineAClass(className, bytes);
    }
    ret loadedClass;
  }
  
  A newInstance() {
    ret main newInstance(load());
  }
  
  void addField(FieldGen fg) {
    cg.addField(fg.getField());
  }
  
  ConstantPoolGen getConstantPool() {
    ret cg.getConstantPool();
  }
}

Author comment

Began life as a copy of #1034311

download  show line numbers  debug dex  old transpilations   

Travelled to 4 computer(s): bhatertpkbcr, ekrmjmnbrukm, mowyntqkapby, mqqgnosmbjvj

No comments. add comment

Snippet ID: #1034314
Snippet name: ClassMaker [BCEL helper]
Eternal ID of this version: #1034314/27
Text MD5: f685d5b204cbcd7d4e87378caf1198ac
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-12-16 04:43:17
Source code size: 2482 bytes / 94 lines
Pitched / IR pitched: No / No
Views / Downloads: 268 / 523
Version history: 26 change(s)
Referenced in: #1003674 - Standard Classes + Interfaces (LIVE continued in #1034167)