--- a/jdk/src/java.base/share/classes/java/lang/Class.java Tue Mar 15 13:48:26 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/Class.java Thu Mar 17 19:04:16 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
package java.lang;
+import java.lang.annotation.Annotation;
+import java.lang.module.ModuleReader;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
@@ -33,15 +35,19 @@
import java.lang.reflect.Field;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
+import java.lang.reflect.Module;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.AnnotatedType;
+import java.lang.reflect.Proxy;
import java.lang.ref.SoftReference;
+import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectStreamField;
+import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
@@ -55,9 +61,11 @@
import java.util.HashMap;
import java.util.Objects;
import java.util.StringJoiner;
+import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.loader.BootLoader;
+import jdk.internal.loader.BuiltinClassLoader;
import jdk.internal.misc.Unsafe;
import jdk.internal.misc.VM;
-import jdk.internal.HotSpotIntrinsicCandidate;
import sun.reflect.CallerSensitive;
import sun.reflect.ConstantPool;
import sun.reflect.Reflection;
@@ -69,8 +77,6 @@
import sun.reflect.generics.repository.ConstructorRepository;
import sun.reflect.generics.scope.ClassScope;
import sun.security.util.SecurityConstants;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Proxy;
import sun.reflect.annotation.*;
import sun.reflect.misc.ReflectUtil;
@@ -378,6 +384,86 @@
Class<?> caller)
throws ClassNotFoundException;
+
+ /**
+ * Returns the {@code Class} with the given <a href="ClassLoader.html#name">
+ * binary name</a> in the given module.
+ *
+ * <p> This method attempts to locate, load, and link the class or interface.
+ * It does not run the class initializer. If the class is not found, this
+ * method returns {@code null}. </p>
+ *
+ * <p> If the class loader of the given module defines other modules and
+ * the given name is a class defined in a different module, this method
+ * returns {@code null} after the class is loaded. </p>
+ *
+ * <p> This method does not check whether the requested class is
+ * accessible to its caller. </p>
+ *
+ * @apiNote
+ * This method returns {@code null} on failure rather than
+ * throwing a {@link ClassNotFoundException}, as is done by
+ * the {@link #forName(String, boolean, ClassLoader)} method.
+ * The security check is a stack-based permission check if the caller
+ * loads a class in another module.
+ *
+ * @param module A module
+ * @param name The <a href="ClassLoader.html#name">binary name</a>
+ * of the class
+ * @return {@code Class} object of the given name defined in the given module;
+ * {@code null} if not found.
+ *
+ * @throws NullPointerException if the given module or name is {@code null}
+ *
+ * @throws LinkageError if the linkage fails
+ *
+ * @throws SecurityException
+ * <ul>
+ * <li> if the caller is not the specified module and
+ * {@code RuntimePermission("getClassLoader")} permission is denied; or</li>
+ * <li> access to the module content is denied. For example,
+ * permission check will be performed when a class loader calls
+ * {@link ModuleReader#open(String)} to read the bytes of a class file
+ * in a module.</li>
+ * </ul>
+ *
+ * @since 9
+ */
+ @CallerSensitive
+ public static Class<?> forName(Module module, String name) {
+ Objects.requireNonNull(module);
+ Objects.requireNonNull(name);
+
+ Class<?> caller = Reflection.getCallerClass();
+ if (caller != null && caller.getModule() != module) {
+ // if caller is null, Class.forName is the last java frame on the stack.
+ // java.base has all permissions
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
+ }
+ }
+
+ PrivilegedAction<ClassLoader> pa = module::getClassLoader;
+ ClassLoader cl = AccessController.doPrivileged(pa);
+ if (module.isNamed() && cl != null) {
+ return cl.loadLocalClass(module, name);
+ }
+
+ final Class<?> c;
+ if (cl != null) {
+ c = cl.loadLocalClass(name);
+ } else {
+ c = BootLoader.loadClassOrNull(name);
+ }
+
+ if (c != null && c.getModule() == module) {
+ return c;
+ } else {
+ return null;
+ }
+ }
+
/**
* Creates a new instance of the class represented by this {@code Class}
* object. The class is instantiated as if by a {@code new}
@@ -453,13 +539,11 @@
}
Constructor<T> tmpConstructor = cachedConstructor;
// Security check (same as in java.lang.reflect.Constructor)
- int modifiers = tmpConstructor.getModifiers();
- if (!Reflection.quickCheckMemberAccess(this, modifiers)) {
- Class<?> caller = Reflection.getCallerClass();
- if (newInstanceCallerCache != caller) {
- Reflection.ensureMemberAccess(caller, this, null, modifiers);
- newInstanceCallerCache = caller;
- }
+ Class<?> caller = Reflection.getCallerClass();
+ if (newInstanceCallerCache != caller) {
+ int modifiers = tmpConstructor.getModifiers();
+ Reflection.ensureMemberAccess(caller, this, null, modifiers);
+ newInstanceCallerCache = caller;
}
// Run constructor
try {
@@ -717,6 +801,29 @@
// Package-private to allow ClassLoader access
ClassLoader getClassLoader0() { return classLoader; }
+ /**
+ * Returns the module that this class or interface is a member of.
+ *
+ * If this class represents an array type then this method returns the
+ * {@code Module} for the element type. If this class represents a
+ * primitive type or void, then the {@code Module} object for the
+ * {@code java.base} module is returned.
+ *
+ * If this class is in an unnamed module then the {@link
+ * ClassLoader#getUnnamedModule() unnamed} {@code Module} of the class
+ * loader for this class is returned.
+ *
+ * @return the module that this class or interface is a member of
+ *
+ * @since 9
+ */
+ public Module getModule() {
+ return module;
+ }
+
+ // set by VM
+ private transient Module module;
+
// Initialized in JVM not by private constructor
// This field is filtered from reflection access, i.e. getDeclaredField
// will throw NoSuchFieldException
@@ -808,24 +915,60 @@
}
/**
- * Gets the package for this class. The class loader of this class is used
- * to find the package. If the class was loaded by the bootstrap class
- * loader the set of packages loaded from CLASSPATH is searched to find the
- * package of the class. Null is returned if no package object was created
- * by the class loader of this class.
+ * Gets the package of this class.
*
- * <p> Packages have attributes for versions and specifications only if the
- * information was defined in the manifests that accompany the classes, and
- * if the class loader created the package instance with the attributes
- * from the manifest.
+ * <p>If this class represents an array type, a primitive type or void,
+ * this method returns {@code null}.
*
- * @return the package of the class, or null if no package
- * information is available from the archive or codebase.
+ * @return the package of this class.
*/
public Package getPackage() {
- return Package.getPackage(this);
+ if (isPrimitive() || isArray()) {
+ return null;
+ }
+ ClassLoader cl = getClassLoader0();
+ return cl != null ? cl.definePackage(this)
+ : BootLoader.definePackage(this);
}
+ /**
+ * Returns the fully qualified package name.
+ *
+ * <p> If this class is a top level class, then this method returns the fully
+ * qualified name of the package that the class is a member of, or the
+ * empty string if the class is in an unnamed package.
+ *
+ * <p> If this class is a member class, then this method is equivalent to
+ * invoking {@code getPackageName()} on the {@link #getEnclosingClass
+ * enclosing class}.
+ *
+ * <p> If this class is a {@link #isLocalClass local class} or an {@link
+ * #isAnonymousClass() anonymous class}, then this method is equivalent to
+ * invoking {@code getPackageName()} on the {@link #getDeclaringClass
+ * declaring class} of the {@link #getEnclosingMethod enclosing method} or
+ * {@link #getEnclosingConstructor enclosing constructor}.
+ *
+ * <p> This method returns {@code null} if this class represents an array type,
+ * a primitive type or void.
+ *
+ * @return the fully qualified package name
+ *
+ * @since 9
+ * @jls 6.7 Fully Qualified Names
+ */
+ public String getPackageName() {
+ String pn = this.packageName;
+ if (pn == null && !isArray() && !isPrimitive()) {
+ String cn = getName();
+ int dot = cn.lastIndexOf('.');
+ pn = (dot != -1) ? cn.substring(0, dot).intern() : "";
+ this.packageName = pn;
+ }
+ return pn;
+ }
+
+ // cached package name
+ private String packageName;
/**
* Returns the interfaces directly implemented by the class or interface
@@ -2213,15 +2356,19 @@
}
/**
- * Finds a resource with a given name. The rules for searching resources
+ * Finds a resource with a given name. If this class is in a named {@link
+ * Module Module}, and the caller of this method is in the same module,
+ * then this method will attempt to find the resource in that module.
+ * Otherwise, the rules for searching resources
* associated with a given class are implemented by the defining
* {@linkplain ClassLoader class loader} of the class. This method
* delegates to this object's class loader. If this object was loaded by
* the bootstrap class loader, the method delegates to {@link
* ClassLoader#getSystemResourceAsStream}.
*
- * <p> Before delegation, an absolute resource name is constructed from the
- * given resource name using this algorithm:
+ * <p> Before finding a resource in the caller's module or delegation to a
+ * class loader, an absolute resource name is constructed from the given
+ * resource name using this algorithm:
*
* <ul>
*
@@ -2242,26 +2389,60 @@
* </ul>
*
* @param name name of the desired resource
- * @return A {@link java.io.InputStream} object or {@code null} if
- * no resource with this name is found
+ * @return A {@link java.io.InputStream} object or {@code null} if
+ * no resource with this name is found
* @throws NullPointerException If {@code name} is {@code null}
* @since 1.1
*/
- public InputStream getResourceAsStream(String name) {
+ @CallerSensitive
+ public InputStream getResourceAsStream(String name) {
name = resolveName(name);
+
+ // if this Class and the caller are in the same named module
+ // then attempt to get an input stream to the resource in the
+ // module
+ Module module = getModule();
+ if (module.isNamed()) {
+ Class<?> caller = Reflection.getCallerClass();
+ if (caller != null && caller.getModule() == module) {
+ ClassLoader cl = getClassLoader0();
+ String mn = module.getName();
+ try {
+
+ // special-case built-in class loaders to avoid the
+ // need for a URL connection
+ if (cl == null) {
+ return BootLoader.findResourceAsStream(mn, name);
+ } else if (cl instanceof BuiltinClassLoader) {
+ return ((BuiltinClassLoader) cl).findResourceAsStream(mn, name);
+ } else {
+ URL url = cl.findResource(mn, name);
+ return (url != null) ? url.openStream() : null;
+ }
+
+ } catch (IOException | SecurityException e) {
+ return null;
+ }
+ }
+ }
+
+ // this Class and caller not in the same named module
ClassLoader cl = getClassLoader0();
- if (cl==null) {
- // A system class.
+ if (cl == null) {
return ClassLoader.getSystemResourceAsStream(name);
+ } else {
+ return cl.getResourceAsStream(name);
}
- return cl.getResourceAsStream(name);
}
/**
- * Finds a resource with a given name. The rules for searching resources
+ * Finds a resource with a given name. If this class is in a named {@link
+ * Module Module}, and the caller of this method is in the same module,
+ * then this method will attempt to find the resource in that module.
+ * Otherwise, the rules for searching resources
* associated with a given class are implemented by the defining
* {@linkplain ClassLoader class loader} of the class. This method
- * delegates to this object's class loader. If this object was loaded by
+ * delegates to this object's class loader. If this object was loaded by
* the bootstrap class loader, the method delegates to {@link
* ClassLoader#getSystemResource}.
*
@@ -2287,22 +2468,43 @@
* </ul>
*
* @param name name of the desired resource
- * @return A {@link java.net.URL} object or {@code null} if no
- * resource with this name is found
+ * @return A {@link java.net.URL} object; {@code null} if no
+ * resource with this name is found or the resource cannot
+ * be located by a URL.
* @since 1.1
*/
- public java.net.URL getResource(String name) {
+ @CallerSensitive
+ public URL getResource(String name) {
name = resolveName(name);
+
+ // if this Class and the caller are in the same named module
+ // then attempt to get URL to the resource in the module
+ Module module = getModule();
+ if (module.isNamed()) {
+ Class<?> caller = Reflection.getCallerClass();
+ if (caller != null && caller.getModule() == module) {
+ String mn = getModule().getName();
+ ClassLoader cl = getClassLoader0();
+ try {
+ if (cl == null) {
+ return BootLoader.findResource(mn, name);
+ } else {
+ return cl.findResource(mn, name);
+ }
+ } catch (IOException ioe) {
+ return null;
+ }
+ }
+ }
+
ClassLoader cl = getClassLoader0();
- if (cl==null) {
- // A system class.
+ if (cl == null) {
return ClassLoader.getSystemResource(name);
+ } else {
+ return cl.getResource(name);
}
- return cl.getResource(name);
}
-
-
/** protection domain returned when the internal domain is null */
private static java.security.ProtectionDomain allPermDomain;
@@ -2845,15 +3047,15 @@
private void remove(int i) {
if (methods[i] != null && methods[i].isDefault())
defaults--;
- methods[i] = null;
- }
+ methods[i] = null;
+ }
private boolean matchesNameAndDescriptor(Method m1, Method m2) {
return m1.getReturnType() == m2.getReturnType() &&
m1.getName() == m2.getName() && // name is guaranteed to be interned
arrayContentsEq(m1.getParameterTypes(),
m2.getParameterTypes());
- }
+ }
void compactAndTrim() {
int newPos = 0;