jdk/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp
changeset 32641 ac2c73b45253
child 32757 79d34d4b9627
equal deleted inserted replaced
32640:e00364b38376 32641:ac2c73b45253
       
     1 /*
       
     2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  *
       
    23  */
       
    24 
       
    25 #include <string.h>
       
    26 
       
    27 #include "jni.h"
       
    28 #include "jni_util.h"
       
    29 #include "jdk_util.h"
       
    30 #include "endian.hpp"
       
    31 #include "imageDecompressor.hpp"
       
    32 #include "imageFile.hpp"
       
    33 #include "inttypes.hpp"
       
    34 #include "jimage.hpp"
       
    35 #include "osSupport.hpp"
       
    36 
       
    37 #include "jdk_internal_jimage_ImageNativeSubstrate.h"
       
    38 
       
    39 extern bool MemoryMapImage;
       
    40 
       
    41 // jdk.internal.jimage /////////////////////////////////////////////////////////
       
    42 
       
    43 // Java entry to open an image file for sharing.
       
    44 
       
    45 static jlong JIMAGE_Open(JNIEnv *env, const char *nativePath, jboolean big_endian) {
       
    46     // Open image file for reading.
       
    47     ImageFileReader* reader = ImageFileReader::open(nativePath, big_endian != JNI_FALSE);
       
    48     // Return image ID as a jlong.
       
    49     return ImageFileReader::readerToID(reader);
       
    50 }
       
    51 
       
    52 // Java entry for closing a shared image file.
       
    53 
       
    54 static void JIMAGE_Close(JNIEnv *env, jlong id) {
       
    55     // Convert image ID to image reader structure.
       
    56     ImageFileReader* reader = ImageFileReader::idToReader(id);
       
    57     // If valid reader the close.
       
    58     if (reader != NULL) {
       
    59         ImageFileReader::close(reader);
       
    60     }
       
    61 }
       
    62 
       
    63 // Java entry for accessing the base address of the image index.
       
    64 
       
    65 static jlong JIMAGE_GetIndexAddress(JNIEnv *env, jlong id) {
       
    66     // Convert image ID to image reader structure.
       
    67     ImageFileReader* reader = ImageFileReader::idToReader(id);
       
    68     // If valid reader return index base address (as jlong) else zero.
       
    69     return reader != NULL ? (jlong) reader->get_index_address() : 0L;
       
    70 }
       
    71 
       
    72 // Java entry for accessing the base address of the image data.
       
    73 
       
    74 static jlong JIMAGE_GetDataAddress(JNIEnv *env, jlong id) {
       
    75     // Convert image ID to image reader structure.
       
    76     ImageFileReader* reader = ImageFileReader::idToReader(id);
       
    77     // If valid reader return data base address (as jlong) else zero.
       
    78     return MemoryMapImage && reader != NULL ? (jlong) reader->get_data_address() : 0L;
       
    79 }
       
    80 
       
    81 // Java entry for reading an uncompressed resource from the image.
       
    82 
       
    83 static jboolean JIMAGE_Read(JNIEnv *env, jlong id, jlong offset,
       
    84         unsigned char* uncompressedAddress, jlong uncompressed_size) {
       
    85     // Convert image ID to image reader structure.
       
    86     ImageFileReader* reader = ImageFileReader::idToReader(id);\
       
    87   // If not a valid reader the fail the read.
       
    88     if (reader == NULL) return false;
       
    89     // Get the file offset of resource data.
       
    90     u8 file_offset = reader->get_index_size() + offset;
       
    91     // Check validity of arguments.
       
    92     if (offset < 0 ||
       
    93             uncompressed_size < 0 ||
       
    94             file_offset > reader->file_size() - uncompressed_size) {
       
    95         return false;
       
    96     }
       
    97     // Read file content into buffer.
       
    98     return (jboolean) reader->read_at((u1*) uncompressedAddress, uncompressed_size,
       
    99             file_offset);
       
   100 }
       
   101 
       
   102 // Java entry for reading a compressed resource from the image.
       
   103 
       
   104 static jboolean JIMAGE_ReadCompressed(JNIEnv *env,
       
   105         jlong id, jlong offset,
       
   106         unsigned char* compressedAddress, jlong compressed_size,
       
   107         unsigned char* uncompressedAddress, jlong uncompressed_size) {
       
   108     // Convert image ID to image reader structure.
       
   109     ImageFileReader* reader = ImageFileReader::idToReader(id);
       
   110     // If not a valid reader the fail the read.
       
   111     if (reader == NULL) return false;
       
   112     // Get the file offset of resource data.
       
   113     u8 file_offset = reader->get_index_size() + offset;
       
   114     // Check validity of arguments.
       
   115     if (offset < 0 ||
       
   116             compressed_size < 0 ||
       
   117             uncompressed_size < 0 ||
       
   118             file_offset > reader->file_size() - compressed_size) {
       
   119         return false;
       
   120     }
       
   121 
       
   122     // Read file content into buffer.
       
   123     bool is_read = reader->read_at(compressedAddress, compressed_size,
       
   124             file_offset);
       
   125     // If successfully read then decompress.
       
   126     if (is_read) {
       
   127         const ImageStrings strings = reader->get_strings();
       
   128         ImageDecompressor::decompress_resource(compressedAddress, uncompressedAddress,
       
   129                 (u4) uncompressed_size, &strings);
       
   130     }
       
   131     return (jboolean) is_read;
       
   132 }
       
   133 
       
   134 // Java entry for retrieving UTF-8 bytes from image string table.
       
   135 
       
   136 static const char* JIMAGE_GetStringBytes(JNIEnv *env, jlong id, jint offset) {
       
   137     // Convert image ID to image reader structure.
       
   138     ImageFileReader* reader = ImageFileReader::idToReader(id);
       
   139     // Fail if not valid reader.
       
   140     if (reader == NULL) return NULL;
       
   141     // Manage image string table.
       
   142     ImageStrings strings = reader->get_strings();
       
   143     // Retrieve string adrress from table.
       
   144     const char* data = strings.get(offset);
       
   145     return data;
       
   146 }
       
   147 
       
   148 // Utility function to copy location information into a jlong array.
       
   149 // WARNING: This function is experimental and temporary during JDK 9 development
       
   150 // cycle. It will not be supported in the eventual JDK 9 release.
       
   151 
       
   152 static void image_expand_location(JNIEnv *env, jlong* rawAttributes, ImageLocation& location) {
       
   153     // Copy attributes from location.
       
   154     for (int kind = ImageLocation::ATTRIBUTE_END + 1;
       
   155             kind < ImageLocation::ATTRIBUTE_COUNT;
       
   156             kind++) {
       
   157         rawAttributes[kind] = location.get_attribute(kind);
       
   158     }
       
   159 }
       
   160 
       
   161 // Java entry for retrieving location attributes for attribute offset.
       
   162 
       
   163 static jlong* JIMAGE_GetAttributes(JNIEnv *env, jlong* rawAttributes, jlong id, jint offset) {
       
   164     // Convert image ID to image reader structure.
       
   165     ImageFileReader* reader = ImageFileReader::idToReader(id);
       
   166     // Fail if not valid reader.
       
   167     if (reader == NULL) return NULL;
       
   168     // Retrieve first byte address of resource's location attribute stream.
       
   169     u1* data = reader->get_location_offset_data(offset);
       
   170     // Fail if not valid offset.
       
   171     if (data == NULL) return NULL;
       
   172     // Expand stream into array.
       
   173     ImageLocation location(data);
       
   174     image_expand_location(env, rawAttributes, location);
       
   175     return rawAttributes;
       
   176 }
       
   177 
       
   178 // Java entry for retrieving location attributes count for attribute offset.
       
   179 
       
   180 static jsize JIMAGE_GetAttributesCount(JNIEnv *env) {
       
   181     return ImageLocation::ATTRIBUTE_COUNT;
       
   182 }
       
   183 
       
   184 // Java entry for retrieving location attributes for named resource.
       
   185 
       
   186 static jlong* JIMAGE_FindAttributes(JNIEnv *env, jlong* rawAttributes, jbyte* rawBytes, jsize size, jlong id) {
       
   187     // Convert image ID to image reader structure.
       
   188     ImageFileReader* reader = ImageFileReader::idToReader(id);
       
   189     // Fail if not valid reader.
       
   190     if (reader == NULL) return NULL;
       
   191     // Convert byte array to a cstring.
       
   192     char* path = new char[size + 1];
       
   193     memcpy(path, rawBytes, size);
       
   194     path[size] = '\0';
       
   195     // Locate resource location data.
       
   196     ImageLocation location;
       
   197     bool found = reader->find_location(path, location);
       
   198     delete path;
       
   199     // Resource not found.
       
   200     if (!found) return NULL;
       
   201     // Expand stream into array.
       
   202     image_expand_location(env, rawAttributes, location);
       
   203     return rawAttributes;
       
   204 }
       
   205 
       
   206 // Java entry for retrieving all the attribute stream offsets from an image.
       
   207 
       
   208 static jint* JIMAGE_AttributeOffsets(JNIEnv *env, jint* rawOffsets, unsigned int length, jlong id) {
       
   209     // Convert image ID to image reader structure.
       
   210     ImageFileReader* reader = ImageFileReader::idToReader(id);
       
   211     // Fail if not valid reader.
       
   212     if (reader == NULL) return NULL;
       
   213     // Determine endian for reader.
       
   214     Endian* endian = reader->endian();
       
   215     // Get base address of attribute stream offsets table.
       
   216     u4* offsets_table = reader->offsets_table();
       
   217     // Allocate int array result.
       
   218     // Copy values to result (converting endian.)
       
   219     for (u4 i = 0; i < length; i++) {
       
   220         rawOffsets[i] = endian->get(offsets_table[i]);
       
   221     }
       
   222     return rawOffsets;
       
   223 }
       
   224 
       
   225 // Java entry for retrieving all the attribute stream offsets length from an image.
       
   226 
       
   227 static unsigned int JIMAGE_AttributeOffsetsLength(JNIEnv *env, jlong id) {
       
   228     // Convert image ID to image reader structure.
       
   229     ImageFileReader* reader = ImageFileReader::idToReader(id);
       
   230     // Fail if not valid reader.
       
   231     if (reader == NULL) return 0;
       
   232     // Get perfect hash table length.
       
   233     u4 length = reader->table_length();
       
   234     return (jint) length;
       
   235 }
       
   236 
       
   237 JNIEXPORT jint JNICALL
       
   238 JNI_OnLoad(JavaVM *vm, void *reserved) {
       
   239     JNIEnv *env;
       
   240 
       
   241     if (vm->GetEnv((void**) &env, JNI_VERSION_1_2) != JNI_OK) {
       
   242         return JNI_EVERSION; /* JNI version not supported */
       
   243     }
       
   244 
       
   245     return JNI_VERSION_1_2;
       
   246 }
       
   247 
       
   248 JNIEXPORT jlong JNICALL
       
   249 Java_jdk_internal_jimage_ImageNativeSubstrate_openImage(JNIEnv *env,
       
   250         jclass cls, jstring path, jboolean big_endian) {
       
   251     const char *nativePath;
       
   252     jlong ret;
       
   253 
       
   254     nativePath = env->GetStringUTFChars(path, NULL);
       
   255     ret = JIMAGE_Open(env, nativePath, big_endian);
       
   256     env->ReleaseStringUTFChars(path, nativePath);
       
   257     return ret;
       
   258 }
       
   259 
       
   260 JNIEXPORT void JNICALL
       
   261 Java_jdk_internal_jimage_ImageNativeSubstrate_closeImage(JNIEnv *env,
       
   262         jclass cls, jlong id) {
       
   263     JIMAGE_Close(env, id);
       
   264 }
       
   265 
       
   266 JNIEXPORT jlong JNICALL
       
   267 Java_jdk_internal_jimage_ImageNativeSubstrate_getIndexAddress(JNIEnv *env,
       
   268         jclass cls, jlong id) {
       
   269     return JIMAGE_GetIndexAddress(env, id);
       
   270 }
       
   271 
       
   272 JNIEXPORT jlong JNICALL
       
   273 Java_jdk_internal_jimage_ImageNativeSubstrate_getDataAddress(JNIEnv *env,
       
   274         jclass cls, jlong id) {
       
   275     return JIMAGE_GetDataAddress(env, id);
       
   276 }
       
   277 
       
   278 JNIEXPORT jboolean JNICALL
       
   279 Java_jdk_internal_jimage_ImageNativeSubstrate_read(JNIEnv *env,
       
   280         jclass cls, jlong id, jlong offset,
       
   281         jobject uncompressedBuffer, jlong uncompressed_size) {
       
   282     unsigned char* uncompressedAddress;
       
   283 
       
   284     uncompressedAddress = (unsigned char*) env->GetDirectBufferAddress(uncompressedBuffer);
       
   285     if (uncompressedAddress == NULL) {
       
   286         return JNI_FALSE;
       
   287     }
       
   288     return JIMAGE_Read(env, id, offset, uncompressedAddress, uncompressed_size);
       
   289 }
       
   290 
       
   291 JNIEXPORT jboolean JNICALL
       
   292 Java_jdk_internal_jimage_ImageNativeSubstrate_readCompressed(JNIEnv *env,
       
   293         jclass cls, jlong id, jlong offset,
       
   294         jobject compressedBuffer, jlong compressed_size,
       
   295         jobject uncompressedBuffer, jlong uncompressed_size) {
       
   296     // Get address of read direct buffer.
       
   297     unsigned char* compressedAddress;
       
   298     unsigned char* uncompressedAddress;
       
   299 
       
   300     compressedAddress = (unsigned char*) env->GetDirectBufferAddress(compressedBuffer);
       
   301     // Get address of decompression direct buffer.
       
   302     uncompressedAddress = (unsigned char*) env->GetDirectBufferAddress(uncompressedBuffer);
       
   303     if (compressedAddress == NULL || uncompressedAddress == NULL) {
       
   304         return JNI_FALSE;
       
   305     }
       
   306     return JIMAGE_ReadCompressed(env, id, offset, compressedAddress, compressed_size,
       
   307             uncompressedAddress, uncompressed_size);
       
   308 }
       
   309 
       
   310 JNIEXPORT jbyteArray JNICALL
       
   311 Java_jdk_internal_jimage_ImageNativeSubstrate_getStringBytes(JNIEnv *env,
       
   312         jclass cls, jlong id, jint offset) {
       
   313     const char* data;
       
   314     size_t size;
       
   315     jbyteArray byteArray;
       
   316     jbyte* rawBytes;
       
   317 
       
   318     data = JIMAGE_GetStringBytes(env, id, offset);
       
   319     // Determine String length.
       
   320     size = strlen(data);
       
   321     // Allocate byte array.
       
   322     byteArray = env->NewByteArray((jsize) size);
       
   323     if (byteArray == NULL) {
       
   324         return NULL;
       
   325     }
       
   326     // Get array base address.
       
   327     rawBytes = env->GetByteArrayElements(byteArray, NULL);
       
   328     // Copy bytes from image string table.
       
   329     memcpy(rawBytes, data, size);
       
   330     // Release byte array base address.
       
   331     env->ReleaseByteArrayElements(byteArray, rawBytes, 0);
       
   332     return byteArray;
       
   333 }
       
   334 
       
   335 JNIEXPORT jlongArray JNICALL
       
   336 Java_jdk_internal_jimage_ImageNativeSubstrate_getAttributes(JNIEnv *env,
       
   337         jclass cls, jlong id, jint offset) {
       
   338     // Allocate a jlong large enough for all location attributes.
       
   339     jlongArray attributes;
       
   340     jlong* rawAttributes;
       
   341     jlong* ret;
       
   342 
       
   343     attributes = env->NewLongArray(JIMAGE_GetAttributesCount(env));
       
   344     if (attributes == NULL) {
       
   345         return NULL;
       
   346     }
       
   347     // Get base address for jlong array.
       
   348     rawAttributes = env->GetLongArrayElements(attributes, NULL);
       
   349     ret = JIMAGE_GetAttributes(env, rawAttributes, id, offset);
       
   350     // Release jlong array base address.
       
   351     env->ReleaseLongArrayElements(attributes, rawAttributes, 0);
       
   352     return ret == NULL ? NULL : attributes;
       
   353 }
       
   354 
       
   355 JNIEXPORT jlongArray JNICALL
       
   356 Java_jdk_internal_jimage_ImageNativeSubstrate_findAttributes(JNIEnv *env,
       
   357         jclass cls, jlong id, jbyteArray utf8) {
       
   358     // Allocate a jlong large enough for all location attributes.
       
   359     jsize count;
       
   360     jlongArray attributes;
       
   361     jlong* rawAttributes;
       
   362     jsize size;
       
   363     jbyte* rawBytes;
       
   364     jlong* ret;
       
   365 
       
   366     count = JIMAGE_GetAttributesCount(env);
       
   367     attributes = env->NewLongArray(JIMAGE_GetAttributesCount(env));
       
   368     if (attributes == NULL) {
       
   369         return NULL;
       
   370     }
       
   371     // Get base address for jlong array.
       
   372     rawAttributes = env->GetLongArrayElements(attributes, NULL);
       
   373     size = env->GetArrayLength(utf8);
       
   374     rawBytes = env->GetByteArrayElements(utf8, NULL);
       
   375     ret = JIMAGE_FindAttributes(env, rawAttributes, rawBytes, size, id);
       
   376     env->ReleaseByteArrayElements(utf8, rawBytes, 0);
       
   377     // Release jlong array base address.
       
   378     env->ReleaseLongArrayElements(attributes, rawAttributes, 0);
       
   379     return ret == NULL ? NULL : attributes;
       
   380 
       
   381 }
       
   382 
       
   383 JNIEXPORT jintArray JNICALL
       
   384 Java_jdk_internal_jimage_ImageNativeSubstrate_attributeOffsets(JNIEnv *env,
       
   385         jclass cls, jlong id) {
       
   386     unsigned int length;
       
   387     jintArray offsets;
       
   388     jint* rawOffsets;
       
   389     jint* ret;
       
   390 
       
   391     length = JIMAGE_AttributeOffsetsLength(env, id);
       
   392     offsets = env->NewIntArray(length);
       
   393     if (offsets == NULL) {
       
   394         return NULL;
       
   395     }
       
   396     // Get base address of result.
       
   397     rawOffsets = env->GetIntArrayElements(offsets, NULL);
       
   398     ret = JIMAGE_AttributeOffsets(env, rawOffsets, length, id);
       
   399     if (length == 0) {
       
   400         return NULL;
       
   401     }
       
   402     // Release result base address.
       
   403     env->ReleaseIntArrayElements(offsets, rawOffsets, 0);
       
   404     return ret == NULL ? NULL : offsets;
       
   405 }
       
   406 
       
   407 /*
       
   408  * Class:     jdk_internal_jimage_ImageNativeSubstrate
       
   409  * Method:    JIMAGE_open
       
   410  * Signature: (Ljava/lang/String;)J
       
   411  */
       
   412 JNIEXPORT jlong JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1Open
       
   413 (JNIEnv *env, jclass, jstring path) {
       
   414     const char *nativePath = env->GetStringUTFChars(path, NULL);
       
   415     if (nativePath == NULL)
       
   416         return 0; // Exception already thrown
       
   417     jint error;
       
   418     jlong ret = (jlong) JIMAGE_Open(nativePath, &error);
       
   419     env->ReleaseStringUTFChars(path, nativePath);
       
   420     return ret;
       
   421 }
       
   422 
       
   423 /*
       
   424  * Class:     jdk_internal_jimage_ImageNativeSubstrate
       
   425  * Method:    JIMAGE_Close
       
   426  * Signature: (J)J
       
   427  */
       
   428 JNIEXPORT void JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1Close
       
   429 (JNIEnv *env, jclass, jlong jimageHandle) {
       
   430     JIMAGE_Close((JImageFile*) jimageHandle);
       
   431 }
       
   432 
       
   433 /*
       
   434  * Class:     jdk_internal_jimage_ImageNativeSubstrate
       
   435  * Method:    JIMAGE_FindResource
       
   436  * Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;[J)J
       
   437  */
       
   438 JNIEXPORT jlong JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1FindResource
       
   439 (JNIEnv *env, jclass, jlong jimageHandle, jstring moduleName,
       
   440         jstring version, jstring path, jlongArray output_size) {
       
   441     const char *native_module = NULL;
       
   442     const char *native_version = NULL;
       
   443     const char *native_path = NULL;
       
   444     jlong * native_array = NULL;
       
   445     jlong size = 0;
       
   446     jlong ret = 0;
       
   447 
       
   448     do {
       
   449         native_module = env->GetStringUTFChars(moduleName, NULL);
       
   450         if (native_module == NULL)
       
   451             break;
       
   452         native_version = env->GetStringUTFChars(version, NULL);
       
   453         if (native_version == NULL)
       
   454             break;
       
   455         native_path = env->GetStringUTFChars(path, NULL);
       
   456         if (native_path == NULL)
       
   457             break;
       
   458         if (env->GetArrayLength(output_size) < 1)
       
   459             break;
       
   460         // Get base address for jlong array.
       
   461         native_array = env->GetLongArrayElements(output_size, NULL);
       
   462         if (native_array == NULL)
       
   463             break;
       
   464 
       
   465         ret = (jlong) JIMAGE_FindResource((JImageFile *) jimageHandle,
       
   466                 native_module, native_version, native_path, &size);
       
   467         if (ret != 0)
       
   468             *native_array = size;
       
   469     } while (0);
       
   470 
       
   471     if (native_array != NULL)
       
   472         env->ReleaseLongArrayElements(output_size, native_array, 0);
       
   473     if (native_path != NULL)
       
   474         env->ReleaseStringUTFChars(path, native_path);
       
   475     if (native_version != NULL)
       
   476         env->ReleaseStringUTFChars(path, native_version);
       
   477     if (native_module != NULL)
       
   478         env->ReleaseStringUTFChars(path, native_module);
       
   479 
       
   480     return ret;
       
   481 }
       
   482 
       
   483 /*
       
   484  * Class:     jdk_internal_jimage_ImageNativeSubstrate
       
   485  * Method:    JIMAGE_GetResource
       
   486  * Signature: (JJ[BJ)J
       
   487  */
       
   488 JNIEXPORT jlong JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1GetResource
       
   489 (JNIEnv *env, jclass, jlong jimageHandle, jlong jlocationHandle, jbyteArray buffer, jlong size) {
       
   490     jbyte * native_buffer = NULL;
       
   491     jlong actual_size = 0;
       
   492     do {
       
   493         if (env->GetArrayLength(buffer) < size)
       
   494             break;
       
   495 
       
   496         native_buffer = env->GetByteArrayElements(buffer, NULL);
       
   497         if (native_buffer == NULL)
       
   498             break;
       
   499 
       
   500         actual_size = JIMAGE_GetResource((JImageFile*) jimageHandle,
       
   501                 (JImageLocationRef) jlocationHandle,
       
   502                 (char *) native_buffer, size);
       
   503     } while (0);
       
   504     // Release byte array
       
   505     if (native_buffer != NULL)
       
   506         env->ReleaseByteArrayElements(buffer, native_buffer, 0);
       
   507 
       
   508     return actual_size;
       
   509 }
       
   510 
       
   511 // Structure passed from iterator to a visitor to accumulate the results
       
   512 
       
   513 struct VisitorData {
       
   514     JNIEnv *env;
       
   515     int size; // current number of strings
       
   516     int max; // Maximum number of strings
       
   517     jobjectArray array; // String array to store the strings
       
   518 };
       
   519 
       
   520 // Visitor to accumulate fully qualified resource names
       
   521 
       
   522 static bool resourceVisitor(JImageFile* image,
       
   523         const char* module, const char* version, const char* package,
       
   524         const char* name, const char* extension, void* arg) {
       
   525     struct VisitorData *vdata = (struct VisitorData *) arg;
       
   526     JNIEnv* env = vdata->env;
       
   527     if (vdata->size < vdata->max) {
       
   528         // Store if there is room in the array
       
   529         // Concatenate to get full path
       
   530         char fullpath[IMAGE_MAX_PATH];
       
   531         fullpath[0] = '\0';
       
   532         if (*module != '\0') {
       
   533             strncpy(fullpath, "/", IMAGE_MAX_PATH - 1);
       
   534             strncat(fullpath, module, IMAGE_MAX_PATH - 1);
       
   535             strncat(fullpath, "/", IMAGE_MAX_PATH - 1);
       
   536         }
       
   537         if (*package != '\0') {
       
   538             strncat(fullpath, package, IMAGE_MAX_PATH - 1);
       
   539             strncat(fullpath, "/", IMAGE_MAX_PATH - 1);
       
   540         }
       
   541         strncat(fullpath, name, IMAGE_MAX_PATH - 1);
       
   542         if (*extension != '\0') {
       
   543             strncat(fullpath, ".", IMAGE_MAX_PATH - 1);
       
   544             strncat(fullpath, extension, IMAGE_MAX_PATH - 1);
       
   545         }
       
   546         jobject str = env->NewStringUTF(fullpath);
       
   547         JNU_CHECK_EXCEPTION_RETURN(env, true);
       
   548         env->SetObjectArrayElement(vdata->array, vdata->size, str);
       
   549         JNU_CHECK_EXCEPTION_RETURN(env, true);
       
   550     }
       
   551     vdata->size++; // always count so the total size is returned
       
   552     return true;
       
   553 }
       
   554 
       
   555 /*
       
   556  * Class:     jdk_internal_jimage_ImageNativeSubstrate
       
   557  * Method:    JIMAGE_Resources
       
   558  * Signature: (J)V
       
   559  */
       
   560 JNIEXPORT jint JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1Resources
       
   561 (JNIEnv *env, jclass, jlong jimageHandle,
       
   562         jobjectArray outputNames) {
       
   563     struct VisitorData vdata;
       
   564     vdata.env = env;
       
   565     vdata.max = 0;
       
   566     vdata.size = 0;
       
   567     vdata.array = outputNames;
       
   568 
       
   569     vdata.max = (outputNames != NULL) ? env->GetArrayLength(outputNames) : 0;
       
   570     JIMAGE_ResourceIterator((JImageFile*) jimageHandle, &resourceVisitor, &vdata);
       
   571     return vdata.size;
       
   572 }
       
   573 
       
   574 /*
       
   575  * Class:     jdk_internal_jimage_ImageNativeSubstrate
       
   576  * Method:    JIMAGE_PackageToModule
       
   577  * Signature: (JLjava/lang/String;)Ljava/lang/String;
       
   578  */
       
   579 JNIEXPORT jstring JNICALL Java_jdk_internal_jimage_ImageNativeSubstrate_JIMAGE_1PackageToModule
       
   580 (JNIEnv *env, jclass, jlong jimageHandle, jstring package_name) {
       
   581     const char *native_package = NULL;
       
   582     const char *native_module = NULL;
       
   583     jstring module = NULL;
       
   584 
       
   585     native_package = env->GetStringUTFChars(package_name, NULL);
       
   586     JNU_CHECK_EXCEPTION_RETURN(env, NULL);
       
   587 
       
   588     native_module = JIMAGE_PackageToModule((JImageFile*) jimageHandle, native_package);
       
   589     if (native_module != NULL) {
       
   590         module = env->NewStringUTF(native_module);
       
   591     }
       
   592     env->ReleaseStringUTFChars(package_name, native_package);
       
   593     return module;
       
   594 }
       
   595 
       
   596 JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {
       
   597     ImageDecompressor::image_decompressor_close();
       
   598 }