private void createStaticConstructor(ClassNode owner) throws UnsupportedEncodingException { MethodNode original = BytecodeHelper.getMethod(owner, "<clinit>", "()V"); MethodVisitor mv = owner.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V", null, null); // generate instructions InstructionAdapter builder = new InstructionAdapter(mv); builder.iconst(stringList.size()); builder.newarray(Type.getType(String.class)); for (int i = 0; i < stringList.size(); i++) { builder.dup(); builder.iconst(i); builder.aconst(Base64.getEncoder().encodeToString(stringList.get(i).getBytes("UTF-8"))); builder.astore(InstructionAdapter.OBJECT_TYPE); } builder.putstatic(unscrambleClass.name, FIELD_NAME, "[Ljava/lang/String;"); // merge with original if it exists if (original != null) { // original should already end with RETURN owner.methods.remove(original); original.instructions.accept(builder); } else { builder.areturn(Type.VOID_TYPE); } }
@Override public int writeCLInit(String fieldName, InstructionAdapter insts, String className) { insts.iconst(values.size()); insts.newarray(Type.INT_TYPE); int curIndex = 0; for (Integer value : values) { insts.dup(); insts.iconst(curIndex); insts.iconst(value); insts.astore(Type.INT_TYPE); ++curIndex; } insts.putstatic(className, fieldName, DESC); // Needs up to 4 stack slots for: the array ref for the putstatic, the dup of the array ref // for the store, the index, and the value to store. return 4; }
private static void writeStaticClassInit( ClassWriter classWriter, String className, Map<String, FieldInitializer> deferredInitializers) { MethodVisitor visitor = classWriter.visitMethod( Opcodes.ACC_STATIC, "<clinit>", "()V", null, /* signature */ null /* exceptions */); visitor.visitCode(); int stackSlotsNeeded = 0; InstructionAdapter insts = new InstructionAdapter(visitor); for (Entry<String, FieldInitializer> fieldEntry : deferredInitializers.entrySet()) { final FieldInitializer fieldInit = fieldEntry.getValue(); stackSlotsNeeded = Math.max(stackSlotsNeeded, fieldInit.writeCLInit(fieldEntry.getKey(), insts, className)); } insts.areturn(Type.VOID_TYPE); visitor.visitMaxs(stackSlotsNeeded, 0); visitor.visitEnd(); }
@Override public int writeCLInit(String fieldName, InstructionAdapter insts, String className) { insts.iconst(value); insts.putstatic(className, fieldName, DESC); // Just needs one stack slot for the iconst. return 1; }
/** * Write the bytecode for the clinit portion of initializer. * @return the number of stack slots needed for the code. */ int writeCLInit(String fieldName, InstructionAdapter insts, String className);