From 5827c450c96cc0ee6edf4e7f2ff095ad1bca3c1a Mon Sep 17 00:00:00 2001 From: Simon Ochsenreither Date: Wed, 6 Nov 2013 14:05:25 +0100 Subject: [PATCH 1/7] Adds separatorChar and pathSeparatorChar fields to File ... ... and fixes a bug which caused path.separator to always return null. --- classpath/java-lang.cpp | 4 ++++ classpath/java/io/File.java | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/classpath/java-lang.cpp b/classpath/java-lang.cpp index 93ac9a1afd..8b6c11156a 100644 --- a/classpath/java-lang.cpp +++ b/classpath/java-lang.cpp @@ -653,6 +653,8 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, r = e->NewStringUTF("\r\n"); } else if (strcmp(chars, "file.separator") == 0) { r = e->NewStringUTF("\\"); + } else if (strcmp(chars, "path.separator") == 0) { + r = e->NewStringUTF(";"); } else if (strcmp(chars, "os.name") == 0) { # if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) r = e->NewStringUTF("Windows"); @@ -726,6 +728,8 @@ Java_java_lang_System_getProperty(JNIEnv* e, jclass, jstring name, r = e->NewStringUTF("\n"); } else if (strcmp(chars, "file.separator") == 0) { r = e->NewStringUTF("/"); + } else if (strcmp(chars, "path.separator") == 0) { + r = e->NewStringUTF(":"); } else if (strcmp(chars, "os.name") == 0) { #ifdef __APPLE__ r = e->NewStringUTF("Mac OS X"); diff --git a/classpath/java/io/File.java b/classpath/java/io/File.java index 8eceed4b71..55a142db8d 100644 --- a/classpath/java/io/File.java +++ b/classpath/java/io/File.java @@ -16,11 +16,15 @@ public class File implements Serializable { public static final String separator = FileSeparator; + public static final char separatorChar = FileSeparator.charAt(0); + private static final String PathSeparator = System.getProperty("path.separator"); public static final String pathSeparator = PathSeparator; + public static final char pathSeparatorChar = PathSeparator.charAt(0); + // static { // System.loadLibrary("natives"); // } From efb3ef9b51e6e71176f0d3bf6ea1dadfc997b149 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 29 Oct 2013 16:36:50 -0500 Subject: [PATCH 2/7] Initialize the context class loader to the app class loader Previously, we initialized it to the boot class loader, but that is inconsistent with Java; if compiling against OpenJDK's class library, the context class loader is therefore initialized to the app class loader, too. Signed-off-by: Johannes Schindelin --- src/classpath-avian.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index 320e6158a1..6d2c5afeb6 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -53,7 +53,7 @@ class MyClasspath : public Classpath { return vm::makeThread (t, 0, 0, 0, 0, NewState, NormalPriority, 0, 0, 0, - root(t, Machine::BootLoader), 0, 0, group, 0); + root(t, Machine::AppLoader), 0, 0, group, 0); } virtual object From dba8d39e633f92acef1b0754a9a0c3104f13d76c Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 31 Oct 2013 17:01:33 -0500 Subject: [PATCH 3/7] Implement Class#getDeclaredClasses Signed-off-by: Johannes Schindelin --- classpath/avian/ClassAddendum.java | 2 +- classpath/avian/InnerClassReference.java | 18 +++++++++++++ classpath/java/lang/Class.java | 32 ++++++++++++++++++++++++ src/types.def | 6 +---- test/Reflection.java | 11 ++++++++ 5 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 classpath/avian/InnerClassReference.java diff --git a/classpath/avian/ClassAddendum.java b/classpath/avian/ClassAddendum.java index c1d3550250..c445b86dbd 100644 --- a/classpath/avian/ClassAddendum.java +++ b/classpath/avian/ClassAddendum.java @@ -12,7 +12,7 @@ package avian; public class ClassAddendum extends Addendum { public Object[] interfaceTable; - public Object[] innerClassTable; + public InnerClassReference[] innerClassTable; public Object[] methodTable; public Object enclosingClass; public Object enclosingMethod; diff --git a/classpath/avian/InnerClassReference.java b/classpath/avian/InnerClassReference.java new file mode 100644 index 0000000000..73a3895b74 --- /dev/null +++ b/classpath/avian/InnerClassReference.java @@ -0,0 +1,18 @@ +/* Copyright (c) 2008-2013, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +public class InnerClassReference { + public byte[] inner; + public byte[] outer; + public byte[] name; + public short flags; +} diff --git a/classpath/java/lang/Class.java b/classpath/java/lang/Class.java index 255884ef51..70bd4dc81e 100644 --- a/classpath/java/lang/Class.java +++ b/classpath/java/lang/Class.java @@ -15,6 +15,7 @@ import avian.ClassAddendum; import avian.AnnotationInvocationHandler; import avian.SystemClassLoader; import avian.Classes; +import avian.InnerClassReference; import java.lang.reflect.Constructor; import java.lang.reflect.Method; @@ -402,6 +403,37 @@ public final class Class implements Type, AnnotatedElement { } } + public Class[] getDeclaredClasses() { + if (vmClass.addendum == null || vmClass.addendum.innerClassTable == null) { + return new Class[0]; + } + InnerClassReference[] table = vmClass.addendum.innerClassTable; + Class[] result = new Class[table.length]; + int counter = 0; + String prefix = getName().replace('.', '/') + "$"; + for (int i = 0; i < table.length; ++i) try { + byte[] inner = table[i].inner; + if (inner != null && inner.length > 1) { + String name = new String(inner, 0, inner.length - 1); + if (name.startsWith(prefix)) { + Class innerClass = getClassLoader().loadClass(name); + result[counter++] = innerClass; + } + } + } catch (ClassNotFoundException e) { + throw new Error(e); + } + if (counter == result.length) { + return result; + } + if (counter == 0) { + return new Class[0]; + } + Class[] result2 = new Class[counter]; + System.arraycopy(result, 0, result2, 0, counter); + return result2; + } + public ClassLoader getClassLoader() { return vmClass.loader; } diff --git a/src/types.def b/src/types.def index c7731f648d..7bb8bc1fb0 100644 --- a/src/types.def +++ b/src/types.def @@ -156,11 +156,7 @@ (void* value) (object next)) -(type innerClassReference - (object inner) - (object outer) - (object name) - (int16_t flags)) +(type innerClassReference avian/InnerClassReference) (type continuationContext (object next) diff --git a/test/Reflection.java b/test/Reflection.java index 23d34abf7e..306b6959c2 100644 --- a/test/Reflection.java +++ b/test/Reflection.java @@ -38,7 +38,18 @@ public class Reflection { if (! v) throw new RuntimeException(); } + private static class Hello { } + + private static void innerClasses() throws Exception { + Class c = Reflection.class; + Class[] inner = c.getDeclaredClasses(); + expect(1 == inner.length); + expect(Hello.class == inner[0]); + } + public static void main(String[] args) throws Exception { + innerClasses(); + Class system = Class.forName("java.lang.System"); Field out = system.getDeclaredField("out"); Class output = Class.forName("java.io.PrintStream"); From 874bf4ef4c95083b8f8cfa7ded0a826be91fd72c Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 25 Oct 2013 15:37:17 -0500 Subject: [PATCH 4/7] Initialize Logger instances to the 'INFO' level by default ... otherwise, logging would throw an exception when trying to determine whether the current level allows the message to be logged. Signed-off-by: Johannes Schindelin --- classpath/java/util/logging/Logger.java | 1 + 1 file changed, 1 insertion(+) diff --git a/classpath/java/util/logging/Logger.java b/classpath/java/util/logging/Logger.java index 62ac923efc..ae60507a4e 100644 --- a/classpath/java/util/logging/Logger.java +++ b/classpath/java/util/logging/Logger.java @@ -32,6 +32,7 @@ public class Logger { if (name.equals("")) return rootLogger; Logger logger = new Logger(name); logger.parent = rootLogger; + logger.setLevel(Level.INFO); return logger; } From 6159f5cd3cc88315eff4761743cdc57ea43309ed Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 28 Oct 2013 11:37:46 -0500 Subject: [PATCH 5/7] Support Logger#log(Level,String,Object) Signed-off-by: Johannes Schindelin --- classpath/java/util/logging/Logger.java | 24 ++++++++++++++++++++++++ test/Logging.java | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/classpath/java/util/logging/Logger.java b/classpath/java/util/logging/Logger.java index ae60507a4e..1236821061 100644 --- a/classpath/java/util/logging/Logger.java +++ b/classpath/java/util/logging/Logger.java @@ -80,6 +80,30 @@ public class Logger { log(level, Method.getCaller(), message, exception); } + public void log(Level level, String message, Object param) { + log(level, Method.getCaller(), replaceParameters(message, param), null); + } + + private static String replaceParameters(String message, Object... params) { + StringBuilder builder = new StringBuilder(); + int offset = 0; + for (int i = 0; i < params.length; ++i) { + int curly = message.indexOf("{}", offset); + if (curly < 0) { + break; + } + if (curly > offset) { + builder.append(message, offset, curly); + } + offset = curly + 2; + builder.append(params[i]); + } + if (message.length() > offset) { + builder.append(message, offset, message.length()); + } + return builder.toString(); + } + public void logp(Level level, String sourceClass, String sourceMethod, String msg) { if (!isLoggable(level)) { return; diff --git a/test/Logging.java b/test/Logging.java index ec88986f89..c7e5b4d6ae 100644 --- a/test/Logging.java +++ b/test/Logging.java @@ -66,7 +66,7 @@ public class Logging { public void run() { log.info("Started run"); a(); - log.info("Ended run"); + log.log(Level.INFO, "Ended {}!", "run"); } private void a() { From f8028c98644780b03038377147070862d9bf1274 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 29 Oct 2013 10:19:17 -0500 Subject: [PATCH 6/7] Add a dummy implementation of EmptyStackException Signed-off-by: Johannes Schindelin --- classpath/java/util/EmptyStackException.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 classpath/java/util/EmptyStackException.java diff --git a/classpath/java/util/EmptyStackException.java b/classpath/java/util/EmptyStackException.java new file mode 100644 index 0000000000..ccc2a7917d --- /dev/null +++ b/classpath/java/util/EmptyStackException.java @@ -0,0 +1,13 @@ +/* Copyright (c) 2008-2013, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util; + +public class EmptyStackException extends RuntimeException {} From 6a7c03aef93ae96efe6f44f3e109144563d5bc15 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 2 Nov 2013 00:23:42 -0500 Subject: [PATCH 7/7] Implement the Math#signum method Signed-off-by: Johannes Schindelin --- classpath/java/lang/Math.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/classpath/java/lang/Math.java b/classpath/java/lang/Math.java index 05f98fa900..6c9273e033 100644 --- a/classpath/java/lang/Math.java +++ b/classpath/java/lang/Math.java @@ -75,6 +75,14 @@ public final class Math { return (int) Math.floor(v + 0.5); } + public static double signum(double d) { + return d > 0 ? +1.0 : d < 0 ? -1.0 : 0; + } + + public static float signum(float f) { + return f > 0 ? +1.0f : f < 0 ? -1.0f : 0; + } + public static double random() { return random.nextDouble(); }