Search in sources :

Example 11 with ClassWriter

use of jodd.asm5.ClassWriter in project component-runtime by Talend.

the class RepositoryModelBuilderTest method createChainPlugin.

private File createChainPlugin(final File dir, final String plugin) {
    final File target = new File(dir, plugin);
    try (final JarOutputStream outputStream = new JarOutputStream(new FileOutputStream(target))) {
        final String packageName = toPackage(target.getParentFile().getParentFile().getName()).replace(".", "/");
        final String sourcePackage = "org/talend/test";
        final String fromPack = sourcePackage.replace('/', '.');
        final String toPack = packageName.replace('.', '/');
        final File root = new File(jarLocation(getClass()), sourcePackage);
        ofNullable(root.listFiles()).map(Stream::of).orElseGet(Stream::empty).filter(c -> c.getName().endsWith(".class")).forEach(clazz -> {
            try (final InputStream is = new FileInputStream(clazz)) {
                final ClassReader reader = new ClassReader(is);
                final ClassWriter writer = new ClassWriter(COMPUTE_FRAMES);
                reader.accept(new ClassRemapper(writer, new Remapper() {

                    @Override
                    public String map(final String key) {
                        return key.replace(sourcePackage, toPack).replace(fromPack, packageName);
                    }
                }), EXPAND_FRAMES);
                outputStream.putNextEntry(new JarEntry(toPack + '/' + clazz.getName()));
                outputStream.write(writer.toByteArray());
            } catch (final IOException e) {
                fail(e.getMessage());
            }
        });
    } catch (final IOException e) {
        throw new IllegalStateException(e);
    }
    return target;
}
Also used : Assertions.fail(org.junit.jupiter.api.Assertions.fail) Assertions.assertNotNull(org.junit.jupiter.api.Assertions.assertNotNull) COMPUTE_FRAMES(org.apache.xbean.asm9.ClassWriter.COMPUTE_FRAMES) ComponentFamilyMeta(org.talend.sdk.component.runtime.manager.ComponentFamilyMeta) HashMap(java.util.HashMap) EXPAND_FRAMES(org.apache.xbean.asm9.ClassReader.EXPAND_FRAMES) Collections.singletonList(java.util.Collections.singletonList) DataStore1(org.talend.test.DataStore1) JarEntry(java.util.jar.JarEntry) Collections.singleton(java.util.Collections.singleton) ClassReader(org.apache.xbean.asm9.ClassReader) ParameterModelService(org.talend.sdk.component.runtime.manager.reflect.ParameterModelService) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) Path(java.nio.file.Path) JarOutputStream(java.util.jar.JarOutputStream) ParameterMeta(org.talend.sdk.component.runtime.manager.ParameterMeta) Collections.emptyMap(java.util.Collections.emptyMap) ClassWriter(org.apache.xbean.asm9.ClassWriter) Container(org.talend.sdk.component.container.Container) Collections.emptyList(java.util.Collections.emptyList) Optional.ofNullable(java.util.Optional.ofNullable) FileOutputStream(java.io.FileOutputStream) WrappingStore(org.talend.test.WrappingStore) IOException(java.io.IOException) FileInputStream(java.io.FileInputStream) IdGenerator(org.talend.sdk.component.runtime.manager.util.IdGenerator) Remapper(org.apache.xbean.asm9.commons.Remapper) Collectors.joining(java.util.stream.Collectors.joining) File(java.io.File) TestInfo(org.junit.jupiter.api.TestInfo) RepositoryModel(org.talend.sdk.component.design.extension.RepositoryModel) Test(org.junit.jupiter.api.Test) Collectors.toList(java.util.stream.Collectors.toList) List(java.util.List) Stream(java.util.stream.Stream) TempDir(org.junit.jupiter.api.io.TempDir) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) JarLocation.jarLocation(org.apache.ziplock.JarLocation.jarLocation) PropertyEditorRegistry(org.apache.xbean.propertyeditor.PropertyEditorRegistry) ComponentManager(org.talend.sdk.component.runtime.manager.ComponentManager) MigrationHandlerFactory(org.talend.sdk.component.runtime.manager.reflect.MigrationHandlerFactory) ReflectionService(org.talend.sdk.component.runtime.manager.reflect.ReflectionService) Collections(java.util.Collections) ClassRemapper(org.apache.xbean.asm9.commons.ClassRemapper) InputStream(java.io.InputStream) PartitionMapper1(org.talend.test.PartitionMapper1) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) JarOutputStream(java.util.jar.JarOutputStream) IOException(java.io.IOException) JarEntry(java.util.jar.JarEntry) ClassRemapper(org.apache.xbean.asm9.commons.ClassRemapper) FileInputStream(java.io.FileInputStream) ClassWriter(org.apache.xbean.asm9.ClassWriter) Remapper(org.apache.xbean.asm9.commons.Remapper) ClassRemapper(org.apache.xbean.asm9.commons.ClassRemapper) FileOutputStream(java.io.FileOutputStream) ClassReader(org.apache.xbean.asm9.ClassReader) JarOutputStream(java.util.jar.JarOutputStream) FileOutputStream(java.io.FileOutputStream) FileInputStream(java.io.FileInputStream) Stream(java.util.stream.Stream) InputStream(java.io.InputStream) File(java.io.File)

