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