changeset 10800:b7eeec9aac5d

Add compression support to jimage format Contributed-by: sundararajan.athijegannathan@oracle.com
author alanb
date Sat, 11 Oct 2014 14:44:43 +0100
parents 0ecba7b109ab
children 256a69aebbd4
files make/lib/CoreLibraries.gmk make/mapfiles/libzip/mapfile-vers src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java src/java.base/share/classes/jdk/internal/jimage/BasicImageWriter.java src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java src/java.base/share/classes/jdk/internal/jimage/PackageModuleMap.java src/java.base/share/classes/sun/misc/URLClassPath.java src/java.base/share/classes/sun/net/www/protocol/jimage/Handler.java src/java.base/share/native/libzip/zip_util.c src/java.base/share/native/libzip/zip_util.h src/jdk.dev/share/classes/jdk/tools/jimage/JImageTask.java
diffstat 11 files changed, 104 insertions(+), 74 deletions(-) [+]
line wrap: on
line diff
--- a/make/lib/CoreLibraries.gmk	Thu Oct 09 11:20:05 2014 +0100
+++ b/make/lib/CoreLibraries.gmk	Sat Oct 11 14:44:43 2014 +0100
@@ -224,8 +224,8 @@
         $(call SET_SHARED_LIBRARY_ORIGIN) \
         $(EXPORT_ZIP_FUNCS), \
     LDFLAGS_windows := -export:ZIP_Open -export:ZIP_Close -export:ZIP_FindEntry \
-        -export:ZIP_ReadEntry -export:ZIP_GetNextEntry jvm.lib \
-        $(WIN_JAVA_LIB), \
+        -export:ZIP_ReadEntry -export:ZIP_GetNextEntry -export:ZIP_InflateFully \
+        jvm.lib $(WIN_JAVA_LIB), \
     LDFLAGS_SUFFIX_linux := -ljvm -ljava $(LIBZ), \
     LDFLAGS_SUFFIX_solaris := -ljvm -ljava $(LIBZ) -lc, \
     LDFLAGS_SUFFIX_aix := -ljvm -ljava $(LIBZ),\
--- a/make/mapfiles/libzip/mapfile-vers	Thu Oct 09 11:20:05 2014 +0100
+++ b/make/mapfiles/libzip/mapfile-vers	Sat Oct 11 14:44:43 2014 +0100
@@ -72,6 +72,7 @@
 		ZIP_FindEntry;
 		ZIP_GetEntry;
 		ZIP_GetNextEntry;
+	        ZIP_InflateFully;
 		ZIP_Lock;
 		ZIP_Open;
 		ZIP_Read;
--- a/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java	Thu Oct 09 11:20:05 2014 +0100
+++ b/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java	Sat Oct 11 14:44:43 2014 +0100
@@ -190,7 +190,7 @@
         return strings.get(offset).toString();
     }
 
-    synchronized public byte[] getResource(long offset, long size) throws IOException {
+    private synchronized byte[] read(long offset, long size) throws IOException {
         byte[] bytes = new byte[(int)size];
         file.seek(indexSize + offset);
         file.read(bytes);
@@ -198,8 +198,13 @@
         return bytes;
     }
 
-    protected byte[] getResource(ImageLocation loc) throws IOException {
-        // handle decompression here!
-        return getResource(loc.getContentOffset(), loc.getUncompressedSize());
+    public byte[] getResource(ImageLocation loc) throws IOException {
+        long compressedSize = loc.getCompressedSize();
+        if (compressedSize == 0) {
+            return read(loc.getContentOffset(), loc.getUncompressedSize());
+        } else {
+            byte[] buf = read(loc.getContentOffset(), compressedSize);
+            return ImageFile.Compressor.decompress(buf);
+        }
     }
 }
--- a/src/java.base/share/classes/jdk/internal/jimage/BasicImageWriter.java	Thu Oct 09 11:20:05 2014 +0100
+++ b/src/java.base/share/classes/jdk/internal/jimage/BasicImageWriter.java	Sat Oct 11 14:44:43 2014 +0100
@@ -104,7 +104,7 @@
     }
 
     public void addLocation(String fullname, long contentOffset, long compressedSize, long uncompressedSize) {
-        ImageLocation location = ImageLocation.newLocation(new UTF8String(fullname), strings, contentOffset, uncompressedSize);
+        ImageLocation location = ImageLocation.newLocation(new UTF8String(fullname), strings, contentOffset, compressedSize, uncompressedSize);
         input.add(location);
         count++;
     }
--- a/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java	Thu Oct 09 11:20:05 2014 +0100
+++ b/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java	Sat Oct 11 14:44:43 2014 +0100
@@ -186,7 +186,7 @@
         }
     }
 
