Search in sources :

Example 6 with ExprEditor

use of org.hotswap.agent.javassist.expr.ExprEditor 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)

Aggregations

CannotCompileException (org.hotswap.agent.javassist.CannotCompileException)6 CtMethod (org.hotswap.agent.javassist.CtMethod)6 ExprEditor (org.hotswap.agent.javassist.expr.ExprEditor)6 OnClassLoadEvent (org.hotswap.agent.annotation.OnClassLoadEvent)5 CtClass (org.hotswap.agent.javassist.CtClass)4 MethodCall (org.hotswap.agent.javassist.expr.MethodCall)4 Method (java.lang.reflect.Method)2 CtConstructor (org.hotswap.agent.javassist.CtConstructor)2 CtField (org.hotswap.agent.javassist.CtField)2 NotFoundException (org.hotswap.agent.javassist.NotFoundException)2 IOException (java.io.IOException)1 Field (java.lang.reflect.Field)1 Command (org.hotswap.agent.command.Command)1 PluginManager (org.hotswap.agent.config.PluginManager)1 FieldAccess (org.hotswap.agent.javassist.expr.FieldAccess)1 NewExpr (org.hotswap.agent.javassist.expr.NewExpr)1 WeldPlugin (org.hotswap.agent.plugin.weld.WeldPlugin)1