Example 12 with ClassWriter

use of jodd.asm5.ClassWriter in project component-runtime by Talend.

the class GenericComponentExtensionSupportTest method run.

@Test
void run(@TempDir final Path path) throws IOException {
    final Path pluginFolder = path.resolve("test-plugins_" + UUID.randomUUID().toString());
    Files.createDirectories(pluginFolder);
    final Path target = pluginFolder.resolve("test-compo.jar");
    try (final JarOutputStream outputStream = new JarOutputStream(Files.newOutputStream(target))) {
        final String packageName = "org.talend.generated.test." + getClass().getSimpleName();
        final String sourcePackage = "org/talend/test/generic";
        final String fromPack = sourcePackage.replace('/', '.');
        final String toPack = packageName.replace('.', '/');
        final File root = new File(jarLocation(getClass()), sourcePackage);
        ofNullable(root.listFiles()).map(Stream::of).orElseGet(Stream::empty).filter(c -> c.getName().endsWith(".class")).forEach(clazz -> {
            try (final InputStream is = new FileInputStream(clazz)) {
                final ClassReader reader = new ClassReader(is);
                final ClassWriter writer = new ClassWriter(COMPUTE_FRAMES);
                reader.accept(new ClassRemapper(writer, new Remapper() {

                    @Override
                    public String map(final String key) {
                        return key.replace(sourcePackage, toPack).replace(fromPack, packageName);
                    }
                }), EXPAND_FRAMES);
                outputStream.putNextEntry(new JarEntry(toPack + '/' + clazz.getName()));
                outputStream.write(writer.toByteArray());
                outputStream.closeEntry();
            } catch (final IOException e) {
                fail(e.getMessage());
            }
        });
        outputStream.putNextEntry(new JarEntry("META-INF/services/" + GenericComponentExtension.class.getName()));
        outputStream.write((packageName + '.' + MyGenericImpl.class.getSimpleName()).getBytes(StandardCharsets.UTF_8));
        outputStream.closeEntry();
    } catch (final IOException e) {
        throw new IllegalStateException(e);
    }
    try (final ComponentManager manager = new ComponentManager(new File("target/test-dependencies"), "META-INF/test/dependencies", null)) {
        manager.addPlugin(target.toAbsolutePath().toString());
        final Mapper mapper = manager.findMapper("my-generic", "the-first", 1, singletonMap("a", "a->1")).orElseThrow(IllegalStateException::new);
        // we bypass a bit the lifecycle cause we know the test component we
        final Input input = mapper.create();
        // use
        final Record next = Record.class.cast(input.next());
        assertEquals("my-generic", next.getString("plugin"));
        assertEquals("the-first", next.getString("name"));
        assertEquals("a", next.getString("key"));
        assertEquals("a->1", next.getString("value"));
        assertNull(input.next());
    }
}
Also used : Path(java.nio.file.Path) Assertions.fail(org.junit.jupiter.api.Assertions.fail) COMPUTE_FRAMES(org.apache.xbean.asm9.ClassWriter.COMPUTE_FRAMES) Assertions.assertNull(org.junit.jupiter.api.Assertions.assertNull) EXPAND_FRAMES(org.apache.xbean.asm9.ClassReader.EXPAND_FRAMES) JarEntry(java.util.jar.JarEntry) ClassReader(org.apache.xbean.asm9.ClassReader) Collections.singletonMap(java.util.Collections.singletonMap) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) Input(org.talend.sdk.component.runtime.input.Input) Path(java.nio.file.Path) JarOutputStream(java.util.jar.JarOutputStream) MyGenericImpl(org.talend.test.generic.MyGenericImpl) ClassWriter(org.apache.xbean.asm9.ClassWriter) Files(java.nio.file.Files) Optional.ofNullable(java.util.Optional.ofNullable) Record(org.talend.sdk.component.api.record.Record) IOException(java.io.IOException) FileInputStream(java.io.FileInputStream) UUID(java.util.UUID) Remapper(org.apache.xbean.asm9.commons.Remapper) File(java.io.File) StandardCharsets(java.nio.charset.StandardCharsets) Test(org.junit.jupiter.api.Test) Mapper(org.talend.sdk.component.runtime.input.Mapper) Stream(java.util.stream.Stream) GenericComponentExtension(org.talend.sdk.component.spi.component.GenericComponentExtension) TempDir(org.junit.jupiter.api.io.TempDir) JarLocation.jarLocation(org.apache.ziplock.JarLocation.jarLocation) ClassRemapper(org.apache.xbean.asm9.commons.ClassRemapper) InputStream(java.io.InputStream) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) JarOutputStream(java.util.jar.JarOutputStream) IOException(java.io.IOException) JarEntry(java.util.jar.JarEntry) ClassRemapper(org.apache.xbean.asm9.commons.ClassRemapper) FileInputStream(java.io.FileInputStream) ClassWriter(org.apache.xbean.asm9.ClassWriter) Mapper(org.talend.sdk.component.runtime.input.Mapper) Input(org.talend.sdk.component.runtime.input.Input) Remapper(org.apache.xbean.asm9.commons.Remapper) ClassRemapper(org.apache.xbean.asm9.commons.ClassRemapper) GenericComponentExtension(org.talend.sdk.component.spi.component.GenericComponentExtension) ClassReader(org.apache.xbean.asm9.ClassReader) JarOutputStream(java.util.jar.JarOutputStream) FileInputStream(java.io.FileInputStream) Stream(java.util.stream.Stream) InputStream(java.io.InputStream) Record(org.talend.sdk.component.api.record.Record) File(java.io.File) Test(org.junit.jupiter.api.Test)

