📄 loaderfile.c
字号:
/* * Copyright (c) 1998-2001 Sun Microsystems, Inc. All Rights Reserved. * * This software is the confidential and proprietary information of Sun * Microsystems, Inc. ("Confidential Information"). You shall not * disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into * with Sun. * * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING * THIS SOFTWARE OR ITS DERIVATIVES. * * Use is subject to license terms. *//*========================================================================= * SYSTEM: KVM * SUBSYSTEM: Class loader * FILE: loaderFile.c * OVERVIEW: Structures and operations needed for loading * Java classfiles from the file system. This file * (loaderFile.c) provides the default file system * operations that are typically very useful on all those * target platforms that have a regular file system. * * These operations have been separated from the actual * class loading operations (VmCommon/src/loader.c), since * the mapping between the KVM and the Java classfile * storage mechanisms of the host operating system can vary * considerably in different embedded devices. * AUTHOR: Tasneem Sayeed, Consumer & Embedded division * Frank Yellin *=======================================================================*//*========================================================================= * Include files *=======================================================================*/#include "global.h"#include "stdio.h"#include "sys/stat.h"#include "jar.h"#if !JAR_FILES_USE_STDIO#include "sys/types.h"#include "fcntl.h"#include "sys/mman.h"#endif/*========================================================================= * Definitions and declarations *=======================================================================*/struct filePointerStruct { /* If set to true, indicates a JAR file */ bool_t isJarFile;};struct stdioPointerStruct { bool_t isJarFile; /* Always TRUE */ long size; /* size of file in bytes */ FILE* file; /* Pointer to class file */};struct jarPointerStruct { bool_t isJarFile; /* always FALSE */ long dataLen; /* length of data stream */ long dataIndex; /* current position for reading */ unsigned char data[1];};typedef struct classPathEntryStruct { union { struct jarInfoStruct jarInfo; /* if it's a jar file */ /* Leave possibility of other types, for later */ } u; char type; char name[1];} *CLASS_PATH_ENTRY, **CLASS_PATH_ENTRY_HANDLE;/*========================================================================= * Variables *=======================================================================*//* A table for storing the individual directory paths along classpath. * Each entry is one element in the list. * * An entry consists of the letter 'j' or 'd' followed by more information. * 'd' means this is a directory. It is immediately followed by the name * of the directory. * 'j' means a zip file. It is followed by 3 ignored spaces, then 4 bytes * giving the location of the first local header, 4 bytes giving * the location of the first central header, and then the name of the * zip file. *//* Remember: This table contains object pointers (= GC root) */static POINTERLIST ClassPathTable = NIL;/* Set in main() to classpath environment */char* UserClassPath = NULL;static unsigned int MaxClassPathTableLength = 0;/* * pointerlist that maintains mapping from file descriptor to filepointer for * resource files in MIDP */POINTERLIST filePointerRoot = NULL;/*========================================================================= * Static operations (used only in this file) *=======================================================================*/static FILEPOINTER openClassfileInternal(BYTES_HANDLE);/*========================================================================= * Class loading file operations *=======================================================================*//*========================================================================= * NOTE: The functions below provide an implementation of * the abstract class loading interface defined in * VmCommon/h/loader.h. The implementation here is * suitable only for those target platforms that have * a conventional file system. *=======================================================================*//*========================================================================= * FUNCTION: openClassFile * TYPE: class reading * OVERVIEW: Returns a FILEPOINTER object to read the bytes of the * given class name * INTERFACE: * parameters: clazz: Clazz to open * returns: a FILEPOINTER, or error if none exists *=======================================================================*/FILEPOINTERopenClassfile(INSTANCE_CLASS clazz) { FILEPOINTER ClassFile; START_TEMPORARY_ROOTS UString UPackageName = clazz->clazz.packageName; UString UBaseName = clazz->clazz.baseName; int baseLength = UBaseName->length; int packageLength = UPackageName == 0 ? 0 : UPackageName->length; int length = packageLength + 1 + baseLength + 7; DECLARE_TEMPORARY_ROOT(char*, fileName, mallocBytes(length)); char* to; ASSERTING_NO_ALLOCATION to = fileName; if (UPackageName != NULL) { int packageLength = UPackageName->length; memcpy(to, UStringInfo(UPackageName), packageLength); to += packageLength; *to++ = '/'; } memcpy(to, UStringInfo(UBaseName), baseLength); to += baseLength; strcpy(to, ".class"); END_ASSERTING_NO_ALLOCATION ClassFile = openClassfileInternal(&fileName); if (ClassFile == NULL) { #if INCLUDEDEBUGCODE if (traceclassloadingverbose) { DECLARE_TEMPORARY_ROOT(char*, className, getClassName((CLASS)clazz)); sprintf(str_buffer, KVM_MSG_CLASS_NOT_FOUND_1STRPARAM, className); fprintf(stdout, str_buffer); }#endif /* INCLUDEDEBUGCODE */ } END_TEMPORARY_ROOTS return ClassFile;}/*========================================================================= * FUNCTION: openResourceFile * TYPE: resource reading * OVERVIEW: Returns a FILEPOINTER object to read the bytes of the * given resource name * INTERFACE: * parameters: resourceName: Name of resource to read * returns: a FILEPOINTER, or error if none exists *=======================================================================*/FILEPOINTERopenResourcefile(BYTES resourceNameArg) { FILEPOINTER ClassFile; START_TEMPORARY_ROOTS DECLARE_TEMPORARY_ROOT(BYTES, resourceName, resourceNameArg); ClassFile = openClassfileInternal(&resourceName); if (ClassFile == NULL) {#if INCLUDEDEBUGCODE if (traceclassloadingverbose) { sprintf(str_buffer, KVM_MSG_RESOURCE_NOT_FOUND_1STRPARAM, resourceName); fprintf(stdout, str_buffer); }#endif /* INCLUDEDEBUGCODE */ } END_TEMPORARY_ROOTS return ClassFile;}/*========================================================================= * FUNCTION: openClassfileInternal() * TYPE: class reading * OVERVIEW: Internal function used by openClassfile(). * It returns a FILE* for reading the class if a file exists. * NULL otherwise. * INTERFACE: * parameters: fileName: Name of class file to read * returns: FILE* for reading the class, or NULL. *=======================================================================*/static FILEPOINTER openClassfileInternal(BYTES_HANDLE filenameH) { int filenameLength = strlen(unhand(filenameH)); int paths = ClassPathTable->length; int i; FILE* file = NULL; FILEPOINTER fp = NULL; START_TEMPORARY_ROOTS int fullnameLength = MaxClassPathTableLength + filenameLength + 2; DECLARE_TEMPORARY_ROOT(char*, fullname, (char*)mallocBytes(fullnameLength)); DECLARE_TEMPORARY_ROOT(CLASS_PATH_ENTRY, entry, NULL); for (i = 0; i < paths && fp == NULL; i++) { entry = (CLASS_PATH_ENTRY)ClassPathTable->data[i].cellp; switch (entry->type) { case 'd': /* A directory */ sprintf(fullname, "%s/%s", entry->name, unhand(filenameH)); file = fopen(fullname, "rb"); if (file != NULL) { struct stat statbuf; fp = (FILEPOINTER) mallocBytes(sizeof(struct stdioPointerStruct)); fp->isJarFile = FALSE; if (fstat(fileno(file), &statbuf) == 0) ((struct stdioPointerStruct*)fp)->size = statbuf.st_size; else ((struct stdioPointerStruct*)fp)->size = 0; ((struct stdioPointerStruct*)fp)->file = file; } break; case 'j': { /* A JAR file */ long length; struct jarPointerStruct* result = (struct jarPointerStruct*) loadJARFileEntry(&entry->u.jarInfo, unhand(filenameH), &length, offsetof(struct jarPointerStruct, data[0])); if (result != NULL) { result->isJarFile = TRUE; result->dataLen = length; result->dataIndex = 0; fp = (FILEPOINTER)result; } break; } } } END_TEMPORARY_ROOTS return fp;}/*========================================================================= * FUNCTION: loadByte(), loadShort(), loadCell() * loadBytes, skipBytes() * TYPE: private class file reading operations * OVERVIEW: Read the next 1, 2, 4 or n bytes from the * given class file. * INTERFACE: * parameters: classfile pointer * returns: unsigned char, short or integer * NOTE: For safety it might be a good idea to check * explicitly for EOF in these operations. *=======================================================================*/intloadByteNoEOFCheck(FILEPOINTER_HANDLE ClassFileH){ FILEPOINTER ClassFile = unhand(ClassFileH); if (!ClassFile->isJarFile) { FILE* file = ((struct stdioPointerStruct*)ClassFile)->file; return getc(file); } else { struct jarPointerStruct* ds = (struct jarPointerStruct*)ClassFile; if (ds->dataIndex < ds->dataLen) { return ds->data[ds->dataIndex++]; } else { return -1; } }}unsigned char loadByte(FILEPOINTER_HANDLE ClassFileH){ int c = loadByteNoEOFCheck(ClassFileH); if (c == -1) { fatalError(KVM_MSG_CLASSFILE_SIZE_DOES_NOT_MATCH); } return (unsigned char)c;}unsigned short loadShort(FILEPOINTER_HANDLE ClassFileH){ unsigned char c1 = loadByte(ClassFileH); unsigned char c2 = loadByte(ClassFileH); unsigned short c = c1 << 8 | c2; return c;}unsigned longloadCell(FILEPOINTER_HANDLE ClassFileH){ unsigned char c1 = loadByte(ClassFileH); unsigned char c2 = loadByte(ClassFileH); unsigned char c3 = loadByte(ClassFileH); unsigned char c4 = loadByte(ClassFileH); unsigned int c; c = c1 << 24 | c2 << 16 | c3 << 8 | c4; return c;}static int loadBytesInternal(FILEPOINTER_HANDLE ClassFileH, char* buffer, int pos, int length, bool_t checkEOF) { int n; FILEPOINTER ClassFile = unhand(ClassFileH); if (!ClassFile->isJarFile) { FILE* file = ((struct stdioPointerStruct*)ClassFile)->file; /* * If 'pos' is -1 then just read sequentially. Used internally by * loadBytes() which is called from classloader. */ if (pos != -1) fseek(file, pos, SEEK_SET); n = fread(buffer, 1, length, file);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -