Search in sources :

Example 11 with CannotCompileException

use of org.hotswap.agent.javassist.CannotCompileException in project HotswapAgent by HotswapProjects.

the class ClassInitPlugin method patch.

@OnClassLoadEvent(classNameRegexp = ".*", events = LoadEvent.REDEFINE)
public static void patch(final CtClass ctClass, final ClassLoader classLoader, final Class<?> originalClass) throws IOException, CannotCompileException, NotFoundException {
    if (isSyntheticClass(originalClass)) {
        return;
    }
    final String className = ctClass.getName();
    try {
        CtMethod origMethod = ctClass.getDeclaredMethod(HOTSWAP_AGENT_CLINIT_METHOD);
        ctClass.removeMethod(origMethod);
    } catch (org.hotswap.agent.javassist.NotFoundException ex) {
    // swallow
    }
    CtConstructor clinit = ctClass.getClassInitializer();
    if (clinit != null) {
        LOGGER.debug("Adding __ha_clinit to class: {}", className);
        CtConstructor haClinit = new CtConstructor(clinit, ctClass, null);
        haClinit.getMethodInfo().setName(HOTSWAP_AGENT_CLINIT_METHOD);
        haClinit.setModifiers(Modifier.PUBLIC | Modifier.STATIC);
        ctClass.addConstructor(haClinit);
        final boolean[] reinitializeStatics = new boolean[] { false };
        haClinit.instrument(new ExprEditor() {

            public void edit(FieldAccess f) throws CannotCompileException {
                try {
                    if (f.isStatic() && f.isWriter()) {
                        Field originalField = null;
                        try {
                            originalField = originalClass.getDeclaredField(f.getFieldName());
                        } catch (NoSuchFieldException e) {
                            LOGGER.debug("New field will be initialized {}", f.getFieldName());
                            reinitializeStatics[0] = true;
                        }
                        if (originalField != null) {
                            // ENUM$VALUES is last in enumeration
                            if (originalClass.isEnum() && "ENUM$VALUES".equals(f.getFieldName())) {
                                if (reinitializeStatics[0]) {
                                    LOGGER.debug("New field will be initialized {}", f.getFieldName());
                                } else {
                                    reinitializeStatics[0] = checkOldEnumValues(ctClass, originalClass);
                                }
                            } else {
                                LOGGER.debug("Skipping old field {}", f.getFieldName());
                                f.replace("{}");
                            }
                        }
                    }
                } catch (Exception e) {
                    LOGGER.error("Patching __ha_clinit method failed.", e);
                }
            }
        });
        if (reinitializeStatics[0]) {
            PluginManager.getInstance().getScheduler().scheduleCommand(new Command() {

                @Override
                public void executeCommand() {
                    try {
                        Class<?> clazz = classLoader.loadClass(className);
                        Method m = clazz.getDeclaredMethod(HOTSWAP_AGENT_CLINIT_METHOD, new Class[] {});
                        if (m != null) {
                            m.invoke(null, new Object[] {});
                        }
                    } catch (Exception e) {
                        LOGGER.error("Error initializing redefined class {}", e, className);
                    } finally {
                        reloadFlag = false;
                    }
                }
            }, // Hack : init should be done after dependant class redefinition. Since the class can
            150);
        // be proxied by syntetic proxy, the class init must be scheduled after proxy redefinition.
        // Currently proxy redefinition (in ProxyPlugin) is scheduled with 100ms delay, therefore
        // the class init must be scheduled after it.
        } else {
            reloadFlag = false;
        }
    }
}
Also used : CannotCompileException(org.hotswap.agent.javassist.CannotCompileException) CtMethod(org.hotswap.agent.javassist.CtMethod) Method(java.lang.reflect.Method) CannotCompileException(org.hotswap.agent.javassist.CannotCompileException) IOException(java.io.IOException) NotFoundException(org.hotswap.agent.javassist.NotFoundException) CtConstructor(org.hotswap.agent.javassist.CtConstructor) Field(java.lang.reflect.Field) CtField(org.hotswap.agent.javassist.CtField) Command(org.hotswap.agent.command.Command) NotFoundException(org.hotswap.agent.javassist.NotFoundException) ExprEditor(org.hotswap.agent.javassist.expr.ExprEditor) CtClass(org.hotswap.agent.javassist.CtClass) FieldAccess(org.hotswap.agent.javassist.expr.FieldAccess) CtMethod(org.hotswap.agent.javassist.CtMethod) OnClassLoadEvent(org.hotswap.agent.annotation.OnClassLoadEvent)

Example 12 with CannotCompileException

use of org.hotswap.agent.javassist.CannotCompileException in project HotswapAgent by HotswapProjects.

