Search in sources :

Example 1 with ClassReader

use of act.asm.ClassReader in project actframework by actframework.

the class AppClassLoader method asmEnhance.

private byte[] asmEnhance(String className, byte[] bytecode) {
    if (!enhanceEligible(className))
        return bytecode;
    $.Var<ClassWriter> cw = $.var(null);
    ByteCodeVisitor enhancer = Act.enhancerManager().appEnhancer(app, className, cw);
    if (null == enhancer) {
        return bytecode;
    }
    EnvMatcher matcher = new EnvMatcher();
    matcher.setDownstream(enhancer);
    cw.set(new ClassWriter(ClassWriter.COMPUTE_FRAMES));
    enhancer.commitDownstream();
    ClassReader r = new ClassReader(bytecode);
    try {
        r.accept(matcher, ClassReader.EXPAND_FRAMES);
    } catch (EnvNotMatchException e) {
        return bytecode;
    } catch (AsmException e) {
        logger.error(e, "error enhancing bytecode at %s", e.context());
        throw ActErrorResult.enhancingError(e);
    }
    return cw.get().toByteArray();
}
Also used : EnvMatcher(act.app.util.EnvMatcher) EnvNotMatchException(act.exception.EnvNotMatchException) org.osgl.$(org.osgl.$) ClassReader(act.asm.ClassReader) AsmException(act.asm.AsmException) ClassWriter(act.asm.ClassWriter)

Example 2 with ClassReader

use of act.asm.ClassReader in project actframework by actframework.

the class AppClassLoader method scanByteCode.

/**
 * This method implement a event listener based scan process:
 * <ol>
 * <li>First loop: through all cached bytecode. Chain all scanner's bytecode visitor</li>
 * <li>Rest loops: through dependencies. Thus if some bytecode missed by a certain scanner
 * due to the context is not established can be captured eventually</li>
 * </ol>
 */
protected void scanByteCode(Iterable<String> classes, $.Function<String, byte[]> bytecodeProvider) {
    logger.debug("start to scan bytecode ...");
    final AppCodeScannerManager scannerManager = app().scannerManager();
    Map<String, List<AppByteCodeScanner>> dependencies = new HashMap<>();
    for (String className : classes) {
        logger.debug("scanning %s ...", className);
        dependencies.remove(className);
        byte[] ba = bytecodeProvider.apply(className);
        if (null == ba) {
            logger.warn("Cannot find any bytecode for class: %s. You might have an empty Java source file for that.", className);
            continue;
        }
        libClsCache.put(className, ba);
        act.metric.Timer timer = metric.startTimer("act:classload:scan:bytecode:" + className);
        List<ByteCodeVisitor> visitors = new ArrayList<>();
        List<AppByteCodeScanner> scanners = new ArrayList<>();
        for (AppByteCodeScanner scanner : scannerManager.byteCodeScanners()) {
            if (scanner.start(className)) {
                // LOGGER.trace("scanner %s added to the list", scanner.getClass().getName());
                visitors.add(scanner.byteCodeVisitor());
                scanners.add(scanner);
            }
        }
        if (visitors.isEmpty()) {
            continue;
        }
        ByteCodeVisitor theVisitor = ByteCodeVisitor.chain(visitors);
        EnvMatcher matcher = new EnvMatcher();
        matcher.setDownstream(theVisitor);
        ClassReader cr = new ClassReader(ba);
        try {
            cr.accept(matcher, 0);
        } catch (EnvNotMatchException e) {
            continue;
        } catch (AsmException e) {
            Throwable t = e.getCause();
            if (t instanceof ClassNotFoundException) {
                continue;
            } else {
                logger.error(e, "Error scanning bytecode at %s", e.context());
                ActErrorResult error = ActErrorResult.scanningError(e);
                if (Act.isDev()) {
                    app.setBlockIssue(error);
                } else {
                    throw error;
                }
            }
        }
        for (AppByteCodeScanner scanner : scanners) {
            scanner.scanFinished(className);
            Map<Class<? extends AppByteCodeScanner>, Set<String>> ss = scanner.dependencyClasses();
            if (ss.isEmpty()) {
                // LOGGER.trace("no dependencies found for %s by scanner %s", className, scanner);
                continue;
            }
            for (Class<? extends AppByteCodeScanner> scannerClass : ss.keySet()) {
                AppByteCodeScanner scannerA = scannerManager.byteCodeScannerByClass(scannerClass);
                for (String dependencyClass : ss.get(scannerClass)) {
                    logger.trace("dependencies[%s] found for %s by scanner %s", dependencyClass, className, scannerA);
                    List<AppByteCodeScanner> l = dependencies.get(dependencyClass);
                    if (null == l) {
                        l = new ArrayList<>();
                        dependencies.put(dependencyClass, l);
                    }
                    if (!l.contains(scanner))
                        l.add(scannerA);
                }
            }
        }
        timer.stop();
    }
    // loop through dependencies until it's all processed
    while (!dependencies.isEmpty()) {
        String className = dependencies.keySet().iterator().next();
        act.metric.Timer timer = metric.startTimer("act:classload:scan:bytecode:" + className);
        List<AppByteCodeScanner> scanners = dependencies.remove(className);
        List<ByteCodeVisitor> visitors = new ArrayList<>();
        for (AppByteCodeScanner scanner : scanners) {
            scanner.start(className);
            visitors.add(scanner.byteCodeVisitor());
        }
        ByteCodeVisitor theVisitor = ByteCodeVisitor.chain(visitors);
        byte[] bytes = bytecodeProvider.apply(className);
        libClsCache.put(className, bytes);
        ClassReader cr = new ClassReader(bytes);
        try {
            cr.accept(theVisitor, 0);
        } catch (AsmException e) {
            throw ActErrorResult.of(e);
        }
        for (AppByteCodeScanner scanner : scanners) {
            scanner.scanFinished(className);
            Map<Class<? extends AppByteCodeScanner>, Set<String>> ss = scanner.dependencyClasses();
            if (ss.isEmpty()) {
                logger.trace("no dependencies found for %s by scanner %s", className, scanner);
                continue;
            }
            for (Class<? extends AppByteCodeScanner> scannerClass : ss.keySet()) {
                AppByteCodeScanner scannerA = scannerManager.byteCodeScannerByClass(scannerClass);
                for (String dependencyClass : ss.get(scannerClass)) {
                    logger.trace("dependencies[%s] found for %s by scanner %s", dependencyClass, className, scannerA);
                    List<AppByteCodeScanner> l = dependencies.get(dependencyClass);
                    if (null == l) {
                        l = new ArrayList<>();
                        dependencies.put(dependencyClass, l);
                    }
                    if (!l.contains(scanner))
                        l.add(scannerA);
                }
            }
        }
        timer.stop();
    }
}
Also used : EnvNotMatchException(act.exception.EnvNotMatchException) ActErrorResult(act.view.ActErrorResult) AsmException(act.asm.AsmException) EnvMatcher(act.app.util.EnvMatcher) ClassReader(act.asm.ClassReader)

