Search in sources :

Example 1 with AsmException

use of act.asm.AsmException 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 AsmException

use of act.asm.AsmException 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)

Aggregations

EnvMatcher (act.app.util.EnvMatcher)2 AsmException (act.asm.AsmException)2 ClassReader (act.asm.ClassReader)2 EnvNotMatchException (act.exception.EnvNotMatchException)2 ClassWriter (act.asm.ClassWriter)1 ActErrorResult (act.view.ActErrorResult)1 org.osgl.$ (org.osgl.$)1