Example 13 with ClassWriter

use of jodd.asm5.ClassWriter in project component-runtime by Talend.

the class PluginGenerator method createModel.

public byte[] createModel(final JarOutputStream outputStream, final String packageName) throws IOException {
    final String className = packageName + "/AModel.class";
    outputStream.putNextEntry(new ZipEntry(className));
    final ClassWriter writer = new ClassWriter(COMPUTE_FRAMES);
    writer.visit(V1_8, ACC_PUBLIC + ACC_SUPER, className.substring(0, className.length() - ".class".length()), null, Type.getInternalName(Object.class), null);
    writer.visitSource(className.replace(".class", ".java"), null);
    addConstructor(writer);
    // no real content (fields/methods) for now
    writer.visitEnd();
    return writer.toByteArray();
}
Also used : ZipEntry(java.util.zip.ZipEntry) ClassWriter(org.apache.xbean.asm9.ClassWriter)

Example 14 with ClassWriter

use of jodd.asm5.ClassWriter in project component-runtime by Talend.

the class ProxyGenerator method generateProxy.

public Class<?> generateProxy(final ClassLoader loader, final Class<?> classToProxy, final String plugin, final String key) {
    final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
    final String proxyClassName = fixPreservedPackages((classToProxy.getSigners() != null ? getSignedClassProxyName(classToProxy) : classToProxy.getName()) + "$$TalendServiceProxy");
    final String classFileName = proxyClassName.replace('.', '/');
    final String[] interfaceNames = { Type.getInternalName(Serializable.class) };
    final String superClassName = Type.getInternalName(classToProxy);
    cw.visit(findJavaVersion(classToProxy), ACC_PUBLIC + ACC_SUPER + ACC_SYNTHETIC, classFileName, null, superClassName, interfaceNames);
    cw.visitSource(classFileName + ".java", null);
    if (!Serializable.class.isAssignableFrom(classToProxy)) {
        try {
            classToProxy.getMethod("writeReplace");
        } catch (final NoSuchMethodException e) {
            createSerialisation(cw, plugin, key);
        }
    }
    final boolean hasInterceptors = hasInterceptors(classToProxy);
    if (hasInterceptors) {
        cw.visitField(ACC_PRIVATE, FIELD_INTERCEPTOR_HANDLER, Type.getDescriptor(InterceptorHandler.class), null, null).visitEnd();
        cw.visitField(ACC_PRIVATE | ACC_STATIC, FIELD_INTERCEPTED_METHODS, Type.getDescriptor(Method[].class), null, null).visitEnd();
    }
    createConstructor(cw, classToProxy, superClassName, classFileName, Stream.of(classToProxy.getDeclaredConstructors()).filter(c -> {
        final int modifiers = c.getModifiers();
        return Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers);
    }).sorted((o1, o2) -> {
        // prefer public constructor and then the smallest parameter count
        final int mod1 = o1.getModifiers();
        final int mod2 = o2.getModifiers();
        if (Modifier.isProtected(mod1) && !Modifier.isPublic(mod2)) {
            return 1;
        }
        if (Modifier.isProtected(mod2) && !Modifier.isPublic(mod1)) {
            return -1;
        }
        return o1.getParameterCount() - o2.getParameterCount();
    }).findFirst().orElseThrow(() -> new IllegalArgumentException(classToProxy + " has no default constructor, put at least a protected one")), hasInterceptors);
    final Method[] interceptedMethods;
    if (hasInterceptors) {
        final Collection<Annotation> globalInterceptors = Stream.of(classToProxy.getAnnotations()).filter(this::isInterceptor).collect(toList());
        final AtomicInteger methodIndex = new AtomicInteger();
        interceptedMethods = Stream.of(classToProxy.getMethods()).filter(m -> !"<init>".equals(m.getName()) && (!globalInterceptors.isEmpty() || Stream.of(m.getAnnotations()).anyMatch(this::isInterceptor))).peek(method -> delegateMethod(cw, method, classFileName, methodIndex.getAndIncrement())).toArray(Method[]::new);
    } else {
        interceptedMethods = null;
    }
    final Class<Object> objectClass = Unsafes.defineAndLoadClass(loader, proxyClassName, cw.toByteArray());
    if (hasInterceptors) {
        try {
            final Field interceptedMethodsField = objectClass.getDeclaredField(FIELD_INTERCEPTED_METHODS);
            interceptedMethodsField.setAccessible(true);
            interceptedMethodsField.set(null, interceptedMethods);
        } catch (final Exception e) {
            throw new IllegalStateException(e);
        }
    }
    return objectClass;
}
Also used : IRETURN(org.apache.xbean.asm9.Opcodes.IRETURN) Intercepts(org.talend.sdk.component.api.service.interceptor.Intercepts) ANEWARRAY(org.apache.xbean.asm9.Opcodes.ANEWARRAY) ACC_PROTECTED(org.apache.xbean.asm9.Opcodes.ACC_PROTECTED) LRETURN(org.apache.xbean.asm9.Opcodes.LRETURN) DUP(org.apache.xbean.asm9.Opcodes.DUP) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ClassReader(org.apache.xbean.asm9.ClassReader) MethodVisitor(org.apache.xbean.asm9.MethodVisitor) DLOAD(org.apache.xbean.asm9.Opcodes.DLOAD) Method(java.lang.reflect.Method) LLOAD(org.apache.xbean.asm9.Opcodes.LLOAD) ACC_SUPER(org.apache.xbean.asm9.Opcodes.ACC_SUPER) RETURN(org.apache.xbean.asm9.Opcodes.RETURN) ACC_PRIVATE(org.apache.xbean.asm9.Opcodes.ACC_PRIVATE) EmptyVisitor(org.apache.xbean.asm9.shade.commons.EmptyVisitor) Collection(java.util.Collection) AASTORE(org.apache.xbean.asm9.Opcodes.AASTORE) Serializable(java.io.Serializable) NEW(org.apache.xbean.asm9.Opcodes.NEW) FRETURN(org.apache.xbean.asm9.Opcodes.FRETURN) Stream(java.util.stream.Stream) GETSTATIC(org.apache.xbean.asm9.Opcodes.GETSTATIC) Modifier(java.lang.reflect.Modifier) Annotation(java.lang.annotation.Annotation) FLOAD(org.apache.xbean.asm9.Opcodes.FLOAD) SKIP_FRAMES(org.apache.xbean.asm9.ClassReader.SKIP_FRAMES) INVOKESTATIC(org.apache.xbean.asm9.Opcodes.INVOKESTATIC) ACONST_NULL(org.apache.xbean.asm9.Opcodes.ACONST_NULL) GETFIELD(org.apache.xbean.asm9.Opcodes.GETFIELD) INVOKESPECIAL(org.apache.xbean.asm9.Opcodes.INVOKESPECIAL) InterceptorHandlerFacade(org.talend.sdk.component.runtime.manager.interceptor.InterceptorHandlerFacade) InterceptorHandler(org.talend.sdk.component.api.service.interceptor.InterceptorHandler) V1_8(org.apache.xbean.asm9.Opcodes.V1_8) BIPUSH(org.apache.xbean.asm9.Opcodes.BIPUSH) POP(org.apache.xbean.asm9.Opcodes.POP) SKIP_DEBUG(org.apache.xbean.asm9.ClassReader.SKIP_DEBUG) IFEQ(org.apache.xbean.asm9.Opcodes.IFEQ) DRETURN(org.apache.xbean.asm9.Opcodes.DRETURN) ACC_VARARGS(org.apache.xbean.asm9.Opcodes.ACC_VARARGS) Constructor(java.lang.reflect.Constructor) Type(org.apache.xbean.asm9.Type) ACC_PUBLIC(org.apache.xbean.asm9.Opcodes.ACC_PUBLIC) ATHROW(org.apache.xbean.asm9.Opcodes.ATHROW) ACC_STATIC(org.apache.xbean.asm9.Opcodes.ACC_STATIC) PUTFIELD(org.apache.xbean.asm9.Opcodes.PUTFIELD) ClassWriter(org.apache.xbean.asm9.ClassWriter) ASTORE(org.apache.xbean.asm9.Opcodes.ASTORE) Label(org.apache.xbean.asm9.Label) Field(java.lang.reflect.Field) INVOKEVIRTUAL(org.apache.xbean.asm9.Opcodes.INVOKEVIRTUAL) AALOAD(org.apache.xbean.asm9.Opcodes.AALOAD) CHECKCAST(org.apache.xbean.asm9.Opcodes.CHECKCAST) SIPUSH(org.apache.xbean.asm9.Opcodes.SIPUSH) SKIP_CODE(org.apache.xbean.asm9.ClassReader.SKIP_CODE) INVOKEINTERFACE(org.apache.xbean.asm9.Opcodes.INVOKEINTERFACE) ObjectStreamException(java.io.ObjectStreamException) Collectors.toList(java.util.stream.Collectors.toList) ICONST_5(org.apache.xbean.asm9.Opcodes.ICONST_5) ILOAD(org.apache.xbean.asm9.Opcodes.ILOAD) ICONST_4(org.apache.xbean.asm9.Opcodes.ICONST_4) ICONST_3(org.apache.xbean.asm9.Opcodes.ICONST_3) ICONST_2(org.apache.xbean.asm9.Opcodes.ICONST_2) ICONST_1(org.apache.xbean.asm9.Opcodes.ICONST_1) ICONST_0(org.apache.xbean.asm9.Opcodes.ICONST_0) ALOAD(org.apache.xbean.asm9.Opcodes.ALOAD) AllArgsConstructor(lombok.AllArgsConstructor) ACC_SYNTHETIC(org.apache.xbean.asm9.Opcodes.ACC_SYNTHETIC) ARETURN(org.apache.xbean.asm9.Opcodes.ARETURN) InputStream(java.io.InputStream) Serializable(java.io.Serializable) Method(java.lang.reflect.Method) ClassWriter(org.apache.xbean.asm9.ClassWriter) Annotation(java.lang.annotation.Annotation) ObjectStreamException(java.io.ObjectStreamException) Field(java.lang.reflect.Field) AtomicInteger(java.util.concurrent.atomic.AtomicInteger)

