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 #ifndef SHARE_VM_CLASSFILE_IMAGEDECOMPRESSOR_HPP |
|
26 #define SHARE_VM_CLASSFILE_IMAGEDECOMPRESSOR_HPP |
|
27 |
|
28 #include "runtime/thread.inline.hpp" |
|
29 #include "classfile/classLoader.hpp" |
|
30 #include "classfile/imageFile.hpp" |
|
31 #include "classfile/symbolTable.hpp" |
|
32 #include "oops/symbol.hpp" |
|
33 #include "utilities/growableArray.hpp" |
|
34 |
|
35 /* |
|
36 * Compressed resources located in image have an header. |
|
37 * This header contains: |
|
38 * - _magic: A magic u4, required to retrieved the header in the compressed content |
|
39 * - _size: The size of the compressed resource. |
|
40 * - _uncompressed_size: The uncompressed size of the compressed resource. |
|
41 * - _decompressor_name_offset: The ImageDecompressor instance name StringsTable offset. |
|
42 * - _decompressor_config_offset: StringsTable offset of configuration that could be needed by |
|
43 * the decompressor in order to decompress. |
|
44 * - _is_terminal: 1: the compressed content is terminal. Uncompressing it would |
|
45 * create the actual resource. 0: the compressed content is not terminal. Uncompressing it |
|
46 * will result in a compressed content to be decompressed (This occurs when a stack of compressors |
|
47 * have been used to compress the resource. |
|
48 */ |
|
49 struct ResourceHeader { |
|
50 /* Length of header, needed to retrieve content offset */ |
|
51 static const u1 resource_header_length = 21; |
|
52 /* magic bytes that identifies a compressed resource header*/ |
|
53 static const u4 resource_header_magic = 0xCAFEFAFA; |
|
54 u4 _magic; // Resource header |
|
55 u4 _size; // Resource size |
|
56 u4 _uncompressed_size; // Expected uncompressed size |
|
57 u4 _decompressor_name_offset; // Strings table decompressor offset |
|
58 u4 _decompressor_config_offset; // Strings table config offset |
|
59 u1 _is_terminal; // Last decompressor 1, otherwise 0. |
|
60 }; |
|
61 |
|
62 /* |
|
63 * Resources located in jimage file can be compressed. Compression occurs at |
|
64 * jimage file creation time. When compressed a resource is added an header that |
|
65 * contains the name of the compressor that compressed it. |
|
66 * Various compression strategies can be applied to compress a resource. |
|
67 * The same resource can even be compressed multiple time by a stack of compressors. |
|
68 * At runtime, a resource is decompressed in a loop until there is no more header |
|
69 * meaning that the resource is equivalent to the not compressed resource. |
|
70 * In each iteration, the name of the compressor located in the current header |
|
71 * is used to retrieve the associated instance of ImageDecompressor. |
|
72 * For example “zip” is the name of the compressor that compresses resources |
|
73 * using the zip algorithm. The ZipDecompressor class name is also “zip”. |
|
74 * ImageDecompressor instances are retrieved from a static array in which |
|
75 * they are registered. |
|
76 */ |
|
77 class ImageDecompressor: public CHeapObj<mtClass> { |
|
78 |
|
79 private: |
|
80 const Symbol* _name; |
|
81 |
|
82 /* |
|
83 * Array of concrete decompressors. This array is used to retrieve the decompressor |
|
84 * that can handle resource decompression. |
|
85 */ |
|
86 static GrowableArray<ImageDecompressor*>* _decompressors; |
|
87 |
|
88 /* |
|
89 * Identifier of a decompressor. This name is the identification key to retrieve |
|
90 * decompressor from a resource header. |
|
91 */ |
|
92 inline const Symbol* get_name() const { return _name; } |
|
93 |
|
94 protected: |
|
95 ImageDecompressor(const Symbol* name) : _name(name) { |
|
96 } |
|
97 virtual void decompress_resource(u1* data, u1* uncompressed, |
|
98 ResourceHeader* header, const ImageStrings* strings) = 0; |
|
99 |
|
100 public: |
|
101 inline static void add_decompressor(ImageDecompressor* decompressor) { |
|
102 _decompressors->append(decompressor); |
|
103 } |
|
104 inline static ImageDecompressor* get_decompressor(const char * decompressor_name) { |
|
105 Thread* THREAD = Thread::current(); |
|
106 TempNewSymbol sym = SymbolTable::new_symbol(decompressor_name, |
|
107 (int) strlen(decompressor_name), CHECK_NULL); |
|
108 if (HAS_PENDING_EXCEPTION) { |
|
109 warning("can't create symbol\n"); |
|
110 CLEAR_PENDING_EXCEPTION; |
|
111 return NULL; |
|
112 } |
|
113 for (int i = 0; i < _decompressors->length(); i++) { |
|
114 ImageDecompressor* decompressor = _decompressors->at(i); |
|
115 if (decompressor->get_name()->fast_compare(sym) == 0) { |
|
116 return decompressor; |
|
117 } |
|
118 } |
|
119 guarantee(false, "No decompressor found."); |
|
120 return NULL; |
|
121 } |
|
122 static void decompress_resource(u1* compressed, u1* uncompressed, |
|
123 u4 uncompressed_size, const ImageStrings* strings, bool is_C_heap); |
|
124 }; |
|
125 |
|
126 /** |
|
127 * Zip decompressor. |
|
128 */ |
|
129 class ZipDecompressor : public ImageDecompressor { |
|
130 public: |
|
131 ZipDecompressor(const Symbol* sym) : ImageDecompressor(sym) { } |
|
132 void decompress_resource(u1* data, u1* uncompressed, ResourceHeader* header, |
|
133 const ImageStrings* strings); |
|
134 }; |
|
135 |
|
136 #endif // SHARE_VM_CLASSFILE_IMAGEDECOMPRESSOR_HPP |
|