-    static ImageLocation newLocation(UTF8String fullname, ImageStrings strings, long contentOffset, long uncompressedSize) {
+    static ImageLocation newLocation(UTF8String fullname, ImageStrings strings, long contentOffset, long compressedSize, long uncompressedSize) {
         UTF8String base;
         UTF8String extension = extension(fullname);
         int parentOffset = ImageStrings.EMPTY_OFFSET;
@@ -209,6 +209,7 @@
                .addAttribute(ATTRIBUTE_PARENT, parentOffset)
                .addAttribute(ATTRIBUTE_EXTENSION, extensionOffset)
                .addAttribute(ATTRIBUTE_OFFSET, contentOffset)
+               .addAttribute(ATTRIBUTE_COMPRESSED, compressedSize)
                .addAttribute(ATTRIBUTE_UNCOMPRESSED, uncompressedSize);
     }
 
--- a/src/java.base/share/classes/jdk/internal/jimage/PackageModuleMap.java	Thu Oct 09 11:20:05 2014 +0100
+++ b/src/java.base/share/classes/jdk/internal/jimage/PackageModuleMap.java	Sat Oct 11 14:44:43 2014 +0100
@@ -49,7 +49,7 @@
     static Map<String,String> readFrom(ImageReader reader) throws IOException {
         Map<String,String> result = new HashMap<>();
         ImageLocation loc = reader.findLocation(MODULES_ENTRY);
-        byte[] bytes = reader.getResource(loc.getContentOffset(), loc.getUncompressedSize());
+        byte[] bytes = reader.getResource(loc);
         IntBuffer mbufs = ByteBuffer.wrap(bytes).asIntBuffer();
         List<String> mnames = new ArrayList<>();
         while (mbufs.hasRemaining()) {
@@ -59,7 +59,7 @@
 
         for (String mn : mnames) {
             ImageLocation mindex = reader.findLocation(mn + "/" + PACKAGES_ENTRY);
-            byte[] poffsets = reader.getResource(mindex.getContentOffset(), mindex.getUncompressedSize());
+            byte[] poffsets = reader.getResource(mindex);
             IntBuffer pbufs = ByteBuffer.wrap(poffsets).asIntBuffer();
             while (pbufs.hasRemaining()) {
                 int poffset = pbufs.get();
--- a/src/java.base/share/classes/sun/misc/URLClassPath.java	Thu Oct 09 11:20:05 2014 +0100
+++ b/src/java.base/share/classes/sun/misc/URLClassPath.java	Sat Oct 11 14:44:43 2014 +0100
@@ -1180,18 +1180,7 @@
                 }
                 @Override
                 public InputStream getInputStream() throws IOException {
-                    long offset = location.getContentOffset();
-                    long size = location.getUncompressedSize();
-                    long compressedSize = location.getCompressedSize();
-                    byte[] resource;
-                    if (compressedSize != 0) {
-                        // TODO - handle compression.
-                        resource = jimage.getResource(offset, compressedSize);
-                        // resource = decompress(resource);
-                    } else {
-                        resource = jimage.getResource(offset, size);
-                    }
-
+                    byte[] resource = jimage.getResource(location);
                     return new ByteArrayInputStream(resource);
                 }
                 public int getContentLength() {
--- a/src/java.base/share/classes/sun/net/www/protocol/jimage/Handler.java	Thu Oct 09 11:20:05 2014 +0100
+++ b/src/java.base/share/classes/sun/net/www/protocol/jimage/Handler.java	Sat Oct 11 14:44:43 2014 +0100
@@ -46,43 +46,48 @@
 
     @Override
     protected URLConnection openConnection(URL url) throws IOException {
+        return new JImageURLConnection(url);
+    }
+}
+
+class JImageURLConnection extends URLConnection {
+    private final ImageReader jimage;
+    private final ImageLocation location;
+
+    JImageURLConnection(URL url) throws IOException {
+        super(url);
+
         String s = url.toString();
         int index = s.indexOf("!/");
         if (index == -1)
             throw new MalformedURLException("no !/ found in url spec:" + s);
         URL base = new URL(s.substring(0, index++));
 
-        // use jiage cache to open or get existing connection to jimage file
-        final ImageReader jimage = sun.misc.JImageCache.get(base);
+        // use jimage cache to open or get existing connection to jimage file
+        // (this checks access to the jimage file)
+        ImageReader jimage = sun.misc.JImageCache.get(base);
         if (jimage == null)
             throw new IOException("cannot open " + base);
 
         String entry = sun.net.www.ParseUtil.decode(s.substring(index+1));
-        final ImageLocation location = jimage.findLocation(entry);
+        ImageLocation location = jimage.findLocation(entry);
         if (location == null)
             throw new IOException(entry + " not found");
-        return new URLConnection(url) {
-            @Override
-            public void connect() { }
-            @Override
-            public InputStream getInputStream() throws IOException {
-                long offset = location.getContentOffset();
-                long size = location.getUncompressedSize();
-                long compressedSize = location.getCompressedSize();
-                byte[] resource;
-                if (compressedSize != 0) {
-                    // TODO - handle compression.
-                    resource = jimage.getResource(offset, compressedSize);
-                    // resource = decompress(resource);
-                } else {
-                    resource = jimage.getResource(offset, size);
-                }
-                return new ByteArrayInputStream(resource);
-            }
-            @Override
-            public long getContentLengthLong() {
-                return location.getUncompressedSize();
-            }
-        };
+
+        this.jimage = jimage;
+        this.location = location;
+    }
+
+    @Override
+    public void connect() { }
+
+    @Override
+    public InputStream getInputStream() throws IOException {
+        byte[] resource = jimage.getResource(location);
+        return new ByteArrayInputStream(resource);
+    }
+    @Override
+    public long getContentLengthLong() {
+        return location.getUncompressedSize();
     }
 }
--- a/src/java.base/share/native/libzip/zip_util.c	Thu Oct 09 11:20:05 2014 +0100
+++ b/src/java.base/share/native/libzip/zip_util.c	Sat Oct 11 14:44:43 2014 +0100
@@ -1392,6 +1392,7 @@
             }
         } while (strm.avail_in > 0);
     }
+
     inflateEnd(&strm);
     return JNI_TRUE;
 }
