📄 rmiclassloader.java
字号:
/** * Returns the annotation string (representing a location for * the class definition) that RMI will use to annotate the class * descriptor when marshalling objects of the given class. * * <p>This method delegates to the * {@link RMIClassLoaderSpi#getClassAnnotation(Class)} method * of the provider instance, passing <code>cl</code> as the argument. * * @param cl the class to obtain the annotation for * * @return a string to be used to annotate the given class when * it gets marshalled, or <code>null</code> * * @since 1.2 */ /* * REMIND: Should we say that the returned class annotation will or * should be a (space-separated) list of URLs? */ public static String getClassAnnotation(Class cl) { return provider.getClassAnnotation(cl); } /** * Returns the canonical instance of the default provider * for the service provider interface {@link RMIClassLoaderSpi}. * If the system property <code>java.rmi.server.RMIClassLoaderSpi</code> * is not defined, then the <code>RMIClassLoader</code> static * methods * * <ul> * * <li>{@link #loadClass(URL,String)} * <li>{@link #loadClass(String,String)} * <li>{@link #loadClass(String,String,ClassLoader)} * <li>{@link #loadProxyClass(String,String[],ClassLoader)} * <li>{@link #getClassLoader(String)} * <li>{@link #getClassAnnotation(Class)} * * </ul> * * will use the canonical instance of the default provider * as the service provider instance. * * <p>If there is a security manager, its * <code>checkPermission</code> method will be invoked with a * <code>RuntimePermission("setFactory")</code> permission; this * could result in a <code>SecurityException</code>. * * <p>The default service provider instance implements * {@link RMIClassLoaderSpi} as follows: * * <blockquote> * * <p>The <b>{@link RMIClassLoaderSpi#getClassAnnotation(Class) * getClassAnnotation}</b> method returns a <code>String</code> * representing the codebase URL path that a remote party should * use to download the definition for the specified class. The * format of the returned string is a path of URLs separated by * spaces. * * The codebase string returned depends on the defining class * loader of the specified class: * * <ul> * * <p><li>If the class loader is the system class loader (see * {@link ClassLoader#getSystemClassLoader}), a parent of the * system class loader such as the loader used for installed * extensions, or the bootstrap class loader (which may be * represented by <code>null</code>), then the value of the * <code>java.rmi.server.codebase</code> property is returned, or * <code>null</code> is returned if that property is not set. * * <p><li>Otherwise, if the class loader is an instance of * <code>URLClassLoader</code>, then the returned string is a * space-separated list of the external forms of the URLs returned * by invoking the <code>getURLs</code> methods of the loader. If * the <code>URLClassLoader</code> was created by this provider to * service an invocation of its <code>loadClass</code> or * <code>loadProxyClass</code> methods, then no permissions are * required to get the associated codebase string. If it is an * arbitrary other <code>URLClassLoader</code> instance, then if * there is a security manager, its <code>checkPermission</code> * method will be invoked once for each URL returned by the * <code>getURLs</code> method, with the permission returned by * invoking <code>openConnection().getPermission()</code> on each * URL; if any of those invocations throws a * <code>SecurityException</code> or an <code>IOException</code>, * then the value of the <code>java.rmi.server.codebase</code> * property is returned, or <code>null</code> is returned if that * property is not set. * * <p><li>Finally, if the class loader is not an instance of * <code>URLClassLoader</code>, then the value of the * <code>java.rmi.server.codebase</code> property is returned, or * <code>null</code> is returned if that property is not set. * * </ul> * * <p>For the implementations of the methods described below, * which all take a <code>String</code> parameter named * <code>codebase</code> that is a space-separated list of URLs, * each invocation has an associated <i>codebase loader</i> that * is identified using the <code>codebase</code> argument in * conjunction with the current thread's context class loader (see * {@link Thread#getContextClassLoader()}). When there is a * security manager, this provider maintains an internal table of * class loader instances (which are at least instances of {@link * java.net.URLClassLoader}) keyed by the pair of their parent * class loader and their codebase URL path (an ordered list of * URLs). For a given codebase URL path passed as the * <code>codebase</code> argument to an invocation of one of the * below methods in a given context, the codebase loader is the * loader in the table with the specified codebase URL path and * the current thread's context class loader as its parent. If no * such loader exists, then one is created and added to the table. * The table does not maintain strong references to its contained * loaders, in order to allow them and their defined classes to be * garbage collected when not otherwise reachable. In order to * prevent arbitrary untrusted code from being implicitly loaded * into a virtual machine with no security manager, if there is no * security manager set, the codebase loader is just the current * thread's context class loader (the supplied codebase URL path * is ignored, so remote class loading is disabled). * * <p>The <b>{@link RMIClassLoaderSpi#getClassLoader(String) * getClassLoader}</b> method returns the codebase loader for the * specified codebase URL path. If there is a security manager, * then if the calling context does not have permission to connect * to all of the URLs in the codebase URL path, a * <code>SecurityException</code> will be thrown. * * <p>The <b>{@link * RMIClassLoaderSpi#loadClass(String,String,ClassLoader) * loadClass}</b> method attempts to load the class with the * specified name as follows: * * <blockquote> * * If the <code>defaultLoader</code> argument is * non-<code>null</code>, it first attempts to load the class with the * specified <code>name</code> using the * <code>defaultLoader</code>, such as by evaluating * * <pre> * Class.forName(name, false, defaultLoader) * </pre> * * If the class is successfully loaded from the * <code>defaultLoader</code>, that class is returned. If an * exception other than <code>ClassNotFoundException</code> is * thrown, that exception is thrown to the caller. * * <p>Next, the <code>loadClass</code> method attempts to load the * class with the specified <code>name</code> using the codebase * loader for the specified codebase URL path; the supplied * <code>codebase</code> string must be a space-separated list of * URLs. If there is a security manager, then the calling context * must have permission to connect to all of the URLs in the * codebase URL path; otherwise, the current thread's context * class loader will be used instead of the codebase loader. * * </blockquote> * * <p>The <b>{@link * RMIClassLoaderSpi#loadProxyClass(String,String[],ClassLoader) * loadProxyClass}</b> method attempts to return a dynamic proxy * class with the named interface as follows: * * <blockquote> * * <p>If the <code>defaultLoader</code> argument is * non-<code>null</code> and all of the named interfaces can be * resolved through that loader, then, * * <ul> * * <li>if all of the resolved interfaces are <code>public</code>, * then it first attempts to obtain a dynamic proxy class (using * {@link * java.lang.reflect.Proxy#getProxyClass(ClassLoader,Class[]) * Proxy.getProxyClass}) for the resolved interfaces defined in * the codebase loader; if that attempt throws an * <code>IllegalArgumentException</code>, it then attempts to * obtain a dynamic proxy class for the resolved interfaces * defined in the <code>defaultLoader</code>. If both attempts * throw <code>IllegalArgumentException</code>, then this method * throws a <code>ClassNotFoundException</code>. If any other * exception is thrown, that exception is thrown to the caller. * * <li>if all of the non-<code>public</code> resolved interfaces * are defined in the same class loader, then it attempts to * obtain a dynamic proxy class for the resolved interfaces * defined in that loader. * * <li>otherwise, a <code>LinkageError</code> is thrown (because a * class that implements all of the specified interfaces cannot be * defined in any loader). * * </ul> * * <p>Otherwise, if all of the named interfaces can be resolved * through the codebase loader, then, * * <ul> * * <li>if all of the resolved interfaces are <code>public</code>, * then it attempts to obtain a dynamic proxy class for the * resolved interfaces in the codebase loader. If the attempt * throws an <code>IllegalArgumentException</code>, then this * method throws a <code>ClassNotFoundException</code>. * * <li>if all of the non-<code>public</code> resolved interfaces * are defined in the same class loader, then it attempts to * obtain a dynamic proxy class for the resolved interfaces * defined in that loader. * * <li>otherwise, a <code>LinkageError</code> is thrown (because a * class that implements all of the specified interfaces cannot be * defined in any loader). * * </ul> * * <p>Otherwise, a <code>ClassNotFoundException</code> is thrown * for one of the named interfaces that could not be resolved. * * </blockquote> * * </blockquote> * * @return the canonical instance of the default service provider * * @throws SecurityException if there is a security manager and the * invocation of its <code>checkPermission</code> method fails * * @since 1.4 */ public static RMIClassLoaderSpi getDefaultProviderInstance() { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(new RuntimePermission("setFactory")); } return defaultProvider; } /** * Returns the security context of the given class loader. * * @param loader a class loader from which to get the security context * * @return the security context * * @deprecated no replacement. As of the Java 2 platform v1.2, RMI no * longer uses this method to obtain a class loader's security context. * @see java.lang.SecurityManager#getSecurityContext() */ public static Object getSecurityContext(ClassLoader loader) { return sun.rmi.server.LoaderHandler.getSecurityContext(loader); } /** * Creates an instance of the default provider class. */ private static RMIClassLoaderSpi newDefaultProviderInstance() { return new RMIClassLoaderSpi() { public Class loadClass(String codebase, String name, ClassLoader defaultLoader) throws MalformedURLException, ClassNotFoundException { return sun.rmi.server.LoaderHandler.loadClass( codebase, name, defaultLoader); } public Class loadProxyClass(String codebase, String[] interfaces, ClassLoader defaultLoader) throws MalformedURLException, ClassNotFoundException { return sun.rmi.server.LoaderHandler.loadProxyClass( codebase, interfaces, defaultLoader); } public ClassLoader getClassLoader(String codebase) throws MalformedURLException { return sun.rmi.server.LoaderHandler.getClassLoader(codebase); } public String getClassAnnotation(Class cl) { return sun.rmi.server.LoaderHandler.getClassAnnotation(cl); } }; } /** * Chooses provider instance, following above documentation. * * This method assumes that it has been invoked in a privileged block. */ private static RMIClassLoaderSpi initializeProvider() { /* * First check for the system property being set: */ String providerClassName = System.getProperty("java.rmi.server.RMIClassLoaderSpi"); if (providerClassName != null) { if (providerClassName.equals("default")) { return defaultProvider; } try { Class providerClass = Class.forName(providerClassName, false, ClassLoader.getSystemClassLoader()); return (RMIClassLoaderSpi) providerClass.newInstance(); } catch (ClassNotFoundException e) { throw new NoClassDefFoundError(e.getMessage()); } catch (IllegalAccessException e) { throw new IllegalAccessError(e.getMessage()); } catch (InstantiationException e) { throw new InstantiationError(e.getMessage()); } catch (ClassCastException e) { Error error = new LinkageError( "provider class not assignable to RMIClassLoaderSpi"); error.initCause(e); throw error; } } /* * Next look for a provider configuration file intalled: */ Iterator iter = Service.providers(RMIClassLoaderSpi.class, ClassLoader.getSystemClassLoader()); if (iter.hasNext()) { try { return (RMIClassLoaderSpi) iter.next(); } catch (ClassCastException e) { Error error = new LinkageError( "provider class not assignable to RMIClassLoaderSpi"); error.initCause(e); throw error; } } /* * Finally, return the canonical instance of the default provider. */ return defaultProvider; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -