jdk/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp
changeset 36511 9d0388c6b336
parent 36510 043f1af70518
child 36512 1b1dea65af3e
equal deleted inserted replaced
36510:043f1af70518 36511:9d0388c6b336
     1 /*
       
     2  * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
       
     3  *
       
     4  * Redistribution and use in source and binary forms, with or without
       
     5  * modification, are permitted provided that the following conditions
       
     6  * are met:
       
     7  *
       
     8  *   - Redistributions of source code must retain the above copyright
       
     9  *     notice, this list of conditions and the following disclaimer.
       
    10  *
       
    11  *   - Redistributions in binary form must reproduce the above copyright
       
    12  *     notice, this list of conditions and the following disclaimer in the
       
    13  *     documentation and/or other materials provided with the distribution.
       
    14  *
       
    15  *   - Neither the name of Oracle nor the names of its
       
    16  *     contributors may be used to endorse or promote products derived
       
    17  *     from this software without specific prior written permission.
       
    18  *
       
    19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
       
    20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
       
    21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
       
    22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
       
    23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
       
    24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
       
    25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
       
    26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
       
    27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
       
    28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
       
    29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    30  */
       
    31 
       
    32 #include <string.h>
       
    33 
       
    34 #include "jni.h"
       
    35 #include "jni_util.h"
       
    36 
       
    37 #include "endian.hpp"
       
    38 #include "imageDecompressor.hpp"
       
    39 #include "imageFile.hpp"
       
    40 #include "inttypes.hpp"
       
    41 #include "jimage.hpp"
       
    42 #include "osSupport.hpp"
       
    43 
       
    44 #include "jdk_internal_jimage_ImageNativeSubstrate.h"
       
    45 
       
    46 extern bool MemoryMapImage;
       
    47 
       
    48 /////////////////////////////////////////////////////////////////////////////
       
    49 
       
    50 // Static function for primitive throw since libjimage is not linked with libjava
       
    51 static void JNICALL ThrowByName(JNIEnv *env, const char *name, const char *msg)
       
    52 {
       
    53     jclass cls = (env)->FindClass(name);
       
    54 
       
    55     if (cls != 0) /* Otherwise an exception has already been thrown */
       
    56         (env)->ThrowNew(cls, msg);
       
    57 }
       
    58 
       
    59 // jdk.internal.jimage /////////////////////////////////////////////////////////
       
    60 
       
    61 // Java entry to open an image file for sharing.
       
    62 
       
    63 static jlong JIMAGE_Open(JNIEnv *env, const char *nativePath, jboolean big_endian) {
       
    64     // Open image file for reading.
       
    65     ImageFileReader* reader = ImageFileReader::open(nativePath, big_endian != JNI_FALSE);
       
    66     // Return image ID as a jlong.
       
    67     return ImageFileReader::readerToID(reader);
       
    68 }
       
    69 
       
    70 // Java entry for closing a shared image file.
       
    71 
       
    72 static void JIMAGE_Close(JNIEnv *env, jlong id) {
       
    73     // Convert image ID to image reader structure.
       
    74     ImageFileReader* reader = ImageFileReader::idToReader(id);
       
    75     // If valid reader the close.
       
    76     if (reader != NULL) {
       
    77         ImageFileReader::close(reader);
       
    78     }
       
    79 }
       
    80 
       
    81 // Java entry for accessing the base address of the image index.
       
    82 
       
    83 static jlong JIMAGE_GetIndexAddress(JNIEnv *env, jlong id) {
       
    84     // Convert image ID to image reader structure.
       
    85     ImageFileReader* reader = ImageFileReader::idToReader(id);
       
    86     // If valid reader return index base address (as jlong) else zero.
       
    87     return reader != NULL ? (jlong) reader->get_index_address() : 0L;
       
    88 }
       
    89 
       
    90 // Java entry for accessing the base address of the image data.
       
    91 
       
    92 static jlong JIMAGE_GetDataAddress(JNIEnv *env, jlong id) {
       
    93     // Convert image ID to image reader structure.
       
    94     ImageFileReader* reader = ImageFileReader::idToReader(id);
       
    95     // If valid reader return data base address (as jlong) else zero.
       
    96     return MemoryMapImage && reader != NULL ? (jlong) reader->get_data_address() : 0L;
       
    97 }
       
    98 
       
    99 // Java entry for reading an uncompressed resource from the image.
       
   100 
       
   101 static jboolean JIMAGE_Read(JNIEnv *env, jlong id, jlong offset,
       
   102         unsigned char* uncompressedAddress, jlong uncompressed_size) {
       
   103     // Convert image ID to image reader structure.
       
   104     ImageFileReader* reader = ImageFileReader::idToReader(id);\
       
   105   // If not a valid reader the fail the read.
       
   106     if (reader == NULL) return false;
       
   107     // Get the file offset of resource data.
       
   108     u8 file_offset = reader->get_index_size() + offset;
       
   109     // Check validity of arguments.
       
   110     if (offset < 0 ||
       
   111             uncompressed_size < 0 ||
       
   112             file_offset > reader->file_size() - uncompressed_size) {
       
   113         return false;
       
   114     }
       
   115     // Read file content into buffer.
       
   116     return (jboolean) reader->read_at((u1*) uncompressedAddress, uncompressed_size,
       
   117             file_offset);
       
   118 }
       
   119 
       
   120 // Java entry for reading a compressed resource from the image.
       
   121 
       
   122 static jboolean JIMAGE_ReadCompressed(JNIEnv *env,
       
   123         jlong id, jlong offset,
       
   124         unsigned char* compressedAddress, jlong compressed_size,
       
   125         unsigned char* uncompressedAddress, jlong uncompressed_size) {
       
   126     // Convert image ID to image reader structure.
       
   127     ImageFileReader* reader = ImageFileReader::idToReader(id);
       
   128     // If not a valid reader the fail the read.
       
   129     if (reader == NULL) return false;
       
   130     // Get the file offset of resource data.
       
   131     u8 file_offset = reader->get_index_size() + offset;
       
   132     // Check validity of arguments.
       
   133     if (offset < 0 ||
       
   134             compressed_size < 0 ||
       
   135             uncompressed_size < 0 ||
       
   136             file_offset > reader->file_size() - compressed_size) {
       
   137         return false;
       
   138     }
       
   139 
       
   140     // Read file content into buffer.
       
   141     bool is_read = reader->read_at(compressedAddress, compressed_size,
       
   142             file_offset);
       
   143     // If successfully read then decompress.
       
   144     if (is_read) {
       
   145         const ImageStrings strings = reader->get_strings();
       
   146         ImageDecompressor::decompress_resource(compressedAddress, uncompressedAddress,
       
   147                 (u4) uncompressed_size, &strings);
       
   148     }
       
   149     return (jboolean) is_read;
       
   150 }
       
   151 
       
   152 // Java entry for retrieving UTF-8 bytes from image string table.
       
   153 
       
   154 static const char* JIMAGE_GetStringBytes(JNIEnv *env, jlong id, jint offset) {
       
   155     // Convert image ID to image reader structure.
       
   156     ImageFileReader* reader = ImageFileReader::idToReader(id);
       
   157     // Fail if not valid reader.
       
   158     if (reader == NULL) return NULL;
       
   159     // Manage image string table.
       
   160     ImageStrings strings = reader->get_strings();
       
   161     // Retrieve string adrress from table.
       
   162     const char* data = strings.get(offset);
       
   163     return data;
       
   164 }
       
   165 
       
   166 // Utility function to copy location information into a jlong array.
       
   167 // WARNING: This function is experimental and temporary during JDK 9 development
       
   168 // cycle. It will not be supported in the eventual JDK 9 release.
       
   169 
       
   170 static void image_expand_location(JNIEnv *env, jlong* rawAttributes, ImageLocation& location) {
       
   171     // Copy attributes from location.
       
   172     for (int kind = ImageLocation::ATTRIBUTE_END + 1;
       
   173             kind < ImageLocation::ATTRIBUTE_COUNT;
       
   174             kind++) {
       
   175         rawAttributes[kind] = location.get_attribute(kind);
       
   176     }
       
   177 }
       
   178 
       
   179 // Java entry for retrieving location attributes for attribute offset.
       
   180 
       
   181 static jlong* JIMAGE_GetAttributes(JNIEnv *env, jlong* rawAttributes, jlong id, jint offset) {
       
   182     // Convert image ID to image reader structure.
       
   183     ImageFileReader* reader = ImageFileReader::idToReader(id);
       
   184     // Fail if not valid reader.
       
   185     if (reader == NULL) return NULL;
       
   186     // Retrieve first byte address of resource's location attribute stream.
       
   187     u1* data = reader->get_location_offset_data(offset);
       
   188     // Fail if not valid offset.
       
   189     if (data == NULL) return NULL;
       
   190     // Expand stream into array.
       
   191     ImageLocation location(data);
       
   192     image_expand_location(env, rawAttributes, location);
       
   193     return rawAttributes;
       
   194 }
       
   195 
       
   196 // Java entry for retrieving location attributes count for attribute offset.
       
   197 
       
   198 static jsize JIMAGE_GetAttributesCount(JNIEnv *env) {
       
   199     return ImageLocation::ATTRIBUTE_COUNT;
       
   200 }
       
   201 
       
   202 // Java entry for retrieving location attributes for named resource.
       
   203 
       
   204 static jlong* JIMAGE_FindAttributes(JNIEnv *env, jlong* rawAttributes, jbyte* rawBytes, jsize size, jlong id) {
       
   205     // Convert image ID to image reader structure.
       
   206     ImageFileReader* reader = ImageFileReader::idToReader(id);
       
   207     // Fail if not valid reader.
       
   208     if (reader == NULL) return NULL;
       
   209     // Convert byte array to a cstring.
       
   210     char* path = new char[size + 1];
       
   211     if (path == NULL) {
       
   212         return NULL;
       
   213     }
       
   214     memcpy(path, rawBytes, size);
       
   215     path[size] = '\0';
       
   216     // Locate resource location data.
       
   217     ImageLocation location;
       
   218     bool found = reader->find_location(path, location);
       
   219     delete[] path;
       
   220     // Resource not found.
       
   221     if (!found) return NULL;
       
   222     // Expand stream into array.
       
   223     image_expand_location(env, rawAttributes, location);
       
   224     return rawAttributes;
       
   225 }
       
   226 
       
   227 // Java entry for retrieving all the attribute stream offsets from an image.
       
   228 
       
   229 static jint* JIMAGE_AttributeOffsets(JNIEnv *env, jint* rawOffsets, unsigned int length, jlong id) {
       
   230     // Convert image ID to image reader structure.
       
   231     ImageFileReader* reader = ImageFileReader::idToReader(id);
       
   232     // Fail if not valid reader.
       
   233     if (reader == NULL) return NULL;
       
   234     // Determine endian for reader.
       
   235     Endian* endian = reader->endian();
       
   236     // Get base address of attribute stream offsets table.
       
   237     u4* offsets_table = reader->offsets_table();
       
   238     // Allocate int array result.
       
   239     // Copy values to result (converting endian.)
       
   240     for (u4 i = 0; i < length; i++) {
       
   241         rawOffsets[i] = endian->get(offsets_table[i]);
       
   242     }
       
   243     return rawOffsets;
       
   244 }
       
   245 
       
   246 // Java entry for retrieving all the attribute stream offsets length from an image.
       
   247 
       
   248 static unsigned int JIMAGE_AttributeOffsetsLength(JNIEnv *env, jlong id) {
       
   249     // Convert image ID to image reader structure.
       
   250     ImageFileReader* reader = ImageFileReader::idToReader(id);
       
   251     // Fail if not valid reader.
       
   252     if (reader == NULL) return 0;
       
   253     // Get perfect hash table length.
       
   254     u4 length = reader->table_length();
       
   255     return (jint) length;
       
   256 }
       
   257 
       
   258 JNIEXPORT jint JNICALL
       
   259 DEF_JNI_OnLoad(JavaVM *vm, void *reserved) {
       
   260     JNIEnv *env;
       
   261 
       
   262     if (vm->GetEnv((void**) &env, JNI_VERSION_1_2) != JNI_OK) {
       
   263         return JNI_EVERSION; /* JNI version not supported */
       
   264     }
       
   265 
       
   266     return JNI_VERSION_1_2;
       
   267 }
       
   268 
       
   269 JNIEXPORT jlong JNICALL
       
   270 Java_jdk_internal_jimage_ImageNativeSubstrate_openImage(JNIEnv *env,
       
   271         jclass cls, jstring path, jboolean big_endian) {
       
   272     const char *nativePath;
       
   273     jlong ret;
       
   274 
       
   275     nativePath = env->GetStringUTFChars(path, NULL);
       
   276     ret = JIMAGE_Open(env, nativePath, big_endian);
       
   277     env->ReleaseStringUTFChars(path, nativePath);
       
   278     return ret;
       
   279 }
       
   280 
       
   281 JNIEXPORT void JNICALL
       
   282 Java_jdk_internal_jimage_ImageNativeSubstrate_closeImage(JNIEnv *env,
       
   283         jclass cls, jlong id) {
       
   284     JIMAGE_Close(env, id);
       
   285 }
       
   286 
       
   287 JNIEXPORT jlong JNICALL
       
   288 Java_jdk_internal_jimage_ImageNativeSubstrate_getIndexAddress(JNIEnv *env,
       
   289         jclass cls, jlong id) {
       
   290     return JIMAGE_GetIndexAddress(env, id);
       
   291 }
       
   292 
       
   293 JNIEXPORT jlong JNICALL
       
   294 Java_jdk_internal_jimage_ImageNativeSubstrate_getDataAddress(JNIEnv *env,
       
   295         jclass cls, jlong id) {
       
   296     return JIMAGE_GetDataAddress(env, id);
       
   297 }
       
   298 
       
   299 JNIEXPORT jboolean JNICALL
       
   300 Java_jdk_internal_jimage_ImageNativeSubstrate_read(JNIEnv *env,
       
   301         jclass cls, jlong id, jlong offset,
       
   302         jobject uncompressedBuffer, jlong uncompressed_size) {
       
   303     unsigned char* uncompressedAddress;
       
   304 
       
   305     uncompressedAddress = (unsigned char*) env->GetDirectBufferAddress(uncompressedBuffer);
       
   306     if (uncompressedAddress == NULL) {
       
   307         return JNI_FALSE;
       
   308     }
       
   309     return JIMAGE_Read(env, id, offset, uncompressedAddress, uncompressed_size);
       
   310 }
       
   311 
       
   312 JNIEXPORT jboolean JNICALL
       
   313 Java_jdk_internal_jimage_ImageNativeSubstrate_readCompressed(JNIEnv *env,
       
   314         jclass cls, jlong id, jlong offset,
       
   315         jobject compressedBuffer, jlong compressed_size,
       
   316         jobject uncompressedBuffer, jlong uncompressed_size) {
       
   317     // Get address of read direct buffer.
       
   318     unsigned char* compressedAddress;
       
   319     unsigned char* uncompressedAddress;
       
   320 
       
   321     compressedAddress = (unsigned char*) env->GetDirectBufferAddress(compressedBuffer);
       
   322     // Get address of decompression direct buffer.
       
   323     uncompressedAddress = (unsigned char*) env->GetDirectBufferAddress(uncompressedBuffer);
       
   324     if (compressedAddress == NULL || uncompressedAddress == NULL) {
       
   325         return JNI_FALSE;
       
   326     }
       
   327     return JIMAGE_ReadCompressed(env, id, offset, compressedAddress, compressed_size,
       
   328             uncompressedAddress, uncompressed_size);
       
   329 }
       
   330 
       
   331 JNIEXPORT jbyteArray JNICALL
       
   332 Java_jdk_internal_jimage_ImageNativeSubstrate_getStringBytes(JNIEnv *env,
       
   333         jclass cls, jlong id, jint offset) {
       
   334     const char* data;
       
   335     size_t size;
       
   336     jbyteArray byteArray;
       
   337     jbyte* rawBytes;
       
   338 
       
   339     data = JIMAGE_GetStringBytes(env, id, offset);
       
   340     // Determine String length.
       
   341     size = strlen(data);
       
   342     // Allocate byte array.
       
   343     byteArray = env->NewByteArray((jsize) size);
       
   344     if (byteArray == NULL) {
       
   345         return NULL;
       
   346     }
       
   347     // Get array base address.
       
   348     rawBytes = env->GetByteArrayElements(byteArray, NULL);
       
   349     // Copy bytes from image string table.
       
   350     memcpy(rawBytes, data, size);
       
   351     // Release byte array base address.
       
   352     env->ReleaseByteArrayElements(byteArray, rawBytes, 0);
       
   353     return byteArray;
       
   354 }
       
   355 
       
   356 JNIEXPORT jlongArray JNICALL
       
   357 Java_jdk_internal_jimage_ImageNativeSubstrate_getAttributes(JNIEnv *env,
       
   358         jclass cls, jlong id, jint offset) {
       
   359     // Allocate a jlong large enough for all location attributes.
       
   360     jlongArray attributes;
       
   361     jlong* rawAttributes;
       
   362     jlong* ret;
       
   363 
       
   364     attributes = env->NewLongArray(JIMAGE_GetAttributesCount(env));
       
   365     if (attributes == NULL) {
       
   366         return NULL;
       
   367     }
       
   368     // Get base address for jlong array.
       
   369     rawAttributes = env->GetLongArrayElements(attributes, NULL);
       
   370     ret = JIMAGE_GetAttributes(env, rawAttributes, id, offset);
       
   371     // Release jlong array base address.
       
   372     env->ReleaseLongArrayElements(attributes, rawAttributes, 0);
       
   373     return ret == NULL ? NULL : attributes;
       
   374 }
       
   375 
       
   376 JNIEXPORT jlongArray JNICALL
       
   377 Java_jdk_internal_jimage_ImageNativeSubstrate_findAttributes(JNIEnv *env,
       
   378         jclass cls, jlong id, jbyteArray utf8) {
       
   379     // Allocate a jlong large enough for all location attributes.
       
   380     jsize count;
       
   381     jlongArray attributes;
       
   382     jlong* rawAttributes;
       
   383     jsize size;
       
   384     jbyte* rawBytes;
       
   385     jlong* ret;
       
   386 
       
   387     count = JIMAGE_GetAttributesCount(env);
       
   388     attributes = env->NewLongArray(JIMAGE_GetAttributesCount(env));
       
   389     if (attributes == NULL) {
       
   390         return NULL;
       
   391     }
       
   392     // Get base address for jlong array.
       
   393     rawAttributes = env->GetLongArrayElements(attributes, NULL);
       
   394     size = env->GetArrayLength(utf8);
       
   395     rawBytes = env->GetByteArrayElements(utf8, NULL);
       
   396     ret = JIMAGE_FindAttributes(env, rawAttributes, rawBytes, size, id);
       
   397     env->ReleaseByteArrayElements(utf8, rawBytes, 0);
       
   398     // Release jlong array base address.
       
   399     env->ReleaseLongArrayElements(attributes, rawAttributes, 0);
       
   400     return ret == NULL ? NULL : attributes;
       
   401 
       
   402 }
       
   403 
       
   404 JNIEXPORT jintArray JNICALL
       
   405 Java_jdk_internal_jimage_ImageNativeSubstrate_attributeOffsets(JNIEnv *env,
       
   406         jclass cls, jlong id) {
       
   407     unsigned int length;
       
   408     jintArray offsets;
       
   409     jint* rawOffsets;
       
   410     jint* ret;
       
   411 
       
   412     length = JIMAGE_AttributeOffsetsLength(env, id);
       
   413     offsets = env->NewIntArray(length);
       
   414     if (offsets == NULL) {
       
   415         return NULL;
       
   416     }
       
   417     // Get base address of result.
       
   418     rawOffsets = env->GetIntArrayElements(offsets, NULL);
       
   419     ret = JIMAGE_AttributeOffsets(env, rawOffsets, length, id);
       
   420     if (length == 0) {
       
   421         return NULL;
       
   422     }
       
   423     // Release result base address.
       
   424     env->ReleaseIntArrayElements(offsets, rawOffsets, 0);
       
   425     return ret == NULL ? NULL : offsets;
       
   426 }
       
   427 
       
   428 /*
       
   429  * Class:     jdk_internal_jimage_ImageNativeSubstrate
       
   430  * Method:    JIMAGE_open
       
   431  * Signature: (Ljava/lang/String;)J
       
   432  */
       
   433 JNIEXPORT jlong JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1Open
       
   434 (JNIEnv *env, jclass, jstring path) {
       
   435     const char *nativePath = env->GetStringUTFChars(path, NULL);
       
   436     if (nativePath == NULL)
       
   437         return 0; // Exception already thrown
       
   438     jint error;
       
   439     jlong ret = (jlong) JIMAGE_Open(nativePath, &error);
       
   440     env->ReleaseStringUTFChars(path, nativePath);
       
   441     return ret;
       
   442 }
       
   443 
       
   444 /*
       
   445  * Class:     jdk_internal_jimage_ImageNativeSubstrate
       
   446  * Method:    JIMAGE_Close
       
   447  * Signature: (J)J
       
   448  */
       
   449 JNIEXPORT void JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1Close
       
   450 (JNIEnv *env, jclass, jlong jimageHandle) {
       
   451     JIMAGE_Close((JImageFile*) jimageHandle);
       
   452 }
       
   453 
       
   454 /*
       
   455  * Class:     jdk_internal_jimage_ImageNativeSubstrate
       
   456  * Method:    JIMAGE_FindResource
       
   457  * Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;[J)J
       
   458  */
       
   459 JNIEXPORT jlong JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1FindResource
       
   460 (JNIEnv *env, jclass, jlong jimageHandle, jstring moduleName,
       
   461         jstring version, jstring path, jlongArray output_size) {
       
   462     const char *native_module = NULL;
       
   463     const char *native_version = NULL;
       
   464     const char *native_path = NULL;
       
   465     jlong * native_array = NULL;
       
   466     jlong size = 0;
       
   467     jlong ret = 0;
       
   468 
       
   469     if (moduleName == NULL) {
       
   470         ThrowByName(env, "java/lang/NullPointerException", "moduleName");
       
   471         return 0;
       
   472     }
       
   473     if (version == NULL) {
       
   474         ThrowByName(env, "java/lang/NullPointerException", "version");
       
   475         return 0;
       
   476     }
       
   477     if (path == NULL) {
       
   478         ThrowByName(env, "java/lang/NullPointerException", "path");
       
   479         return 0;
       
   480     }
       
   481     if (output_size == NULL) {
       
   482         ThrowByName(env, "java/lang/NullPointerException", "size");
       
   483         return 0;
       
   484     }
       
   485 
       
   486     do {
       
   487         native_module = env->GetStringUTFChars(moduleName, NULL);
       
   488         if (native_module == NULL)
       
   489             break;
       
   490         native_version = env->GetStringUTFChars(version, NULL);
       
   491         if (native_version == NULL)
       
   492             break;
       
   493         native_path = env->GetStringUTFChars(path, NULL);
       
   494         if (native_path == NULL)
       
   495             break;
       
   496         if (env->GetArrayLength(output_size) < 1)
       
   497             break;
       
   498         // Get base address for jlong array.
       
   499         native_array = env->GetLongArrayElements(output_size, NULL);
       
   500         if (native_array == NULL)
       
   501             break;
       
   502 
       
   503         ret = (jlong) JIMAGE_FindResource((JImageFile *) jimageHandle,
       
   504                 native_module, native_version, native_path, &size);
       
   505         if (ret != 0)
       
   506             *native_array = size;
       
   507     } while (0);
       
   508 
       
   509     if (native_array != NULL)
       
   510         env->ReleaseLongArrayElements(output_size, native_array, 0);
       
   511     if (native_path != NULL)
       
   512         env->ReleaseStringUTFChars(path, native_path);
       
   513     if (native_version != NULL)
       
   514         env->ReleaseStringUTFChars(path, native_version);
       
   515     if (native_module != NULL)
       
   516         env->ReleaseStringUTFChars(path, native_module);
       
   517 
       
   518     return ret;
       
   519 }
       
   520 
       
   521 /*
       
   522  * Class:     jdk_internal_jimage_ImageNativeSubstrate
       
   523  * Method:    JIMAGE_GetResource
       
   524  * Signature: (JJ[BJ)J
       
   525  */
       
   526 JNIEXPORT jlong JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1GetResource
       
   527 (JNIEnv *env, jclass, jlong jimageHandle, jlong jlocationHandle, jbyteArray buffer, jlong size) {
       
   528     jbyte * native_buffer = NULL;
       
   529     jlong actual_size = 0;
       
   530     do {
       
   531         if (env->GetArrayLength(buffer) < size)
       
   532             break;
       
   533 
       
   534         native_buffer = env->GetByteArrayElements(buffer, NULL);
       
   535         if (native_buffer == NULL)
       
   536             break;
       
   537 
       
   538         actual_size = JIMAGE_GetResource((JImageFile*) jimageHandle,
       
   539                 (JImageLocationRef) jlocationHandle,
       
   540                 (char *) native_buffer, size);
       
   541     } while (0);
       
   542     // Release byte array
       
   543     if (native_buffer != NULL)
       
   544         env->ReleaseByteArrayElements(buffer, native_buffer, 0);
       
   545 
       
   546     return actual_size;
       
   547 }
       
   548 
       
   549 // Structure passed from iterator to a visitor to accumulate the results
       
   550 
       
   551 struct VisitorData {
       
   552     JNIEnv *env;
       
   553     int size; // current number of strings
       
   554     int max; // Maximum number of strings
       
   555     jobjectArray array; // String array to store the strings
       
   556 };
       
   557 
       
   558 // Visitor to accumulate fully qualified resource names
       
   559 
       
   560 static bool resourceVisitor(JImageFile* image,
       
   561         const char* module, const char* version, const char* package,
       
   562         const char* name, const char* extension, void* arg) {
       
   563     struct VisitorData *vdata = (struct VisitorData *) arg;
       
   564     JNIEnv* env = vdata->env;
       
   565     if (vdata->size < vdata->max) {
       
   566         // Store if there is room in the array
       
   567         // Concatenate to get full path
       
   568         char fullpath[IMAGE_MAX_PATH];
       
   569         size_t moduleLen = strlen(module);
       
   570         size_t packageLen = strlen(package);
       
   571         size_t nameLen = strlen(name);
       
   572         size_t extLen = strlen(extension);
       
   573         size_t index;
       
   574 
       
   575         if (1 + moduleLen + 1 + packageLen + 1 + nameLen + 1 + extLen + 1 > IMAGE_MAX_PATH) {
       
   576             ThrowByName(env, "java/lang/InternalError", "concatenated name too long");
       
   577             return true;
       
   578         }
       
   579 
       
   580         index = 0;
       
   581         if (moduleLen > 0) {
       
   582             fullpath[index++] = '/';
       
   583             memcpy(&fullpath[index], module, moduleLen);
       
   584             index += moduleLen;
       
   585             fullpath[index++] = '/';
       
   586         }
       
   587         if (packageLen > 0) {
       
   588             memcpy(&fullpath[index], package, packageLen);
       
   589             index += packageLen;
       
   590             fullpath[index++] = '/';
       
   591         }
       
   592         memcpy(&fullpath[index], name, nameLen);
       
   593         index += nameLen;
       
   594         if (extLen > 0) {
       
   595             fullpath[index++] = '.';
       
   596             memcpy(&fullpath[index], extension, extLen);
       
   597             index += extLen;
       
   598         }
       
   599         fullpath[index++] = '\0';
       
   600 
       
   601         jobject str = env->NewStringUTF(fullpath);
       
   602         if (env->ExceptionCheck()) {
       
   603             return true;
       
   604         }
       
   605 
       
   606         env->SetObjectArrayElement(vdata->array, vdata->size, str);
       
   607         if (env->ExceptionCheck()) {
       
   608             return true;
       
   609         }
       
   610     }
       
   611     vdata->size++; // always count so the total size is returned
       
   612     return true;
       
   613 }
       
   614 
       
   615 /*
       
   616  * Class:     jdk_internal_jimage_ImageNativeSubstrate
       
   617  * Method:    JIMAGE_Resources
       
   618  * Signature: (J)V
       
   619  */
       
   620 JNIEXPORT jint JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1Resources
       
   621 (JNIEnv *env, jclass, jlong jimageHandle,
       
   622         jobjectArray outputNames) {
       
   623     struct VisitorData vdata;
       
   624     vdata.env = env;
       
   625     vdata.max = 0;
       
   626     vdata.size = 0;
       
   627     vdata.array = outputNames;
       
   628 
       
   629     vdata.max = (outputNames != NULL) ? env->GetArrayLength(outputNames) : 0;
       
   630     JIMAGE_ResourceIterator((JImageFile*) jimageHandle, &resourceVisitor, &vdata);
       
   631     return vdata.size;
       
   632 }
       
   633 
       
   634 /*
       
   635  * Class:     jdk_internal_jimage_ImageNativeSubstrate
       
   636  * Method:    JIMAGE_PackageToModule
       
   637  * Signature: (JLjava/lang/String;)Ljava/lang/String;
       
   638  */
       
   639 JNIEXPORT jstring JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1PackageToModule
       
   640 (JNIEnv *env, jclass, jlong jimageHandle, jstring package_name) {
       
   641     const char *native_package = NULL;
       
   642     const char *native_module = NULL;
       
   643     jstring module = NULL;
       
   644 
       
   645     native_package = env->GetStringUTFChars(package_name, NULL);
       
   646     if (env->ExceptionCheck()) {
       
   647         return NULL;
       
   648     }
       
   649 
       
   650 
       
   651     native_module = JIMAGE_PackageToModule((JImageFile*) jimageHandle, native_package);
       
   652     if (native_module != NULL) {
       
   653         module = env->NewStringUTF(native_module);
       
   654     }
       
   655     env->ReleaseStringUTFChars(package_name, native_package);
       
   656     return module;
       
   657 }
       
   658 
       
   659 JNIEXPORT void JNICALL DEF_JNI_OnUnload(JavaVM *vm, void *reserved) {
       
   660     ImageDecompressor::image_decompressor_close();
       
   661 }