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;
}
}
}
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);
}
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);
}
}
}
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;
}
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);
}
}
Aggregations