Example 15 with ClassWriter

use of jodd.asm5.ClassWriter in project tomee by apache.

the class DynamicSubclass method generateBytes.

private static byte[] generateBytes(final Class<?> classToProxy, final boolean proxyNonAbstractMethods) throws ProxyGenerationException {
    final Map<String, MethodVisitor> visitors = new HashMap<>();
    final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
    final String proxyClassFileName = getSubclassName(classToProxy).replace('.', '/');
    final String classFileName = classToProxy.getName().replace('.', '/');
    cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, proxyClassFileName, null, classFileName, null);
    cw.visitSource(classFileName + ".java", null);
    // push InvocationHandler field
    cw.visitField(ACC_FINAL + ACC_PRIVATE, "this$handler", "Ljava/lang/reflect/InvocationHandler;", null, null).visitEnd();
    for (final Constructor<?> constructor : classToProxy.getConstructors()) {
        if (!Modifier.isPublic(constructor.getModifiers())) {
            continue;
        }
        final MethodVisitor mv = visitConstructor(cw, proxyClassFileName, classFileName, constructor);
        visitors.put("<init>" + Type.getConstructorDescriptor(constructor), mv);
    }
    final Map<String, List<Method>> methodMap = new HashMap<>();
    getNonPrivateMethods(classToProxy, methodMap);
    // Iterate over the public methods
    for (final Map.Entry<String, List<Method>> entry : methodMap.entrySet()) {
        for (final Method method : entry.getValue()) {
            if (Modifier.isAbstract(method.getModifiers()) || (proxyNonAbstractMethods && Modifier.isPublic(method.getModifiers()))) {
                final MethodVisitor visitor = LocalBeanProxyFactory.visit(cw, method, proxyClassFileName, "this$handler");
                visitors.put(method.getName() + Type.getMethodDescriptor(method), visitor);
            }
        }
    }
    copyClassAnnotations(classToProxy, cw);
    copyMethodAnnotations(classToProxy, visitors);
    // This should never be reached, but just in case
    for (final MethodVisitor visitor : visitors.values()) {
        visitor.visitEnd();
    }
    return cw.toByteArray();
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Arrays.asList(java.util.Arrays.asList) List(java.util.List) Method(java.lang.reflect.Method) HashMap(java.util.HashMap) Map(java.util.Map) ClassWriter(org.apache.xbean.asm9.ClassWriter) MethodVisitor(org.apache.xbean.asm9.MethodVisitor)

Aggregations

ClassWriter (org.apache.xbean.asm9.ClassWriter)17 MethodVisitor (org.apache.xbean.asm9.MethodVisitor)11 IOException (java.io.IOException)7 ClassReader (org.apache.xbean.asm9.ClassReader)7 File (java.io.File)6 InputStream (java.io.InputStream)6 JarOutputStream (java.util.jar.JarOutputStream)6 Stream (java.util.stream.Stream)6 ZipEntry (java.util.zip.ZipEntry)6 FileInputStream (java.io.FileInputStream)5 FileOutputStream (java.io.FileOutputStream)5 Optional.ofNullable (java.util.Optional.ofNullable)5 JarEntry (java.util.jar.JarEntry)5 JarLocation.jarLocation (org.apache.ziplock.JarLocation.jarLocation)5 Method (java.lang.reflect.Method)4 HashMap (java.util.HashMap)4 List (java.util.List)4 AnnotationVisitor (org.apache.xbean.asm9.AnnotationVisitor)4 EXPAND_FRAMES (org.apache.xbean.asm9.ClassReader.EXPAND_FRAMES)4 COMPUTE_FRAMES (org.apache.xbean.asm9.ClassWriter.COMPUTE_FRAMES)4