@@ -1463,3 +1464,52 @@
 
     return JNI_TRUE;
 }
+
+jboolean JNICALL
+ZIP_InflateFully(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg)
+{
+    z_stream strm;
+    int i = 0;
+    memset(&strm, 0, sizeof(z_stream));
+
+    *pmsg = 0; /* Reset error message */
+
+    if (inflateInit2(&strm, MAX_WBITS) != Z_OK) {
+        *pmsg = strm.msg;
+        return JNI_FALSE;
+    }
+
+    strm.next_out = (Bytef *) outBuf;
+    strm.avail_out = (uInt)outLen;
+    strm.next_in = (Bytef *) inBuf;
+    strm.avail_in = (uInt)inLen;
+
+    do {
+        switch (inflate(&strm, Z_PARTIAL_FLUSH)) {
+            case Z_OK:
+                break;
+            case Z_STREAM_END:
+                if (strm.total_out != outLen) {
+                    *pmsg = "INFLATER_inflateFully: Unexpected end of stream";
+                    inflateEnd(&strm);
+                    return JNI_FALSE;
+                }
+                break;
+            case Z_DATA_ERROR:
+                *pmsg = "INFLATER_inflateFully: Compressed data corrupted";
+                inflateEnd(&strm);
+                return JNI_FALSE;
+            case Z_MEM_ERROR:
+                *pmsg = "INFLATER_inflateFully: out of memory";
+                inflateEnd(&strm);
+                return JNI_FALSE;
+            default:
+                *pmsg = "INFLATER_inflateFully: internal error";
+                inflateEnd(&strm);
+                return JNI_FALSE;
+        }
+    } while (strm.avail_in > 0);
+
+    inflateEnd(&strm);
+    return JNI_TRUE;
+}
--- a/src/java.base/share/native/libzip/zip_util.h	Thu Oct 09 11:20:05 2014 +0100
+++ b/src/java.base/share/native/libzip/zip_util.h	Sat Oct 11 14:44:43 2014 +0100
@@ -270,4 +270,7 @@
 void ZIP_FreeEntry(jzfile *zip, jzentry *ze);
 jlong ZIP_GetEntryDataOffset(jzfile *zip, jzentry *entry);
 
+jboolean JNICALL
+ZIP_InflateFully(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg);
+
 #endif /* !_ZIP_H_ */
--- a/src/jdk.dev/share/classes/jdk/tools/jimage/JImageTask.java	Thu Oct 09 11:20:05 2014 +0100
+++ b/src/jdk.dev/share/classes/jdk/tools/jimage/JImageTask.java	Sat Oct 11 14:44:43 2014 +0100
@@ -327,20 +327,7 @@
 
     private void expand(BasicImageReader reader, String name, ImageLocation location) throws IOException, BadArgs {
         File directory = new File(options.directory);
-        long offset = location.getContentOffset();
-        long size = location.getUncompressedSize();
-        long compressedSize = location.getCompressedSize();
-        boolean isCompressed = compressedSize != 0;
-
-        byte[] bytes;
-
-        if (isCompressed) {
-            bytes = reader.getResource(offset, compressedSize);
-            // TODO compression
-        } else {
-            bytes = reader.getResource(offset, size);
-        }
-
+        byte[] bytes = reader.getResource(location);
         File resource =  new File(directory, name);
         File parent = resource.getParentFile();
 
@@ -395,20 +382,9 @@
 
     void verify(BasicImageReader reader, String name, ImageLocation location) {
         if (name.endsWith(".class")) {
-            long offset = location.getContentOffset();
-            long size = location.getUncompressedSize();
-            long compressedSize = location.getCompressedSize();
-            boolean isCompressed = compressedSize != 0;
-
             byte[] bytes;
-
             try {
-                if (isCompressed) {
-                    bytes = reader.getResource(offset, compressedSize);
-                    // TODO compression
-                } else {
-                    bytes = reader.getResource(offset, size);
-                }
+                bytes = reader.getResource(location);
             } catch (IOException ex) {
                 log.println(ex);
                 bytes = null;