mirror of
https://github.com/corda/corda.git
synced 2025-01-01 02:36:44 +00:00
add support for accessing embedded JARs as if they were directories
This allows OpenJDK to access time zone data which is normally found under java.home, but which we must embed in the executable itself to create a self-contained build. The VM intercepts various file operations, looking for paths which start with a prefix specified by the avian.embed.prefix property and redirecting those operations to an embedded JAR. For example, if avian.embed.prefix is "/avian-embedded", and code calls File.exists() with a path of "/avian-embedded/javahomeJar/foo.txt", the VM looks for a function named javahomeJar via dlsym, calls the function to find the memory region containing the embeded JAR, and finally consults the JAR to see if the file "foo.txt" exists.
This commit is contained in:
parent
4cb796d2fb
commit
d0a6096eb0
53
makefile
53
makefile
@ -52,25 +52,29 @@ classpath = avian
|
||||
|
||||
test-executable = $(executable)
|
||||
boot-classpath = $(classpath-build)
|
||||
java-home = /avian-embedded
|
||||
embed-prefix = /avian-embedded
|
||||
|
||||
ifdef openjdk
|
||||
ifdef openjdk-src
|
||||
include openjdk-src.mk
|
||||
options := $(options)-openjdk-src
|
||||
classpath-objects = $(openjdk-objects)
|
||||
classpath-cflags = -DAVIAN_OPENJDK_SRC
|
||||
classpath-cflags = -DAVIAN_OPENJDK_SRC -DBOOT_JAVAHOME
|
||||
openjdk-jar-dep = $(build)/openjdk-jar.dep
|
||||
classpath-jar-dep = $(openjdk-jar-dep)
|
||||
javahome = $(embed-prefix)/javahomeJar
|
||||
javahome-files = lib/zi
|
||||
javahome-object = $(build)/javahome-jar.o
|
||||
else
|
||||
options := $(options)-openjdk
|
||||
test-executable = $(executable-dynamic)
|
||||
library-path = LD_LIBRARY_PATH=$(build)
|
||||
java-home = $(openjdk)/jre
|
||||
javahome = $(openjdk)/jre
|
||||
endif
|
||||
|
||||
classpath = openjdk
|
||||
boot-classpath := $(boot-classpath):$(openjdk)/jre/lib/rt.jar
|
||||
build-javahome = $(openjdk)/jre
|
||||
endif
|
||||
|
||||
ifeq ($(classpath),avian)
|
||||
@ -120,7 +124,8 @@ warnings = -Wall -Wextra -Werror -Wunused-parameter -Winit-self \
|
||||
common-cflags = $(warnings) -fno-rtti -fno-exceptions -fno-omit-frame-pointer \
|
||||
"-I$(JAVA_HOME)/include" -idirafter $(src) -I$(build) $(classpath-cflags) \
|
||||
-D__STDC_LIMIT_MACROS -D_JNI_IMPLEMENTATION_ -DAVIAN_VERSION=\"$(version)\" \
|
||||
-DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(java-home)\"
|
||||
-DUSE_ATOMIC_OPERATIONS -DAVIAN_JAVA_HOME=\"$(javahome)\" \
|
||||
-DAVIAN_EMBED_PREFIX=\"$(embed-prefix)\"
|
||||
|
||||
build-cflags = $(common-cflags) -fPIC -fvisibility=hidden \
|
||||
"-I$(JAVA_HOME)/include/linux" -I$(src) -pthread
|
||||
@ -593,12 +598,6 @@ $(driver-dynamic-object): $(driver-source)
|
||||
$(boot-object): $(boot-source)
|
||||
$(compile-object)
|
||||
|
||||
$(build)/classpath.jar: $(classpath-dep) $(classpath-jar-dep)
|
||||
@echo "creating $(@)"
|
||||
(wd=$$(pwd) && \
|
||||
cd $(classpath-build) && \
|
||||
$(jar) c0f "$$($(native-path) "$${wd}/$(@)")" .)
|
||||
|
||||
$(build)/binaryToObject-main.o: $(src)/binaryToObject/main.cpp
|
||||
$(build-cxx) -c $(^) -o $(@)
|
||||
|
||||
@ -620,11 +619,28 @@ $(build)/binaryToObject-pe.o: $(src)/binaryToObject/pe.cpp
|
||||
$(converter): $(converter-objects)
|
||||
$(build-cxx) $(^) -o $(@)
|
||||
|
||||
$(build)/classpath.jar: $(classpath-dep) $(classpath-jar-dep)
|
||||
@echo "creating $(@)"
|
||||
(wd=$$(pwd) && \
|
||||
cd $(classpath-build) && \
|
||||
$(jar) c0f "$$($(native-path) "$${wd}/$(@)")" .)
|
||||
|
||||
$(classpath-object): $(build)/classpath.jar $(converter)
|
||||
@echo "creating $(@)"
|
||||
$(converter) $(<) $(@) _binary_classpath_jar_start \
|
||||
_binary_classpath_jar_end $(platform) $(arch)
|
||||
|
||||
$(build)/javahome.jar: $(foreach x,$(javahome-files),$(build-javahome)/$(x))
|
||||
@echo "creating $(@)"
|
||||
(wd=$$(pwd) && \
|
||||
cd $(build-javahome) && \
|
||||
$(jar) c0f "$$($(native-path) "$${wd}/$(@)")" $(javahome-files))
|
||||
|
||||
$(javahome-object): $(build)/javahome.jar $(converter)
|
||||
@echo "creating $(@)"
|
||||
$(converter) $(<) $(@) _binary_javahome_jar_start \
|
||||
_binary_javahome_jar_end $(platform) $(arch)
|
||||
|
||||
$(generator-objects): $(generator-depends)
|
||||
$(generator-objects): $(build)/%-build.o: $(src)/%.cpp
|
||||
@echo "compiling $(@)"
|
||||
@ -651,7 +667,8 @@ $(bootimage-object): $(bootimage-bin) $(converter)
|
||||
writable executable
|
||||
|
||||
executable-objects = $(vm-objects) $(classpath-objects) $(driver-object) \
|
||||
$(vm-heapwalk-objects) $(boot-object) $(vm-classpath-object)
|
||||
$(vm-heapwalk-objects) $(boot-object) $(vm-classpath-object) \
|
||||
$(javahome-object)
|
||||
|
||||
$(executable): $(executable-objects)
|
||||
@echo "linking $(@)"
|
||||
@ -696,18 +713,16 @@ else
|
||||
$(ld) $(^) $(rdynamic) $(lflags) -o $(@)
|
||||
endif
|
||||
|
||||
dynamic-library-objects = $(vm-objects) $(dynamic-object) \
|
||||
$(classpath-objects) $(vm-heapwalk-objects) $(boot-object) \
|
||||
$(vm-classpath-object) $(classpath-libraries)
|
||||
|
||||
$(dynamic-library): $(dynamic-library-objects)
|
||||
$(dynamic-library): $(vm-objects) $(dynamic-object) $(classpath-objects) \
|
||||
$(vm-heapwalk-objects) $(boot-object) $(vm-classpath-object) \
|
||||
$(classpath-libraries) $(javahome-object)
|
||||
@echo "linking $(@)"
|
||||
ifdef msvc
|
||||
$(ld) $(shared) $(lflags) $(dynamic-library-objects) -out:$(@) \
|
||||
-PDB:$(@).pdb -IMPLIB:$(build)/$(name).lib -MANIFESTFILE:$(@).manifest
|
||||
$(ld) $(shared) $(lflags) $(^) -out:$(@) -PDB:$(@).pdb \
|
||||
-IMPLIB:$(build)/$(name).lib -MANIFESTFILE:$(@).manifest
|
||||
$(mt) -manifest $(@).manifest -outputresource:"$(@);2"
|
||||
else
|
||||
$(ld) $(dynamic-library-objects) -Wl,--version-script=openjdk.ld \
|
||||
$(ld) $(^) -Wl,--version-script=openjdk.ld \
|
||||
$(shared) $(lflags) $(bootimage-lflags) -o $(@)
|
||||
endif
|
||||
$(strip) $(strip-all) $(@)
|
||||
|
30
src/boot.cpp
30
src/boot.cpp
@ -52,6 +52,8 @@ extern "C" {
|
||||
|
||||
}
|
||||
|
||||
#undef SYMBOL
|
||||
|
||||
#endif//BOOT_IMAGE
|
||||
|
||||
#ifdef BOOT_CLASSPATH
|
||||
@ -76,4 +78,32 @@ extern "C" {
|
||||
|
||||
}
|
||||
|
||||
#undef SYMBOL
|
||||
|
||||
#endif//BOOT_CLASSPATH
|
||||
|
||||
#ifdef BOOT_JAVAHOME
|
||||
|
||||
#if (defined __MINGW32__) || (defined _MSC_VER)
|
||||
# define SYMBOL(x) binary_javahome_jar_##x
|
||||
#else
|
||||
# define SYMBOL(x) _binary_javahome_jar_##x
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
|
||||
extern const uint8_t SYMBOL(start)[];
|
||||
extern const uint8_t SYMBOL(end)[];
|
||||
|
||||
EXPORT const uint8_t*
|
||||
javahomeJar(unsigned* size)
|
||||
{
|
||||
*size = SYMBOL(end) - SYMBOL(start);
|
||||
return SYMBOL(start);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#undef SYMBOL
|
||||
|
||||
#endif//BOOT_JAVAHOME
|
||||
|
@ -85,8 +85,9 @@ Avian_avian_SystemClassLoader_resourceExists
|
||||
RUNTIME_ARRAY(char, n, stringLength(t, name) + 1);
|
||||
stringChars(t, name, RUNTIME_ARRAY_BODY(n));
|
||||
|
||||
bool r = static_cast<Finder*>(systemClassLoaderFinder(t, loader))->exists
|
||||
(RUNTIME_ARRAY_BODY(n));
|
||||
unsigned length;
|
||||
bool r = static_cast<Finder*>(systemClassLoaderFinder(t, loader))->stat
|
||||
(RUNTIME_ARRAY_BODY(n), &length) == System::TypeFile;
|
||||
|
||||
// fprintf(stderr, "resource %s exists? %d\n", n, r);
|
||||
|
||||
|
@ -128,7 +128,7 @@ enumerateThreads(Thread* t, Thread* x, object array, unsigned* index,
|
||||
namespace vm {
|
||||
|
||||
Classpath*
|
||||
makeClasspath(System*, Allocator* allocator, const char*)
|
||||
makeClasspath(System*, Allocator* allocator, const char*, const char*)
|
||||
{
|
||||
return new (allocator->allocate(sizeof(local::MyClasspath)))
|
||||
local::MyClasspath(allocator);
|
||||
|
@ -88,6 +88,7 @@ namespace local {
|
||||
|
||||
const unsigned InterfaceVersion = 4;
|
||||
const unsigned PageSize = 4 * 1024;
|
||||
const int VirtualFileBase = 1000000000;
|
||||
|
||||
Machine* globalMachine;
|
||||
|
||||
@ -145,7 +146,6 @@ makeClassNameString(Thread* t, object name)
|
||||
return makeString(t, "%s", s);
|
||||
}
|
||||
|
||||
#ifdef AVIAN_OPENJDK_SRC
|
||||
// only safe to call during bootstrap when there's only one thread
|
||||
// running:
|
||||
void
|
||||
@ -171,51 +171,20 @@ intercept(Thread* t, object c, const char* name, const char* spec,
|
||||
}
|
||||
}
|
||||
|
||||
const char*
|
||||
zipLibrary(Thread*);
|
||||
|
||||
int64_t JNICALL
|
||||
getFileAttributes
|
||||
(Thread* t, object method, uintptr_t* arguments)
|
||||
{
|
||||
const unsigned Exists = 1;
|
||||
const unsigned Regular = 2;
|
||||
(Thread* t, object method, uintptr_t* arguments);
|
||||
|
||||
object file = reinterpret_cast<object>(arguments[1]);
|
||||
|
||||
object pathField = findFieldInClass2
|
||||
(t, objectClass(t, file), "path", "Ljava/lang/String;");
|
||||
|
||||
if (pathField) {
|
||||
object path = cast<object>(file, fieldOffset(t, pathField));
|
||||
|
||||
RUNTIME_ARRAY(char, p, stringLength(t, path) + 1);
|
||||
stringChars(t, path, RUNTIME_ARRAY_BODY(p));
|
||||
|
||||
if (strcmp(zipLibrary(t), p) == 0) {
|
||||
return Exists | Regular;
|
||||
} else {
|
||||
object r = t->m->processor->invoke
|
||||
(t, nativeInterceptOriginal(t, methodCode(t, method)),
|
||||
reinterpret_cast<object>(arguments[0]), file);
|
||||
return (r ? intValue(t, r) : 0);
|
||||
}
|
||||
} else {
|
||||
object message = makeString
|
||||
(t, "path Ljava/lang/String; not found in %s",
|
||||
&byteArrayBody(t, className(t, objectClass(t, file)), 0));
|
||||
t->exception = t->m->classpath->makeThrowable
|
||||
(t, Machine::RuntimeExceptionType, message);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif // AVIAN_OPENJDK_SRC
|
||||
int64_t JNICALL
|
||||
getLength
|
||||
(Thread* t, object method, uintptr_t* arguments);
|
||||
|
||||
class MyClasspath : public Classpath {
|
||||
public:
|
||||
static const unsigned BufferSize = 1024;
|
||||
|
||||
MyClasspath(System* s, Allocator* allocator, const char* javaHome):
|
||||
MyClasspath(System* s, Allocator* allocator, const char* javaHome,
|
||||
const char* embedPrefix):
|
||||
allocator(allocator)
|
||||
{
|
||||
class StringBuilder {
|
||||
@ -285,6 +254,11 @@ class MyClasspath : public Classpath {
|
||||
sb.append(LIBRARY_PREFIX);
|
||||
sb.append("zip");
|
||||
sb.append(LIBRARY_SUFFIX);
|
||||
sb.append('\0');
|
||||
|
||||
this->embedPrefix = sb.pointer;
|
||||
sb.append(embedPrefix);
|
||||
this->embedPrefixLength = sb.pointer - this->embedPrefix;
|
||||
}
|
||||
|
||||
virtual object
|
||||
@ -377,13 +351,32 @@ class MyClasspath : public Classpath {
|
||||
globalMachine = t->m;
|
||||
|
||||
#ifdef AVIAN_OPENJDK_SRC
|
||||
{ object c = resolveClass
|
||||
{ object ufsClass = resolveClass
|
||||
(t, root(t, Machine::BootLoader), "java/io/UnixFileSystem");
|
||||
|
||||
if (c) {
|
||||
intercept(t, c, "getBooleanAttributes0", "(Ljava/io/File;)I",
|
||||
voidPointer(getFileAttributes));
|
||||
if (ufsClass) {
|
||||
PROTECT(t, ufsClass);
|
||||
|
||||
object fileClass = resolveClass
|
||||
(t, root(t, Machine::BootLoader), "java/io/File");
|
||||
|
||||
if (fileClass) {
|
||||
object pathField = findFieldInClass2
|
||||
(t, fileClass, "path", "Ljava/lang/String;");
|
||||
|
||||
if (pathField) {
|
||||
this->pathField = fieldOffset(t, pathField);
|
||||
|
||||
intercept(t, ufsClass, "getBooleanAttributes0",
|
||||
"(Ljava/io/File;)I", voidPointer(getFileAttributes));
|
||||
|
||||
intercept(t, ufsClass, "getLength", "(Ljava/io/File;)J",
|
||||
voidPointer(getLength));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
}
|
||||
#else // not AVIAN_OPENJDK_SRC
|
||||
if (loadLibrary(t, libraryPath, "java", true, true) == 0) {
|
||||
@ -437,7 +430,7 @@ class MyClasspath : public Classpath {
|
||||
|
||||
virtual void
|
||||
dispose()
|
||||
{
|
||||
{
|
||||
allocator->free(this, sizeof(*this));
|
||||
}
|
||||
|
||||
@ -446,33 +439,202 @@ class MyClasspath : public Classpath {
|
||||
const char* classpath;
|
||||
const char* libraryPath;
|
||||
const char* zipLibrary;
|
||||
const char* embedPrefix;
|
||||
unsigned embedPrefixLength;
|
||||
unsigned pathField;
|
||||
char buffer[BufferSize];
|
||||
};
|
||||
|
||||
struct JVM_ExceptionTableEntryType{
|
||||
jint start_pc;
|
||||
jint end_pc;
|
||||
jint handler_pc;
|
||||
jint catchType;
|
||||
struct JVM_ExceptionTableEntryType {
|
||||
jint start_pc;
|
||||
jint end_pc;
|
||||
jint handler_pc;
|
||||
jint catchType;
|
||||
};
|
||||
|
||||
struct jvm_version_info {
|
||||
unsigned int jvm_version;
|
||||
unsigned int update_version: 8;
|
||||
unsigned int special_update_version: 8;
|
||||
unsigned int reserved1: 16;
|
||||
unsigned int reserved2;
|
||||
unsigned int is_attach_supported: 1;
|
||||
unsigned int is_kernel_jvm: 1;
|
||||
unsigned int: 30;
|
||||
unsigned int: 32;
|
||||
unsigned int: 32;
|
||||
unsigned jvm_version;
|
||||
unsigned update_version: 8;
|
||||
unsigned special_update_version: 8;
|
||||
unsigned reserved1: 16;
|
||||
unsigned reserved2;
|
||||
unsigned is_attach_supported: 1;
|
||||
unsigned is_kernel_jvm: 1;
|
||||
unsigned: 30;
|
||||
unsigned: 32;
|
||||
unsigned: 32;
|
||||
};
|
||||
|
||||
const char*
|
||||
zipLibrary(Thread* t)
|
||||
Finder*
|
||||
getFinder(Thread* t, const char* name, unsigned nameLength)
|
||||
{
|
||||
return static_cast<MyClasspath*>(t->m->classpath)->zipLibrary;
|
||||
ACQUIRE(t, t->m->referenceLock);
|
||||
|
||||
for (object p = root(t, Machine::VirtualFileFinders);
|
||||
p; p = finderNext(t, p))
|
||||
{
|
||||
if (byteArrayLength(t, finderName(t, p)) == nameLength
|
||||
and strncmp(reinterpret_cast<const char*>
|
||||
(&byteArrayBody(t, finderName(t, p), 0)),
|
||||
name, nameLength))
|
||||
{
|
||||
return static_cast<Finder*>(finderFinder(t, p));
|
||||
}
|
||||
}
|
||||
|
||||
object n = makeByteArray(t, nameLength + 1);
|
||||
memcpy(&byteArrayBody(t, n, 0), name, nameLength);
|
||||
|
||||
void* p = t->m->libraries->resolve
|
||||
(reinterpret_cast<const char*>(&byteArrayBody(t, n, 0)));
|
||||
if (p) {
|
||||
uint8_t* (*function)(unsigned*);
|
||||
memcpy(&function, &p, BytesPerWord);
|
||||
|
||||
unsigned size;
|
||||
uint8_t* data = function(&size);
|
||||
if (data) {
|
||||
Finder* f = makeFinder(t->m->system, t->m->heap, data, size);
|
||||
object finder = makeFinder
|
||||
(t, f, n, root(t, Machine::VirtualFileFinders));
|
||||
|
||||
setRoot(t, Machine::VirtualFileFinders, finder);
|
||||
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
class EmbeddedFile {
|
||||
public:
|
||||
EmbeddedFile(MyClasspath* cp, const char* path, unsigned pathLength) {
|
||||
if (strncmp(cp->embedPrefix, path, cp->embedPrefixLength) == 0) {
|
||||
const char* p = path + cp->embedPrefixLength;
|
||||
while (*p == '/') ++ p;
|
||||
|
||||
this->jar = p;
|
||||
|
||||
if (*p == 0) {
|
||||
this->jarLength = 0;
|
||||
this->path = 0;
|
||||
this->pathLength = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
while (*p and *p != '/') ++p;
|
||||
|
||||
this->jarLength = p - this->jar;
|
||||
|
||||
while (*p == '/') ++p;
|
||||
|
||||
this->path = p;
|
||||
this->pathLength = pathLength - (p - path);
|
||||
} else {
|
||||
this->jar = 0;
|
||||
this->jarLength =0;
|
||||
this->path = 0;
|
||||
this->pathLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const char* jar;
|
||||
const char* path;
|
||||
unsigned jarLength;
|
||||
unsigned pathLength;
|
||||
};
|
||||
|
||||
int64_t JNICALL
|
||||
getFileAttributes
|
||||
(Thread* t, object method, uintptr_t* arguments)
|
||||
{
|
||||
const unsigned Exists = 1;
|
||||
const unsigned Regular = 2;
|
||||
const unsigned Directory = 4;
|
||||
|
||||
MyClasspath* cp = static_cast<MyClasspath*>(t->m->classpath);
|
||||
|
||||
object file = reinterpret_cast<object>(arguments[1]);
|
||||
object path = cast<object>(file, cp->pathField);
|
||||
|
||||
RUNTIME_ARRAY(char, p, stringLength(t, path) + 1);
|
||||
stringChars(t, path, RUNTIME_ARRAY_BODY(p));
|
||||
|
||||
if (strcmp(cp->zipLibrary, RUNTIME_ARRAY_BODY(p)) == 0) {
|
||||
return Exists | Regular;
|
||||
} else {
|
||||
EmbeddedFile ef(cp, RUNTIME_ARRAY_BODY(p), stringLength(t, path));
|
||||
if (ef.jar) {
|
||||
if (ef.jarLength == 0) {
|
||||
return Exists | Directory;
|
||||
}
|
||||
|
||||
Finder* finder = getFinder(t, ef.jar, ef.jarLength);
|
||||
if (finder) {
|
||||
if (ef.pathLength == 0) {
|
||||
return Exists | Directory;
|
||||
}
|
||||
|
||||
unsigned length;
|
||||
System::FileType type = finder->stat(ef.path, &length, true);
|
||||
switch (type) {
|
||||
case System::TypeUnknown: return Exists;
|
||||
case System::TypeDoesNotExist: return 0;
|
||||
case System::TypeFile: return Exists | Regular;
|
||||
case System::TypeDirectory: return Exists | Directory;
|
||||
default: abort(t);
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
object r = t->m->processor->invoke
|
||||
(t, nativeInterceptOriginal(t, methodCode(t, method)),
|
||||
reinterpret_cast<object>(arguments[0]), file);
|
||||
|
||||
return (r ? intValue(t, r) : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int64_t JNICALL
|
||||
getLength
|
||||
(Thread* t, object method, uintptr_t* arguments)
|
||||
{
|
||||
MyClasspath* cp = static_cast<MyClasspath*>(t->m->classpath);
|
||||
|
||||
object file = reinterpret_cast<object>(arguments[1]);
|
||||
object path = cast<object>(file, cp->pathField);
|
||||
|
||||
RUNTIME_ARRAY(char, p, stringLength(t, path) + 1);
|
||||
stringChars(t, path, RUNTIME_ARRAY_BODY(p));
|
||||
|
||||
EmbeddedFile ef(cp, RUNTIME_ARRAY_BODY(p), stringLength(t, path));
|
||||
if (ef.jar) {
|
||||
if (ef.jarLength == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Finder* finder = getFinder(t, ef.jar, ef.jarLength);
|
||||
if (finder) {
|
||||
if (ef.pathLength == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned fileLength;
|
||||
finder->stat(ef.path, &fileLength);
|
||||
return fileLength;
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
object r = t->m->processor->invoke
|
||||
(t, nativeInterceptOriginal(t, methodCode(t, method)),
|
||||
reinterpret_cast<object>(arguments[0]), file);
|
||||
|
||||
return (r ? longValue(t, r) : 0);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned
|
||||
@ -735,10 +897,11 @@ interruptLock(Thread* t, object thread)
|
||||
namespace vm {
|
||||
|
||||
Classpath*
|
||||
makeClasspath(System* s, Allocator* allocator, const char* javaHome)
|
||||
makeClasspath(System* s, Allocator* allocator, const char* javaHome,
|
||||
const char* embedPrefix)
|
||||
{
|
||||
return new (allocator->allocate(sizeof(local::MyClasspath)))
|
||||
local::MyClasspath(s, allocator, javaHome);
|
||||
local::MyClasspath(s, allocator, javaHome, embedPrefix);
|
||||
}
|
||||
|
||||
} // namespace vm
|
||||
@ -1308,7 +1471,9 @@ JVM_LoadLibrary(const char* name)
|
||||
Thread* t = static_cast<Thread*>(local::globalMachine->localThread->get());
|
||||
|
||||
#ifdef AVIAN_OPENJDK_SRC
|
||||
if (strcmp(local::zipLibrary(t), name) == 0) {
|
||||
if (strcmp(static_cast<local::MyClasspath*>(t->m->classpath)->zipLibrary,
|
||||
name) == 0)
|
||||
{
|
||||
return t->m->libraries;
|
||||
}
|
||||
#endif // AVIAN_OPENJDK_SRC
|
||||
@ -2475,21 +2640,126 @@ JVM_NativePath(char* path)
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
JVM_Open(const char* name, jint flags, jint mode)
|
||||
JVM_Open(const char* path, jint flags, jint mode)
|
||||
{
|
||||
return OPEN(name, flags, mode);
|
||||
Thread* t = static_cast<Thread*>(local::globalMachine->localThread->get());
|
||||
local::MyClasspath* cp = static_cast<local::MyClasspath*>(t->m->classpath);
|
||||
|
||||
local::EmbeddedFile ef(cp, path, strlen(path));
|
||||
if (ef.jar) {
|
||||
if (flags != O_RDONLY) {
|
||||
errno = EACCES;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ef.jarLength == 0 or ef.pathLength == 0) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
Finder* finder = local::getFinder(t, ef.jar, ef.jarLength);
|
||||
if (finder == 0) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
System::Region* r = finder->find(ef.path);
|
||||
if (r == 0) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
ACQUIRE(t, t->m->referenceLock);
|
||||
|
||||
int index = -1;
|
||||
unsigned oldLength = root(t, Machine::VirtualFiles)
|
||||
? arrayLength(t, root(t, Machine::VirtualFiles)) : 0;
|
||||
|
||||
for (unsigned i = 0; i < oldLength; ++i) {
|
||||
if (arrayBody(t, root(t, Machine::VirtualFiles), i) == 0) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index == -1) {
|
||||
object newArray = growArray(t, root(t, Machine::VirtualFiles));
|
||||
setRoot(t, Machine::VirtualFiles, newArray);
|
||||
index = oldLength;
|
||||
}
|
||||
|
||||
object region = makeRegion(t, r, 0);
|
||||
set(t, root(t, Machine::VirtualFiles), ArrayBody + (index * BytesPerWord),
|
||||
region);
|
||||
|
||||
return index + local::VirtualFileBase;
|
||||
} else {
|
||||
int r = OPEN(path, flags, mode);
|
||||
expect(t, r < local::VirtualFileBase);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
JVM_Close(jint fd)
|
||||
{
|
||||
return CLOSE(fd);
|
||||
if (fd >= local::VirtualFileBase) {
|
||||
Thread* t = static_cast<Thread*>(local::globalMachine->localThread->get());
|
||||
unsigned index = fd - local::VirtualFileBase;
|
||||
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
ACQUIRE(t, t->m->referenceLock);
|
||||
|
||||
object region = arrayBody(t, root(t, Machine::VirtualFiles), index);
|
||||
if (region) {
|
||||
static_cast<System::Region*>(regionRegion(t, region))->dispose();
|
||||
}
|
||||
|
||||
set(t, root(t, Machine::VirtualFiles), ArrayBody + (index * BytesPerWord),
|
||||
0);
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
return CLOSE(fd);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
JVM_Read(jint fd, char* dst, jint length)
|
||||
{
|
||||
return READ(fd, dst, length);
|
||||
if (fd >= local::VirtualFileBase) {
|
||||
Thread* t = static_cast<Thread*>(local::globalMachine->localThread->get());
|
||||
unsigned index = fd - local::VirtualFileBase;
|
||||
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
ACQUIRE(t, t->m->referenceLock);
|
||||
|
||||
object region = arrayBody(t, root(t, Machine::VirtualFiles), index);
|
||||
if (region) {
|
||||
System::Region* r = static_cast<System::Region*>
|
||||
(regionRegion(t, region));
|
||||
|
||||
int available = r->length() - regionPosition(t, region);
|
||||
if (length > available) {
|
||||
length = available;
|
||||
}
|
||||
|
||||
memcpy(dst, r->start(), length);
|
||||
|
||||
regionPosition(t, region) += length;
|
||||
|
||||
return length;
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return READ(fd, dst, length);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
@ -2501,34 +2771,94 @@ JVM_Write(jint fd, char* src, jint length)
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
JVM_Available(jint fd, jlong* result)
|
||||
{
|
||||
struct stat buffer;
|
||||
int n;
|
||||
if (FSTAT(fd, &buffer) >= 0
|
||||
and (S_ISCHR(buffer.st_mode)
|
||||
or S_ISFIFO(buffer.st_mode)
|
||||
or S_ISSOCK(buffer.st_mode))
|
||||
and ioctl(fd, FIONREAD, &n) >= 0)
|
||||
{
|
||||
*result = n;
|
||||
if (fd >= local::VirtualFileBase) {
|
||||
Thread* t = static_cast<Thread*>(local::globalMachine->localThread->get());
|
||||
unsigned index = fd - local::VirtualFileBase;
|
||||
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
ACQUIRE(t, t->m->referenceLock);
|
||||
|
||||
object region = arrayBody(t, root(t, Machine::VirtualFiles), index);
|
||||
if (region) {
|
||||
return static_cast<System::Region*>(regionRegion(t, region))->length()
|
||||
- regionPosition(t, region);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
struct stat buffer;
|
||||
int n;
|
||||
if (FSTAT(fd, &buffer) >= 0
|
||||
and (S_ISCHR(buffer.st_mode)
|
||||
or S_ISFIFO(buffer.st_mode)
|
||||
or S_ISSOCK(buffer.st_mode))
|
||||
and ioctl(fd, FIONREAD, &n) >= 0)
|
||||
{
|
||||
*result = n;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int current = LSEEK(fd, 0, SEEK_CUR);
|
||||
if (current == -1) return 0;
|
||||
|
||||
int end = LSEEK(fd, 0, SEEK_END);
|
||||
if (end == -1) return 0;
|
||||
|
||||
if (LSEEK(fd, current, SEEK_SET) == -1) return 0;
|
||||
|
||||
*result = end - current;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int current = LSEEK(fd, 0, SEEK_CUR);
|
||||
if (current == -1) return 0;
|
||||
|
||||
int end = LSEEK(fd, 0, SEEK_END);
|
||||
if (end == -1) return 0;
|
||||
|
||||
if (LSEEK(fd, current, SEEK_SET) == -1) return 0;
|
||||
|
||||
*result = end - current;
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
JVM_Lseek(jint fd, jlong offset, jint start)
|
||||
JVM_Lseek(jint fd, jlong offset, jint seek)
|
||||
{
|
||||
return LSEEK(fd, offset, start);
|
||||
if (fd >= local::VirtualFileBase) {
|
||||
Thread* t = static_cast<Thread*>(local::globalMachine->localThread->get());
|
||||
unsigned index = fd - local::VirtualFileBase;
|
||||
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
ACQUIRE(t, t->m->referenceLock);
|
||||
|
||||
object region = arrayBody(t, root(t, Machine::VirtualFiles), index);
|
||||
if (region) {
|
||||
System::Region* r = static_cast<System::Region*>
|
||||
(regionRegion(t, region));
|
||||
|
||||
switch (seek) {
|
||||
case SEEK_SET:
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
offset += regionPosition(t, region);
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
offset += r->length();
|
||||
break;
|
||||
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (offset >= 0 and offset <= static_cast<int>(r->length())) {
|
||||
regionPosition(t, region) = offset;
|
||||
return offset;
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return LSEEK(fd, offset, seek);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
|
@ -7156,7 +7156,7 @@ class SegFaultHandler: public System::SignalHandler {
|
||||
t->exception = root(t, Machine::NullPointerException);
|
||||
}
|
||||
|
||||
// printTrace(t, t->exception);
|
||||
printTrace(t, t->exception);
|
||||
|
||||
object continuation;
|
||||
findUnwindTarget(t, ip, base, stack, &continuation);
|
||||
|
269
src/finder.cpp
269
src/finder.cpp
@ -20,12 +20,12 @@ namespace {
|
||||
const bool DebugFind = false;
|
||||
|
||||
const char*
|
||||
append(System* s, const char* a, const char* b, const char* c)
|
||||
append(Allocator* allocator, const char* a, const char* b, const char* c)
|
||||
{
|
||||
unsigned al = strlen(a);
|
||||
unsigned bl = strlen(b);
|
||||
unsigned cl = strlen(c);
|
||||
char* p = static_cast<char*>(allocate(s, (al + bl + cl) + 1));
|
||||
char* p = static_cast<char*>(allocator->allocate((al + bl + cl) + 1));
|
||||
memcpy(p, a, al);
|
||||
memcpy(p + al, b, bl);
|
||||
memcpy(p + al + bl, c, cl + 1);
|
||||
@ -33,10 +33,10 @@ append(System* s, const char* a, const char* b, const char* c)
|
||||
}
|
||||
|
||||
const char*
|
||||
copy(System* s, const char* a)
|
||||
copy(Allocator* allocator, const char* a)
|
||||
{
|
||||
unsigned al = strlen(a);
|
||||
char* p = static_cast<char*>(allocate(s, al + 1));
|
||||
char* p = static_cast<char*>(allocator->allocate(al + 1));
|
||||
memcpy(p, a, al + 1);
|
||||
return p;
|
||||
}
|
||||
@ -63,7 +63,8 @@ class Element {
|
||||
|
||||
virtual Iterator* iterator() = 0;
|
||||
virtual System::Region* find(const char* name) = 0;
|
||||
virtual bool exists(const char* name) = 0;
|
||||
virtual System::FileType stat(const char* name, unsigned* length,
|
||||
bool tryDirectory) = 0;
|
||||
virtual void dispose() = 0;
|
||||
|
||||
Element* next;
|
||||
@ -73,8 +74,9 @@ class DirectoryElement: public Element {
|
||||
public:
|
||||
class Iterator: public Element::Iterator {
|
||||
public:
|
||||
Iterator(System* s, const char* name, unsigned skip):
|
||||
s(s), name(name), skip(skip), directory(0), last(0), it(0)
|
||||
Iterator(System* s, Allocator* allocator, const char* name, unsigned skip):
|
||||
s(s), allocator(allocator), name(name), skip(skip), directory(0),
|
||||
last(0), it(0)
|
||||
{
|
||||
if (not s->success(s->open(&directory, name))) {
|
||||
directory = 0;
|
||||
@ -93,15 +95,17 @@ class DirectoryElement: public Element {
|
||||
}
|
||||
|
||||
if (last) {
|
||||
s->free(last);
|
||||
allocator->free(last, strlen(last) + 1);
|
||||
}
|
||||
|
||||
if (directory) {
|
||||
for (const char* v = directory->next(); v; v = directory->next()) {
|
||||
if (v[0] != '.') {
|
||||
last = append(s, name, "/", v);
|
||||
if (s->identify(last) == System::TypeDirectory) {
|
||||
it = new (allocate(s, sizeof(Iterator))) Iterator(s, last, skip);
|
||||
last = append(allocator, name, "/", v);
|
||||
unsigned length;
|
||||
if (s->stat(last, &length) == System::TypeDirectory) {
|
||||
it = new (allocator->allocate(sizeof(Iterator)))
|
||||
Iterator(s, allocator, last, skip);
|
||||
it->name = last;
|
||||
}
|
||||
const char* result = last + skip;
|
||||
@ -116,10 +120,11 @@ class DirectoryElement: public Element {
|
||||
|
||||
virtual void dispose() {
|
||||
directory->dispose();
|
||||
s->free(this);
|
||||
allocator->free(this, sizeof(*this));
|
||||
}
|
||||
|
||||
System* s;
|
||||
Allocator* allocator;
|
||||
const char* name;
|
||||
unsigned skip;
|
||||
System::Directory* directory;
|
||||
@ -127,20 +132,20 @@ class DirectoryElement: public Element {
|
||||
Iterator* it;
|
||||
};
|
||||
|
||||
DirectoryElement(System* s, const char* name):
|
||||
s(s), name(name)
|
||||
DirectoryElement(System* s, Allocator* allocator, const char* name):
|
||||
s(s), allocator(allocator), name(name)
|
||||
{ }
|
||||
|
||||
virtual Element::Iterator* iterator() {
|
||||
return new (allocate(s, sizeof(Iterator)))
|
||||
Iterator(s, name, strlen(name) + 1);
|
||||
return new (allocator->allocate(sizeof(Iterator)))
|
||||
Iterator(s, allocator, name, strlen(name) + 1);
|
||||
}
|
||||
|
||||
virtual System::Region* find(const char* name) {
|
||||
const char* file = append(s, this->name, "/", name);
|
||||
const char* file = append(allocator, this->name, "/", name);
|
||||
System::Region* region;
|
||||
System::Status status = s->map(®ion, file);
|
||||
s->free(file);
|
||||
allocator->free(file, strlen(file) + 1);
|
||||
|
||||
if (s->success(status)) {
|
||||
if (DebugFind) {
|
||||
@ -155,26 +160,29 @@ class DirectoryElement: public Element {
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool exists(const char* name) {
|
||||
const char* file = append(s, this->name, "/", name);
|
||||
System::FileType type = s->identify(file);
|
||||
s->free(file);
|
||||
return type != System::TypeDoesNotExist;
|
||||
virtual System::FileType stat(const char* name, unsigned* length, bool) {
|
||||
const char* file = append(allocator, this->name, "/", name);
|
||||
System::FileType type = s->stat(file, length);
|
||||
allocator->free(file, strlen(file) + 1);
|
||||
return type;
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
s->free(name);
|
||||
s->free(this);
|
||||
allocator->free(name, strlen(name) + 1);
|
||||
allocator->free(this, sizeof(*this));
|
||||
}
|
||||
|
||||
System* s;
|
||||
Allocator* allocator;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
class PointerRegion: public System::Region {
|
||||
public:
|
||||
PointerRegion(System* s, const uint8_t* start, size_t length):
|
||||
PointerRegion(System* s, Allocator* allocator, const uint8_t* start,
|
||||
size_t length):
|
||||
s(s),
|
||||
allocator(allocator),
|
||||
start_(start),
|
||||
length_(length)
|
||||
{ }
|
||||
@ -188,18 +196,20 @@ class PointerRegion: public System::Region {
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
s->free(this);
|
||||
allocator->free(this, sizeof(*this));
|
||||
}
|
||||
|
||||
System* s;
|
||||
Allocator* allocator;
|
||||
const uint8_t* start_;
|
||||
size_t length_;
|
||||
};
|
||||
|
||||
class DataRegion: public System::Region {
|
||||
public:
|
||||
DataRegion(System* s, size_t length):
|
||||
DataRegion(System* s, Allocator* allocator, size_t length):
|
||||
s(s),
|
||||
allocator(allocator),
|
||||
length_(length)
|
||||
{ }
|
||||
|
||||
@ -212,10 +222,11 @@ class DataRegion: public System::Region {
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
s->free(this);
|
||||
allocator->free(this, sizeof(*this));
|
||||
}
|
||||
|
||||
System* s;
|
||||
Allocator* allocator;
|
||||
size_t length_;
|
||||
uint8_t data[0];
|
||||
};
|
||||
@ -241,11 +252,12 @@ class JarIndex {
|
||||
Node* next;
|
||||
};
|
||||
|
||||
JarIndex(System* s, unsigned capacity):
|
||||
JarIndex(System* s, Allocator* allocator, unsigned capacity):
|
||||
s(s),
|
||||
allocator(allocator),
|
||||
capacity(capacity),
|
||||
position(0),
|
||||
nodes(static_cast<Node*>(allocate(s, sizeof(Node) * capacity)))
|
||||
nodes(static_cast<Node*>(allocator->allocate(sizeof(Node) * capacity)))
|
||||
{
|
||||
memset(table, 0, sizeof(Node*) * capacity);
|
||||
}
|
||||
@ -322,14 +334,16 @@ class JarIndex {
|
||||
commentFieldLength(p);
|
||||
}
|
||||
|
||||
static JarIndex* make(System* s, unsigned capacity) {
|
||||
static JarIndex* make(System* s, Allocator* allocator, unsigned capacity) {
|
||||
return new
|
||||
(allocate(s, sizeof(JarIndex) + (sizeof(Node*) * capacity)))
|
||||
JarIndex(s, capacity);
|
||||
(allocator->allocate(sizeof(JarIndex) + (sizeof(Node*) * capacity)))
|
||||
JarIndex(s, allocator, capacity);
|
||||
}
|
||||
|
||||
static JarIndex* open(System* s, System::Region* region) {
|
||||
JarIndex* index = make(s, 32);
|
||||
static JarIndex* open(System* s, Allocator* allocator,
|
||||
System::Region* region)
|
||||
{
|
||||
JarIndex* index = make(s, allocator, 32);
|
||||
|
||||
const uint8_t* start = region->start();
|
||||
const uint8_t* end = start + region->length();
|
||||
@ -362,7 +376,7 @@ class JarIndex {
|
||||
table[i] = new (nodes + (position++)) Node(hash, entry, table[i]);
|
||||
return this;
|
||||
} else {
|
||||
JarIndex* index = make(s, capacity * 2);
|
||||
JarIndex* index = make(s, allocator, capacity * 2);
|
||||
for (unsigned i = 0; i < capacity; ++i) {
|
||||
index->add(nodes[i].hash, nodes[i].entry);
|
||||
}
|
||||
@ -390,15 +404,15 @@ class JarIndex {
|
||||
const uint8_t* p = n->entry;
|
||||
switch (compressionMethod(p)) {
|
||||
case Stored: {
|
||||
return new (allocate(s, sizeof(PointerRegion)))
|
||||
PointerRegion(s, fileData(start + localHeaderOffset(p)),
|
||||
return new (allocator->allocate(sizeof(PointerRegion)))
|
||||
PointerRegion(s, allocator, fileData(start + localHeaderOffset(p)),
|
||||
compressedSize(p));
|
||||
} break;
|
||||
|
||||
case Deflated: {
|
||||
DataRegion* region = new
|
||||
(allocate(s, sizeof(DataRegion) + uncompressedSize(p)))
|
||||
DataRegion(s, uncompressedSize(p));
|
||||
(allocator->allocate(sizeof(DataRegion) + uncompressedSize(p)))
|
||||
DataRegion(s, allocator, uncompressedSize(p));
|
||||
|
||||
z_stream zStream; memset(&zStream, 0, sizeof(z_stream));
|
||||
|
||||
@ -428,16 +442,41 @@ class JarIndex {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool exists(const char* name) {
|
||||
return findNode(name) != 0;
|
||||
System::FileType stat(const char* name, unsigned* length, bool tryDirectory)
|
||||
{
|
||||
Node* node = findNode(name);
|
||||
if (node) {
|
||||
*length = uncompressedSize(node->entry);
|
||||
return System::TypeFile;
|
||||
} else if (tryDirectory) {
|
||||
*length = 0;
|
||||
|
||||
// try again with '/' appended
|
||||
unsigned length = strlen(name);
|
||||
RUNTIME_ARRAY(char, n, length + 2);
|
||||
memcpy(RUNTIME_ARRAY_BODY(n), name, length);
|
||||
RUNTIME_ARRAY_BODY(n)[length] = '/';
|
||||
RUNTIME_ARRAY_BODY(n)[length + 1] = 0;
|
||||
|
||||
node = findNode(n);
|
||||
if (node) {
|
||||
return System::TypeDirectory;
|
||||
} else {
|
||||
return System::TypeDoesNotExist;
|
||||
}
|
||||
} else {
|
||||
*length = 0;
|
||||
return System::TypeDoesNotExist;
|
||||
}
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
s->free(nodes);
|
||||
s->free(this);
|
||||
allocator->free(nodes, sizeof(Node) * capacity);
|
||||
allocator->free(this, sizeof(*this) + (sizeof(Node*) * capacity));
|
||||
}
|
||||
|
||||
System* s;
|
||||
Allocator* allocator;
|
||||
unsigned capacity;
|
||||
unsigned position;
|
||||
|
||||
@ -449,7 +488,9 @@ class JarElement: public Element {
|
||||
public:
|
||||
class Iterator: public Element::Iterator {
|
||||
public:
|
||||
Iterator(System* s, JarIndex* index): s(s), index(index), position(0) { }
|
||||
Iterator(System* s, Allocator* allocator, JarIndex* index):
|
||||
s(s), allocator(allocator), index(index), position(0)
|
||||
{ }
|
||||
|
||||
virtual const char* next(unsigned* size) {
|
||||
if (position < index->position) {
|
||||
@ -462,22 +503,34 @@ class JarElement: public Element {
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
s->free(this);
|
||||
allocator->free(this, sizeof(*this));
|
||||
}
|
||||
|
||||
System* s;
|
||||
Allocator* allocator;
|
||||
JarIndex* index;
|
||||
unsigned position;
|
||||
};
|
||||
|
||||
JarElement(System* s, const char* name):
|
||||
s(s), name(name), region(0), index(0)
|
||||
JarElement(System* s, Allocator* allocator, const char* name):
|
||||
s(s), allocator(allocator), name(name), region(0), index(0)
|
||||
{ }
|
||||
|
||||
JarElement(System* s, Allocator* allocator, const uint8_t* jarData,
|
||||
unsigned jarLength):
|
||||
s(s),
|
||||
allocator(allocator),
|
||||
name(0),
|
||||
region(new (allocator->allocate(sizeof(PointerRegion)))
|
||||
PointerRegion(s, allocator, jarData, jarLength)),
|
||||
index(JarIndex::open(s, allocator, region))
|
||||
{ }
|
||||
|
||||
virtual Element::Iterator* iterator() {
|
||||
init();
|
||||
|
||||
return new (allocate(s, sizeof(Iterator))) Iterator(s, index);
|
||||
return new (allocator->allocate(sizeof(Iterator)))
|
||||
Iterator(s, allocator, index);
|
||||
}
|
||||
|
||||
virtual void init() {
|
||||
@ -485,7 +538,7 @@ class JarElement: public Element {
|
||||
System::Region* r;
|
||||
if (s->success(s->map(&r, name))) {
|
||||
region = r;
|
||||
index = JarIndex::open(s, r);
|
||||
index = JarIndex::open(s, allocator, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -506,26 +559,34 @@ class JarElement: public Element {
|
||||
return r;
|
||||
}
|
||||
|
||||
virtual bool exists(const char* name) {
|
||||
virtual System::FileType stat(const char* name, unsigned* length,
|
||||
bool tryDirectory)
|
||||
{
|
||||
init();
|
||||
|
||||
while (*name == '/') name++;
|
||||
|
||||
return (index ? index->exists(name) : 0);
|
||||
return (index ? index->stat(name, length, tryDirectory)
|
||||
: System::TypeDoesNotExist);
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
s->free(name);
|
||||
dispose(sizeof(*this));
|
||||
}
|
||||
|
||||
virtual void dispose(unsigned size) {
|
||||
allocator->free(name, strlen(name) + 1);
|
||||
if (index) {
|
||||
index->dispose();
|
||||
}
|
||||
if (region) {
|
||||
region->dispose();
|
||||
}
|
||||
s->free(this);
|
||||
allocator->free(this, size);
|
||||
}
|
||||
|
||||
System* s;
|
||||
Allocator* allocator;
|
||||
const char* name;
|
||||
System::Region* region;
|
||||
JarIndex* index;
|
||||
@ -533,9 +594,10 @@ class JarElement: public Element {
|
||||
|
||||
class BuiltinElement: public JarElement {
|
||||
public:
|
||||
BuiltinElement(System* s, const char* name, const char* libraryName):
|
||||
JarElement(s, name),
|
||||
libraryName(libraryName ? copy(s, libraryName) : 0)
|
||||
BuiltinElement(System* s, Allocator* allocator, const char* name,
|
||||
const char* libraryName):
|
||||
JarElement(s, allocator, name),
|
||||
libraryName(libraryName ? copy(allocator, libraryName) : 0)
|
||||
{ }
|
||||
|
||||
virtual void init() {
|
||||
@ -549,9 +611,9 @@ class BuiltinElement: public JarElement {
|
||||
unsigned size;
|
||||
uint8_t* data = function(&size);
|
||||
if (data) {
|
||||
region = new (allocate(s, sizeof(PointerRegion)))
|
||||
PointerRegion(s, data, size);
|
||||
index = JarIndex::open(s, region);
|
||||
region = new (allocator->allocate(sizeof(PointerRegion)))
|
||||
PointerRegion(s, allocator, data, size);
|
||||
index = JarIndex::open(s, allocator, region);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -560,8 +622,10 @@ class BuiltinElement: public JarElement {
|
||||
|
||||
virtual void dispose() {
|
||||
library->disposeAll();
|
||||
s->free(libraryName);
|
||||
JarElement::dispose();
|
||||
if (libraryName) {
|
||||
allocator->free(libraryName, strlen(libraryName) + 1);
|
||||
}
|
||||
JarElement::dispose(sizeof(*this));
|
||||
}
|
||||
|
||||
System::Library* library;
|
||||
@ -569,7 +633,8 @@ class BuiltinElement: public JarElement {
|
||||
};
|
||||
|
||||
Element*
|
||||
parsePath(System* s, const char* path, const char* bootLibrary)
|
||||
parsePath(System* s, Allocator* allocator, const char* path,
|
||||
const char* bootLibrary)
|
||||
{
|
||||
Element* first = 0;
|
||||
Element* prev = 0;
|
||||
@ -578,29 +643,31 @@ parsePath(System* s, const char* path, const char* bootLibrary)
|
||||
|
||||
Element* e;
|
||||
if (*token.s == '[' and token.s[token.length - 1] == ']') {
|
||||
char* name = static_cast<char*>(allocate(s, token.length - 1));
|
||||
char* name = static_cast<char*>(allocator->allocate(token.length - 1));
|
||||
memcpy(name, token.s + 1, token.length - 1);
|
||||
name[token.length - 2] = 0;
|
||||
|
||||
e = new (allocate(s, sizeof(BuiltinElement)))
|
||||
BuiltinElement(s, name, bootLibrary);
|
||||
e = new (allocator->allocate(sizeof(BuiltinElement)))
|
||||
BuiltinElement(s, allocator, name, bootLibrary);
|
||||
} else {
|
||||
char* name = static_cast<char*>(allocate(s, token.length + 1));
|
||||
char* name = static_cast<char*>(allocator->allocate(token.length + 1));
|
||||
memcpy(name, token.s, token.length);
|
||||
name[token.length] = 0;
|
||||
|
||||
switch (s->identify(name)) {
|
||||
unsigned length;
|
||||
switch (s->stat(name, &length)) {
|
||||
case System::TypeFile: {
|
||||
e = new (allocate(s, sizeof(JarElement))) JarElement(s, name);
|
||||
e = new (allocator->allocate(sizeof(JarElement)))
|
||||
JarElement(s, allocator, name);
|
||||
} break;
|
||||
|
||||
case System::TypeDirectory: {
|
||||
e = new (allocate(s, sizeof(DirectoryElement)))
|
||||
DirectoryElement(s, name);
|
||||
e = new (allocator->allocate(sizeof(DirectoryElement)))
|
||||
DirectoryElement(s, allocator, name);
|
||||
} break;
|
||||
|
||||
default: {
|
||||
s->free(name);
|
||||
allocator->free(name, strlen(name) + 1);
|
||||
e = 0;
|
||||
} break;
|
||||
}
|
||||
@ -621,8 +688,9 @@ parsePath(System* s, const char* path, const char* bootLibrary)
|
||||
|
||||
class MyIterator: public Finder::IteratorImp {
|
||||
public:
|
||||
MyIterator(System* s, Element* path):
|
||||
s(s), e(path ? path->next : 0), it(path ? path->iterator() : 0)
|
||||
MyIterator(System* s, Allocator* allocator, Element* path):
|
||||
s(s), allocator(allocator), e(path ? path->next : 0),
|
||||
it(path ? path->iterator() : 0)
|
||||
{ }
|
||||
|
||||
virtual const char* next(unsigned* size) {
|
||||
@ -645,25 +713,37 @@ class MyIterator: public Finder::IteratorImp {
|
||||
|
||||
virtual void dispose() {
|
||||
if (it) it->dispose();
|
||||
s->free(this);
|
||||
allocator->free(this, sizeof(*this));
|
||||
}
|
||||
|
||||
System* s;
|
||||
Allocator* allocator;
|
||||
Element* e;
|
||||
Element::Iterator* it;
|
||||
};
|
||||
|
||||
class MyFinder: public Finder {
|
||||
public:
|
||||
MyFinder(System* system, const char* path, const char* bootLibrary):
|
||||
MyFinder(System* system, Allocator* allocator, const char* path,
|
||||
const char* bootLibrary):
|
||||
system(system),
|
||||
path_(parsePath(system, path, bootLibrary)),
|
||||
pathString(copy(system, path))
|
||||
allocator(allocator),
|
||||
path_(parsePath(system, allocator, path, bootLibrary)),
|
||||
pathString(copy(allocator, path))
|
||||
{ }
|
||||
|
||||
MyFinder(System* system, Allocator* allocator, const uint8_t* jarData,
|
||||
unsigned jarLength):
|
||||
system(system),
|
||||
allocator(allocator),
|
||||
path_(new (allocator->allocate(sizeof(JarElement)))
|
||||
JarElement(system, allocator, jarData, jarLength)),
|
||||
pathString(0)
|
||||
{ }
|
||||
|
||||
virtual IteratorImp* iterator() {
|
||||
return new (allocate(system, sizeof(MyIterator)))
|
||||
MyIterator(system, path_);
|
||||
return new (allocator->allocate(sizeof(MyIterator)))
|
||||
MyIterator(system, allocator, path_);
|
||||
}
|
||||
|
||||
virtual System::Region* find(const char* name) {
|
||||
@ -677,14 +757,17 @@ class MyFinder: public Finder {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual bool exists(const char* name) {
|
||||
virtual System::FileType stat(const char* name, unsigned* length,
|
||||
bool tryDirectory)
|
||||
{
|
||||
for (Element* e = path_; e; e = e->next) {
|
||||
if (e->exists(name)) {
|
||||
return true;
|
||||
System::FileType type = e->stat(name, length, tryDirectory);
|
||||
if (type != System::TypeDoesNotExist) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return System::TypeDoesNotExist;
|
||||
}
|
||||
|
||||
virtual const char* path() {
|
||||
@ -697,11 +780,12 @@ class MyFinder: public Finder {
|
||||
e = e->next;
|
||||
t->dispose();
|
||||
}
|
||||
system->free(pathString);
|
||||
system->free(this);
|
||||
allocator->free(pathString, strlen(pathString) + 1);
|
||||
allocator->free(this, sizeof(*this));
|
||||
}
|
||||
|
||||
System* system;
|
||||
Allocator* allocator;
|
||||
Element* path_;
|
||||
const char* pathString;
|
||||
};
|
||||
@ -711,9 +795,16 @@ class MyFinder: public Finder {
|
||||
namespace vm {
|
||||
|
||||
Finder*
|
||||
makeFinder(System* s, const char* path, const char* bootLibrary)
|
||||
makeFinder(System* s, Allocator* a, const char* path, const char* bootLibrary)
|
||||
{
|
||||
return new (allocate(s, sizeof(MyFinder))) MyFinder(s, path, bootLibrary);
|
||||
return new (a->allocate(sizeof(MyFinder))) MyFinder(s, a, path, bootLibrary);
|
||||
}
|
||||
|
||||
Finder*
|
||||
makeFinder(System* s, Allocator* a, const uint8_t* jarData, unsigned jarLength)
|
||||
{
|
||||
return new (a->allocate(sizeof(MyFinder)))
|
||||
MyFinder(s, a, jarData, jarLength);
|
||||
}
|
||||
|
||||
} // namespace vm
|
||||
|
10
src/finder.h
10
src/finder.h
@ -60,13 +60,19 @@ class Finder {
|
||||
|
||||
virtual IteratorImp* iterator() = 0;
|
||||
virtual System::Region* find(const char* name) = 0;
|
||||
virtual bool exists(const char* name) = 0;
|
||||
virtual System::FileType stat(const char* name,
|
||||
unsigned* length,
|
||||
bool tryDirectory = false) = 0;
|
||||
virtual const char* path() = 0;
|
||||
virtual void dispose() = 0;
|
||||
};
|
||||
|
||||
Finder*
|
||||
makeFinder(System* s, const char* path, const char* bootLibrary);
|
||||
makeFinder(System* s, Allocator* a, const char* path, const char* bootLibrary);
|
||||
|
||||
Finder*
|
||||
makeFinder(System* s, Allocator* a, const uint8_t* jarData,
|
||||
unsigned jarLength);
|
||||
|
||||
} // namespace vm
|
||||
|
||||
|
@ -2228,6 +2228,7 @@ populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
|
||||
|
||||
#define BOOTSTRAP_PROPERTY "avian.bootstrap"
|
||||
#define CRASHDIR_PROPERTY "avian.crash.dir"
|
||||
#define EMBED_PREFIX_PROPERTY "avian.embed.prefix"
|
||||
#define CLASSPATH_PROPERTY "java.class.path"
|
||||
#define JAVA_HOME_PROPERTY "java.home"
|
||||
#define BOOTCLASSPATH_PREPEND_OPTION "bootclasspath/p"
|
||||
@ -2250,6 +2251,7 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
|
||||
const char* bootLibrary = 0;
|
||||
const char* classpath = 0;
|
||||
const char* javaHome = AVIAN_JAVA_HOME;
|
||||
const char* embedPrefix = AVIAN_EMBED_PREFIX;
|
||||
const char* bootClasspathPrepend = "";
|
||||
const char* bootClasspath = 0;
|
||||
const char* bootClasspathAppend = "";
|
||||
@ -2293,6 +2295,10 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
|
||||
sizeof(JAVA_HOME_PROPERTY)) == 0)
|
||||
{
|
||||
javaHome = p + sizeof(JAVA_HOME_PROPERTY);
|
||||
} else if (strncmp(p, EMBED_PREFIX_PROPERTY "=",
|
||||
sizeof(EMBED_PREFIX_PROPERTY)) == 0)
|
||||
{
|
||||
embedPrefix = p + sizeof(EMBED_PREFIX_PROPERTY);
|
||||
}
|
||||
|
||||
++ propertyCount;
|
||||
@ -2305,7 +2311,7 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
|
||||
|
||||
System* s = makeSystem(crashDumpDirectory);
|
||||
Heap* h = makeHeap(s, heapLimit);
|
||||
Classpath* c = makeClasspath(s, h, javaHome);
|
||||
Classpath* c = makeClasspath(s, h, javaHome, embedPrefix);
|
||||
|
||||
if (bootClasspath == 0) {
|
||||
bootClasspath = c->bootClasspath();
|
||||
@ -2325,8 +2331,8 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
|
||||
local::append(&bootClasspathPointer, bootClasspathAppend, bcpal, 0);
|
||||
|
||||
Finder* bf = makeFinder
|
||||
(s, RUNTIME_ARRAY_BODY(bootClasspathBuffer), bootLibrary);
|
||||
Finder* af = makeFinder(s, classpath, bootLibrary);
|
||||
(s, h, RUNTIME_ARRAY_BODY(bootClasspathBuffer), bootLibrary);
|
||||
Finder* af = makeFinder(s, h, classpath, bootLibrary);
|
||||
Processor* p = makeProcessor(s, h, true);
|
||||
|
||||
const char** properties = static_cast<const char**>
|
||||
|
@ -193,6 +193,23 @@ turnOffTheLights(Thread* t)
|
||||
}
|
||||
}
|
||||
|
||||
if (root(t, Machine::VirtualFiles)) {
|
||||
for (unsigned i = 0; i < arrayLength(t, root(t, Machine::VirtualFiles));
|
||||
++i)
|
||||
{
|
||||
object region = arrayBody(t, root(t, Machine::VirtualFiles), i);
|
||||
if (region) {
|
||||
static_cast<System::Region*>(regionRegion(t, region))->dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (object p = root(t, Machine::VirtualFileFinders);
|
||||
p; p = finderNext(t, p))
|
||||
{
|
||||
static_cast<Finder*>(finderFinder(t, p))->dispose();
|
||||
}
|
||||
|
||||
Machine* m = t->m;
|
||||
|
||||
disposeAll(t, t->m->rootThread);
|
||||
@ -204,13 +221,13 @@ turnOffTheLights(Thread* t)
|
||||
Finder* bf = m->bootFinder;
|
||||
Finder* af = m->appFinder;
|
||||
|
||||
c->dispose();
|
||||
m->dispose();
|
||||
h->disposeFixies();
|
||||
c->dispose();
|
||||
p->dispose();
|
||||
h->dispose();
|
||||
bf->dispose();
|
||||
af->dispose();
|
||||
h->dispose();
|
||||
s->dispose();
|
||||
}
|
||||
|
||||
|
@ -1198,10 +1198,12 @@ class Machine {
|
||||
ShutdownHooks,
|
||||
ObjectsToFinalize,
|
||||
NullPointerException,
|
||||
ArrayIndexOutOfBoundsException
|
||||
ArrayIndexOutOfBoundsException,
|
||||
VirtualFileFinders,
|
||||
VirtualFiles
|
||||
};
|
||||
|
||||
static const unsigned RootCount = ArrayIndexOutOfBoundsException + 1;
|
||||
static const unsigned RootCount = VirtualFiles + 1;
|
||||
|
||||
Machine(System* system, Heap* heap, Finder* bootFinder, Finder* appFinder,
|
||||
Processor* processor, Classpath* classpath, const char** properties,
|
||||
@ -1446,7 +1448,8 @@ runJavaThread(Thread* t)
|
||||
}
|
||||
|
||||
Classpath*
|
||||
makeClasspath(System* system, Allocator* allocator, const char* javaHome);
|
||||
makeClasspath(System* system, Allocator* allocator, const char* javaHome,
|
||||
const char* embedPrefix);
|
||||
|
||||
typedef uint64_t (JNICALL *FastNativeFunction)(Thread*, object, uintptr_t*);
|
||||
|
||||
|
@ -698,18 +698,22 @@ class MySystem: public System {
|
||||
return status;
|
||||
}
|
||||
|
||||
virtual FileType identify(const char* name) {
|
||||
virtual FileType stat(const char* name, unsigned* length) {
|
||||
struct stat s;
|
||||
int r = stat(name, &s);
|
||||
int r = ::stat(name, &s);
|
||||
if (r == 0) {
|
||||
if (S_ISREG(s.st_mode)) {
|
||||
*length = s.st_size;
|
||||
return TypeFile;
|
||||
} else if (S_ISDIR(s.st_mode)) {
|
||||
*length = 0;
|
||||
return TypeDirectory;
|
||||
} else {
|
||||
*length = 0;
|
||||
return TypeUnknown;
|
||||
}
|
||||
} else {
|
||||
*length = 0;
|
||||
return TypeDoesNotExist;
|
||||
}
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ class System {
|
||||
unsigned count, unsigned size,
|
||||
unsigned returnType) = 0;
|
||||
virtual Status map(Region**, const char* name) = 0;
|
||||
virtual FileType identify(const char* name) = 0;
|
||||
virtual FileType stat(const char* name, unsigned* length) = 0;
|
||||
virtual Status open(Directory**, const char* name) = 0;
|
||||
virtual const char* libraryPrefix() = 0;
|
||||
virtual const char* librarySuffix() = 0;
|
||||
|
@ -2213,7 +2213,31 @@ main(int ac, char** av)
|
||||
}
|
||||
|
||||
System* system = makeSystem(0);
|
||||
Finder* finder = makeFinder(system, av[1], 0);
|
||||
|
||||
class MyAllocator: public Allocator {
|
||||
public:
|
||||
MyAllocator(System* s): s(s) { }
|
||||
|
||||
virtual void* tryAllocate(unsigned size) {
|
||||
return s->tryAllocate(size);
|
||||
}
|
||||
|
||||
virtual void* allocate(unsigned size) {
|
||||
void* p = tryAllocate(size);
|
||||
if (p == 0) {
|
||||
abort(s);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
virtual void free(const void* p, unsigned) {
|
||||
s->free(p);
|
||||
}
|
||||
|
||||
System* s;
|
||||
} allocator(system);
|
||||
|
||||
Finder* finder = makeFinder(system, &allocator, av[1], 0);
|
||||
|
||||
FILE* inStream = ::fopen(av[2], "rb");
|
||||
if (inStream == 0) {
|
||||
|
@ -48,6 +48,15 @@
|
||||
(extends native)
|
||||
(object original))
|
||||
|
||||
(type finder
|
||||
(void* finder)
|
||||
(object name)
|
||||
(object next))
|
||||
|
||||
(type region
|
||||
(void* region)
|
||||
(unsigned position))
|
||||
|
||||
(pod exceptionHandler
|
||||
(uint16_t start)
|
||||
(uint16_t end)
|
||||
|
21
src/util.cpp
21
src/util.cpp
@ -529,11 +529,6 @@ vectorAppend(Thread* t, object vector, object value)
|
||||
vectorSize(t, vector) * BytesPerWord);
|
||||
}
|
||||
|
||||
memset(&vectorBody(t, newVector, vectorSize(t, vector) + 1),
|
||||
0,
|
||||
(vectorLength(t, newVector) - vectorSize(t, vector) - 1)
|
||||
* BytesPerWord);
|
||||
|
||||
vector = newVector;
|
||||
}
|
||||
|
||||
@ -542,6 +537,22 @@ vectorAppend(Thread* t, object vector, object value)
|
||||
return vector;
|
||||
}
|
||||
|
||||
object
|
||||
growArray(Thread* t, object array)
|
||||
{
|
||||
PROTECT(t, array);
|
||||
|
||||
object newArray = makeArray
|
||||
(t, array == 0 ? 16 : (arrayLength(t, array) * 2));
|
||||
|
||||
if (array) {
|
||||
memcpy(&arrayBody(t, newArray, 0), &arrayBody(t, array, 0),
|
||||
arrayLength(t, array));
|
||||
}
|
||||
|
||||
return newArray;
|
||||
}
|
||||
|
||||
object
|
||||
treeQuery(Thread* t, object tree, intptr_t key, object sentinal,
|
||||
intptr_t (*compare)(Thread* t, intptr_t key, object b))
|
||||
|
@ -84,6 +84,9 @@ listAppend(Thread* t, object list, object value);
|
||||
object
|
||||
vectorAppend(Thread* t, object vector, object value);
|
||||
|
||||
object
|
||||
growArray(Thread* t, object array);
|
||||
|
||||
object
|
||||
treeQuery(Thread* t, object tree, intptr_t key, object sentinal,
|
||||
intptr_t (*compare)(Thread* t, intptr_t key, object b));
|
||||
|
@ -204,5 +204,7 @@ public class Misc {
|
||||
} while (x != 1);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println(java.util.Calendar.getInstance().toString());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user