use of com.oracle.truffle.espresso.impl.ObjectKlass in project graal by oracle.
the class InnerClassRedefiner method findLoadedInnerClasses.
Set<ObjectKlass> findLoadedInnerClasses(Klass klass) {
// we use a cache to store inner/outer class mappings
Map<Symbol<Symbol.Type>, Set<ObjectKlass>> classLoaderMap = innerKlassCache.get(klass.getDefiningClassLoader());
if (classLoaderMap == null) {
classLoaderMap = new HashMap<>();
// register a listener on the registry to fill in
// future loaded anonymous inner classes
ClassRegistry classRegistry = context.getRegistries().getClassRegistry(klass.getDefiningClassLoader());
classRegistry.registerOnLoadListener(new DefineKlassListener() {
@Override
public void onKlassDefined(ObjectKlass objectKlass) {
InnerClassRedefiner.this.onKlassDefined(objectKlass);
}
});
// do a one-time look up of all currently loaded
// classes for this loader and fill in the map
List<Klass> loadedKlasses = classRegistry.getLoadedKlasses();
for (Klass loadedKlass : loadedKlasses) {
if (loadedKlass instanceof ObjectKlass) {
ObjectKlass objectKlass = (ObjectKlass) loadedKlass;
Matcher matcher = ANON_INNER_CLASS_PATTERN.matcher(loadedKlass.getNameAsString());
if (matcher.matches()) {
Symbol<Symbol.Name> outerClassName = getOuterClassName(loadedKlass.getName());
if (outerClassName != null && outerClassName.length() > 0) {
Symbol<Symbol.Type> outerType = context.getTypes().fromName(outerClassName);
Set<ObjectKlass> innerKlasses = classLoaderMap.get(outerType);
if (innerKlasses == null) {
innerKlasses = new HashSet<>(1);
classLoaderMap.put(outerType, innerKlasses);
}
innerKlasses.add(objectKlass);
}
}
}
}
// add to cache
innerKlassCache.put(klass.getDefiningClassLoader(), classLoaderMap);
}
Set<ObjectKlass> innerClasses = classLoaderMap.get(klass.getType());
return innerClasses != null ? innerClasses : new HashSet<>(0);
}
use of com.oracle.truffle.espresso.impl.ObjectKlass in project graal by oracle.
the class InnerClassRedefiner method onKlassDefined.
private void onKlassDefined(ObjectKlass klass) {
Matcher matcher = ANON_INNER_CLASS_PATTERN.matcher(klass.getNameAsString());
if (matcher.matches()) {
Map<Symbol<Symbol.Type>, Set<ObjectKlass>> classLoaderMap = innerKlassCache.get(klass.getDefiningClassLoader());
// found inner class, now hunt down the outer
Symbol<Symbol.Name> outerName = getOuterClassName(klass.getName());
Symbol<Symbol.Type> outerType = context.getTypes().fromName(outerName);
Set<ObjectKlass> innerKlasses = classLoaderMap.get(outerType);
if (innerKlasses == null) {
innerKlasses = new HashSet<>(1);
classLoaderMap.put(outerType, innerKlasses);
}
innerKlasses.add(klass);
}
}
use of com.oracle.truffle.espresso.impl.ObjectKlass in project graal by oracle.
the class ClassRedefinition method redefineClass.
public int redefineClass(ChangePacket packet, List<ObjectKlass> invalidatedClasses, List<ObjectKlass> redefinedClasses) {
try {
switch(packet.classChange) {
case METHOD_BODY_CHANGE:
case CONSTANT_POOL_CHANGE:
case CLASS_NAME_CHANGED:
case ADD_METHOD:
case REMOVE_METHOD:
case SCHEMA_CHANGE:
doRedefineClass(packet, invalidatedClasses, redefinedClasses);
return 0;
case CLASS_HIERARCHY_CHANGED:
context.markChangedHierarchy();
doRedefineClass(packet, invalidatedClasses, redefinedClasses);
return 0;
case NEW_CLASS:
ClassInfo classInfo = packet.info;
// if there is a currently loaded class under that name
// we have to replace that in the class loader registry etc.
// otherwise, don't eagerly define the new class
Symbol<Symbol.Type> type = context.getTypes().fromName(classInfo.getName());
ClassRegistry classRegistry = context.getRegistries().getClassRegistry(classInfo.getClassLoader());
Klass loadedKlass = classRegistry.findLoadedKlass(type);
if (loadedKlass != null) {
// OK, we have to define the new klass instance and
// inject it under the existing JDWP ID
classRegistry.onInnerClassRemoved(type);
ObjectKlass newKlass = classRegistry.defineKlass(type, classInfo.getBytes());
packet.info.setKlass(newKlass);
}
return 0;
default:
return 0;
}
} catch (EspressoException ex) {
// we get from parsing the class file
return ErrorCodes.INVALID_CLASS_FORMAT;
}
}
use of com.oracle.truffle.espresso.impl.ObjectKlass in project graal by oracle.
the class ClassRedefinition method doRedefineClass.
private void doRedefineClass(ChangePacket packet, List<ObjectKlass> invalidatedClasses, List<ObjectKlass> redefinedClasses) {
ObjectKlass oldKlass = packet.info.getKlass();
if (packet.info.isRenamed()) {
// renaming a class is done by
// 1. Rename the 'name' and 'type' Symbols in the Klass
// 2. Update the loaded class cache in the associated ClassRegistry
// 3. Set the guest language java.lang.Class#name field to null
// 4. update the JDWP refType ID for the klass instance
// 5. replace/record a classloader constraint for the new type and klass combination
Symbol<Symbol.Name> newName = packet.info.getName();
Symbol<Symbol.Type> newType = context.getTypes().fromName(newName);
oldKlass.patchClassName(newName, newType);
ClassRegistry classRegistry = context.getRegistries().getClassRegistry(packet.info.getClassLoader());
classRegistry.onClassRenamed(oldKlass);
InterpreterToVM.setFieldObject(StaticObject.NULL, oldKlass.mirror(), context.getMeta().java_lang_Class_name);
}
if (packet.classChange == ClassChange.CLASS_HIERARCHY_CHANGED) {
oldKlass.removeAsSubType();
}
oldKlass.redefineClass(packet, invalidatedClasses, ids);
redefinedClasses.add(oldKlass);
if (redefineListener.shouldRerunClassInitializer(oldKlass, packet.detectedChange.clinitChanged())) {
context.rerunclinit(oldKlass);
}
}
use of com.oracle.truffle.espresso.impl.ObjectKlass in project graal by oracle.
the class ClassRedefinition method getLoadedKlass.
private static Klass getLoadedKlass(Symbol<Symbol.Type> klassType, ObjectKlass oldKlass) throws RedefintionNotSupportedException {
Klass klass;
klass = oldKlass.getContext().getRegistries().findLoadedClass(klassType, oldKlass.getDefiningClassLoader());
if (klass == null) {
// new super interface must be loaded eagerly then
StaticObject resourceGuestString = oldKlass.getMeta().toGuestString(Types.binaryName(klassType));
try {
StaticObject loadedClass = (StaticObject) oldKlass.getMeta().java_lang_ClassLoader_loadClass.invokeDirect(oldKlass.getDefiningClassLoader(), resourceGuestString);
klass = loadedClass.getMirrorKlass();
} catch (Throwable t) {
throw new RedefintionNotSupportedException(ErrorCodes.ABSENT_INFORMATION);
}
}
return klass;
}
Aggregations