1 /*
2 * Copyright (c) 2015, 2019, 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 "jvm.h"
27 #include "jimage.hpp"
28 #include "classfile/classListParser.hpp"
29 #include "classfile/classLoaderExt.hpp"
30 #include "classfile/symbolTable.hpp"
31 #include "classfile/systemDictionary.hpp"
32 #include "classfile/systemDictionaryShared.hpp"
33 #include "logging/log.hpp"
34 #include "logging/logTag.hpp"
35 #include "memory/metaspaceShared.hpp"
36 #include "memory/resourceArea.hpp"
37 #include "runtime/fieldType.hpp"
38 #include "runtime/handles.inline.hpp"
39 #include "runtime/javaCalls.hpp"
40 #include "utilities/defaultStream.hpp"
41 #include "utilities/hashtable.inline.hpp"
42 #include "utilities/macros.hpp"
43
44 ClassListParser* ClassListParser::_instance = NULL;
45
ClassListParser(const char * file)46 ClassListParser::ClassListParser(const char* file) {
47 assert(_instance == NULL, "must be singleton");
48 _instance = this;
49 _classlist_file = file;
50 _file = NULL;
51 _line_no = 0;
52 _interfaces = new (ResourceObj::C_HEAP, mtClass) GrowableArray<int>(10, true);
53
54 _file = NULL;
55 // Use os::open() because neither fopen() nor os::fopen()
56 // can handle long path name on Windows.
57 int fd = os::open(file, O_RDONLY, S_IREAD);
58 if (fd != -1) {
59 // Obtain a File* from the file descriptor so that fgets()
60 // can be used in parse_one_line()
61 _file = os::open(fd, "r");
62 }
63
64 if (_file == NULL) {
65 char errmsg[JVM_MAXPATHLEN];
66 os::lasterror(errmsg, JVM_MAXPATHLEN);
67 vm_exit_during_initialization("Loading classlist failed", errmsg);
68 }
69 }
70
~ClassListParser()71 ClassListParser::~ClassListParser() {
72 if (_file) {
73 fclose(_file);
74 }
75 _instance = NULL;
76 }
77
parse_one_line()78 bool ClassListParser::parse_one_line() {
79 for (;;) {
80 if (fgets(_line, sizeof(_line), _file) == NULL) {
81 return false;
82 }
83 ++ _line_no;
84 _line_len = (int)strlen(_line);
85 if (_line_len > _max_allowed_line_len) {
86 error("input line too long (must be no longer than %d chars)", _max_allowed_line_len);
87 }
88 if (*_line == '#') { // comment
89 continue;
90 }
91 break;
92 }
93
94 _id = _unspecified;
95 _super = _unspecified;
96 _interfaces->clear();
97 _source = NULL;
98 _interfaces_specified = false;
99
100 {
101 int len = (int)strlen(_line);
102 int i;
103 // Replace \t\r\n with ' '
104 for (i=0; i<len; i++) {
105 if (_line[i] == '\t' || _line[i] == '\r' || _line[i] == '\n') {
106 _line[i] = ' ';
107 }
108 }
109
110 // Remove trailing newline/space
111 while (len > 0) {
112 if (_line[len-1] == ' ') {
113 _line[len-1] = '\0';
114 len --;
115 } else {
116 break;
117 }
118 }
119 _line_len = len;
120 _class_name = _line;
121 }
122
123 if ((_token = strchr(_line, ' ')) == NULL) {
124 // No optional arguments are specified.
125 return true;
126 }
127
128 // Mark the end of the name, and go to the next input char
129 *_token++ = '\0';
130
131 while (*_token) {
132 skip_whitespaces();
133
134 if (parse_int_option("id:", &_id)) {
135 continue;
136 } else if (parse_int_option("super:", &_super)) {
137 check_already_loaded("Super class", _super);
138 continue;
139 } else if (skip_token("interfaces:")) {
140 int i;
141 while (try_parse_int(&i)) {
142 check_already_loaded("Interface", i);
143 _interfaces->append(i);
144 }
145 } else if (skip_token("source:")) {
146 skip_whitespaces();
147 _source = _token;
148 char* s = strchr(_token, ' ');
149 if (s == NULL) {
150 break; // end of input line
151 } else {
152 *s = '\0'; // mark the end of _source
153 _token = s+1;
154 }
155 } else {
156 error("Unknown input");
157 }
158 }
159
160 // if src is specified
161 // id super interfaces must all be specified
162 // loader may be specified
163 // else
164 // # the class is loaded from classpath
165 // id may be specified
166 // super, interfaces, loader must not be specified
167 return true;
168 }
169
skip_whitespaces()170 void ClassListParser::skip_whitespaces() {
171 while (*_token == ' ' || *_token == '\t') {
172 _token ++;
173 }
174 }
175
skip_non_whitespaces()176 void ClassListParser::skip_non_whitespaces() {
177 while (*_token && *_token != ' ' && *_token != '\t') {
178 _token ++;
179 }
180 }
181
parse_int(int * value)182 void ClassListParser::parse_int(int* value) {
183 skip_whitespaces();
184 if (sscanf(_token, "%i", value) == 1) {
185 skip_non_whitespaces();
186 if (*value < 0) {
187 error("Error: negative integers not allowed (%d)", *value);
188 }
189 } else {
190 error("Error: expected integer");
191 }
192 }
193
try_parse_int(int * value)194 bool ClassListParser::try_parse_int(int* value) {
195 skip_whitespaces();
196 if (sscanf(_token, "%i", value) == 1) {
197 skip_non_whitespaces();
198 return true;
199 }
200 return false;
201 }
202
skip_token(const char * option_name)203 bool ClassListParser::skip_token(const char* option_name) {
204 size_t len = strlen(option_name);
205 if (strncmp(_token, option_name, len) == 0) {
206 _token += len;
207 return true;
208 } else {
209 return false;
210 }
211 }
212
parse_int_option(const char * option_name,int * value)213 bool ClassListParser::parse_int_option(const char* option_name, int* value) {
214 if (skip_token(option_name)) {
215 if (*value != _unspecified) {
216 error("%s specified twice", option_name);
217 } else {
218 parse_int(value);
219 return true;
220 }
221 }
222 return false;
223 }
224
print_specified_interfaces()225 void ClassListParser::print_specified_interfaces() {
226 const int n = _interfaces->length();
227 jio_fprintf(defaultStream::error_stream(), "Currently specified interfaces[%d] = {\n", n);
228 for (int i=0; i<n; i++) {
229 InstanceKlass* k = lookup_class_by_id(_interfaces->at(i));
230 jio_fprintf(defaultStream::error_stream(), " %4d = %s\n", _interfaces->at(i), k->name()->as_klass_external_name());
231 }
232 jio_fprintf(defaultStream::error_stream(), "}\n");
233 }
234
print_actual_interfaces(InstanceKlass * ik)235 void ClassListParser::print_actual_interfaces(InstanceKlass *ik) {
236 int n = ik->local_interfaces()->length();
237 jio_fprintf(defaultStream::error_stream(), "Actual interfaces[%d] = {\n", n);
238 for (int i = 0; i < n; i++) {
239 InstanceKlass* e = InstanceKlass::cast(ik->local_interfaces()->at(i));
240 jio_fprintf(defaultStream::error_stream(), " %s\n", e->name()->as_klass_external_name());
241 }
242 jio_fprintf(defaultStream::error_stream(), "}\n");
243 }
244
error(const char * msg,...)245 void ClassListParser::error(const char *msg, ...) {
246 va_list ap;
247 va_start(ap, msg);
248 int error_index = _token - _line;
249 if (error_index >= _line_len) {
250 error_index = _line_len - 1;
251 }
252 if (error_index < 0) {
253 error_index = 0;
254 }
255
256 jio_fprintf(defaultStream::error_stream(),
257 "An error has occurred while processing class list file %s %d:%d.\n",
258 _classlist_file, _line_no, (error_index + 1));
259 jio_vfprintf(defaultStream::error_stream(), msg, ap);
260
261 if (_line_len <= 0) {
262 jio_fprintf(defaultStream::error_stream(), "\n");
263 } else {
264 jio_fprintf(defaultStream::error_stream(), ":\n");
265 for (int i=0; i<_line_len; i++) {
266 char c = _line[i];
267 if (c == '\0') {
268 jio_fprintf(defaultStream::error_stream(), "%s", " ");
269 } else {
270 jio_fprintf(defaultStream::error_stream(), "%c", c);
271 }
272 }
273 jio_fprintf(defaultStream::error_stream(), "\n");
274 for (int i=0; i<error_index; i++) {
275 jio_fprintf(defaultStream::error_stream(), "%s", " ");
276 }
277 jio_fprintf(defaultStream::error_stream(), "^\n");
278 }
279
280 vm_exit_during_initialization("class list format error.", NULL);
281 va_end(ap);
282 }
283
284 // This function is used for loading classes for customized class loaders
285 // during archive dumping.
load_class_from_source(Symbol * class_name,TRAPS)286 InstanceKlass* ClassListParser::load_class_from_source(Symbol* class_name, TRAPS) {
287 #if !(defined(_LP64) && (defined(LINUX)|| defined(SOLARIS)))
288 // The only supported platforms are: (1) Linux/64-bit and (2) Solaris/64-bit
289 //
290 // This #if condition should be in sync with the areCustomLoadersSupportedForCDS
291 // method in test/lib/jdk/test/lib/Platform.java.
292 error("AppCDS custom class loaders not supported on this platform");
293 #endif
294
295 if (!is_super_specified()) {
296 error("If source location is specified, super class must be also specified");
297 }
298 if (!is_id_specified()) {
299 error("If source location is specified, id must be also specified");
300 }
301 InstanceKlass* k = ClassLoaderExt::load_class(class_name, _source, THREAD);
302
303 if (strncmp(_class_name, "java/", 5) == 0) {
304 log_info(cds)("Prohibited package for non-bootstrap classes: %s.class from %s",
305 _class_name, _source);
306 return NULL;
307 }
308
309 if (k != NULL) {
310 if (k->local_interfaces()->length() != _interfaces->length()) {
311 print_specified_interfaces();
312 print_actual_interfaces(k);
313 error("The number of interfaces (%d) specified in class list does not match the class file (%d)",
314 _interfaces->length(), k->local_interfaces()->length());
315 }
316
317 if (!SystemDictionaryShared::add_non_builtin_klass(class_name, ClassLoaderData::the_null_class_loader_data(),
318 k, THREAD)) {
319 error("Duplicated class %s", _class_name);
320 }
321
322 // This tells JVM_FindLoadedClass to not find this class.
323 k->set_shared_classpath_index(UNREGISTERED_INDEX);
324 k->clear_class_loader_type();
325 }
326
327 return k;
328 }
329
load_current_class(TRAPS)330 Klass* ClassListParser::load_current_class(TRAPS) {
331 TempNewSymbol class_name_symbol = SymbolTable::new_symbol(_class_name, THREAD);
332 guarantee(!HAS_PENDING_EXCEPTION, "Exception creating a symbol.");
333
334 Klass *klass = NULL;
335 if (!is_loading_from_source()) {
336 // Load classes for the boot/platform/app loaders only.
337 if (is_super_specified()) {
338 error("If source location is not specified, super class must not be specified");
339 }
340 if (are_interfaces_specified()) {
341 error("If source location is not specified, interface(s) must not be specified");
342 }
343
344 bool non_array = !FieldType::is_array(class_name_symbol);
345
346 JavaValue result(T_OBJECT);
347 if (non_array) {
348 // At this point, we are executing in the context of the boot loader. We
349 // cannot call Class.forName because that is context dependent and
350 // would load only classes for the boot loader.
351 //
352 // Instead, let's call java_system_loader().loadClass() directly, which will
353 // delegate to the correct loader (boot, platform or app) depending on
354 // the class name.
355
356 Handle s = java_lang_String::create_from_symbol(class_name_symbol, CHECK_0);
357 // ClassLoader.loadClass() wants external class name format, i.e., convert '/' chars to '.'
358 Handle ext_class_name = java_lang_String::externalize_classname(s, CHECK_0);
359 Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
360
361 JavaCalls::call_virtual(&result,
362 loader, //SystemDictionary::java_system_loader(),
363 SystemDictionary::ClassLoader_klass(),
364 vmSymbols::loadClass_name(),
365 vmSymbols::string_class_signature(),
366 ext_class_name,
367 THREAD);
368 } else {
369 // array classes are not supported in class list.
370 THROW_NULL(vmSymbols::java_lang_ClassNotFoundException());
371 }
372 assert(result.get_type() == T_OBJECT, "just checking");
373 oop obj = (oop) result.get_jobject();
374 if (!HAS_PENDING_EXCEPTION && (obj != NULL)) {
375 klass = java_lang_Class::as_Klass(obj);
376 } else { // load classes in bootclasspath/a
377 if (HAS_PENDING_EXCEPTION) {
378 CLEAR_PENDING_EXCEPTION;
379 }
380
381 if (non_array) {
382 Klass* k = SystemDictionary::resolve_or_null(class_name_symbol, CHECK_NULL);
383 if (k != NULL) {
384 klass = k;
385 } else {
386 if (!HAS_PENDING_EXCEPTION) {
387 THROW_NULL(vmSymbols::java_lang_ClassNotFoundException());
388 }
389 }
390 }
391 }
392 } else {
393 // If "source:" tag is specified, all super class and super interfaces must be specified in the
394 // class list file.
395 klass = load_class_from_source(class_name_symbol, CHECK_NULL);
396 }
397
398 if (klass != NULL && klass->is_instance_klass() && is_id_specified()) {
399 InstanceKlass* ik = InstanceKlass::cast(klass);
400 int id = this->id();
401 SystemDictionaryShared::update_shared_entry(ik, id);
402 InstanceKlass* old = table()->lookup(id);
403 if (old != NULL && old != ik) {
404 error("Duplicated ID %d for class %s", id, _class_name);
405 }
406 table()->add(id, ik);
407 }
408
409 return klass;
410 }
411
is_loading_from_source()412 bool ClassListParser::is_loading_from_source() {
413 return (_source != NULL);
414 }
415
lookup_class_by_id(int id)416 InstanceKlass* ClassListParser::lookup_class_by_id(int id) {
417 InstanceKlass* klass = table()->lookup(id);
418 if (klass == NULL) {
419 error("Class ID %d has not been defined", id);
420 }
421 return klass;
422 }
423
424
lookup_super_for_current_class(Symbol * super_name)425 InstanceKlass* ClassListParser::lookup_super_for_current_class(Symbol* super_name) {
426 if (!is_loading_from_source()) {
427 return NULL;
428 }
429
430 InstanceKlass* k = lookup_class_by_id(super());
431 if (super_name != k->name()) {
432 error("The specified super class %s (id %d) does not match actual super class %s",
433 k->name()->as_klass_external_name(), super(),
434 super_name->as_klass_external_name());
435 }
436 return k;
437 }
438
lookup_interface_for_current_class(Symbol * interface_name)439 InstanceKlass* ClassListParser::lookup_interface_for_current_class(Symbol* interface_name) {
440 if (!is_loading_from_source()) {
441 return NULL;
442 }
443
444 const int n = _interfaces->length();
445 if (n == 0) {
446 error("Class %s implements the interface %s, but no interface has been specified in the input line",
447 _class_name, interface_name->as_klass_external_name());
448 ShouldNotReachHere();
449 }
450
451 int i;
452 for (i=0; i<n; i++) {
453 InstanceKlass* k = lookup_class_by_id(_interfaces->at(i));
454 if (interface_name == k->name()) {
455 return k;
456 }
457 }
458
459 // interface_name is not specified by the "interfaces:" keyword.
460 print_specified_interfaces();
461 error("The interface %s implemented by class %s does not match any of the specified interface IDs",
462 interface_name->as_klass_external_name(), _class_name);
463 ShouldNotReachHere();
464 return NULL;
465 }
466
467