use of com.oracle.truffle.espresso.descriptors.Symbol 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);
}
}
use of com.oracle.truffle.espresso.descriptors.Symbol in project graal by oracle.
the class ClassRegistry method createKlass.
@SuppressWarnings("try")
private ObjectKlass createKlass(Meta meta, ParserKlass parserKlass, Symbol<Type> type, Symbol<Type> superKlassType, ClassDefinitionInfo info) {
EspressoThreadLocalState threadLocalState = meta.getContext().getLanguage().getThreadLocalState();
TypeStack chain = threadLocalState.getTypeStack();
ObjectKlass superKlass = null;
ObjectKlass[] superInterfaces = null;
LinkedKlass[] linkedInterfaces = null;
chain.push(type);
try {
if (superKlassType != null) {
if (chain.contains(superKlassType)) {
throw meta.throwException(meta.java_lang_ClassCircularityError);
}
superKlass = loadKlassRecursively(meta, superKlassType, true);
}
final Symbol<Type>[] superInterfacesTypes = parserKlass.getSuperInterfaces();
linkedInterfaces = superInterfacesTypes.length == 0 ? LinkedKlass.EMPTY_ARRAY : new LinkedKlass[superInterfacesTypes.length];
superInterfaces = superInterfacesTypes.length == 0 ? ObjectKlass.EMPTY_ARRAY : new ObjectKlass[superInterfacesTypes.length];
for (int i = 0; i < superInterfacesTypes.length; ++i) {
if (chain.contains(superInterfacesTypes[i])) {
throw meta.throwException(meta.java_lang_ClassCircularityError);
}
ObjectKlass interf = loadKlassRecursively(meta, superInterfacesTypes[i], false);
superInterfaces[i] = interf;
linkedInterfaces[i] = interf.getLinkedKlass();
}
} finally {
chain.pop();
}
if (getContext().getJavaVersion().java16OrLater() && superKlass != null) {
if (superKlass.isFinalFlagSet()) {
throw meta.throwExceptionWithMessage(meta.java_lang_IncompatibleClassChangeError, "class " + type + " is a subclass of final class " + superKlassType);
}
}
ObjectKlass klass;
try (DebugCloseable define = KLASS_DEFINE.scope(context.getTimers())) {
// FIXME(peterssen): Do NOT create a LinkedKlass every time, use a global cache.
ContextDescription description = new ContextDescription(context.getLanguage(), context.getJavaVersion());
LinkedKlass linkedKlass = LinkedKlass.create(description, parserKlass, superKlass == null ? null : superKlass.getLinkedKlass(), linkedInterfaces);
klass = new ObjectKlass(context, linkedKlass, superKlass, superInterfaces, getClassLoader(), info);
}
if (superKlass != null) {
if (!Klass.checkAccess(superKlass, klass)) {
throw meta.throwExceptionWithMessage(meta.java_lang_IllegalAccessError, "class " + type + " cannot access its superclass " + superKlassType);
}
if (!superKlass.permittedSubclassCheck(klass)) {
throw meta.throwExceptionWithMessage(meta.java_lang_IncompatibleClassChangeError, "class " + type + " is not a permitted subclass of class " + superKlassType);
}
}
for (ObjectKlass interf : superInterfaces) {
if (interf != null) {
if (!Klass.checkAccess(interf, klass)) {
throw meta.throwExceptionWithMessage(meta.java_lang_IllegalAccessError, "class " + type + " cannot access its superinterface " + interf.getType());
}
if (!interf.permittedSubclassCheck(klass)) {
throw meta.throwExceptionWithMessage(meta.java_lang_IncompatibleClassChangeError, "class " + type + " is not a permitted subclass of interface " + superKlassType);
}
}
}
return klass;
}
use of com.oracle.truffle.espresso.descriptors.Symbol in project graal by oracle.
the class Target_sun_reflect_NativeMethodAccessorImpl method callMethodReflectively.
@JavaType(Object.class)
public static StaticObject callMethodReflectively(Meta meta, @JavaType(Object.class) StaticObject receiver, @JavaType(Object[].class) StaticObject args, Method m, Klass klass, @JavaType(Class[].class) StaticObject parameterTypes) {
// Klass should be initialized if method is static, and could be delayed until method
// invocation, according to specs. However, JCK tests that it is indeed always initialized
// before doing anything, even if the method to be invoked is from another class.
klass.safeInitialize();
Method reflectedMethod = m;
if (reflectedMethod.isRemovedByRedefition()) {
reflectedMethod = m.getContext().getClassRedefinition().handleRemovedMethod(reflectedMethod, reflectedMethod.isStatic() ? reflectedMethod.getDeclaringKlass() : receiver.getKlass());
}
// actual method to invoke
Method method;
// target klass, receiver's klass for non-static
Klass targetKlass;
if (reflectedMethod.isStatic()) {
// Ignore receiver argument;.
method = reflectedMethod;
targetKlass = klass;
} else {
if (StaticObject.isNull(receiver)) {
throw meta.throwNullPointerException();
}
// Check class of receiver against class declaring method.
if (!klass.isAssignableFrom(receiver.getKlass())) {
throw meta.throwExceptionWithMessage(meta.java_lang_IllegalArgumentException, "object is not an instance of declaring class");
}
// target klass is receiver's klass
targetKlass = receiver.getKlass();
// no need to resolve if method is private or <init>
if (reflectedMethod.isPrivate() || Name._init_.equals(reflectedMethod.getName())) {
method = reflectedMethod;
} else {
// resolve based on the receiver
if (reflectedMethod.getDeclaringKlass().isInterface()) {
// resolve interface call
// Match resolution errors with those thrown due to reflection inlining
// Linktime resolution & IllegalAccessCheck already done by Class.getMethod()
method = reflectedMethod;
assert targetKlass instanceof ObjectKlass;
method = ((ObjectKlass) targetKlass).itableLookup(method.getDeclaringKlass(), method.getITableIndex());
if (method != null) {
// Check for abstract methods as well
if (!method.hasCode()) {
// new default: 65315
throw meta.throwExceptionWithCause(meta.java_lang_reflect_InvocationTargetException, Meta.initException(meta.java_lang_AbstractMethodError));
}
}
} else {
// if the method can be overridden, we resolve using the vtable index.
method = reflectedMethod;
// VTable is live, use it
method = targetKlass.vtableLookup(method.getVTableIndex());
if (method != null) {
// Check for abstract methods as well
if (method.isAbstract()) {
// new default: 65315
throw meta.throwExceptionWithCause(meta.java_lang_reflect_InvocationTargetException, Meta.initException(meta.java_lang_AbstractMethodError));
}
}
}
}
}
// an internal vtable bug. If you ever get this please let Karen know.
if (method == null) {
throw meta.throwExceptionWithMessage(meta.java_lang_NoSuchMethodError, "please let Karen know");
}
int argsLen = StaticObject.isNull(args) ? 0 : args.length();
final Symbol<Type>[] signature = method.getParsedSignature();
// Check number of arguments.
if (Signatures.parameterCount(signature, false) != argsLen) {
throw meta.throwExceptionWithMessage(meta.java_lang_IllegalArgumentException, "wrong number of arguments!");
}
Object[] adjustedArgs = new Object[argsLen];
for (int i = 0; i < argsLen; ++i) {
StaticObject arg = args.get(i);
StaticObject paramTypeMirror = parameterTypes.get(i);
Klass paramKlass = paramTypeMirror.getMirrorKlass();
// Throws guest IllegallArgumentException if the parameter cannot be casted or widened.
adjustedArgs[i] = checkAndWiden(meta, arg, paramKlass);
}
Object result;
try {
result = method.invokeDirect(receiver, adjustedArgs);
} catch (EspressoException e) {
throw meta.throwExceptionWithCause(meta.java_lang_reflect_InvocationTargetException, e.getGuestException());
}
if (reflectedMethod.getReturnKind() == JavaKind.Void) {
return StaticObject.NULL;
}
if (reflectedMethod.getReturnKind().isPrimitive()) {
return Meta.box(meta, result);
}
// Result is not void nor primitive, pass through.
return (StaticObject) result;
}
use of com.oracle.truffle.espresso.descriptors.Symbol in project graal by oracle.
the class ClassfileParser method parseMethod.
private ParserMethod parseMethod(boolean isInterface) {
int methodFlags = stream.readU2();
int nameIndex = stream.readU2();
int signatureIndex = stream.readU2();
final Symbol<Name> name;
final Symbol<Signature> signature;
int attributeCount;
Attribute[] methodAttributes;
int extraFlags = methodFlags;
boolean isClinit = false;
boolean isInit = false;
try (DebugCloseable closeable = METHOD_INIT.scope(context.getTimers())) {
try (DebugCloseable nameCheck = NAME_CHECK.scope(context.getTimers())) {
pool.utf8At(nameIndex).validateMethodName(true);
name = pool.symbolAt(nameIndex, "method name");
if (name.equals(Name._clinit_)) {
// ACC_STRICT flag.
if (majorVersion < JAVA_7_VERSION) {
// Backwards compatibility.
methodFlags = ACC_STATIC;
} else if ((methodFlags & ACC_STATIC) == ACC_STATIC) {
methodFlags &= (ACC_STRICT | ACC_STATIC);
} else if (context.getJavaVersion().java9OrLater()) {
throw ConstantPool.classFormatError("Method <clinit> is not static.");
}
// extraFlags = INITIALIZER | methodFlags;
isClinit = true;
} else if (name.equals(Name._init_)) {
if (isInterface) {
throw ConstantPool.classFormatError("Method <init> is not valid in an interface.");
}
isInit = true;
}
}
final boolean isStatic = Modifier.isStatic(extraFlags);
verifyMethodFlags(methodFlags, isInterface, isInit, isClinit, majorVersion);
/*
* A method is a class or interface initialization method if all of the following are
* true:
*
* It has the special name <clinit>.
*
* It is void (4.3.3). (checked earlier)
*
* In a class file whose version number is 51.0 or above, the method has its ACC_STATIC
* flag set and takes no arguments (4.6).
*/
try (DebugCloseable signatureCheck = SIGNATURE_CHECK.scope(context.getTimers())) {
// Checks for void method if init or clinit.
/*
* Obtain slot number for the signature. Forces a validation, but better in startup
* than going twice through the sequence, once for validation, once for slots.
*/
int slots = pool.utf8At(signatureIndex).validateSignatureGetSlots(isInit || isClinit);
signature = Signatures.check(pool.symbolAt(signatureIndex, "method descriptor"));
if (isClinit && majorVersion >= JAVA_7_VERSION) {
// Checks clinit takes no arguments.
if (!signature.equals(Signature._void)) {
throw ConstantPool.classFormatError("Method <clinit> has invalid signature: " + signature);
}
}
if (slots + (isStatic ? 0 : 1) > 255) {
throw ConstantPool.classFormatError("Too many arguments in method signature: " + signature);
}
if (name.equals(Name.finalize) && signature.equals(Signature._void) && !Modifier.isStatic(methodFlags) && !Type.java_lang_Object.equals(classType)) {
// This class has a finalizer method implementation (ignore for
// java.lang.Object).
classFlags |= ACC_FINALIZER;
}
}
attributeCount = stream.readU2();
methodAttributes = spawnAttributesArray(attributeCount);
}
CodeAttribute codeAttribute = null;
Attribute checkedExceptions = null;
Attribute runtimeVisibleAnnotations = null;
CommonAttributeParser commonAttributeParser = new CommonAttributeParser(InfoType.Method);
MethodParametersAttribute methodParameters = null;
for (int i = 0; i < attributeCount; ++i) {
final int attributeNameIndex = stream.readU2();
final Symbol<Name> attributeName = pool.symbolAt(attributeNameIndex, "attribute name");
final int attributeSize = stream.readS4();
final int startPosition = stream.getPosition();
if (attributeName.equals(Name.Code)) {
if (codeAttribute != null) {
throw ConstantPool.classFormatError("Duplicate Code attribute");
}
try (DebugCloseable code = CODE_PARSE.scope(context.getTimers())) {
methodAttributes[i] = codeAttribute = parseCodeAttribute(attributeName);
}
} else if (attributeName.equals(Name.Exceptions)) {
if (checkedExceptions != null) {
throw ConstantPool.classFormatError("Duplicate Exceptions attribute");
}
methodAttributes[i] = checkedExceptions = parseExceptions(attributeName);
} else if (attributeName.equals(Name.Synthetic)) {
methodFlags |= ACC_SYNTHETIC;
methodAttributes[i] = checkedExceptions = new Attribute(attributeName, null);
} else if (majorVersion >= JAVA_1_5_VERSION) {
if (attributeName.equals(Name.RuntimeVisibleAnnotations)) {
if (runtimeVisibleAnnotations != null) {
throw ConstantPool.classFormatError("Duplicate RuntimeVisibleAnnotations attribute");
}
// Check if java.lang.invoke.LambdaForm.Compiled is present here.
byte[] data = stream.readByteArray(attributeSize);
ClassfileStream subStream = new ClassfileStream(data, this.classfile);
int count = subStream.readU2();
for (int j = 0; j < count; j++) {
int typeIndex = parseAnnotation(subStream);
Utf8Constant constant = pool.utf8At(typeIndex, "annotation type");
// Validation of the type is done at runtime by guest java code.
Symbol<Type> annotType = constant.value();
if (Type.java_lang_invoke_LambdaForm$Compiled.equals(annotType)) {
methodFlags |= ACC_LAMBDA_FORM_COMPILED;
} else if (Type.java_lang_invoke_LambdaForm$Hidden.equals(annotType) || Type.jdk_internal_vm_annotation_Hidden.equals(annotType)) {
methodFlags |= ACC_HIDDEN;
} else if (Type.sun_reflect_CallerSensitive.equals(annotType) || Type.jdk_internal_reflect_CallerSensitive.equals(annotType)) {
methodFlags |= ACC_CALLER_SENSITIVE;
}
}
methodAttributes[i] = runtimeVisibleAnnotations = new Attribute(attributeName, data);
} else if (attributeName.equals(Name.MethodParameters)) {
if (methodParameters != null) {
throw ConstantPool.classFormatError("Duplicate MethodParameters attribute");
}
methodAttributes[i] = methodParameters = parseMethodParameters(attributeName);
} else {
Attribute attr = commonAttributeParser.parseCommonAttribute(attributeName, attributeSize);
// stream.skip(attributeSize);
methodAttributes[i] = attr == null ? new Attribute(attributeName, stream.readByteArray(attributeSize)) : attr;
}
} else {
// stream.skip(attributeSize);
methodAttributes[i] = new Attribute(attributeName, stream.readByteArray(attributeSize));
}
final int distance = stream.getPosition() - startPosition;
if (attributeSize != distance) {
final String message = "Invalid attribute_length for " + attributeName + " attribute (reported " + attributeSize + " != parsed " + distance + ")";
throw ConstantPool.classFormatError(message);
}
}
if (Modifier.isAbstract(methodFlags) || Modifier.isNative(methodFlags)) {
if (codeAttribute != null) {
throw ConstantPool.classFormatError("Code attribute supplied for native or abstract method");
}
} else {
if (codeAttribute == null) {
throw ConstantPool.classFormatError("Missing Code attribute");
}
}
if (classDefinitionInfo.isHidden()) {
methodFlags |= ACC_HIDDEN;
}
return ParserMethod.create(methodFlags, name, signature, methodAttributes);
}
use of com.oracle.truffle.espresso.descriptors.Symbol in project graal by oracle.
the class ClassfileParser method parseClassImpl.
private ParserKlass parseClassImpl() {
readMagic();
minorVersion = stream.readU2();
majorVersion = stream.readU2();
verifyVersion(majorVersion, minorVersion);
try (DebugCloseable closeable = CONSTANT_POOL.scope(context.getTimers())) {
this.pool = ConstantPool.parse(context.getLanguage(), stream, this, classDefinitionInfo.patches, context, majorVersion, minorVersion);
}
// JVM_ACC_MODULE is defined in JDK-9 and later.
if (majorVersion >= JAVA_9_VERSION) {
classFlags = stream.readU2() & (JVM_RECOGNIZED_CLASS_MODIFIERS | ACC_MODULE);
} else {
classFlags = stream.readU2() & (JVM_RECOGNIZED_CLASS_MODIFIERS);
}
if ((classFlags & ACC_INTERFACE) != 0 && majorVersion < JAVA_6_VERSION) {
// Set abstract bit for old class files for backward compatibility
classFlags |= ACC_ABSTRACT;
}
boolean isModule = (classFlags & ACC_MODULE) != 0;
if (isModule) {
throw ConstantPool.noClassDefFoundError(classType + " is not a class because access_flag ACC_MODULE is set");
}
if (badConstantSeen != null) {
// https://bugs.openjdk.java.net/browse/JDK-8175383
throw ConstantPool.classFormatError(String.format("Unknown constant tag %s [in class file %s]", badConstantSeen, classfile));
}
verifyClassFlags(classFlags, majorVersion);
// this class
int thisKlassIndex = stream.readU2();
Symbol<Name> thisKlassName = pool.classAt(thisKlassIndex).getName(pool);
final boolean isInterface = Modifier.isInterface(classFlags);
// TODO(peterssen): Verify class names.
Symbol<Type> thisKlassType = context.getTypes().fromName(thisKlassName);
if (Types.isPrimitive(thisKlassType) || Types.isArray(thisKlassType)) {
throw ConstantPool.classFormatError(".this_class cannot be array nor primitive " + classType);
}
// Update classType which could be null previously to reflect the name in the constant pool.
classType = thisKlassType;
// Checks if name in class file matches requested name
if (requestedClassType != null && !classDefinitionInfo.isHidden() && !requestedClassType.equals(classType)) {
throw ConstantPool.noClassDefFoundError(classType + " (wrong name: " + requestedClassType + ")");
}
Symbol<Type> superKlass = parseSuperKlass();
if (!Type.java_lang_Object.equals(classType) && superKlass == null) {
throw ConstantPool.classFormatError("Class " + classType + " must have a superclass");
}
if (isInterface && !Type.java_lang_Object.equals(superKlass)) {
throw ConstantPool.classFormatError("Interface " + classType + " must extend java.lang.Object");
}
Symbol<Type>[] superInterfaces;
try (DebugCloseable closeable = PARSE_INTERFACES.scope(context.getTimers())) {
superInterfaces = parseInterfaces();
}
final ParserField[] fields;
try (DebugCloseable closeable = PARSE_FIELD.scope(context.getTimers())) {
fields = parseFields(isInterface);
}
final ParserMethod[] methods;
try (DebugCloseable closeable = PARSE_METHODS.scope(context.getTimers())) {
methods = parseMethods(isInterface);
}
final Attribute[] attributes;
try (DebugCloseable closeable = PARSE_CLASSATTR.scope(context.getTimers())) {
attributes = parseClassAttributes();
}
// Ensure there are no trailing bytes
stream.checkEndOfFile();
if (classDefinitionInfo.isHidden()) {
assert requestedClassType != null;
int futureKlassID = context.getNewKlassId();
classDefinitionInfo.initKlassID(futureKlassID);
thisKlassName = context.getNames().getOrCreate(Types.hiddenClassName(requestedClassType, futureKlassID));
thisKlassType = context.getTypes().fromName(thisKlassName);
pool = pool.patchForHiddenClass(thisKlassIndex, thisKlassName);
}
return new ParserKlass(pool, classDefinitionInfo.patchFlags(classFlags), thisKlassName, thisKlassType, superKlass, superInterfaces, methods, fields, attributes, thisKlassIndex);
}
Aggregations