diff --git a/makefile b/makefile index 7bd1e40fe4..c0b82b48e7 100755 --- a/makefile +++ b/makefile @@ -169,9 +169,11 @@ ifneq ($(android),) -D_FILE_OFFSET_BITS=64 \ -g3 \ -Werror \ - -fPIC - classpath-lflags := $(android)/icu4c/lib/libicuuc.a \ + -fPIC \ + -fvisibility=hidden + classpath-lflags := \ $(android)/icu4c/lib/libicui18n.a \ + $(android)/icu4c/lib/libicuuc.a \ $(android)/icu4c/lib/libicudata.a \ $(android)/fdlibm/libfdm.a \ $(android)/expat/.libs/libexpat.a \ @@ -1413,9 +1415,10 @@ $(classpath-build)/%.class: $(classpath-src)/%.java $(classpath-dep): $(classpath-sources) $(classpath-jar-dep) @echo "compiling classpath classes" @mkdir -p $(classpath-build) - $(javac) -d $(classpath-build) -bootclasspath $(boot-classpath) \ - $(shell $(MAKE) -s --no-print-directory build=$(build) \ - $(classpath-classes)) + classes="$(shell $(MAKE) -s --no-print-directory build=$(build) \ + $(classpath-classes))"; if [ -n "$${classes}" ]; then \ + $(javac) -d $(classpath-build) -bootclasspath $(boot-classpath) \ + $${classes}; fi @touch $(@) $(build)/android-src/%.cpp: $(luni-native)/%.cpp diff --git a/src/classpath-android.cpp b/src/classpath-android.cpp index 369dc3b5c3..356c445f4d 100644 --- a/src/classpath-android.cpp +++ b/src/classpath-android.cpp @@ -123,7 +123,7 @@ initVmThread(Thread* t, object thread) if (fieldAtOffset(thread, fieldOffset(t, field)) == 0) { PROTECT(t, field); - + object c = resolveClass (t, root(t, Machine::BootLoader), "java/lang/VMThread"); PROTECT(t, c); @@ -235,6 +235,8 @@ class MyClasspath : public Classpath { t->m->processor->invoke (t, constructor, thread, group, 0, NormalPriority, false); + set(t, thread, ThreadContextClassLoader, root(t, Machine::AppLoader)); + initVmThread(t, thread); return thread; @@ -325,6 +327,10 @@ class MyClasspath : public Classpath { virtual void preBoot(Thread* t) { + // Android's System.initSystemProperties throws an NPE if + // LD_LIBRARY_PATH is not set as of this writing: + setenv("LD_LIBRARY_PATH", "", false); + { object c = resolveClass (t, root(t, Machine::BootLoader), "java/lang/Runtime", false); @@ -531,6 +537,8 @@ jniRegisterNativeMethods(JNIEnv* e, const char* className, if (c) { e->vtable->RegisterNatives(e, c, methods, methodCount); + } else { + e->vtable->ExceptionClear(e); } return 0; @@ -693,8 +701,9 @@ extern "C" JNIEXPORT int64_t JNICALL Avian_java_lang_String_equals (Thread* t, object, uintptr_t* arguments) { - return stringEqual(t, reinterpret_cast(arguments[0]), - reinterpret_cast(arguments[1])); + return arguments[1] and stringEqual + (t, reinterpret_cast(arguments[0]), + reinterpret_cast(arguments[1])); } extern "C" JNIEXPORT int64_t JNICALL @@ -917,8 +926,14 @@ extern "C" JNIEXPORT int64_t JNICALL Avian_dalvik_system_VMRuntime_properties (Thread* t, object, uintptr_t*) { - return reinterpret_cast - (makeObjectArray(t, type(t, Machine::StringType), 0)); + object array = makeObjectArray(t, type(t, Machine::StringType), 1); + PROTECT(t, array); + + object property = makeString(t, "java.protocol.handler.pkgs=avian"); + + set(t, array, ArrayBody, property); + + return reinterpret_cast(array); } extern "C" JNIEXPORT void JNICALL @@ -928,6 +943,24 @@ Avian_java_lang_Runtime_gc collect(t, Heap::MajorCollection); } +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Runtime_nativeLoad +(Thread* t, object, uintptr_t* arguments) +{ + object name = reinterpret_cast(arguments[0]); + PROTECT(t, name); + + unsigned length = stringLength(t, name); + THREAD_RUNTIME_ARRAY(t, char, n, length + 1); + stringChars(t, name, RUNTIME_ARRAY_BODY(n)); + + if (loadLibrary(t, "", RUNTIME_ARRAY_BODY(n), false, true)) { + return 0; + } else { + return reinterpret_cast(name); + } +} + extern "C" JNIEXPORT void JNICALL Avian_java_lang_System_arraycopy (Thread* t, object, uintptr_t* arguments) @@ -1085,27 +1118,19 @@ Avian_java_lang_Math_max } extern "C" JNIEXPORT int64_t JNICALL -Avian_java_lang_Math_floor +Avian_java_lang_Math_cos (Thread*, object, uintptr_t* arguments) { int64_t v; memcpy(&v, arguments, 8); - return doubleToBits(floor(bitsToDouble(v))); + return doubleToBits(cos(bitsToDouble(v))); } extern "C" JNIEXPORT int64_t JNICALL -Avian_java_lang_Math_ceil +Avian_java_lang_Math_sin (Thread*, object, uintptr_t* arguments) { int64_t v; memcpy(&v, arguments, 8); - return doubleToBits(ceil(bitsToDouble(v))); -} - -extern "C" JNIEXPORT int64_t JNICALL -Avian_java_lang_Math_log -(Thread*, object, uintptr_t* arguments) -{ - int64_t v; memcpy(&v, arguments, 8); - return doubleToBits(log(bitsToDouble(v))); + return doubleToBits(sin(bitsToDouble(v))); } extern "C" JNIEXPORT int64_t JNICALL @@ -1213,8 +1238,12 @@ Avian_java_lang_Class_getNameNative object name = className (t, jclassVmClass(t, reinterpret_cast(arguments[0]))); + THREAD_RUNTIME_ARRAY(t, char, s, byteArrayLength(t, name)); + replace('/', '.', RUNTIME_ARRAY_BODY(s), + reinterpret_cast(&byteArrayBody(t, name, 0))); + return reinterpret_cast - (t->m->classpath->makeString(t, name, 0, byteArrayLength(t, name) - 1)); + (makeString(t, "%s", RUNTIME_ARRAY_BODY(s))); } extern "C" JNIEXPORT int64_t JNICALL @@ -1605,17 +1634,6 @@ Avian_libcore_io_Memory_peekByte return *reinterpret_cast(address); } -extern "C" JNIEXPORT void JNICALL -Avian_libcore_io_Memory_peekByteArray -(Thread* t, object, uintptr_t* arguments) -{ - int64_t address; memcpy(&address, arguments, 8); - object array = reinterpret_cast(arguments[2]); - memcpy(&byteArrayBody(t, array, arguments[3]), - reinterpret_cast(address), - arguments[4]); -} - extern "C" JNIEXPORT int64_t JNICALL Avian_java_lang_System_nanoTime (Thread* t, object, uintptr_t*) @@ -1636,3 +1654,19 @@ Avian_java_lang_System_identityHashCode { return objectHash(t, reinterpret_cast(arguments[0])); } + +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_System_mapLibraryName +(Thread* t, object, uintptr_t* arguments) +{ + object original = reinterpret_cast(arguments[0]); + unsigned originalLength = stringUTFLength(t, original); + THREAD_RUNTIME_ARRAY(t, char, originalChars, originalLength); + stringUTFChars + (t, original, RUNTIME_ARRAY_BODY(originalChars), originalLength); + + return reinterpret_cast + (makeString(t, "%s%.*s%s", t->m->system->libraryPrefix(), originalLength, + RUNTIME_ARRAY_BODY(originalChars), + t->m->system->librarySuffix())); +} diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 1b070c53ed..8722be07ef 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -3254,13 +3254,21 @@ registerNatives(Thread* t, uintptr_t* arguments) for (int i = 0; i < methodCount; ++i) { if (methods[i].function) { + // Android's class library sometimes prepends a mysterious "!" + // to the method signature, which we happily ignore: + const char* sig = methods[i].signature; + if (*sig == '!') ++ sig; + object method = findMethodOrNull - (t, jclassVmClass(t, *c), methods[i].name, methods[i].signature); + (t, jclassVmClass(t, *c), methods[i].name, sig); if (method == 0 or (methodFlags(t, method) & ACC_NATIVE) == 0) { // The JNI spec says we must throw a NoSuchMethodError in this // case, but that would prevent using a code shrinker like // ProGuard effectively. Instead, we just ignore it. + + // fprintf(stderr, "not found: %s.%s%s\n", &byteArrayBody(t, className(t, jclassVmClass(t, *c)), 0), methods[i].name, sig); + // abort(t); } else { registerNative(t, method, methods[i].function); } diff --git a/src/main.cpp b/src/main.cpp index f6ae72eec7..53760b753d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -259,7 +259,10 @@ main(int ac, const char** av) JNI_CreateJavaVM(&vm, &env, &vmArgs); JNIEnv* e = static_cast(env); - jclass c = e->FindClass(class_); + jclass c = 0; + if (not e->ExceptionCheck()) { + c = e->FindClass(class_); + } if (jar) { free(const_cast(class_));