use of com.oracle.truffle.espresso.impl.ClassRegistry 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.ClassRegistry 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.ClassRegistry 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.ClassRegistry in project graal by oracle.
the class VM method defineModule.
@SuppressWarnings("try")
public void defineModule(StaticObject module, String moduleName, boolean is_open, String[] packages, SubstitutionProfiler profiler) {
Meta meta = getMeta();
StaticObject loader = meta.java_lang_Module_loader.getObject(module);
if (loader != nonReflectionClassLoader(loader)) {
profiler.profile(15);
throw meta.throwExceptionWithMessage(meta.java_lang_IllegalArgumentException, "Class loader is an invalid delegating class loader");
}
// Prepare variables
ClassRegistry registry = getRegistries().getClassRegistry(loader);
assert registry != null;
PackageTable packageTable = registry.packages();
ModuleTable moduleTable = registry.modules();
assert moduleTable != null && packageTable != null;
boolean loaderIsBootOrPlatform = ClassRegistry.loaderIsBootOrPlatform(loader, meta);
ArrayList<Symbol<Name>> pkgSymbols = new ArrayList<>();
try (EntryTable.BlockLock block = packageTable.write()) {
for (String str : packages) {
// Extract the package symbols. Also checks for duplicates.
if (!loaderIsBootOrPlatform && (str.equals("java") || str.startsWith("java/"))) {
// Only modules defined to either the boot or platform class loader, can define
// a "java/" package.
profiler.profile(14);
throw meta.throwExceptionWithMessage(meta.java_lang_IllegalArgumentException, cat("Class loader (", loader.getKlass().getType(), ") tried to define prohibited package name: ", str));
}
Symbol<Name> symbol = getNames().getOrCreate(str);
if (packageTable.lookup(symbol) != null) {
profiler.profile(13);
throw meta.throwExceptionWithMessage(meta.java_lang_IllegalArgumentException, cat("Package ", str, " is already defined."));
}
pkgSymbols.add(symbol);
}
Symbol<Name> moduleSymbol = getNames().getOrCreate(moduleName);
// Try define module
ModuleEntry moduleEntry = moduleTable.createAndAddEntry(moduleSymbol, registry, is_open, module);
if (moduleEntry == null) {
// Module already defined
profiler.profile(12);
throw meta.throwExceptionWithMessage(meta.java_lang_IllegalArgumentException, cat("Module ", moduleName, " is already defined"));
}
// Register packages
for (Symbol<Name> pkgSymbol : pkgSymbols) {
PackageEntry pkgEntry = packageTable.createAndAddEntry(pkgSymbol, moduleEntry);
// should have been checked before
assert pkgEntry != null;
}
// Link guest module to its host representation
meta.HIDDEN_MODULE_ENTRY.setHiddenObject(module, moduleEntry);
}
if (StaticObject.isNull(loader) && getContext().getVmProperties().bootClassPathType().isExplodedModule()) {
profiler.profile(11);
// If we have an exploded build, and the module is defined to the bootloader, prepend a
// class path entry for this module.
prependModuleClasspath(moduleName);
}
}
Aggregations