Search in sources :

Example 1 with ClassRegistry

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);
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) ClassRegistry(com.oracle.truffle.espresso.impl.ClassRegistry) Matcher(java.util.regex.Matcher) Symbol(com.oracle.truffle.espresso.descriptors.Symbol) ObjectKlass(com.oracle.truffle.espresso.impl.ObjectKlass) Klass(com.oracle.truffle.espresso.impl.Klass) ObjectKlass(com.oracle.truffle.espresso.impl.ObjectKlass)

Example 2 with ClassRegistry

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;
    }
}
Also used : ClassRegistry(com.oracle.truffle.espresso.impl.ClassRegistry) Klass(com.oracle.truffle.espresso.impl.Klass) ObjectKlass(com.oracle.truffle.espresso.impl.ObjectKlass) ParserKlass(com.oracle.truffle.espresso.impl.ParserKlass) EspressoException(com.oracle.truffle.espresso.runtime.EspressoException) ObjectKlass(com.oracle.truffle.espresso.impl.ObjectKlass)

Example 3 with ClassRegistry

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);
    }
}
Also used : ClassRegistry(com.oracle.truffle.espresso.impl.ClassRegistry) ObjectKlass(com.oracle.truffle.espresso.impl.ObjectKlass)

Example 4 with ClassRegistry

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);
    }
}
Also used : Meta(com.oracle.truffle.espresso.meta.Meta) ClassRegistry(com.oracle.truffle.espresso.impl.ClassRegistry) Symbol(com.oracle.truffle.espresso.descriptors.Symbol) ModuleEntry(com.oracle.truffle.espresso.impl.ModuleTable.ModuleEntry) ArrayList(java.util.ArrayList) ModuleTable(com.oracle.truffle.espresso.impl.ModuleTable) PackageTable(com.oracle.truffle.espresso.impl.PackageTable) Name(com.oracle.truffle.espresso.descriptors.Symbol.Name) StaticObject(com.oracle.truffle.espresso.runtime.StaticObject) EntryTable(com.oracle.truffle.espresso.impl.EntryTable) PackageEntry(com.oracle.truffle.espresso.impl.PackageTable.PackageEntry)

Aggregations

ClassRegistry (com.oracle.truffle.espresso.impl.ClassRegistry)4 ObjectKlass (com.oracle.truffle.espresso.impl.ObjectKlass)3 Symbol (com.oracle.truffle.espresso.descriptors.Symbol)2 Klass (com.oracle.truffle.espresso.impl.Klass)2 Name (com.oracle.truffle.espresso.descriptors.Symbol.Name)1 EntryTable (com.oracle.truffle.espresso.impl.EntryTable)1 ModuleTable (com.oracle.truffle.espresso.impl.ModuleTable)1 ModuleEntry (com.oracle.truffle.espresso.impl.ModuleTable.ModuleEntry)1 PackageTable (com.oracle.truffle.espresso.impl.PackageTable)1 PackageEntry (com.oracle.truffle.espresso.impl.PackageTable.PackageEntry)1 ParserKlass (com.oracle.truffle.espresso.impl.ParserKlass)1 Meta (com.oracle.truffle.espresso.meta.Meta)1 EspressoException (com.oracle.truffle.espresso.runtime.EspressoException)1 StaticObject (com.oracle.truffle.espresso.runtime.StaticObject)1 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 Set (java.util.Set)1 Matcher (java.util.regex.Matcher)1