< prev index next >

src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java

Print this page

 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 package jdk.internal.jimage;
 26 
 27 import java.io.ByteArrayInputStream;
 28 import java.io.IOException;
 29 import java.io.InputStream;
 30 import java.lang.reflect.InvocationTargetException;
 31 import java.lang.reflect.Method;
 32 import java.nio.ByteBuffer;
 33 import java.nio.ByteOrder;
 34 import java.nio.IntBuffer;
 35 import java.nio.channels.FileChannel;
 36 import java.nio.file.Path;
 37 import java.nio.file.StandardOpenOption;
 38 import java.security.AccessController;
 39 import java.security.PrivilegedAction;

 40 import java.util.Objects;

 41 import java.util.stream.IntStream;


 42 import jdk.internal.jimage.decompressor.Decompressor;
 43 
 44 /**
 45  * @implNote This class needs to maintain JDK 8 source compatibility.
 46  *
 47  * It is used internally in the JDK to implement jimage/jrtfs access,
 48  * but also compiled and delivered as part of the jrtfs.jar to support access
 49  * to the jimage file provided by the shipped JDK by tools running on JDK 8.
 50  */
 51 public class BasicImageReader implements AutoCloseable {
 52     @SuppressWarnings({ "removal", "suppression" })
 53     private static boolean isSystemProperty(String key, String value, String def) {
 54         // No lambdas during bootstrap
 55         return AccessController.doPrivileged(
 56             new PrivilegedAction<Boolean>() {
 57                 @Override
 58                 public Boolean run() {
 59                     return value.equals(System.getProperty(key, def));
 60                 }
 61             });

300             return -1;
301         }
302     }
303 
304     private int getLocationIndex(String module, String name) {
305         int count = header.getTableLength();
306         int index = redirect.get(ImageStringsReader.hashCode(module, name) % count);
307         if (index < 0) {
308             // index is twos complement of location attributes index.
309             return -index - 1;
310         } else if (index > 0) {
311             // index is hash seed needed to compute location attributes index.
312             return ImageStringsReader.hashCode(module, name, index) % count;
313         } else {
314             // No entry.
315             return -1;
316         }
317     }
318 
319     public String[] getEntryNames() {
320         int[] attributeOffsets = new int[offsets.capacity()];
321         offsets.get(attributeOffsets);
322         return IntStream.of(attributeOffsets)
323                         .filter(o -> o != 0)
324                         .mapToObj(o -> ImageLocation.readFrom(this, o).getFullName())
325                         .sorted()
326                         .toArray(String[]::new);

















































327     }
328 
329     ImageLocation getLocation(int offset) {
330         return ImageLocation.readFrom(this, offset);
331     }
332 
333     public long[] getAttributes(int offset) {
334         if (offset < 0 || offset >= locations.limit()) {
335             throw new IndexOutOfBoundsException("offset");
336         }
337         return ImageLocation.decompress(locations, offset);
338     }
339 
340     public String getString(int offset) {
341         if (offset < 0 || offset >= strings.limit()) {
342             throw new IndexOutOfBoundsException("offset");
343         }
344         return ImageStringsReader.stringFromByteBuffer(strings, offset);
345     }
346 

 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 package jdk.internal.jimage;
 26 
 27 import java.io.ByteArrayInputStream;
 28 import java.io.IOException;
 29 import java.io.InputStream;
 30 import java.lang.reflect.InvocationTargetException;
 31 import java.lang.reflect.Method;
 32 import java.nio.ByteBuffer;
 33 import java.nio.ByteOrder;
 34 import java.nio.IntBuffer;
 35 import java.nio.channels.FileChannel;
 36 import java.nio.file.Path;
 37 import java.nio.file.StandardOpenOption;
 38 import java.security.AccessController;
 39 import java.security.PrivilegedAction;
 40 import java.util.NoSuchElementException;
 41 import java.util.Objects;
 42 import java.util.Random;
 43 import java.util.stream.IntStream;
 44 import java.util.stream.Stream;
 45 
 46 import jdk.internal.jimage.decompressor.Decompressor;
 47 
 48 /**
 49  * @implNote This class needs to maintain JDK 8 source compatibility.
 50  *
 51  * It is used internally in the JDK to implement jimage/jrtfs access,
 52  * but also compiled and delivered as part of the jrtfs.jar to support access
 53  * to the jimage file provided by the shipped JDK by tools running on JDK 8.
 54  */
 55 public class BasicImageReader implements AutoCloseable {
 56     @SuppressWarnings({ "removal", "suppression" })
 57     private static boolean isSystemProperty(String key, String value, String def) {
 58         // No lambdas during bootstrap
 59         return AccessController.doPrivileged(
 60             new PrivilegedAction<Boolean>() {
 61                 @Override
 62                 public Boolean run() {
 63                     return value.equals(System.getProperty(key, def));
 64                 }
 65             });

304             return -1;
305         }
306     }
307 
308     private int getLocationIndex(String module, String name) {
309         int count = header.getTableLength();
310         int index = redirect.get(ImageStringsReader.hashCode(module, name) % count);
311         if (index < 0) {
312             // index is twos complement of location attributes index.
313             return -index - 1;
314         } else if (index > 0) {
315             // index is hash seed needed to compute location attributes index.
316             return ImageStringsReader.hashCode(module, name, index) % count;
317         } else {
318             // No entry.
319             return -1;
320         }
321     }
322 
323     public String[] getEntryNames() {
324         return IntStream.range(0, offsets.capacity())
325                 .map(offsets::get)
326                 .filter(o -> o != 0)
327                 .mapToObj(o -> ImageLocation.readFrom(this, o).getFullName())
328                 .sorted()
329                 .toArray(String[]::new);
330     }
331 
332     /**
333      * Returns the "raw" API for accessing underlying jimage resource entries.
334      *
335      * <p>This is only meaningful for use by code dealing directly with jimage
336      * files, and cannot be used to reliably lookup resources used at runtime.
337      *
338      * <p>This API remains valid until the image reader from which it was
339      * obtained is closed.
340      */
341     // Package visible for use by ImageReader.
342     ResourceEntries getResourceEntries() {
343         return new ResourceEntries() {
344             @Override
345             public Stream<String> getEntryNames(String module) {
346                 if (module.isEmpty() || module.equals("modules") || module.equals("packages")) {
347                     throw new IllegalArgumentException("Invalid module name: " + module);
348                 }
349                 return IntStream.range(0, offsets.capacity())
350                         .map(offsets::get)
351                         .filter(offset -> offset != 0)
352                         // Reusing a location instance or getting the module
353                         // offset directly would save a lot of allocations here.
354                         .mapToObj(offset -> ImageLocation.readFrom(BasicImageReader.this, offset))
355                         // Reverse lookup of module offset would be faster here.
356                         .filter(loc -> module.equals(loc.getModule()))
357                         .map(ImageLocation::getFullName);
358             }
359 
360             private ImageLocation getResourceLocation(String name) {
361                 if (!name.startsWith("/modules/") && !name.startsWith("/packages/")) {
362                     ImageLocation location = BasicImageReader.this.findLocation(name);
363                     if (location != null) {
364                         return location;
365                     }
366                 }
367                 throw new NoSuchElementException("No such resource entry: " + name);
368             }
369 
370             @Override
371             public long getSize(String name) {
372                 return getResourceLocation(name).getUncompressedSize();
373             }
374 
375             @Override
376             public byte[] getBytes(String name) {
377                 return BasicImageReader.this.getResource(getResourceLocation(name));
378             }
379         };
380     }
381 
382     ImageLocation getLocation(int offset) {
383         return ImageLocation.readFrom(this, offset);
384     }
385 
386     public long[] getAttributes(int offset) {
387         if (offset < 0 || offset >= locations.limit()) {
388             throw new IndexOutOfBoundsException("offset");
389         }
390         return ImageLocation.decompress(locations, offset);
391     }
392 
393     public String getString(int offset) {
394         if (offset < 0 || offset >= strings.limit()) {
395             throw new IndexOutOfBoundsException("offset");
396         }
397         return ImageStringsReader.stringFromByteBuffer(strings, offset);
398     }
399 
< prev index next >