classLoader.cpp revision 844
/*
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
#include "incls/_precompiled.incl"
#include "incls/_classLoader.cpp.incl"
typedef jboolean (JNICALL *ReadEntry_t)(jzfile *zip, jzentry *entry, unsigned char *buf, char *namebuf);
typedef jboolean (JNICALL *ReadMappedEntry_t)(jzfile *zip, jzentry *entry, unsigned char **buf, char *namebuf);
// Globals
// helper routines
if (str_to_find_len > str_len) {
return false;
}
}
if (str_to_find_len > str_len) {
return false;
}
}
if (num_meta_package_names == 0) {
} else {
}
}
FREE_C_HEAP_ARRAY(char*, _meta_package_names);
}
if ( _num_meta_package_names == 0) {
return false;
}
for (int i = 0; i < _num_meta_package_names; i++) {
char* pkg = _meta_package_names[i];
return true;
}
}
return false;
}
}
bool ClassPathEntry::is_lazy() {
return false;
}
}
// construct full path name
char path[JVM_MAXPATHLEN];
return NULL;
}
// check if file exists
// found file, open it
if (file_handle != -1) {
// read contents into resource array
// close file
// construct ClassFileStream
}
}
}
return NULL;
}
}
}
FREE_C_HEAP_ARRAY(char, _zip_name);
}
// enable call to C land
// check whether zip archive contains name
char name_buf[128];
char* filename;
if (name_len < 128) {
} else {
}
// file found, get pointer to class in mmaped jar file.
if (ReadMappedEntry == NULL ||
// mmaped access not available, perhaps due to compression,
// read contents into resource array
}
// return result
}
// invoke function for each entry in the zip file
for (int n = 0; ; n++) {
}
}
_meta_index = NULL;
}
bool LazyClassPathEntry::is_jar_file() {
}
if (_resolved_entry != NULL) {
return (ClassPathEntry*) _resolved_entry;
}
{
if (_resolved_entry == NULL) {
return new_entry;
}
}
delete new_entry;
return (ClassPathEntry*) _resolved_entry;
}
if (_meta_index != NULL &&
return NULL;
}
}
bool LazyClassPathEntry::is_lazy() {
return true;
}
GrowableArray<char*>& meta_packages) {
for (int i = 0; i < meta_packages.length(); i++) {
}
}
void ClassLoader::setup_meta_index() {
// Set up meta index which allows us to open boot jars lazily if
// class data sharing is enabled
const char* known_version = "% VERSION 2";
int line_no = 0;
char package_name[256];
bool skipCurrentJar = false;
++line_no;
// Remove trailing newline
switch(package_name[0]) {
case '%':
{
if (TraceClassLoading && Verbose) {
}
return;
}
}
// These directives indicate jar files which contain only
// classes, only non-classfile resources, or a combination of
// make/tools/MetaIndex/BuildMetaIndex.java in the J2SE
// workspace.
case '#':
case '!':
case '@':
{
// Hand off current packages to current lazy entry (if any)
(boot_class_path_packages.length() > 0)) {
if (TraceClassLoading && Verbose) {
}
}
// Find lazy entry corresponding to this jar file
break;
}
}
// If the first character is '@', it indicates the following jar
// file is a resource only jar file in which case, we should skip
// reading the subsequent entries since the resource loading is
// totally handled by J2SE side.
if (package_name[0] == '@') {
}
skipCurrentJar = true;
} else {
skipCurrentJar = false;
}
break;
}
default:
{
}
}
}
}
// Hand off current packages to current lazy entry (if any)
(boot_class_path_packages.length() > 0)) {
if (TraceClassLoading && Verbose) {
}
}
}
}
void ClassLoader::setup_bootstrap_search_path() {
if (TraceClassLoading && Verbose) {
}
int end = 0;
// Iterate over class path entries
end++;
}
update_class_path_entry_list(path, false);
FREE_C_HEAP_ARRAY(char, path);
end++;
}
}
}
void ClassLoader::create_class_path_entry(char *path, struct stat st, ClassPathEntry **new_entry, bool lazy) {
if (lazy) {
return;
}
// Regular file, should be a zip file
// Canonicalized filename
char canonical_path[JVM_MAXPATHLEN];
// This matches the classic VM
}
{
// enable call to C land
}
if (TraceClassLoading) {
}
} else {
char *msg;
} else {
}
}
} else {
// Directory
if (TraceClassLoading) {
}
}
}
// Create a class path zip entry for a given path (return NULL if not found
// check for a regular file
char orig_path[JVM_MAXPATHLEN];
char canonical_path[JVM_MAXPATHLEN];
{
// enable call to C land
}
// create using canonical path
}
}
}
}
return NULL;
}
// returns true if entry already on class path
ClassPathEntry* e = _first_entry;
while (e != NULL) {
// assume zip entries have been canonicalized
return true;
}
e = e->next();
}
return false;
}
if (_last_entry == NULL) {
} else {
}
}
}
bool check_for_duplicates) {
// File or directory found
// The kernel VM adds dynamically to the end of the classloader path and
// doesn't reorder the bootclasspath which would break java.lang.Package
// (see PackageInfo).
// Add new entry to linked list
}
}
}
void ClassLoader::print_bootclasspath() {
ClassPathEntry* e = _first_entry;
while (e != NULL) {
e = e->next();
}
}
void ClassLoader::load_zip_library() {
// First make sure native library is loaded
// Load zip library
char path[JVM_MAXPATHLEN];
char ebuf[1024];
}
// Lookup zip entry points
ReadMappedEntry = CAST_TO_FN_PTR(ReadMappedEntry_t, hpi::dll_lookup(handle, "ZIP_ReadMappedEntry"));
// ZIP_Close is not exported on Windows in JDK5.0 so don't abort if ZIP_Close is NULL
}
// Lookup canonicalize entry in libjava.dll
CanonicalizeEntry = CAST_TO_FN_PTR(canonicalize_fn_t, hpi::dll_lookup(javalib_handle, "Canonicalize"));
// This lookup only works on 1.3. Do not check for non-null here
}
// PackageInfo data exists in order to support the java.lang.Package
// class. A Package object provides information about a java package
// (version, vendor, etc.) which originates in the manifest of the jar
// file supplying the package. For application classes, the ClassLoader
// object takes care of this.
// For system (boot) classes, the Java code in the Package class needs
// to be able to identify which source jar file contained the boot
// class, so that it can extract the manifest from it. This table
// identifies java packages with jar files in the boot classpath.
// Because the boot classpath cannot change, the classpath index is
// sufficient to identify the source jar file or directory. (Since
// directories have no manifests, the directory name is not required,
// but is available.)
// When using sharing -- the pathnames of entries in the boot classpath
// may not be the same at runtime as they were when the archive was
// created (NFS, Samba, etc.). The actual files and directories named
// in the classpath must be the same files, in the same order, even
// though the exact name is not the same.
class PackageInfo: public BasicHashtableEntry {
public:
const char* _pkgname; // Package name
int _classpath_index; // Index of directory or JAR file loaded from
PackageInfo* next() {
}
const char* filename() {
}
}
};
class PackageHashtable : public BasicHashtable {
private:
inline unsigned int compute_hash(const char *s, int n) {
unsigned int val = 0;
while (--n >= 0) {
}
return val;
}
}
return pp;
}
}
return NULL;
}
public:
}
return pp;
}
}
void copy_pkgnames(const char** packages) {
int n = 0;
for (int i = 0; i < table_size(); ++i) {
}
}
}
};
// Copy (relocate) the table to the shared space.
// Calculate the space needed for the package name strings.
int i;
int n = 0;
for (i = 0; i < table_size(); ++i) {
}
}
warning("\nThe shared miscellaneous data space is not large "
"enough to \npreload requested classes. Use "
"-XX:SharedMiscDataSize= to increase \nthe initial "
"size of the miscellaneous data space.\n");
exit(2);
}
// Copy the table data (the strings) to the shared space.
n = align_size_up(n, sizeof(HeapWord));
for (i = 0; i < table_size(); ++i) {
}
}
}
}
}
// Package prefix found
}
return NULL;
}
// Bootstrap loader no longer holds system loader lock obj serializing
// load_instance_class and thereby add_package
{
// First check for previously loaded entry
// Existing entry found, check source of package
return true;
}
// Package prefix found
if (new_pkgname == NULL) {
return false;
}
new_pkgname[n] = '\0';
// Insert into hash table
}
return true;
}
}
{
}
return NULL;
} else {
return p();
}
}
int nof_entries;
const char** packages;
{
// Allocate resource char* array containing package names
return NULL;
}
}
// Allocate objArray and fill with java.lang.String
for (int i = 0; i < nof_entries; i++) {
}
return result();
}
// st.print() uses too much stack space while handling a StackOverflowError
// st.print("%s.class", h_name->as_utf8());
// Lookup stream for parsing .class file
int classpath_index = 0;
{
ClassPathEntry* e = _first_entry;
while (e != NULL) {
break;
}
e = e->next();
}
}
// class file found, parse it
CHECK_(h));
// add to package table
h = result;
}
}
return h;
}
int number_of_entries) {
"bad shared package info size.");
}
void ClassLoader::create_package_info_table() {
}
// Initialize the class loader's access to methods in libzip. Parse and
// process the boot classpath into a list ClassPathEntry objects. Once
// this list has been created, it must not change order (see class PackageInfo)
// it can be appended to and is by jvmti and the kernel vm.
void ClassLoader::initialize() {
if (UsePerfData) {
// jvmstat performance counters
// The following performance counters are added for measuring the impact
// of the bug fix of 6365597. They are mainly focused on finding out
// the behavior of system & user-defined classloader lock, whether
// ClassLoader.loadClass/findClass is being called synchronized or not.
// Also two additional counters are created to see whether 'UnsyncloadClass'
// flag is being set or not and how many times load_instance_class call
// fails with linkageError etc.
"systemLoaderLockContentionRate");
"nonSystemLoaderLockContentionRate");
"jvmFindLoadedClassNoLockCalls");
"jvmDefineClassNoLockCalls");
"jniDefineClassNoLockCalls");
"unsafeDefineClassCalls");
"loadInstanceClassFailRate");
// increment the isUnsyncloadClass counter if UnsyncloadClass is set.
if (UnsyncloadClass) {
}
}
// lookup zip library entry points
// initialize search path
if (LazyBootClassLoader) {
// set up meta index which makes boot classpath initialization lazier
}
}
return UsePerfData ?
}
}
return UsePerfData ?
}
return UsePerfData ?
}
}
return UsePerfData ?
}
int ClassLoader::compute_Object_vtable() {
// hardwired for JDK1.2 -- would need to duplicate class file parsing
// code to determine actual value from file
// Would be value '11' if finals were in vtable
int JDK_1_2_Object_vtable_size = 5;
}
void classLoader_init() {
}
if (CanonicalizeEntry != NULL) {
return false;
}
} else {
// On JDK 1.2.2 the Canonicalize does not exist, so just do nothing
}
return true;
}
#ifndef PRODUCT
void ClassLoader::verify() {
}
// CompileTheWorld
//
// Iterates over all class path entries and forces compilation of all methods
//
// The classes are loaded by the Java level bootstrap class loader, and the
// initializer is called. If DelayCompilationDuringStartup is true (default),
// the interpreter will run the initialization code. Note that forcing
// initialization in this way could potentially lead to initialization order
// problems, in which case we could just force the initialization bit to be set.
// jzcell and jzfile definitions from zip_util.h but rename jzfile to real_jzfile,
// since jzfile already has a void* definition.
//
// Note that this is only used in debug mode.
//
// HotSpot integration note:
// Matches zip_util.h 1.14 99/06/01 from jdk1.3 beta H build
// JDK 1.3 version
typedef struct real_jzentry13 { /* Zip file entry */
char *name; /* entry name */
char *comment; /* optional zip file comment */
typedef struct real_jzfile13 { /* Zip file */
char *name; /* zip file name */
void *lock; /* read lock */
char *comment; /* zip file comment */
char *msg; /* zip error message */
void *entries; /* array of hash cells */
unsigned short *table; /* Hash chain heads: indexes into entries */
/* Information on metadata names in META-INF directory */
char **metanames; /* array of meta names (may have null names) */
/* If there are any per-entry comments, they are in the comments array */
char **comments;
// JDK 1.2 version
typedef struct real_jzentry12 { /* Zip file entry */
char *name; /* entry name */
char *comment; /* optional zip file comment */
typedef struct real_jzfile12 { /* Zip file */
char *name; /* zip file name */
void *lock; /* read lock */
char *comment; /* zip file comment */
char *msg; /* zip error message */
}
bool ClassPathDirEntry::is_rt_jar() {
return false;
}
if (JDK_Version::is_jdk12x_version()) {
} else {
}
if (HAS_PENDING_EXCEPTION) {
} else {
}
}
}
// Version that works for JDK 1.3.x
// Iterate over all entries in zip file
for (int n = 0; ; n++) {
}
}
// Version that works for JDK 1.2.x
// Iterate over all entries in zip file
for (int n = 0; ; n++) {
}
}
bool ClassPathZipEntry::is_rt_jar() {
if (JDK_Version::is_jdk12x_version()) {
return is_rt_jar12();
} else {
return is_rt_jar13();
}
}
// JDK 1.3 version
bool ClassPathZipEntry::is_rt_jar13() {
// Check whether zip name ends in "rt.jar"
// This will match other archives named rt.jar as well, but this is
// only used for debugging.
}
// JDK 1.2 version
bool ClassPathZipEntry::is_rt_jar12() {
// Check whether zip name ends in "rt.jar"
// This will match other archives named rt.jar as well, but this is
// only used for debugging.
}
}
bool LazyClassPathEntry::is_rt_jar() {
return resolve_entry()->is_rt_jar();
}
void ClassLoader::compile_the_world() {
// Make sure we don't run with background compilation
BackgroundCompilation = false;
// Find bootstrap loader
// Iterate over all bootstrap class path entries
ClassPathEntry* e = _first_entry;
while (e != NULL) {
// We stop at rt.jar, unless it is the first bootstrap path entry
if (e->is_rt_jar() && e != _first_entry) break;
e = e->next();
}
{
// Print statistics as if before normal exit:
extern void print_statistics();
}
vm_exit(0);
}
int ClassLoader::_compile_the_world_counter = 0;
// We have a .class file
char buffer[2048];
// If the file has a period after removing .class, it's not really a
// valid class file. The class loader will check everything else.
if (_compile_the_world_counter > CompileTheWorldStopAt) return;
// Construct name without extension
// Use loader to load and initialize class
if (k.not_null() && !HAS_PENDING_EXCEPTION) {
k->initialize(THREAD);
}
if (CompileTheWorldPreloadClasses && k.not_null()) {
if (HAS_PENDING_EXCEPTION) {
// If something went wrong in preloading we just ignore it
}
}
// If something went wrong (e.g. ExceptionInInitializerError) we skip this class
} else {
// Preload all classes to get around uncommon traps
// Iterate over all methods in class
if (CompilationPolicy::canBeCompiled(m)) {
// Force compilation
if (HAS_PENDING_EXCEPTION) {
tty->print_cr("CompileTheWorld (%d) : Skipping method: %s", _compile_the_world_counter, m->name()->as_C_string());
}
if (TieredCompilation) {
// Clobber the first compile and force second tier compilation
// Throw out the code so that the code cache doesn't fill up
nm->make_not_entrant();
m->clear_code();
}
if (HAS_PENDING_EXCEPTION) {
tty->print_cr("CompileTheWorld (%d) : Skipping method: %s", _compile_the_world_counter, m->name()->as_C_string());
}
}
}
// Throw out the code so that the code cache doesn't fill up
nm->make_not_entrant();
m->clear_code();
}
}
}
}
}
}
}
#endif //PRODUCT