Example 3 with ClassReader

use of act.asm.ClassReader in project actframework by actframework.

the class ServerBootstrapClassLoader method loadActClass.

protected Class<?> loadActClass(String name, boolean resolve, boolean pluginOnly) {
    boolean fromPlugin = false;
    byte[] ba = pluginBC.remove(name);
    if (null == ba) {
        if (!pluginOnly) {
            ba = libBC.remove(name);
        }
    } else {
        fromPlugin = true;
    }
    if (null == ba) {
        ba = tryLoadResource(name);
    }
    if (null == ba) {
        if (pluginOnly) {
            return findLoadedClass(name);
        }
        return null;
    }
    Class<?> c = null;
    if (!name.startsWith(ACT_PKG) || name.startsWith(ASM_PKG)) {
        // skip bytecode enhancement for asm classes or non Act classes
        c = super.defineClass(name, ba, 0, ba.length, DOMAIN);
    }
    if (null == c) {
        $.Var<ClassWriter> cw = $.val(null);
        ByteCodeVisitor enhancer = Act.enhancerManager().generalEnhancer(name, cw);
        if (null == enhancer) {
            c = super.defineClass(name, ba, 0, ba.length, DOMAIN);
        } else {
            ClassWriter w = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
            cw.set(w);
            enhancer.commitDownstream();
            ClassReader r;
            r = new ClassReader(ba);
            try {
                r.accept(enhancer, 0);
                byte[] baNew = w.toByteArray();
                c = super.defineClass(name, baNew, 0, baNew.length, DOMAIN);
            } catch (RuntimeException e) {
                throw e;
            } catch (Error e) {
                throw e;
            } catch (Exception e) {
                throw E.unexpected("Error processing class " + name);
            }
        }
    }
    if (resolve) {
        super.resolveClass(c);
    }
    return c;
}
Also used : ByteCodeVisitor(act.util.ByteCodeVisitor) org.osgl.$(org.osgl.$) ClassReader(act.asm.ClassReader) ClassWriter(act.asm.ClassWriter)

Example 4 with ClassReader

use of act.asm.ClassReader in project actframework by actframework.

the class BootstrapClassLoader method defineClass.

protected Class<?> defineClass(String name, byte[] ba) {
    Class<?> c = null;
    $.Var<ClassWriter> cw = $.val(null);
    ByteCodeVisitor enhancer = enhancerManager.generalEnhancer(name, cw);
    if (null == enhancer) {
        c = defineClassX(name, ba, 0, ba.length, DOMAIN);
    } else {
        Exception exception = null;
        ClassWriter w = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
        cw.set(w);
        enhancer.commitDownstream();
        ClassReader r;
        r = new ClassReader(ba);
        try {
            r.accept(enhancer, 0);
            byte[] baNew = w.toByteArray();
            c = defineClassX(name, baNew, 0, baNew.length, DOMAIN);
        } catch (Error e) {
            throw e;
        } catch (Exception e) {
            exception = e;
        }
        if (null != exception) {
            logger.error(exception, "Error enhancing class %s", name);
            throw E.unexpected(exception);
        }
    }
    return c;
}
Also used : ByteCodeVisitor(act.util.ByteCodeVisitor) org.osgl.$(org.osgl.$) ClassReader(act.asm.ClassReader) ClassWriter(act.asm.ClassWriter) IOException(java.io.IOException)

Aggregations

ClassReader (act.asm.ClassReader)4 ClassWriter (act.asm.ClassWriter)3 org.osgl.$ (org.osgl.$)3 EnvMatcher (act.app.util.EnvMatcher)2 AsmException (act.asm.AsmException)2 EnvNotMatchException (act.exception.EnvNotMatchException)2 ByteCodeVisitor (act.util.ByteCodeVisitor)2 ActErrorResult (act.view.ActErrorResult)1 IOException (java.io.IOException)1