the class ClassLoaderDefineClassPatcher method patch.

@Override
public void patch(final ClassLoader classLoaderFrom, final String pluginPath, final ClassLoader classLoaderTo, final ProtectionDomain protectionDomain) {
    List<byte[]> cache = getPluginCache(classLoaderFrom, pluginPath);
    if (cache != null) {
        final ClassPool cp = new ClassPool();
        cp.appendClassPath(new LoaderClassPath(getClass().getClassLoader()));
        for (byte[] pluginBytes : cache) {
            CtClass pluginClass = null;
            try {
                // force to load class in classLoaderFrom (it may not yet be loaded) and if the classLoaderTo
                // is parent of classLoaderFrom, after definition in classLoaderTo will classLoaderFrom return
                // class from parent classloader instead own definition (hence change of behaviour).
                InputStream is = new ByteArrayInputStream(pluginBytes);
                pluginClass = cp.makeClass(is);
                try {
                    classLoaderFrom.loadClass(pluginClass.getName());
                } catch (NoClassDefFoundError e) {
                    LOGGER.trace("Skipping class loading {} in classloader {} - " + "class has probably unresolvable dependency.", pluginClass.getName(), classLoaderTo);
                }
                // and load the class in classLoaderTo as well. NOw the class is defined in BOTH classloaders.
                pluginClass.toClass(classLoaderTo, protectionDomain);
            } catch (CannotCompileException e) {
                LOGGER.trace("Skipping class definition {} in app classloader {} - " + "class is probably already defined.", pluginClass.getName(), classLoaderTo);
            } catch (NoClassDefFoundError e) {
                LOGGER.trace("Skipping class definition {} in app classloader {} - " + "class has probably unresolvable dependency.", pluginClass.getName(), classLoaderTo);
            } catch (Throwable e) {
                LOGGER.trace("Skipping class definition app classloader {} - " + "unknown error.", e, classLoaderTo);
            }
        }
    }
    LOGGER.debug("Classloader {} patched with plugin classes from agent classloader {}.", classLoaderTo, classLoaderFrom);
}
Also used : CtClass(org.hotswap.agent.javassist.CtClass) ByteArrayInputStream(java.io.ByteArrayInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) ClassPool(org.hotswap.agent.javassist.ClassPool) LoaderClassPath(org.hotswap.agent.javassist.LoaderClassPath) CannotCompileException(org.hotswap.agent.javassist.CannotCompileException)

Example 13 with CannotCompileException

use of org.hotswap.agent.javassist.CannotCompileException in project HotswapAgent by HotswapProjects.

the class TransformAccessArrayField method initialize.

public void initialize(ConstPool cp, CtClass clazz, MethodInfo minfo) throws CannotCompileException {
    /*
         * This transformer must be isolated from other transformers, since some
         * of them affect the local variable and stack maximums without updating
         * the code attribute to reflect the changes. This screws up the
         * data-flow analyzer, since it relies on consistent code state. Even
         * if the attribute values were updated correctly, we would have to
         * detect it, and redo analysis, which is not cheap. Instead, we are
         * better off doing all changes in initialize() before everyone else has
         * a chance to muck things up.
         */
    CodeIterator iterator = minfo.getCodeAttribute().iterator();
    while (iterator.hasNext()) {
        try {
            int pos = iterator.next();
            int c = iterator.byteAt(pos);
            if (c == AALOAD)
                initFrames(clazz, minfo);
            if (c == AALOAD || c == BALOAD || c == CALOAD || c == DALOAD || c == FALOAD || c == IALOAD || c == LALOAD || c == SALOAD) {
                pos = replace(cp, iterator, pos, c, getLoadReplacementSignature(c));
            } else if (c == AASTORE || c == BASTORE || c == CASTORE || c == DASTORE || c == FASTORE || c == IASTORE || c == LASTORE || c == SASTORE) {
                pos = replace(cp, iterator, pos, c, getStoreReplacementSignature(c));
            }
        } catch (Exception e) {
            throw new CannotCompileException(e);
        }
    }
}
Also used : CodeIterator(org.hotswap.agent.javassist.bytecode.CodeIterator) CannotCompileException(org.hotswap.agent.javassist.CannotCompileException) NotFoundException(org.hotswap.agent.javassist.NotFoundException) CannotCompileException(org.hotswap.agent.javassist.CannotCompileException)

Example 14 with CannotCompileException

use of org.hotswap.agent.javassist.CannotCompileException in project HotswapAgent by HotswapProjects.

the class TransformNew method transform.

