use of org.hotswap.agent.javassist.CtClass in project HotswapAgent by HotswapProjects.
the class HotswapperPlugin method watchReload.
/**
* For each changed class create a reload command.
*/
@OnClassFileEvent(classNameRegexp = ".*", events = { FileEvent.MODIFY, FileEvent.CREATE })
public void watchReload(CtClass ctClass, ClassLoader appClassLoader, URL url) throws IOException, CannotCompileException {
if (!ClassLoaderHelper.isClassLoaded(appClassLoader, ctClass.getName())) {
LOGGER.trace("Class {} not loaded yet, no need for autoHotswap, skipped URL {}", ctClass.getName(), url);
return;
}
LOGGER.debug("Class {} will be reloaded from URL {}", ctClass.getName(), url);
// search for a class to reload
Class clazz;
try {
clazz = appClassLoader.loadClass(ctClass.getName());
} catch (ClassNotFoundException e) {
LOGGER.warning("Hotswapper tries to reload class {}, which is not known to application classLoader {}.", ctClass.getName(), appClassLoader);
return;
}
synchronized (reloadMap) {
reloadMap.put(clazz, ctClass.toBytecode());
}
scheduler.scheduleCommand(hotswapCommand, 100, Scheduler.DuplicateSheduleBehaviour.SKIP);
}
use of org.hotswap.agent.javassist.CtClass in project HotswapAgent by HotswapProjects.
the class AnonymousClassInfo method getMethodSignature.
private void getMethodSignature(StringBuilder methodsSignature, CtMethod m) throws NotFoundException {
methodsSignature.append(m.getReturnType().getName());
methodsSignature.append(" ");
methodsSignature.append(m.getName());
methodsSignature.append("(");
for (CtClass paramType : m.getParameterTypes()) methodsSignature.append(paramType.getName());
methodsSignature.append(")");
methodsSignature.append(";");
}
use of org.hotswap.agent.javassist.CtClass 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;
}
}
}
use of org.hotswap.agent.javassist.CtClass in project HotswapAgent by HotswapProjects.
the class HotSwapper method swapClasses.
/**
* Swap class definition from another class file.
* <p/>
* This is mainly useful for unit testing - declare multiple version of a class and then
* hotswap definition and do the tests.
*
* @param original original class currently in use
* @param swap fully qualified class name of class to swap
* @throws Exception swap exception
*/
public static void swapClasses(Class original, String swap) throws Exception {
// need to recreate classpool on each swap to avoid stale class definition
ClassPool classPool = new ClassPool();
classPool.appendClassPath(new LoaderClassPath(original.getClassLoader()));
CtClass ctClass = classPool.getAndRename(swap, original.getName());
reload(original, ctClass.toBytecode());
}
use of org.hotswap.agent.javassist.CtClass in project HotswapAgent by HotswapProjects.
the class HotSwapper method newClass.
public static Class newClass(String className, String directory, ClassLoader cl) {
try {
ClassPool classPool = new ClassPool();
classPool.appendClassPath(new LoaderClassPath(cl));
CtClass makeClass = classPool.makeClass(className);
makeClass.writeFile(directory);
return makeClass.toClass();
} catch (Throwable ex) {
Logger.getLogger(HotSwapper.class.getName()).log(Level.SEVERE, null, ex);
throw new RuntimeException(ex);
}
}
Aggregations