--- old/src/java.base/share/classes/sun/misc/URLClassPath.java 2014-11-20 16:03:20.030249038 +0000 +++ new/src/java.base/share/classes/sun/misc/URLClassPath.java 2014-11-20 16:03:19.871238274 +0000 @@ -26,9 +26,8 @@ package sun.misc; import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; import java.util.jar.JarFile; -import sun.misc.JarIndex; -import sun.misc.InvalidJarIndexException; import sun.net.www.ParseUtil; import java.util.zip.ZipEntry; import java.util.jar.JarEntry; @@ -47,11 +46,14 @@ import java.security.AccessControlException; import java.security.CodeSigner; import java.security.Permission; -import java.security.PrivilegedAction; import java.security.PrivilegedExceptionAction; import java.security.cert.Certificate; -import sun.misc.FileURLMapper; + +import jdk.internal.jimage.ImageLocation; +import jdk.internal.jimage.ImageReader; + import sun.net.util.URLUtil; +import sun.net.www.protocol.jrt.JavaRuntimeURLConnection; /** * This class is used to maintain a search path of URLs for loading classes @@ -60,12 +62,15 @@ * @author David Connelly */ public class URLClassPath { - final static String USER_AGENT_JAVA_VERSION = "UA-Java-Version"; - final static String JAVA_VERSION; + private static final String USER_AGENT_JAVA_VERSION = "UA-Java-Version"; + private static final String JAVA_HOME; + private static final String JAVA_VERSION; private static final boolean DEBUG; private static final boolean DISABLE_JAR_CHECKING; static { + JAVA_HOME = java.security.AccessController.doPrivileged( + new sun.security.action.GetPropertyAction("java.home")); JAVA_VERSION = java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("java.version")); DEBUG = (java.security.AccessController.doPrivileged( @@ -363,6 +368,10 @@ return new Loader(url); } } else { + if (file != null && "file".equals(url.getProtocol())) { + if (file.endsWith(".jimage")) + return new JImageLoader(url); + } return new JarLoader(url, jarHandler, lmap); } } @@ -980,7 +989,6 @@ } ensureOpen(); - parseExtensionsDependencies(); if (SharedSecrets.javaUtilJarAccess().jarFileHasClassPathAttribute(jar)) { // Only get manifest when necessary Manifest man = jar.getManifest(); @@ -998,13 +1006,6 @@ } /* - * parse the standard extension dependencies - */ - private void parseExtensionsDependencies() throws IOException { - ExtensionDependency.checkExtensionsDependencies(jar); - } - - /* * Parses value of the Class-Path manifest attribute and returns * an array of URLs relative to the specified base URL. */ @@ -1095,4 +1096,137 @@ return null; } } + + /** + * A Loader of classes and resources from a jimage file located in the + * runtime image. + */ + private static class JImageLoader + extends Loader implements JavaRuntimeURLConnection.ResourceFinder + { + private static final AtomicInteger NEXT_INDEX = new AtomicInteger(); + + private final ImageReader jimage; + private final int index; + + JImageLoader(URL url) throws IOException { + super(url); + + // get path to image file and check that it's in the runtime + String urlPath = url.getFile().replace('/', File.separatorChar); + + File filePath = new File(ParseUtil.decode(urlPath)); + File home = new File(JAVA_HOME); + File parent = filePath.getParentFile(); + while (parent != null) { + if (parent.equals(home)) + break; + parent = parent.getParentFile(); + } + if (parent == null) + throw new IOException(filePath + " not in runtime image"); + + this.jimage = ImageReader.open(filePath.toString()); + this.index = NEXT_INDEX.getAndIncrement(); + + // register with the jimage protocol handler + JavaRuntimeURLConnection.register(this); + } + + /** + * Maps the given resource name to a module. + */ + private String nameToModule(String name) { + int pos = name.lastIndexOf('/'); + if (pos > 0) { + String pkg = name.substring(0, pos); + String module = jimage.getModule(pkg); + if (module != null) + return module; + } + // cannot map to module + return "UNNAMED" + index; + } + + /** + * Constructs a URL for the resource name. + */ + private URL toURL(String name) { + String module = nameToModule(name); + String encodedName = ParseUtil.encodePath(name, false); + try { + return new URL("jrt:/" + module + "/" + encodedName); + } catch (MalformedURLException e) { + throw new InternalError(e); + } + } + + @Override + URL findResource(String name, boolean check) { + ImageLocation location = jimage.findLocation(name); + if (location == null) + return null; + URL url = toURL(name); + if (check) { + try { + URLClassPath.check(url); + } catch (IOException | SecurityException e) { + return null; + } + } + return url; + } + + @Override + Resource getResource(String name, boolean check) { + ImageLocation location = jimage.findLocation(name); + if (location == null) + return null; + URL url = toURL(name); + if (check) { + try { + URLClassPath.check(url); + } catch (IOException | SecurityException e) { + return null; + } + } + return new Resource() { + @Override + public String getName() { return name; } + @Override + public URL getURL() { return url; } + @Override + public URL getCodeSourceURL() { + try { + return new URL("jrt:/" + nameToModule(name)); + } catch (MalformedURLException e) { + throw new InternalError(e); + } + } + @Override + public InputStream getInputStream() throws IOException { + byte[] resource = jimage.getResource(location); + return new ByteArrayInputStream(resource); + } + public int getContentLength() { + long size = location.getUncompressedSize(); + return (size > Integer.MAX_VALUE) ? -1 : (int)size; + } + }; + } + + @Override + public void close() { + throw new UnsupportedOperationException(); + } + + @Override + public Resource find(String module, String name) throws IOException { + String m = nameToModule(name); + if (!m.equals(module)) + return null; + // URLConnection will do the permission check + return getResource(name, false); + } + } }