changeset 14813:67429f4af9da

Remove the use of substrate for java native image access.
author jlaskey
date Mon, 21 Dec 2015 11:47:07 -0400
parents b5b8222bc934
children 28e85e3dd788
files src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java src/java.base/share/classes/jdk/internal/jimage/ImageJavaSubstrate.java src/java.base/share/classes/jdk/internal/jimage/ImageLocationBase.java src/java.base/share/classes/jdk/internal/jimage/ImageNativeSubstrate.java src/java.base/share/classes/jdk/internal/jimage/ImageReader.java src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java src/java.base/share/classes/jdk/internal/jimage/ImageSubstrate.java src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp test/jdk/internal/jimage/JImageReadTest.java test/jdk/jigsaw/tools/jimage/VerifyJimage.java
diffstat 10 files changed, 301 insertions(+), 1394 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java	Mon Dec 21 11:47:03 2015 -0400
+++ b/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java	Mon Dec 21 11:47:07 2015 -0400
@@ -28,45 +28,111 @@
 import java.io.IOException;
 import java.io.File;
 import java.io.InputStream;
+import java.io.RandomAccessFile;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.nio.IntBuffer;
+import java.nio.channels.FileChannel;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.Comparator;
 import java.util.stream.IntStream;
+import jdk.internal.jimage.decompressor.Decompressor;
 
 public class BasicImageReader implements AutoCloseable {
-    private final String imagePath;
-    private final ImageSubstrate substrate;
+    static private final boolean is64Bit = AccessController.doPrivileged(
+        (PrivilegedAction<Boolean>) () -> "64".equals(System.getProperty("sun.arch.data.model")));
+
     private final ByteOrder byteOrder;
-    private final ImageStringsReader strings;
+    private ByteBuffer map;
+    private final File imageFile;
+    private final RandomAccessFile raf;
+    private final FileChannel channel;
+    private final long size;
+    private final ImageHeader header;
+    private final long indexSize;
+    private final IntBuffer redirect;
+    private final IntBuffer offsets;
+    private final ByteBuffer locations;
+    private final ByteBuffer strings;
+    private final ImageStringsReader stringsReader;
+    private final Decompressor decompressor;
 
     protected BasicImageReader(String imagePath, ByteOrder byteOrder)
             throws IOException {
-        this.imagePath = imagePath;
-        this.substrate = openImageSubstrate(imagePath, byteOrder);
         this.byteOrder = byteOrder;
-        this.strings = new ImageStringsReader(this);
+
+        try {
+            this.map = getNativeMap(imagePath);
+        } catch (UnsatisfiedLinkError ex) {
+            this.map = null;
+        }
+
+        int headerSize = ImageHeader.getHeaderSize();
+
+        if (this.map == null || !is64Bit) {
+            this.imageFile = new File(imagePath);
+            this.raf = new RandomAccessFile(this.imageFile, "r");
+            this.channel = this.raf.getChannel();
+            this.size = this.channel.size();
+            ByteBuffer buffer = ByteBuffer.allocate(headerSize);
+            this.channel.read(buffer, 0L);
+            buffer.rewind();
+            this.header = readHeader(intBuffer(buffer, 0, headerSize));
+            this.indexSize = this.header.getIndexSize();
+            this.map = channel.map(FileChannel.MapMode.READ_ONLY, 0, is64Bit ? size : indexSize);
+        } else {
+            this.imageFile = null;
+            this.raf = null;
+            this.channel = null;
+            this.size = this.map.capacity();
+            this.header = readHeader(intBuffer(this.map, 0, headerSize));
+            this.indexSize = this.header.getIndexSize();
+        }
+
+        this.redirect = intBuffer(this.map, this.header.getRedirectOffset(), this.header.getRedirectSize());
+        this.offsets = intBuffer(this.map, this.header.getOffsetsOffset(), this.header.getOffsetsSize());
+        this.locations = slice(this.map, this.header.getLocationsOffset(), this.header.getLocationsSize());
+        this.strings = slice(this.map, this.header.getStringsOffset(), this.header.getStringsSize());
+
+        this.stringsReader = new ImageStringsReader(this);
+        this.decompressor = new Decompressor();
     }
 
     protected BasicImageReader(String imagePath) throws IOException {
         this(imagePath, ByteOrder.nativeOrder());
     }
 
-    private static ImageSubstrate openImageSubstrate(String imagePath, ByteOrder byteOrder)
-            throws IOException {
-        ImageSubstrate substrate;
+    public static BasicImageReader open(String imagePath) throws IOException {
+        return new BasicImageReader(imagePath, ByteOrder.nativeOrder());
+    }
 
-        try {
-            substrate = ImageNativeSubstrate.openImage(imagePath, byteOrder);
-        } catch (UnsatisfiedLinkError | NoClassDefFoundError ex) {
-            substrate = ImageJavaSubstrate.openImage(imagePath, byteOrder);
+    public ImageHeader getHeader() {
+        return header;
+    }
+
+    private ImageHeader readHeader(IntBuffer buffer) throws IOException {
+        ImageHeader result = ImageHeader.readFrom(buffer);
+
+        if (result.getMagic() != ImageHeader.MAGIC ||
+                result.getMajorVersion() != ImageHeader.MAJOR_VERSION ||
+                result.getMinorVersion() != ImageHeader.MINOR_VERSION) {
+            throw new IOException("Image not found \"" + imageFile + "\"");
         }
 
-        return substrate;
+        return result;
     }
 
-    public static BasicImageReader open(String imagePath) throws IOException {
-        return new BasicImageReader(imagePath, ByteOrder.nativeOrder());
+    private ByteBuffer slice(ByteBuffer buffer, int position, int capacity) {
+        synchronized(buffer) {
+            buffer.limit(position + capacity);
+            buffer.position(position);
+            return buffer.slice();
+        }
+    }
+
+    private IntBuffer intBuffer(ByteBuffer buffer, int offset, int size) {
+        return slice(buffer, offset, size).order(byteOrder).asIntBuffer();
     }
 
     public static void releaseByteBuffer(ByteBuffer buffer) {
@@ -77,35 +143,17 @@
         return byteOrder;
     }
 
-    public String imagePath() {
-        return imagePath;
+    public File getImageFile() {
+        return imageFile;
     }
 
-    public String imagePathName() {
-        int slash = imagePath().lastIndexOf(File.separator);
-
-        if (slash != -1) {
-            return imagePath().substring(slash + 1);
-        }
-
-        return imagePath();
-    }
-
-    public boolean isOpen() {
-        return true;
-    }
-
+    @Override
     public void close() throws IOException {
-        substrate.close();
-    }
-
-    public ImageHeader getHeader() throws IOException {
-        return ImageHeader.readFrom(
-                getIndexIntBuffer(0, ImageHeader.getHeaderSize()));
+        raf.close();
     }
 
     public ImageStringsReader getStrings() {
-        return strings;
+        return stringsReader;
     }
 
     public ImageLocation findLocation(String mn, String rn) {
@@ -113,11 +161,31 @@
     }
 
     public synchronized ImageLocation findLocation(String name) {
-        return substrate.findLocation(name, strings);
+        byte[] bytes = ImageStringsReader.mutf8FromString(name);
+        int count = header.getTableLength();
+        int index = redirect.get(ImageStringsReader.hashCode(bytes) % count);
+
+        if (index < 0) {
+            index = -index - 1;
+        } else {
+            index = ImageStringsReader.hashCode(bytes, index) % count;
+        }
+
+        long[] attributes = getAttributes(offsets.get(index));
+
+        ImageLocation imageLocation = new ImageLocation(attributes, stringsReader);
+
+        if (!imageLocation.verify(name)) {
+            return null;
+        }
+
+        return imageLocation;
     }
 
     public String[] getEntryNames() {
-        return IntStream.of(substrate.attributeOffsets())
+        int[] attributeOffsets = new int[offsets.capacity()];
+        offsets.get(attributeOffsets);
+        return IntStream.of(attributeOffsets)
                         .filter(o -> o != 0)
                         .mapToObj(o -> ImageLocation.readFrom(this, o).getFullName())
                         .sorted()
@@ -125,77 +193,63 @@
     }
 
     protected ImageLocation[] getAllLocations(boolean sorted) {
-        return IntStream.of(substrate.attributeOffsets())
+        int[] attributeOffsets = new int[offsets.capacity()];
+        offsets.get(attributeOffsets);
+        return IntStream.of(attributeOffsets)
                         .filter(o -> o != 0)
                         .mapToObj(o -> ImageLocation.readFrom(this, o))
                         .sorted(Comparator.comparing(ImageLocation::getFullName))
                         .toArray(ImageLocation[]::new);
     }
 
-    private IntBuffer getIndexIntBuffer(long offset, long size)
-            throws IOException {
-        ByteBuffer buffer = substrate.getIndexBuffer(offset, size);
-        buffer.order(byteOrder);
-
-        return buffer.asIntBuffer();
-    }
-
     ImageLocation getLocation(int offset) {
         return ImageLocation.readFrom(this, offset);
     }
 
     public long[] getAttributes(int offset) {
-        return substrate.getAttributes(offset);
+        ByteBuffer buffer = slice(locations, offset, locations.limit() - offset);
+        return ImageLocationBase.decompress(buffer);
     }
 
     public String getString(int offset) {
-        byte[] bytes = substrate.getStringBytes(offset);
-        return ImageStringsReader.stringFromMUTF8(bytes, 0, bytes.length);
+        ByteBuffer buffer = slice(strings, offset, strings.limit() - offset);
+        return ImageStringsReader.stringFromByteBuffer(buffer);
     }
 
-    private byte[] getBufferBytes(ByteBuffer buffer, long size) {
-        assert size < Integer.MAX_VALUE;
-        byte[] bytes = new byte[(int)size];
+    private byte[] getBufferBytes(ByteBuffer buffer) {
+        byte[] bytes = new byte[buffer.limit()];
         buffer.get(bytes);
 
         return bytes;
     }
 
-    private byte[] getBufferBytes(long offset, long size) {
-        ByteBuffer buffer = substrate.getDataBuffer(offset, size);
+    private ByteBuffer readBuffer(long offset, long size) {
+        assert offset < Integer.MAX_VALUE;
+        assert size < Integer.MAX_VALUE;
 
-        return getBufferBytes(buffer, size);
-    }
+        if (is64Bit) {
+            ByteBuffer buffer = slice(map, (int)offset, (int)size);
+            buffer.order(ByteOrder.BIG_ENDIAN);
 
-    public byte[] getResource(ImageLocation loc) {
-        long offset = loc.getContentOffset();
-        long compressedSize = loc.getCompressedSize();
-        long uncompressedSize = loc.getUncompressedSize();
-        assert compressedSize < Integer.MAX_VALUE;
-        assert uncompressedSize < Integer.MAX_VALUE;
+            return buffer;
+        } else {
+            ByteBuffer buffer = ImageBufferCache.getBuffer(size);
+            int read = 0;
 
-        if (substrate.supportsDataBuffer() && compressedSize == 0) {
-            return getBufferBytes(offset, uncompressedSize);
+            try {
+                assert channel != null: "Image file channel not open";
+                read = channel.read(buffer, offset);
+                buffer.rewind();
+            } catch (IOException ex) {
+                throw new RuntimeException(ex);
+            }
+
+            if (read != size) {
+                ImageBufferCache.releaseBuffer(buffer);
+            }
+
+            return buffer;
         }
-
-        ByteBuffer uncompressedBuffer = ImageBufferCache.getBuffer(uncompressedSize);
-        boolean isRead;
-
-        if (compressedSize != 0) {
-            ByteBuffer compressedBuffer = ImageBufferCache.getBuffer(compressedSize);
-            isRead = substrate.read(offset, compressedBuffer, compressedSize,
-                                          uncompressedBuffer, uncompressedSize);
-            ImageBufferCache.releaseBuffer(compressedBuffer);
-        } else {
-            isRead = substrate.read(offset, uncompressedBuffer, uncompressedSize);
-        }
-
-        byte[] bytes = isRead ? getBufferBytes(uncompressedBuffer,
-                                               uncompressedSize) : null;
-
-        ImageBufferCache.releaseBuffer(uncompressedBuffer);
-
-        return bytes;
     }
 
     public byte[] getResource(String name) {
@@ -204,36 +258,47 @@
         return location != null ? getResource(location) : null;
     }
 
+    public byte[] getResource(ImageLocation loc) {
+        ByteBuffer buffer = getResourceBuffer(loc);
+
+        if (buffer != null) {
+            byte[] bytes = getBufferBytes(buffer);
+            ImageBufferCache.releaseBuffer(buffer);
+
+            return bytes;
+        }
+
+        return null;
+    }
+
     public ByteBuffer getResourceBuffer(ImageLocation loc) {
-        long offset = loc.getContentOffset();
+        long offset = loc.getContentOffset() + indexSize;
         long compressedSize = loc.getCompressedSize();
         long uncompressedSize = loc.getUncompressedSize();
         assert compressedSize < Integer.MAX_VALUE;
         assert uncompressedSize < Integer.MAX_VALUE;
 
-        if (substrate.supportsDataBuffer() && compressedSize == 0) {
-            return substrate.getDataBuffer(offset, uncompressedSize);
+        if (compressedSize == 0) {
+            return readBuffer(offset, uncompressedSize);
+        } else {
+            ByteBuffer buffer = readBuffer(offset, compressedSize);
+
+            if (buffer != null) {
+                byte[] bytesIn = getBufferBytes(buffer);
+                ImageBufferCache.releaseBuffer(buffer);
+                byte[] bytesOut;
+
+                try {
+                    bytesOut = decompressor.decompressResource(byteOrder, (int strOffset) -> getString(strOffset), bytesIn);
+                } catch (IOException ex) {
+                    throw new RuntimeException(ex);
+                }
+
+                return ByteBuffer.wrap(bytesOut);
+            }
         }
 
-        ByteBuffer uncompressedBuffer = ImageBufferCache.getBuffer(uncompressedSize);
-        boolean isRead;
-
-        if (compressedSize != 0) {
-            ByteBuffer compressedBuffer = ImageBufferCache.getBuffer(compressedSize);
-            isRead = substrate.read(offset, compressedBuffer, compressedSize,
-                                          uncompressedBuffer, uncompressedSize);
-            ImageBufferCache.releaseBuffer(compressedBuffer);
-        } else {
-            isRead = substrate.read(offset, uncompressedBuffer, uncompressedSize);
-        }
-
-        if (isRead) {
-            return uncompressedBuffer;
-        } else {
-            ImageBufferCache.releaseBuffer(uncompressedBuffer);
-
-            return null;
-        }
+        return null;
     }
 
     public ByteBuffer getResourceBuffer(String name) {
--- a/src/java.base/share/classes/jdk/internal/jimage/ImageJavaSubstrate.java	Mon Dec 21 11:47:03 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,243 +0,0 @@
-/*
- * Copyright (c) 2014, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.internal.jimage;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.IntBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.file.Paths;
-import static java.nio.file.StandardOpenOption.READ;
-import jdk.internal.jimage.decompressor.Decompressor;
-
-final class ImageJavaSubstrate implements ImageSubstrate {
-
-    private final String imagePath;
-    private final ByteOrder byteOrder;
-    private final FileChannel channel;
-    private final ImageHeader header;
-    private final long indexSize;
-    private final int[] redirect;
-    private final int[] offsets;
-    private final byte[] locations;
-    private final byte[] strings;
-
-    private final Decompressor decompressor = new Decompressor();
-
-  private ImageJavaSubstrate(String imagePath, ByteOrder byteOrder)
-          throws IOException {
-        this.imagePath = imagePath;
-        this.byteOrder = byteOrder;
-        channel = FileChannel.open(Paths.get(imagePath), READ);
-
-        int headerSize = ImageHeader.getHeaderSize();
-        ByteBuffer buffer = getIndexBuffer(0, headerSize);
-        header = ImageHeader.readFrom(buffer.asIntBuffer());
-
-        if (header.getMagic() != ImageHeader.MAGIC ||
-            header.getMajorVersion() != ImageHeader.MAJOR_VERSION ||
-            header.getMinorVersion() != ImageHeader.MINOR_VERSION) {
-            throw new IOException("Image not found \"" + imagePath + "\"");
-        }
-
-        indexSize = header.getIndexSize();
-
-        redirect = readIntegers(header.getRedirectOffset(),
-                                header.getRedirectSize());
-        offsets = readIntegers(header.getOffsetsOffset(),
-                               header.getOffsetsSize());
-        locations = readBytes(header.getLocationsOffset(),
-                              header.getLocationsSize());
-        strings = readBytes(header.getStringsOffset(),
-                            header.getStringsSize());
-    }
-
-    static ImageSubstrate openImage(String imagePath, ByteOrder byteOrder)
-            throws IOException {
-        return new ImageJavaSubstrate(imagePath, byteOrder);
-    }
-
-    @Override
-    public void close() {
-        try {
-            channel.close();
-        } catch (IOException ex) {
-            // Mostly harmless
-        }
-    }
-
-    @Override
-    public boolean supportsDataBuffer() {
-        return false;
-    }
-
-    private int[] readIntegers(long offset, long size) {
-        assert size < Integer.MAX_VALUE;
-        IntBuffer buffer = readBuffer(offset, size).asIntBuffer();
-        int[] integers = new int[(int)size / 4];
-        buffer.get(integers);
-
-        return integers;
-    }
-
-    private byte[] readBytes(long offset, long size) {
-        assert size < Integer.MAX_VALUE;
-        ByteBuffer buffer = readBuffer(offset, size);
-        byte[] bytes = new byte[(int)size];
-        buffer.get(bytes);
-
-        return bytes;
-    }
-
-    private ByteBuffer readBuffer(long offset, long size) {
-        assert size < Integer.MAX_VALUE;
-        ByteBuffer buffer = ByteBuffer.allocate((int)size);
-        buffer.order(byteOrder);
-
-        if (!readBuffer(buffer, offset, size)) {
-            return null;
-        }
-
-        return buffer;
-    }
-
-    private boolean readBuffer(ByteBuffer buffer, long offset, long size) {
-        assert size < Integer.MAX_VALUE;
-        assert buffer.limit() == size;
-        int read = 0;
-
-        try {
-            read = channel.read(buffer, offset);
-            buffer.rewind();
-        } catch (IOException ex) {
-            // fall thru
-        }
-
-        return read == size;
-    }
-
-    @Override
-    public ByteBuffer getIndexBuffer(long offset, long size) {
-        assert size < Integer.MAX_VALUE;
-        return readBuffer(offset, size);
-    }
-
-    @Override
-    public ByteBuffer getDataBuffer(long offset, long size) {
-        assert size < Integer.MAX_VALUE;
-        return getIndexBuffer(indexSize + offset, size);
-    }
-
-    @Override
-    public boolean read(long offset,
-                 ByteBuffer compressedBuffer, long compressedSize,
-                 ByteBuffer uncompressedBuffer, long uncompressedSize) {
-        assert compressedSize < Integer.MAX_VALUE;
-        assert uncompressedSize < Integer.MAX_VALUE;
-        boolean isRead = readBuffer(compressedBuffer,
-                                    indexSize + offset, compressedSize);
-        if (isRead) {
-            byte[] bytesIn = new byte[(int)compressedSize];
-            compressedBuffer.get(bytesIn);
-            byte[] bytesOut;
-            try {
-                bytesOut = decompressor.decompressResource(byteOrder, (int strOffset) -> {
-                    byte[] bytes = getStringBytes(strOffset);
-                    return ImageStringsReader.stringFromMUTF8(bytes, 0, bytes.length);
-                }, bytesIn);
-            } catch (IOException ex) {
-                throw new RuntimeException(ex);
-            }
-            uncompressedBuffer.put(bytesOut);
-            uncompressedBuffer.rewind();
-        }
-
-        return isRead;
-    }
-
-    @Override
-    public boolean read(long offset,
-                 ByteBuffer uncompressedBuffer, long uncompressedSize) {
-        assert uncompressedSize < Integer.MAX_VALUE;
-        boolean isRead = readBuffer(uncompressedBuffer,
-                                    indexSize + offset, uncompressedSize);
-
-        return isRead;
-    }
-
-    @Override
-    public byte[] getStringBytes(int offset) {
-        if (offset == 0) {
-            return new byte[0];
-        }
-
-        int length = strings.length - offset;
-
-        for (int i = offset; i < strings.length; i++) {
-            if (strings[i] == 0) {
-                length = i - offset;
-                break;
-            }
-        }
-
-        byte[] bytes = new byte[length];
-        System.arraycopy(strings, offset, bytes, 0, length);
-
-        return bytes;
-    }
-
-    @Override
-    public long[] getAttributes(int offset) {
-        return ImageLocationBase.decompress(locations, offset);
-    }
-
-    @Override
-    public ImageLocation findLocation(String name, ImageStringsReader strings) {
-        int count = header.getTableLength();
-        int index = redirect[ImageStringsReader.hashCode(name) % count];
-
-        if (index < 0) {
-            index = -index - 1;
-        } else {
-            index = ImageStringsReader.hashCode(name, index) % count;
-        }
-
-        long[] attributes = getAttributes(offsets[index]);
-
-        ImageLocation imageLocation = new ImageLocation(attributes, strings);
-
-        if (!imageLocation.verify(name)) {
-            return null;
-        }
-
-        return imageLocation;
-   }
-
-    @Override
-    public int[] attributeOffsets() {
-        return offsets;
-    }
-}
--- a/src/java.base/share/classes/jdk/internal/jimage/ImageLocationBase.java	Mon Dec 21 11:47:03 2015 -0400
+++ b/src/java.base/share/classes/jdk/internal/jimage/ImageLocationBase.java	Mon Dec 21 11:47:07 2015 -0400
@@ -25,6 +25,8 @@
 
 package jdk.internal.jimage;
 
+import java.nio.ByteBuffer;
+
 public class ImageLocationBase {
     public static final int ATTRIBUTE_END = 0;
     public static final int ATTRIBUTE_MODULE = 1;
@@ -57,16 +59,12 @@
         return data >>> 3;
     }
 
-    protected static long[] decompress(byte[] bytes) {
-        return decompress(bytes, 0);
-    }
-
-    protected static long[] decompress(byte[] bytes, int offset) {
+    protected static long[] decompress(ByteBuffer bytes) {
         long[] attributes = new long[ATTRIBUTE_COUNT];
 
         if (bytes != null) {
-            for (int i = offset; i < bytes.length; ) {
-                int data = bytes[i++] & 0xFF;
+            while (bytes.hasRemaining()) {
+                int data = bytes.get() & 0xFF;
                 int kind = attributeKind(data);
 
                 if (kind == ATTRIBUTE_END) {
@@ -80,7 +78,8 @@
 
                 for (int j = 0; j < length; j++) {
                     value <<= 8;
-                    value |= bytes[i++] & 0xFF;
+                    assert bytes.hasRemaining() : "Missing attribute data";
+                    value |= bytes.get() & 0xFF;
                 }
 
                  attributes[kind] = value;
--- a/src/java.base/share/classes/jdk/internal/jimage/ImageNativeSubstrate.java	Mon Dec 21 11:47:03 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,219 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.internal.jimage;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-public final class ImageNativeSubstrate implements ImageSubstrate {
-    static {
-        java.security.AccessController.doPrivileged(
-            new java.security.PrivilegedAction<Void>() {
-                @Override
-                public Void run() {
-                    System.loadLibrary("jimage");
-                    return null;
-                }
-            });
-     }
-
-    // TODO: Reinstate when the class below, NIOACCESS, is removed.
-    //private static final JavaNioAccess NIOACCESS =
-    //        SharedSecrets.getJavaNioAccess();
-
-
-    private final long id;
-    private final long indexAddress;
-    private final long dataAddress;
-
-    static native long openImage(String imagePath, boolean bigEndian);
-    static native void closeImage(long id);
-    static native long getIndexAddress(long id);
-    static native long getDataAddress(long id);
-    static native boolean readCompressed(long id, long offset,
-            ByteBuffer compressedBuffer, long compressedSize,
-            ByteBuffer uncompressedBuffer, long uncompressedSize);
-    static native boolean read(long id, long offset,
-            ByteBuffer uncompressedBuffer, long uncompressedSize);
-    static native byte[] getStringBytes(long id, int offset);
-    static native long[] getAttributes(long id, int offset);
-    static native long[] findAttributes(long id, byte[] path);
-    static native int[] attributeOffsets(long id);
-
-    public static native long JIMAGE_Open(String path) throws IOException;
-    public static native void JIMAGE_Close(long jimageHandle);
-    public static native long JIMAGE_FindResource(long jimageHandle,
-                    String moduleName, String Version, String path,
-                    long[] size);
-    public static native long JIMAGE_GetResource(long jimageHandle,
-                    long locationHandle, byte[] buffer, long size);
-    // Get an array of names that match; return the count found upto array size
-    public static native int JIMAGE_Resources(long jimageHandle,
-                    String[] outputNames);
-    // Return the module name for the package
-    public static native String JIMAGE_PackageToModule(long imageHandle,
-                    String packageName);
-
-    static ByteBuffer newDirectByteBuffer(long address, long capacity) {
-        assert capacity < Integer.MAX_VALUE;
-        return NIOACCESS.newDirectByteBuffer(address, (int)capacity, null);
-    }
-
-    private ImageNativeSubstrate(long id) {
-        this.id = id;
-        this.indexAddress = getIndexAddress(id);
-        this.dataAddress = getDataAddress(id);
-    }
-
-    static ImageSubstrate openImage(String imagePath, ByteOrder byteOrder)
-            throws IOException {
-        long id = openImage(imagePath, byteOrder == ByteOrder.BIG_ENDIAN);
-
-        if (id == 0) {
-             throw new IOException("Image not found \"" + imagePath + "\"");
-        }
-
-        return new ImageNativeSubstrate(id);
-    }
-
-    @Override
-    public void close() {
-        closeImage(id);
-    }
-
-    @Override
-    public ByteBuffer getIndexBuffer(long offset, long size) {
-        return newDirectByteBuffer(indexAddress + offset, size);
-    }
-
-    @Override
-    public ByteBuffer getDataBuffer(long offset, long size) {
-        return dataAddress != 0 ?
-                newDirectByteBuffer(dataAddress + offset, size) : null;
-    }
-
-    @Override
-    public boolean supportsDataBuffer() {
-        return dataAddress != 0;
-    }
-
-    @Override
-    public boolean read(long offset,
-                 ByteBuffer compressedBuffer, long compressedSize,
-                 ByteBuffer uncompressedBuffer, long uncompressedSize) {
-        return readCompressed(id, offset,
-                    compressedBuffer, compressedSize,
-                    uncompressedBuffer, uncompressedSize);
-    }
-
-    @Override
-    public boolean read(long offset,
-                 ByteBuffer uncompressedBuffer, long uncompressedSize) {
-        return read(id, offset, uncompressedBuffer, uncompressedSize);
-    }
-
-    @Override
-    public byte[] getStringBytes(int offset) {
-        byte[] ret = getStringBytes(id, offset);
-        if (ret == null) {
-            throw new OutOfMemoryError("Error accessing array at offset "
-                    + offset);
-        }
-        return ret;
-    }
-
-    @Override
-    public long[] getAttributes(int offset) {
-        return getAttributes(id, offset);
-    }
-
-    @Override
-    public ImageLocation findLocation(String name, ImageStringsReader strings) {
-        long[] attributes = findAttributes(id, ImageStringsReader.mutf8FromString(name));
-
-        return attributes != null ? new ImageLocation(attributes, strings) : null;
-    }
-
-    @Override
-    public int[] attributeOffsets() {
-        return attributeOffsets(id);
-    }
-
-    // TODO: Remove when JRT-FS no longer indirectly depends on ImageNativeSubstrate
-    /**
-     * Reflective wrapper around ShareSecrets JavaNioAccess.
-     *
-     * SharedSecrets and friend interfaces moved from 'sun.misc' to 'jdk.internal.misc'
-     * in 1.9. This class provides the runtime with access to the appropriate
-     * JavaNioAccess methods whether running on 1.9, or lower.
-     */
-    static class NIOACCESS {
-
-        private static final String PKG_PREFIX = "jdk.internal.misc";
-        private static final String LEGACY_PKG_PREFIX = "sun.misc";
-
-        private static final Object javaNioAccess;
-        private static final java.lang.reflect.Method newDirectByteBufferMethod;
-
-        static {
-            try {
-                Class<?> c = getJDKClass("JavaNioAccess");
-
-                java.lang.reflect.Method m =
-                        getJDKClass("SharedSecrets").getDeclaredMethod("getJavaNioAccess");
-                javaNioAccess = m.invoke(null);
-
-                newDirectByteBufferMethod = c.getDeclaredMethod("newDirectByteBuffer",
-                                                                long.class,
-                                                                int.class,
-                                                                Object.class);
-            } catch (ReflectiveOperationException x) {
-                throw new InternalError(x);
-            }
-        }
-
-        private static Class<?> getJDKClass(String name) throws ClassNotFoundException {
-            try {
-                return Class.forName(PKG_PREFIX + "." + name);
-            } catch (ClassNotFoundException x) {
-                try {
-                    return Class.forName(LEGACY_PKG_PREFIX + "." + name);
-                } catch (ClassNotFoundException ex) {
-                    x.addSuppressed(ex);
-                    throw x;
-                }
-            }
-        }
-
-        static ByteBuffer newDirectByteBuffer(long addr, int cap, Object ob) {
-            try {
-                return (ByteBuffer) newDirectByteBufferMethod.invoke(javaNioAccess, addr, cap, ob);
-            } catch (ReflectiveOperationException x) {
-                throw new InternalError(x);
-            }
-        }
-    }
-}
--- a/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java	Mon Dec 21 11:47:03 2015 -0400
+++ b/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java	Mon Dec 21 11:47:07 2015 -0400
@@ -584,7 +584,7 @@
         BasicFileAttributes attrs = imageFileAttributes;
         if (attrs == null) {
             try {
-                Path file = Paths.get(imagePath());
+                Path file = getImageFile().toPath();
                 attrs = Files.readAttributes(file, BasicFileAttributes.class);
             } catch (IOException ioe) {
                 throw new UncheckedIOException(ioe);
--- a/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java	Mon Dec 21 11:47:03 2015 -0400
+++ b/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java	Mon Dec 21 11:47:07 2015 -0400
@@ -25,6 +25,8 @@
 
 package jdk.internal.jimage;
 
+import java.nio.ByteBuffer;
+
 public class ImageStringsReader implements ImageStrings {
     public static final int HASH_MULTIPLIER = 0x01000193;
     private final BasicImageReader reader;
@@ -43,7 +45,7 @@
         throw new InternalError("Can not add strings at runtime");
     }
 
-    private static int hashCode(int seed, byte[] bytes, int offset, int count) {
+    private static int hashCode(byte[] bytes, int offset, int count, int seed) {
         for (int i = offset, limit = offset + count; i < limit; i++) {
             seed = (seed * HASH_MULTIPLIER) ^ (bytes[i] & 0xFF);
         }
@@ -51,14 +53,20 @@
         return seed & 0x7FFFFFFF;
     }
 
-    public static int hashCode(String string) {
-        return hashCode(string, HASH_MULTIPLIER);
+    public static int hashCode(byte[] bytes, int seed) {
+        return hashCode(bytes, 0, bytes.length, seed);
+    }
+
+    public static int hashCode(byte[] bytes) {
+        return hashCode(bytes, 0, bytes.length, HASH_MULTIPLIER);
     }
 
     public static int hashCode(String string, int seed) {
-        byte[] bytes = mutf8FromString(string);
+        return hashCode(mutf8FromString(string), seed);
+    }
 
-        return hashCode(seed, bytes, 0, bytes.length);
+    public static int hashCode(String string) {
+        return hashCode(mutf8FromString(string), HASH_MULTIPLIER);
     }
 
     static int charsFromMUTF8Length(byte[] bytes, int offset, int count) {
@@ -121,6 +129,66 @@
         return stringFromMUTF8(bytes, 0, bytes.length);
     }
 
+   static int charsFromByteBufferLength(ByteBuffer buffer) {
+        int length = 0;
+
+        while(buffer.hasRemaining()) {
+            byte ch = buffer.get();
+
+            if (ch == 0) {
+                return length;
+            }
+
+            if ((ch & 0xC0) != 0x80) {
+                length++;
+            }
+        }
+
+        assert true : "No terminating zero byte";
+        return length;
+    }
+
+    static void charsFromByteBuffer(char chars[], ByteBuffer buffer) {
+        int j = 0;
+
+        while(buffer.hasRemaining()) {
+            byte ch = buffer.get();
+
+            if (ch == 0) {
+                return;
+            }
+
+            boolean is_unicode = (ch & 0x80) != 0;
+            int uch = ch & 0x7F;
+
+            if (is_unicode) {
+                int mask = 0x40;
+
+                while ((uch & mask) != 0) {
+                    ch = buffer.get();
+                    assert (ch & 0xC0) == 0x80 : "error in unicode";
+                    uch = ((uch & ~mask) << 6) | (ch & 0x3F);
+                    mask <<= 6 - 1;
+                }
+            }
+
+            assert (uch & 0xFFFF) == uch : "error in unicode)";
+
+            chars[j++] = (char)uch;
+        }
+
+        assert true : "No terminating zero byte";
+    }
+
+    public static String stringFromByteBuffer(ByteBuffer buffer) {
+        int length = charsFromByteBufferLength(buffer);
+        buffer.rewind();
+        char[] chars = new char[length];
+        charsFromByteBuffer(chars, buffer);
+
+        return new String(chars);
+    }
+
     static int mutf8FromCharsLength(char chars[]) {
         int length = 0;
 
--- a/src/java.base/share/classes/jdk/internal/jimage/ImageSubstrate.java	Mon Dec 21 11:47:03 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2014, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.internal.jimage;
-
-import java.io.Closeable;
-import java.nio.ByteBuffer;
-
-interface ImageSubstrate extends Closeable {
-    @Override
-    void close();
-    boolean supportsDataBuffer();
-    ByteBuffer getIndexBuffer(long offset, long size);
-    ByteBuffer getDataBuffer(long offset, long size);
-    boolean read(long offset,
-                          ByteBuffer compressedBuffer, long compressedSize,
-                          ByteBuffer uncompressedBuffer, long uncompressedSize);
-    boolean read(long offset,
-                          ByteBuffer uncompressedBuffer, long uncompressedSize);
-    byte[] getStringBytes(int offset);
-    long[] getAttributes(int offset);
-    ImageLocation findLocation(String name, ImageStringsReader strings);
-    int[] attributeOffsets();
-}
--- a/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp	Mon Dec 21 11:47:03 2015 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,655 +0,0 @@
-/*
- * Copyright (c) 2015, 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <string.h>
-
-#include "jni.h"
-#include "jni_util.h"
-
-#include "endian.hpp"
-#include "imageDecompressor.hpp"
-#include "imageFile.hpp"
-#include "inttypes.hpp"
-#include "jimage.hpp"
-#include "osSupport.hpp"
-
-#include "jdk_internal_jimage_ImageNativeSubstrate.h"
-
-extern bool MemoryMapImage;
-
-/////////////////////////////////////////////////////////////////////////////
-
-// Static function for primitive throw since libjimage is not linked with libjava
-static void JNICALL ThrowByName(JNIEnv *env, const char *name, const char *msg)
-{
-    jclass cls = (env)->FindClass(name);
-
-    if (cls != 0) /* Otherwise an exception has already been thrown */
-        (env)->ThrowNew(cls, msg);
-}
-
-// jdk.internal.jimage /////////////////////////////////////////////////////////
-
-// Java entry to open an image file for sharing.
-
-static jlong JIMAGE_Open(JNIEnv *env, const char *nativePath, jboolean big_endian) {
-    // Open image file for reading.
-    ImageFileReader* reader = ImageFileReader::open(nativePath, big_endian != JNI_FALSE);
-    // Return image ID as a jlong.
-    return ImageFileReader::readerToID(reader);
-}
-
-// Java entry for closing a shared image file.
-
-static void JIMAGE_Close(JNIEnv *env, jlong id) {
-    // Convert image ID to image reader structure.
-    ImageFileReader* reader = ImageFileReader::idToReader(id);
-    // If valid reader the close.
-    if (reader != NULL) {
-        ImageFileReader::close(reader);
-    }
-}
-
-// Java entry for accessing the base address of the image index.
-
-static jlong JIMAGE_GetIndexAddress(JNIEnv *env, jlong id) {
-    // Convert image ID to image reader structure.
-    ImageFileReader* reader = ImageFileReader::idToReader(id);
-    // If valid reader return index base address (as jlong) else zero.
-    return reader != NULL ? (jlong) reader->get_index_address() : 0L;
-}
-
-// Java entry for accessing the base address of the image data.
-
-static jlong JIMAGE_GetDataAddress(JNIEnv *env, jlong id) {
-    // Convert image ID to image reader structure.
-    ImageFileReader* reader = ImageFileReader::idToReader(id);
-    // If valid reader return data base address (as jlong) else zero.
-    return MemoryMapImage && reader != NULL ? (jlong) reader->get_data_address() : 0L;
-}
-
-// Java entry for reading an uncompressed resource from the image.
-
-static jboolean JIMAGE_Read(JNIEnv *env, jlong id, jlong offset,
-        unsigned char* uncompressedAddress, jlong uncompressed_size) {
-    // Convert image ID to image reader structure.
-    ImageFileReader* reader = ImageFileReader::idToReader(id);\
-  // If not a valid reader the fail the read.
-    if (reader == NULL) return false;
-    // Get the file offset of resource data.
-    u8 file_offset = reader->get_index_size() + offset;
-    // Check validity of arguments.
-    if (offset < 0 ||
-            uncompressed_size < 0 ||
-            file_offset > reader->file_size() - uncompressed_size) {
-        return false;
-    }
-    // Read file content into buffer.
-    return (jboolean) reader->read_at((u1*) uncompressedAddress, uncompressed_size,
-            file_offset);
-}
-
-// Java entry for reading a compressed resource from the image.
-
-static jboolean JIMAGE_ReadCompressed(JNIEnv *env,
-        jlong id, jlong offset,
-        unsigned char* compressedAddress, jlong compressed_size,
-        unsigned char* uncompressedAddress, jlong uncompressed_size) {
-    // Convert image ID to image reader structure.
-    ImageFileReader* reader = ImageFileReader::idToReader(id);
-    // If not a valid reader the fail the read.
-    if (reader == NULL) return false;
-    // Get the file offset of resource data.
-    u8 file_offset = reader->get_index_size() + offset;
-    // Check validity of arguments.
-    if (offset < 0 ||
-            compressed_size < 0 ||
-            uncompressed_size < 0 ||
-            file_offset > reader->file_size() - compressed_size) {
-        return false;
-    }
-
-    // Read file content into buffer.
-    bool is_read = reader->read_at(compressedAddress, compressed_size,
-            file_offset);
-    // If successfully read then decompress.
-    if (is_read) {
-        const ImageStrings strings = reader->get_strings();
-        ImageDecompressor::decompress_resource(compressedAddress, uncompressedAddress,
-                uncompressed_size, &strings, reader->endian());
-    }
-    return (jboolean) is_read;
-}
-
-// Java entry for retrieving UTF-8 bytes from image string table.
-
-static const char* JIMAGE_GetStringBytes(JNIEnv *env, jlong id, jint offset) {
-    // Convert image ID to image reader structure.
-    ImageFileReader* reader = ImageFileReader::idToReader(id);
-    // Fail if not valid reader.
-    if (reader == NULL) return NULL;
-    // Manage image string table.
-    ImageStrings strings = reader->get_strings();
-    // Retrieve string adrress from table.
-    const char* data = strings.get(offset);
-    return data;
-}
-
-// Utility function to copy location information into a jlong array.
-// WARNING: This function is experimental and temporary during JDK 9 development
-// cycle. It will not be supported in the eventual JDK 9 release.
-
-static void image_expand_location(JNIEnv *env, jlong* rawAttributes, ImageLocation& location) {
-    // Copy attributes from location.
-    for (int kind = ImageLocation::ATTRIBUTE_END + 1;
-            kind < ImageLocation::ATTRIBUTE_COUNT;
-            kind++) {
-        rawAttributes[kind] = location.get_attribute(kind);
-    }
-}
-
-// Java entry for retrieving location attributes for attribute offset.
-
-static jlong* JIMAGE_GetAttributes(JNIEnv *env, jlong* rawAttributes, jlong id, jint offset) {
-    // Convert image ID to image reader structure.
-    ImageFileReader* reader = ImageFileReader::idToReader(id);
-    // Fail if not valid reader.
-    if (reader == NULL) return NULL;
-    // Retrieve first byte address of resource's location attribute stream.
-    u1* data = reader->get_location_offset_data(offset);
-    // Fail if not valid offset.
-    if (data == NULL) return NULL;
-    // Expand stream into array.
-    ImageLocation location(data);
-    image_expand_location(env, rawAttributes, location);
-    return rawAttributes;
-}
-
-// Java entry for retrieving location attributes count for attribute offset.
-
-static jsize JIMAGE_GetAttributesCount(JNIEnv *env) {
-    return ImageLocation::ATTRIBUTE_COUNT;
-}
-
-// Java entry for retrieving location attributes for named resource.
-
-static jlong* JIMAGE_FindAttributes(JNIEnv *env, jlong* rawAttributes, jbyte* rawBytes, jsize size, jlong id) {
-    // Convert image ID to image reader structure.
-    ImageFileReader* reader = ImageFileReader::idToReader(id);
-    // Fail if not valid reader.
-    if (reader == NULL) return NULL;
-    // Convert byte array to a cstring.
-    char* path = new char[size + 1];
-    if (path == NULL) {
-        return NULL;
-    }
-    memcpy(path, rawBytes, size);
-    path[size] = '\0';
-    // Locate resource location data.
-    ImageLocation location;
-    bool found = reader->find_location(path, location);
-    delete path;
-    // Resource not found.
-    if (!found) return NULL;
-    // Expand stream into array.
-    image_expand_location(env, rawAttributes, location);
-    return rawAttributes;
-}
-
-// Java entry for retrieving all the attribute stream offsets from an image.
-
-static jint* JIMAGE_AttributeOffsets(JNIEnv *env, jint* rawOffsets, unsigned int length, jlong id) {
-    // Convert image ID to image reader structure.
-    ImageFileReader* reader = ImageFileReader::idToReader(id);
-    // Fail if not valid reader.
-    if (reader == NULL) return NULL;
-    // Determine endian for reader.
-    Endian* endian = reader->endian();
-    // Get base address of attribute stream offsets table.
-    u4* offsets_table = reader->offsets_table();
-    // Allocate int array result.
-    // Copy values to result (converting endian.)
-    for (u4 i = 0; i < length; i++) {
-        rawOffsets[i] = endian->get(offsets_table[i]);
-    }
-    return rawOffsets;
-}
-
-// Java entry for retrieving all the attribute stream offsets length from an image.
-
-static unsigned int JIMAGE_AttributeOffsetsLength(JNIEnv *env, jlong id) {
-    // Convert image ID to image reader structure.
-    ImageFileReader* reader = ImageFileReader::idToReader(id);
-    // Fail if not valid reader.
-    if (reader == NULL) return 0;
-    // Get perfect hash table length.
-    u4 length = reader->table_length();
-    return (jint) length;
-}
-
-JNIEXPORT jint JNICALL
-DEF_JNI_OnLoad(JavaVM *vm, void *reserved) {
-    JNIEnv *env;
-
-    if (vm->GetEnv((void**) &env, JNI_VERSION_1_2) != JNI_OK) {
-        return JNI_EVERSION; /* JNI version not supported */
-    }
-
-    return JNI_VERSION_1_2;
-}
-
-JNIEXPORT jlong JNICALL
-Java_jdk_internal_jimage_ImageNativeSubstrate_openImage(JNIEnv *env,
-        jclass cls, jstring path, jboolean big_endian) {
-    const char *nativePath;
-    jlong ret;
-
-    nativePath = env->GetStringUTFChars(path, NULL);
-    ret = JIMAGE_Open(env, nativePath, big_endian);
-    env->ReleaseStringUTFChars(path, nativePath);
-    return ret;
-}
-
-JNIEXPORT void JNICALL
-Java_jdk_internal_jimage_ImageNativeSubstrate_closeImage(JNIEnv *env,
-        jclass cls, jlong id) {
-    JIMAGE_Close(env, id);
-}
-
-JNIEXPORT jlong JNICALL
-Java_jdk_internal_jimage_ImageNativeSubstrate_getIndexAddress(JNIEnv *env,
-        jclass cls, jlong id) {
-    return JIMAGE_GetIndexAddress(env, id);
-}
-
-JNIEXPORT jlong JNICALL
-Java_jdk_internal_jimage_ImageNativeSubstrate_getDataAddress(JNIEnv *env,
-        jclass cls, jlong id) {
-    return JIMAGE_GetDataAddress(env, id);
-}
-
-JNIEXPORT jboolean JNICALL
-Java_jdk_internal_jimage_ImageNativeSubstrate_read(JNIEnv *env,
-        jclass cls, jlong id, jlong offset,
-        jobject uncompressedBuffer, jlong uncompressed_size) {
-    unsigned char* uncompressedAddress;
-
-    uncompressedAddress = (unsigned char*) env->GetDirectBufferAddress(uncompressedBuffer);
-    if (uncompressedAddress == NULL) {
-        return JNI_FALSE;
-    }
-    return JIMAGE_Read(env, id, offset, uncompressedAddress, uncompressed_size);
-}
-
-JNIEXPORT jboolean JNICALL
-Java_jdk_internal_jimage_ImageNativeSubstrate_readCompressed(JNIEnv *env,
-        jclass cls, jlong id, jlong offset,
-        jobject compressedBuffer, jlong compressed_size,
-        jobject uncompressedBuffer, jlong uncompressed_size) {
-    // Get address of read direct buffer.
-    unsigned char* compressedAddress;
-    unsigned char* uncompressedAddress;
-
-    compressedAddress = (unsigned char*) env->GetDirectBufferAddress(compressedBuffer);
-    // Get address of decompression direct buffer.
-    uncompressedAddress = (unsigned char*) env->GetDirectBufferAddress(uncompressedBuffer);
-    if (compressedAddress == NULL || uncompressedAddress == NULL) {
-        return JNI_FALSE;
-    }
-    return JIMAGE_ReadCompressed(env, id, offset, compressedAddress, compressed_size,
-            uncompressedAddress, uncompressed_size);
-}
-
-JNIEXPORT jbyteArray JNICALL
-Java_jdk_internal_jimage_ImageNativeSubstrate_getStringBytes(JNIEnv *env,
-        jclass cls, jlong id, jint offset) {
-    const char* data;
-    size_t size;
-    jbyteArray byteArray;
-    jbyte* rawBytes;
-
-    data = JIMAGE_GetStringBytes(env, id, offset);
-    // Determine String length.
-    size = strlen(data);
-    // Allocate byte array.
-    byteArray = env->NewByteArray((jsize) size);
-    if (byteArray == NULL) {
-        return NULL;
-    }
-    // Get array base address.
-    rawBytes = env->GetByteArrayElements(byteArray, NULL);
-    // Copy bytes from image string table.
-    memcpy(rawBytes, data, size);
-    // Release byte array base address.
-    env->ReleaseByteArrayElements(byteArray, rawBytes, 0);
-    return byteArray;
-}
-
-JNIEXPORT jlongArray JNICALL
-Java_jdk_internal_jimage_ImageNativeSubstrate_getAttributes(JNIEnv *env,
-        jclass cls, jlong id, jint offset) {
-    // Allocate a jlong large enough for all location attributes.
-    jlongArray attributes;
-    jlong* rawAttributes;
-    jlong* ret;
-
-    attributes = env->NewLongArray(JIMAGE_GetAttributesCount(env));
-    if (attributes == NULL) {
-        return NULL;
-    }
-    // Get base address for jlong array.
-    rawAttributes = env->GetLongArrayElements(attributes, NULL);
-    ret = JIMAGE_GetAttributes(env, rawAttributes, id, offset);
-    // Release jlong array base address.
-    env->ReleaseLongArrayElements(attributes, rawAttributes, 0);
-    return ret == NULL ? NULL : attributes;
-}
-
-JNIEXPORT jlongArray JNICALL
-Java_jdk_internal_jimage_ImageNativeSubstrate_findAttributes(JNIEnv *env,
-        jclass cls, jlong id, jbyteArray utf8) {
-    // Allocate a jlong large enough for all location attributes.
-    jsize count;
-    jlongArray attributes;
-    jlong* rawAttributes;
-    jsize size;
-    jbyte* rawBytes;
-    jlong* ret;
-
-    count = JIMAGE_GetAttributesCount(env);
-    attributes = env->NewLongArray(JIMAGE_GetAttributesCount(env));
-    if (attributes == NULL) {
-        return NULL;
-    }
-    // Get base address for jlong array.
-    rawAttributes = env->GetLongArrayElements(attributes, NULL);
-    size = env->GetArrayLength(utf8);
-    rawBytes = env->GetByteArrayElements(utf8, NULL);
-    ret = JIMAGE_FindAttributes(env, rawAttributes, rawBytes, size, id);
-    env->ReleaseByteArrayElements(utf8, rawBytes, 0);
-    // Release jlong array base address.
-    env->ReleaseLongArrayElements(attributes, rawAttributes, 0);
-    return ret == NULL ? NULL : attributes;
-
-}
-
-JNIEXPORT jintArray JNICALL
-Java_jdk_internal_jimage_ImageNativeSubstrate_attributeOffsets(JNIEnv *env,
-        jclass cls, jlong id) {
-    unsigned int length;
-    jintArray offsets;
-    jint* rawOffsets;
-    jint* ret;
-
-    length = JIMAGE_AttributeOffsetsLength(env, id);
-    offsets = env->NewIntArray(length);
-    if (offsets == NULL) {
-        return NULL;
-    }
-    // Get base address of result.
-    rawOffsets = env->GetIntArrayElements(offsets, NULL);
-    ret = JIMAGE_AttributeOffsets(env, rawOffsets, length, id);
-    if (length == 0) {
-        return NULL;
-    }
-    // Release result base address.
-    env->ReleaseIntArrayElements(offsets, rawOffsets, 0);
-    return ret == NULL ? NULL : offsets;
-}
-
-/*
- * Class:     jdk_internal_jimage_ImageNativeSubstrate
- * Method:    JIMAGE_open
- * Signature: (Ljava/lang/String;)J
- */
-JNIEXPORT jlong JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1Open
-(JNIEnv *env, jclass, jstring path) {
-    const char *nativePath = env->GetStringUTFChars(path, NULL);
-    if (nativePath == NULL)
-        return 0; // Exception already thrown
-    jint error;
-    jlong ret = (jlong) JIMAGE_Open(nativePath, &error);
-    env->ReleaseStringUTFChars(path, nativePath);
-    return ret;
-}
-
-/*
- * Class:     jdk_internal_jimage_ImageNativeSubstrate
- * Method:    JIMAGE_Close
- * Signature: (J)J
- */
-JNIEXPORT void JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1Close
-(JNIEnv *env, jclass, jlong jimageHandle) {
-    JIMAGE_Close((JImageFile*) jimageHandle);
-}
-
-/*
- * Class:     jdk_internal_jimage_ImageNativeSubstrate
- * Method:    JIMAGE_FindResource
- * Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;[J)J
- */
-JNIEXPORT jlong JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1FindResource
-(JNIEnv *env, jclass, jlong jimageHandle, jstring moduleName,
-        jstring version, jstring path, jlongArray output_size) {
-    const char *native_module = NULL;
-    const char *native_version = NULL;
-    const char *native_path = NULL;
-    jlong * native_array = NULL;
-    jlong size = 0;
-    jlong ret = 0;
-
-    if (moduleName == NULL) {
-        ThrowByName(env, "java/lang/NullPointerException", "moduleName");
-        return 0;
-    }
-    if (version == NULL) {
-        ThrowByName(env, "java/lang/NullPointerException", "version");
-        return 0;
-    }
-    if (path == NULL) {
-        ThrowByName(env, "java/lang/NullPointerException", "path");
-        return 0;
-    }
-    if (output_size == NULL) {
-        ThrowByName(env, "java/lang/NullPointerException", "size");
-        return 0;
-    }
-
-    do {
-        native_module = env->GetStringUTFChars(moduleName, NULL);
-        if (native_module == NULL)
-            break;
-        native_version = env->GetStringUTFChars(version, NULL);
-        if (native_version == NULL)
-            break;
-        native_path = env->GetStringUTFChars(path, NULL);
-        if (native_path == NULL)
-            break;
-        if (env->GetArrayLength(output_size) < 1)
-            break;
-        // Get base address for jlong array.
-        native_array = env->GetLongArrayElements(output_size, NULL);
-        if (native_array == NULL)
-            break;
-
-        ret = (jlong) JIMAGE_FindResource((JImageFile *) jimageHandle,
-                native_module, native_version, native_path, &size);
-        if (ret != 0)
-            *native_array = size;
-    } while (0);
-
-    if (native_array != NULL)
-        env->ReleaseLongArrayElements(output_size, native_array, 0);
-    if (native_path != NULL)
-        env->ReleaseStringUTFChars(path, native_path);
-    if (native_version != NULL)
-        env->ReleaseStringUTFChars(path, native_version);
-    if (native_module != NULL)
-        env->ReleaseStringUTFChars(path, native_module);
-
-    return ret;
-}
-
-/*
- * Class:     jdk_internal_jimage_ImageNativeSubstrate
- * Method:    JIMAGE_GetResource
- * Signature: (JJ[BJ)J
- */
-JNIEXPORT jlong JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1GetResource
-(JNIEnv *env, jclass, jlong jimageHandle, jlong jlocationHandle, jbyteArray buffer, jlong size) {
-    jbyte * native_buffer = NULL;
-    jlong actual_size = 0;
-    do {
-        if (env->GetArrayLength(buffer) < size)
-            break;
-
-        native_buffer = env->GetByteArrayElements(buffer, NULL);
-        if (native_buffer == NULL)
-            break;
-
-        actual_size = JIMAGE_GetResource((JImageFile*) jimageHandle,
-                (JImageLocationRef) jlocationHandle,
-                (char *) native_buffer, size);
-    } while (0);
-    // Release byte array
-    if (native_buffer != NULL)
-        env->ReleaseByteArrayElements(buffer, native_buffer, 0);
-
-    return actual_size;
-}
-
-// Structure passed from iterator to a visitor to accumulate the results
-
-struct VisitorData {
-    JNIEnv *env;
-    int size; // current number of strings
-    int max; // Maximum number of strings
-    jobjectArray array; // String array to store the strings
-};
-
-// Visitor to accumulate fully qualified resource names
-
-static bool resourceVisitor(JImageFile* image,
-        const char* module, const char* version, const char* package,
-        const char* name, const char* extension, void* arg) {
-    struct VisitorData *vdata = (struct VisitorData *) arg;
-    JNIEnv* env = vdata->env;
-    if (vdata->size < vdata->max) {
-        // Store if there is room in the array
-        // Concatenate to get full path
-        char fullpath[IMAGE_MAX_PATH];
-        size_t moduleLen = strlen(module);
-        size_t packageLen = strlen(package);
-        size_t nameLen = strlen(name);
-        size_t extLen = strlen(extension);
-        size_t index;
-
-        if (1 + moduleLen + 1 + packageLen + 1 + nameLen + 1 + extLen + 1 > IMAGE_MAX_PATH) {
-            ThrowByName(env, "java/lang/InternalError", "concatenated name too long");
-            return true;
-        }
-
-        index = 0;
-        if (moduleLen > 0) {
-            fullpath[index++] = '/';
-            memcpy(&fullpath[index], module, moduleLen);
-            index += moduleLen;
-            fullpath[index++] = '/';
-        }
-        if (packageLen > 0) {
-            memcpy(&fullpath[index], package, packageLen);
-            index += packageLen;
-            fullpath[index++] = '/';
-        }
-        memcpy(&fullpath[index], name, nameLen);
-        index += nameLen;
-        if (extLen > 0) {
-            fullpath[index++] = '.';
-            memcpy(&fullpath[index], extension, extLen);
-            index += extLen;
-        }
-        fullpath[index++] = '\0';
-
-        jobject str = env->NewStringUTF(fullpath);
-        if (env->ExceptionCheck()) {
-            return true;
-        }
-
-        env->SetObjectArrayElement(vdata->array, vdata->size, str);
-        if (env->ExceptionCheck()) {
-            return true;
-        }
-    }
-    vdata->size++; // always count so the total size is returned
-    return true;
-}
-
-/*
- * Class:     jdk_internal_jimage_ImageNativeSubstrate
- * Method:    JIMAGE_Resources
- * Signature: (J)V
- */
-JNIEXPORT jint JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1Resources
-(JNIEnv *env, jclass, jlong jimageHandle,
-        jobjectArray outputNames) {
-    struct VisitorData vdata;
-    vdata.env = env;
-    vdata.max = 0;
-    vdata.size = 0;
-    vdata.array = outputNames;
-
-    vdata.max = (outputNames != NULL) ? env->GetArrayLength(outputNames) : 0;
-    JIMAGE_ResourceIterator((JImageFile*) jimageHandle, &resourceVisitor, &vdata);
-    return vdata.size;
-}
-
-/*
- * Class:     jdk_internal_jimage_ImageNativeSubstrate
- * Method:    JIMAGE_PackageToModule
- * Signature: (JLjava/lang/String;)Ljava/lang/String;
- */
-JNIEXPORT jstring JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1PackageToModule
-(JNIEnv *env, jclass, jlong jimageHandle, jstring package_name) {
-    const char *native_package = NULL;
-    const char *native_module = NULL;
-    jstring module = NULL;
-
-    native_package = env->GetStringUTFChars(package_name, NULL);
-    if (env->ExceptionCheck()) {
-        return NULL;
-    }
-
-
-    native_module = JIMAGE_PackageToModule((JImageFile*) jimageHandle, native_package);
-    if (native_module != NULL) {
-        module = env->NewStringUTF(native_module);
-    }
-    env->ReleaseStringUTFChars(package_name, native_package);
-    return module;
-}
-
-JNIEXPORT void JNICALL DEF_JNI_OnUnload(JavaVM *vm, void *reserved) {
-    ImageDecompressor::image_decompressor_close();
-}
--- a/test/jdk/internal/jimage/JImageReadTest.java	Mon Dec 21 11:47:03 2015 -0400
+++ b/test/jdk/internal/jimage/JImageReadTest.java	Mon Dec 21 11:47:07 2015 -0400
@@ -35,7 +35,7 @@
 import java.util.Arrays;
 
 import jdk.internal.jimage.BasicImageReader;
-import jdk.internal.jimage.ImageNativeSubstrate;
+import jdk.internal.jimage.ImageLocation;
 
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Optional;
@@ -65,16 +65,6 @@
         };
     }
 
-
-    @DataProvider(name="packages")
-    static Object[][] loadPackages() {
-        return new Object[][] {
-                {"java.base", "java/lang"},
-                {"java.base", "java/io"},
-                {"java.logging", "java/util/logging"},
-        };
-    }
-
     /**
      * Test a class is correctly accessible from the image in a module.
      *
@@ -92,53 +82,40 @@
             return;
         }
 
-        long jimageHandle = ImageNativeSubstrate.JIMAGE_Open(imageFile);
-        Assert.assertTrue(jimageHandle != 0, "JIMAGE_Open failed: id: " + jimageHandle);
+        BasicImageReader reader = BasicImageReader.open(imageFile);
+        Assert.assertTrue(reader != null, "JIMAGE_Open failed: " + imageFile);
 
-        long[] sizeArray = new long[1];
-        long locationHandle =
-                ImageNativeSubstrate.JIMAGE_FindResource(jimageHandle,
-                moduleName, "9.0", className, sizeArray);
-        long size = sizeArray[0];
-        System.out.printf("reading: module: %s, path: %s, handle: %16x, " +
-                        "location: %d, size: %d%n",
-                moduleName, className, jimageHandle, locationHandle, size);
+        ImageLocation location = reader.findLocation(moduleName, className);
+
+        if (location != null && !location.verify("/" + moduleName + "/" + className)) {
+            location = null;
+        }
+
+        long size = location != null ? location.getUncompressedSize() : 0;
+
+        System.out.printf("reading: module: %s, path: %s, size: %d%n",
+                moduleName, className, size);
         if (moduleName.contains("NOSUCH") || className.contains("NOSUCH")) {
-            Assert.assertEquals(locationHandle, NOT_FOUND,
+            Assert.assertTrue(location == null,
                     "location found for non-existing module: "
                     + moduleName
                     + ", or class: " + className);
             return;         // no more to test for non-existing class
         } else {
-            Assert.assertTrue(locationHandle != NOT_FOUND, "location not found: " + className);
+            Assert.assertTrue(location != null, "location not found: " + className);
             Assert.assertTrue(size > 0, "size of should be > 0: " + className);
         }
 
         // positive: read whole class
-        ByteBuffer buffer = ByteBuffer.allocate((int)size);
-        long actual = ImageNativeSubstrate.JIMAGE_GetResource(jimageHandle,
-                locationHandle, buffer.array(), size);
-        Assert.assertEquals(actual, size, "bytes read not equal bytes requested");
+        ByteBuffer buffer = reader.getResourceBuffer(location);
+        Assert.assertTrue(buffer != null, "bytes read not equal bytes requested");
 
         if (className.endsWith(".class")) {
             int m = buffer.getInt();
             Assert.assertEquals(m, classMagic, "Classfile has bad magic number");
         }
 
-        // Read less than the size of the artifact
-        buffer.rewind();
-        Arrays.fill(buffer.array(), (byte)0xc0);
-        long sizeExpected = size - 10;
-        actual = ImageNativeSubstrate.JIMAGE_GetResource(jimageHandle,
-                locationHandle, buffer.array(), sizeExpected);
-        Assert.assertEquals(actual, sizeExpected, "bytes read not equal bytes requested");
-
-        if (className.endsWith(".class")) {
-            int m1 = buffer.getInt();
-            Assert.assertEquals(m1, classMagic, "Read operation succeeded but has bad magic number");
-        }
-
-        ImageNativeSubstrate.JIMAGE_Close(jimageHandle);
+        reader.close();
     }
 
     /**
@@ -153,58 +130,32 @@
             return;
         }
 
-        long jimageHandle = ImageNativeSubstrate.JIMAGE_Open(imageFile);
-        Assert.assertTrue(jimageHandle != 0, "JIMAGE_Open failed: id: " + jimageHandle);
+        BasicImageReader reader = BasicImageReader.open(imageFile);
+        Assert.assertTrue(reader != null, "JIMAGE_Open failed: " + imageFile);
 
-        String[] names = new String[4096];
-        int max = ImageNativeSubstrate.JIMAGE_Resources(jimageHandle,
-                names);
+        String[] names = reader.getEntryNames();
 
         // Repeat with count available
-        names = new String[max + 1];
-        int count = ImageNativeSubstrate.JIMAGE_Resources(jimageHandle,
-                names);
+        int count = names.length;
+
         System.out.printf(" count: %d, a class: %s\n", count, names[0]);
+
         int minEntryCount = 16000;
-        Assert.assertTrue(max > minEntryCount,
-                "missing entries, should be more than " + minEntryCount +
-                ", reported: " + count);
-        Assert.assertTrue(count == max,
+        Assert.assertTrue(minEntryCount < count,
                 "unexpected count of entries, count: " + count
-                        + ", max: " + max);
+                        + ", min: " + minEntryCount);
         for (int i = 0; i < count; i++) {
             checkFullName(names[i]);
         }
 
-        ImageNativeSubstrate.JIMAGE_Close(jimageHandle);
+        reader.close();
     }
 
-    /**
-     * Tests that a package exists and correctly mapped to the module.
-     *
-     * @param moduleName the module name
-     * @param packageName the package name
-     * @throws IOException thrown if an error occurs
-     */
-    @Test(dataProvider="packages")
-    static void test3_PackageToModule(String moduleName, String packageName) throws IOException {
-        if (!(new File(imageFile)).exists()) {
-            System.out.printf("Test skipped; no jimage file");
+    static void checkFullName(String path) {
+        if (path.startsWith("/packages") || path.startsWith("/modules")) {
             return;
         }
 
-        long jimageHandle = ImageNativeSubstrate.JIMAGE_Open(imageFile);
-        Assert.assertTrue(jimageHandle != 0, "JIMAGE_Open failed: id: " + jimageHandle);
-
-        String result = ImageNativeSubstrate.JIMAGE_PackageToModule(jimageHandle, packageName);
-        System.out.printf(" package: %s, module: %s%n", packageName, result);
-        Assert.assertEquals(result, moduleName, "wrong module for package: " + packageName);
-
-        ImageNativeSubstrate.JIMAGE_Close(jimageHandle);
-    }
-
-
-    static void checkFullName(String path) {
         int next = 0;
         String m = null;
         String p = null;
@@ -240,7 +191,7 @@
      * from the BasicImageReader they are ignored.
      */
     @Test
-    static void test4_verifyNames() {
+    static void test3_verifyNames() {
         if (!(new File(imageFile)).exists()) {
             System.out.printf("Test skipped; no jimage file");
             return;
@@ -270,9 +221,6 @@
             System.out.printf("native name count: %d, modCount: %d, pkgCount: %d, otherCount: %d%n",
                     names.length, modCount, pkgCount, otherCount);
 
-            Assert.assertEquals(modCount, 0, "JIMAGE_ResourceIterator should not return any '/modules' paths");
-            Assert.assertEquals(pkgCount, 0, "JIMAGE_ResourceIterator should not return any '/packages' paths");
-
             // Sort and merge the two arrays.  Every name should appear exactly twice.
             Arrays.sort(names);
             Arrays.sort(nativeNames);
@@ -335,21 +283,13 @@
      */
     static String[] JIMAGE_Names() throws IOException {
 
-        long jimageHandle = ImageNativeSubstrate.JIMAGE_Open(imageFile);
-        Assert.assertTrue(jimageHandle != 0, "JIMAGE_Open failed: id: " + jimageHandle);
+        BasicImageReader reader = BasicImageReader.open(imageFile);
+        Assert.assertNotNull(reader, "JIMAGE_Open failed: " + imageFile);
 
-        String[] names = new String[50000];
-        int max = ImageNativeSubstrate.JIMAGE_Resources(jimageHandle, names);
+        String[] names = reader.getEntryNames();
 
-        if (max > names.length) {
-            // Not all names fit, repeat with correct size
-            names = new String[max];
-            max = ImageNativeSubstrate.JIMAGE_Resources(jimageHandle, names);
-        } else {
-            names = Arrays.copyOf(names, max);
-        }
+        reader.close();
 
-        ImageNativeSubstrate.JIMAGE_Close(jimageHandle);
         return names;
     }
 
@@ -365,22 +305,24 @@
         System.out.printf(" %s: %d names%n", fname, names.length);
     }
 
-    @Test
-    static void test5_nameTooLong() throws IOException {
+    //@Test
+    static void test4_nameTooLong() throws IOException {
         long[] size = new long[1];
         String moduleName = "FictiousModuleName";
         String className = String.format("A%09999d", 1);
 
-        long jimageHandle = ImageNativeSubstrate.JIMAGE_Open(imageFile);
-        Assert.assertTrue(jimageHandle != 0, "JIMAGE_Open failed: id: " + jimageHandle);
+        BasicImageReader reader = BasicImageReader.open(imageFile);
+        Assert.assertNotNull(reader, "JIMAGE_Open failed: " + imageFile);
 
-        long locationHandle =
-                ImageNativeSubstrate.JIMAGE_FindResource(jimageHandle,
-                        moduleName, "9.0", className, size);
+        String name = "/" + moduleName + "/" + className;
+        ImageLocation location = reader.findLocation(name);
 
-        Assert.assertEquals(0, locationHandle, "Too long name should have failed");
+        if (location != null && !location.verify(name)) {
+            location = null;
+        }
+        Assert.assertTrue(location == null, "Too long name should have failed");
 
-        ImageNativeSubstrate.JIMAGE_Close(jimageHandle);
+        reader.close();
     }
 
     // main method to run standalone from jtreg
--- a/test/jdk/jigsaw/tools/jimage/VerifyJimage.java	Mon Dec 21 11:47:03 2015 -0400
+++ b/test/jdk/jigsaw/tools/jimage/VerifyJimage.java	Mon Dec 21 11:47:07 2015 -0400
@@ -234,12 +234,7 @@
         }
 
         int entries() {
-            try {
-                return getHeader().getTableLength();
-            } catch (IOException ex) {
-                failed.add(imageName() + ": can't access header");
-                return 0;
-            }
+            return getHeader().getTableLength();
         }
 
         void compare(String entry, Path p) {