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 |
|