hotspot/src/share/vm/classfile/imageDecompressor.cpp
changeset 32761 d7c393b4e0d3
parent 32760 3851193a8c60
parent 32757 79d34d4b9627
child 32762 253adb0f4301
equal deleted inserted replaced
32760:3851193a8c60 32761:d7c393b4e0d3
     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 "precompiled.hpp"
       
    26 #include "runtime/thread.inline.hpp"
       
    27 #include "classfile/imageDecompressor.hpp"
       
    28 #include "runtime/thread.hpp"
       
    29 #include "utilities/bytes.hpp"
       
    30 
       
    31 /*
       
    32  * Allocate in C Heap not in resource area, otherwise JVM crashes.
       
    33  * This array life time is the VM life time. Array is never freed and
       
    34  * is not expected to contain more than few references.
       
    35  */
       
    36 GrowableArray<ImageDecompressor*>* ImageDecompressor::_decompressors =
       
    37   new(ResourceObj::C_HEAP, mtInternal) GrowableArray<ImageDecompressor*>(2, true);
       
    38 
       
    39 static Symbol* createSymbol(const char* str) {
       
    40   Thread* THREAD = Thread::current();
       
    41   Symbol* sym = SymbolTable::lookup(str, (int) strlen(str), THREAD);
       
    42   if (HAS_PENDING_EXCEPTION) {
       
    43     warning("can't create symbol\n");
       
    44     CLEAR_PENDING_EXCEPTION;
       
    45     return NULL;
       
    46   }
       
    47   return sym;
       
    48 }
       
    49 
       
    50 /*
       
    51  * Initialize the array of decompressors.
       
    52  */
       
    53 bool image_decompressor_init() {
       
    54   Symbol* zipSymbol = createSymbol("zip");
       
    55   if (zipSymbol == NULL) {
       
    56     return false;
       
    57   }
       
    58   ImageDecompressor::add_decompressor(new ZipDecompressor(zipSymbol));
       
    59 
       
    60   return true;
       
    61 }
       
    62 
       
    63 /*
       
    64  * Decompression entry point. Called from ImageFileReader::get_resource.
       
    65  */
       
    66 void ImageDecompressor::decompress_resource(u1* compressed, u1* uncompressed,
       
    67         u4 uncompressed_size, const ImageStrings* strings, bool is_C_heap) {
       
    68   bool has_header = false;
       
    69   u1* decompressed_resource = compressed;
       
    70   u1* compressed_resource = compressed;
       
    71 
       
    72   // Resource could have been transformed by a stack of decompressors.
       
    73   // Iterate and decompress resources until there is no more header.
       
    74   do {
       
    75     ResourceHeader _header;
       
    76     memcpy(&_header, compressed_resource, sizeof (ResourceHeader));
       
    77     has_header = _header._magic == ResourceHeader::resource_header_magic;
       
    78     if (has_header) {
       
    79       // decompressed_resource array contains the result of decompression
       
    80       // when a resource content is terminal, it means that it is an actual resource,
       
    81       // not an intermediate not fully uncompressed content. In this case
       
    82       // the resource is allocated as an mtClass, otherwise as an mtOther
       
    83       decompressed_resource = is_C_heap && _header._is_terminal ?
       
    84               NEW_C_HEAP_ARRAY(u1, _header._uncompressed_size, mtClass) :
       
    85               NEW_C_HEAP_ARRAY(u1, _header._uncompressed_size, mtOther);
       
    86       // Retrieve the decompressor name
       
    87       const char* decompressor_name = strings->get(_header._decompressor_name_offset);
       
    88       if (decompressor_name == NULL) warning("image decompressor not found\n");
       
    89       guarantee(decompressor_name, "image decompressor not found");
       
    90       // Retrieve the decompressor instance
       
    91       ImageDecompressor* decompressor = get_decompressor(decompressor_name);
       
    92       if (decompressor == NULL) {
       
    93         warning("image decompressor %s not found\n", decompressor_name);
       
    94       }
       
    95       guarantee(decompressor, "image decompressor not found");
       
    96       u1* compressed_resource_base = compressed_resource;
       
    97       compressed_resource += ResourceHeader::resource_header_length;
       
    98       // Ask the decompressor to decompress the compressed content
       
    99       decompressor->decompress_resource(compressed_resource, decompressed_resource,
       
   100         &_header, strings);
       
   101       if (compressed_resource_base != compressed) {
       
   102         FREE_C_HEAP_ARRAY(char, compressed_resource_base);
       
   103       }
       
   104       compressed_resource = decompressed_resource;
       
   105     }
       
   106   } while (has_header);
       
   107   memcpy(uncompressed, decompressed_resource, uncompressed_size);
       
   108 }
       
   109 
       
   110 // Zip decompressor
       
   111 
       
   112 void ZipDecompressor::decompress_resource(u1* data, u1* uncompressed,
       
   113         ResourceHeader* header, const ImageStrings* strings) {
       
   114   char* msg = NULL;
       
   115   jboolean res = ClassLoader::decompress(data, header->_size, uncompressed,
       
   116           header->_uncompressed_size, &msg);
       
   117   if (!res) warning("decompression failed due to %s\n", msg);
       
   118   guarantee(res, "decompression failed");
       
   119 }
       
   120 
       
   121 // END Zip Decompressor