/**
 * Replace a sequence of
 *    NEW classname
 *    DUP
 *    ...
 *    INVOKESPECIAL
 * with
 *    NOP
 *    NOP
 *    ...
 *    INVOKESTATIC trapMethod in trapClass
 */
public int transform(CtClass clazz, int pos, CodeIterator iterator, ConstPool cp) throws CannotCompileException {
    int index;
    int c = iterator.byteAt(pos);
    if (c == NEW) {
        index = iterator.u16bitAt(pos + 1);
        if (cp.getClassInfo(index).equals(classname)) {
            if (iterator.byteAt(pos + 3) != DUP)
                throw new CannotCompileException("NEW followed by no DUP was found");
            iterator.writeByte(NOP, pos);
            iterator.writeByte(NOP, pos + 1);
            iterator.writeByte(NOP, pos + 2);
            iterator.writeByte(NOP, pos + 3);
            ++nested;
            StackMapTable smt = (StackMapTable) iterator.get().getAttribute(StackMapTable.tag);
            if (smt != null)
                smt.removeNew(pos);
            StackMap sm = (StackMap) iterator.get().getAttribute(StackMap.tag);
            if (sm != null)
                sm.removeNew(pos);
        }
    } else if (c == INVOKESPECIAL) {
        index = iterator.u16bitAt(pos + 1);
        int typedesc = cp.isConstructor(classname, index);
        if (typedesc != 0 && nested > 0) {
            int methodref = computeMethodref(typedesc, cp);
            iterator.writeByte(INVOKESTATIC, pos);
            iterator.write16bit(methodref, pos + 1);
            --nested;
        }
    }
    return pos;
}
Also used : CannotCompileException(org.hotswap.agent.javassist.CannotCompileException)

Example 15 with CannotCompileException

use of org.hotswap.agent.javassist.CannotCompileException in project HotswapAgent by HotswapProjects.

the class DefineClassHelper method toClass2.

/**
 * Loads a class file by {@code java.lang.invoke.MethodHandles.Lookup}.
 *
 * @since 3.22
 */
/* TODO: HotswapAgent
    static Class<?> toPublicClass(String className, byte[] bcode)
        throws CannotCompileException
    {
        try {
            Lookup lookup = MethodHandles.lookup();
            lookup = lookup.dropLookupMode(java.lang.invoke.MethodHandles.Lookup.PRIVATE);
            return lookup.defineClass(bcode);
        }
        catch (Throwable t) {
            throw new CannotCompileException(t);
        }
    }
    */
private static Class<?> toClass2(String cname, ClassLoader loader, ProtectionDomain domain, byte[] bcode) throws CannotCompileException {
    try {
        Method method;
        Object[] args;
        if (domain == null) {
            method = defineClass1;
            args = new Object[] { cname, bcode, Integer.valueOf(0), Integer.valueOf(bcode.length) };
        } else {
            method = defineClass2;
            args = new Object[] { cname, bcode, Integer.valueOf(0), Integer.valueOf(bcode.length), domain };
        }
        return toClass3(method, loader, args);
    } catch (RuntimeException e) {
        throw e;
    } catch (java.lang.reflect.InvocationTargetException e) {
        throw new CannotCompileException(e.getTargetException());
    } catch (Exception e) {
        throw new CannotCompileException(e);
    }
}
Also used : Method(java.lang.reflect.Method) CannotCompileException(org.hotswap.agent.javassist.CannotCompileException) CannotCompileException(org.hotswap.agent.javassist.CannotCompileException) IOException(java.io.IOException)

Aggregations

CannotCompileException (org.hotswap.agent.javassist.CannotCompileException)23 CtMethod (org.hotswap.agent.javassist.CtMethod)11 NotFoundException (org.hotswap.agent.javassist.NotFoundException)9 OnClassLoadEvent (org.hotswap.agent.annotation.OnClassLoadEvent)8 CtClass (org.hotswap.agent.javassist.CtClass)7 ExprEditor (org.hotswap.agent.javassist.expr.ExprEditor)6 CtField (org.hotswap.agent.javassist.CtField)4 MethodCall (org.hotswap.agent.javassist.expr.MethodCall)4 IOException (java.io.IOException)3 Method (java.lang.reflect.Method)3 ArrayList (java.util.ArrayList)2 ClassPool (org.hotswap.agent.javassist.ClassPool)2 CtConstructor (org.hotswap.agent.javassist.CtConstructor)2 LoaderClassPath (org.hotswap.agent.javassist.LoaderClassPath)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 InputStream (java.io.InputStream)1 Field (java.lang.reflect.Field)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 ProtectionDomain (java.security.ProtectionDomain)1 LoadEvent (org.hotswap.agent.annotation.LoadEvent)1