From c012e18a8b8b8217c30de8545c033371350ed8de Mon Sep 17 00:00:00 2001 From: Dain Date: Fri, 2 Dec 2011 15:46:36 -0700 Subject: [PATCH 1/9] Add rudimentary support for http/https protocols in URL. --- classpath/java/net/URL.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/classpath/java/net/URL.java b/classpath/java/net/URL.java index 874eec964b..018be16512 100644 --- a/classpath/java/net/URL.java +++ b/classpath/java/net/URL.java @@ -71,7 +71,11 @@ public final class URL { private static URLStreamHandler findHandler(String protocol) throws MalformedURLException { - if ("resource".equals(protocol)) { + if ("http".equals(protocol)) { + return new avian.file.Handler(); + } else if ("https".equals(protocol)) { + return new avian.file.Handler(); + } else if ("resource".equals(protocol)) { return new avian.resource.Handler(); } else if ("file".equals(protocol)) { return new avian.file.Handler(); From 651b0eb49a271c81a38f99922eb6a7fb7f3a9467 Mon Sep 17 00:00:00 2001 From: Dain Date: Fri, 2 Dec 2011 15:46:36 -0700 Subject: [PATCH 2/9] Add rudimentary support for http/https protocols in URL. --- classpath/java/net/URL.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/classpath/java/net/URL.java b/classpath/java/net/URL.java index eb46c61860..6cd8e92095 100644 --- a/classpath/java/net/URL.java +++ b/classpath/java/net/URL.java @@ -81,7 +81,11 @@ public final class URL { private static URLStreamHandler findHandler(String protocol) throws MalformedURLException { - if ("resource".equals(protocol)) { + if ("http".equals(protocol)) { + return new avian.file.Handler(); + } else if ("https".equals(protocol)) { + return new avian.file.Handler(); + } else if ("resource".equals(protocol)) { return new avian.resource.Handler(); } else if ("file".equals(protocol)) { return new avian.file.Handler(); From 70408ea717f5c1929336d8fd790a735f951f4f96 Mon Sep 17 00:00:00 2001 From: Dain Date: Wed, 4 Jan 2012 12:01:43 -0700 Subject: [PATCH 3/9] Fix a bug in parsing the port value from a URL. --- classpath/java/net/URLStreamHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classpath/java/net/URLStreamHandler.java b/classpath/java/net/URLStreamHandler.java index 5c72deada1..7beacae25e 100644 --- a/classpath/java/net/URLStreamHandler.java +++ b/classpath/java/net/URLStreamHandler.java @@ -38,7 +38,7 @@ public abstract class URLStreamHandler { host = s.substring(0, slash); } else { host = s.substring(0, colon); - port = Integer.parseInt(s.substring(colon + 1), slash); + port = Integer.parseInt(s.substring(colon + 1, slash)); } s = s.substring(slash + 1); } From a6753c3dc3fda03dc9948e21911fdb79b0f35881 Mon Sep 17 00:00:00 2001 From: Dain Date: Thu, 19 Jan 2012 15:10:45 -0700 Subject: [PATCH 4/9] Request a share mode of both reading and writing for RandomAccessFile open. This change allows reading and writing to happen concurrently on the file on Windows. --- classpath/java-io.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index 9175c6e978..bd399b46de 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -178,7 +178,8 @@ inline Mapping* map(JNIEnv* e, string_t path) { Mapping* result = 0; - HANDLE file = CreateFileW(path, FILE_READ_DATA, FILE_SHARE_READ, 0, + HANDLE file = CreateFileW(path, FILE_READ_DATA, + FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); if (file != INVALID_HANDLE_VALUE) { unsigned size = GetFileSize(file, 0); From edc768f8374ddd31206caafe222306c6fa9a5e30 Mon Sep 17 00:00:00 2001 From: Joshua Warner Date: Thu, 9 Feb 2012 14:04:42 -0700 Subject: [PATCH 5/9] implement File.setExecutable(), File.canExecute(), and File.createTempFile() --- classpath/java-io.cpp | 64 +++++++++++++++++++++++++++++++++++++ classpath/java/io/File.java | 48 ++++++++++++++++++++++++++++ makefile | 2 +- test/Files.java | 14 ++++++++ 4 files changed, 127 insertions(+), 1 deletion(-) diff --git a/classpath/java-io.cpp b/classpath/java-io.cpp index 9175c6e978..c851a0d75a 100644 --- a/classpath/java-io.cpp +++ b/classpath/java-io.cpp @@ -32,10 +32,13 @@ # define STAT _wstat # define STRUCT_STAT struct _stat # define MKDIR(path, mode) _wmkdir(path) +# define CHMOD(path, mode) _wchmod(path, mode) # define UNLINK _wunlink # define RENAME _wrename # define OPEN_MASK O_BINARY +# define CHECK_X_OK R_OK + # ifdef _MSC_VER # define S_ISREG(x) ((x) & _S_IFREG) # define S_ISDIR(x) ((x) & _S_IFDIR) @@ -67,11 +70,14 @@ typedef wchar_t char_t; # define STAT stat # define STRUCT_STAT struct stat # define MKDIR mkdir +# define CHMOD chmod # define CREAT creat # define UNLINK unlink # define RENAME rename # define OPEN_MASK 0 +# define CHECK_X_OK X_OK + # define GET_CHARS GetStringUTFChars # define RELEASE_CHARS ReleaseStringUTFChars @@ -442,6 +448,64 @@ Java_java_io_File_canWrite(JNIEnv* e, jclass, jstring path) return false; } +extern "C" JNIEXPORT jboolean JNICALL +Java_java_io_File_canExecute(JNIEnv* e, jclass, jstring path) +{ + string_t chars = getChars(e, path); + if (chars) { + int r = ACCESS(chars, CHECK_X_OK); + releaseChars(e, path, chars); + return (r == 0); + } + return false; +} + +#ifndef PLATFORM_WINDOWS +extern "C" JNIEXPORT jboolean JNICALL +Java_java_io_File_setExecutable(JNIEnv* e, jclass, jstring path, jboolean executable, jboolean ownerOnly) +{ + string_t chars = getChars(e, path); + if(chars) { + jboolean v; + int mask; + if(ownerOnly) { + mask = S_IXUSR; + } else { + mask = S_IXUSR | S_IXGRP | S_IXOTH; + } + + STRUCT_STAT s; + int r = STAT(chars, &s); + if(r == 0) { + int mode = s.st_mode; + if(executable) { + mode |= mask; + } else { + mode &= ~mask; + } + if(CHMOD(chars, mode) != 0) { + v = false; + } else { + v = true; + } + } else { + v = false; + } + releaseChars(e, path, chars); + return v; + } + return false; +} + +#else // ifndef PLATFORM_WINDOWS + +extern "C" JNIEXPORT jboolean JNICALL +Java_java_io_File_setExecutable(JNIEnv*, jclass, jstring, jboolean executable, jboolean) +{ + return executable; +} + +#endif extern "C" JNIEXPORT jboolean JNICALL Java_java_io_File_rename(JNIEnv* e, jclass, jstring old, jstring new_) diff --git a/classpath/java/io/File.java b/classpath/java/io/File.java index 9342627bd5..bfae0da9b6 100644 --- a/classpath/java/io/File.java +++ b/classpath/java/io/File.java @@ -35,6 +35,38 @@ public class File implements Serializable { this(parent.getPath() + FileSeparator + child); } + public static File createTempFile(String prefix, String suffix) { + return createTempFile(prefix, suffix, null); + } + + public static File createTempFile(String prefix, String suffix, File directory) { + if(directory == null) { + directory = new File(System.getProperty("java.io.tmpdir")); + } + if(suffix == null) { + suffix = ".tmp"; + } + File ret; + long state = System.currentTimeMillis(); + + do { + ret = generateFile(directory, prefix, state, suffix); + state *= 7; + state += 3; + } while(ret == null); + ret.createNewFile(); + return ret; + } + + private static File generateFile(File directory, String prefix, long state, String suffix) { + File ret = new File(directory, prefix + state + suffix); + if(ret.exists()) { + return null; + } else { + return ret; + } + } + private static String normalize(String path) { if ("\\".equals(FileSeparator)) { return path.replace('/', '\\'); @@ -76,6 +108,22 @@ public class File implements Serializable { public boolean canWrite() { return canWrite(path); } + + private static native boolean canExecute(String path); + + public boolean canExecute() { + return canExecute(path); + } + + private static native boolean setExecutable(String path, boolean executable, boolean ownerOnly); + + public boolean setExecutable(boolean executable) { + return setExecutable(executable, true); + } + + public boolean setExecutable(boolean executable, boolean ownerOnly) { + return setExecutable(path, executable, ownerOnly); + } public String getName() { int index = path.lastIndexOf(FileSeparator); diff --git a/makefile b/makefile index 218216f537..b83cfabad5 100755 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ -MAKEFLAGS = -s +#MAKEFLAGS = -s name = avian version = 0.5 diff --git a/test/Files.java b/test/Files.java index 6bf01dadaa..7661e79018 100644 --- a/test/Files.java +++ b/test/Files.java @@ -20,10 +20,24 @@ public class Files { } } + + private static void setExecutableTestWithPermissions(boolean executable) { + File file = File.createTempFile("avian.", null); + file.setExecutable(executable); + if (executable) { + expect(file.canExecute()); + } else { + // Commented out because this will fail on Windows - both on Avian and on OpenJDK + // The implementation for Windows considers canExecute() to be the same as canRead() + // expect(!file.canExecute()); + } + } public static void main(String[] args) { isAbsoluteTest(true); isAbsoluteTest(false); + setExecutableTestWithPermissions(true); + setExecutableTestWithPermissions(false); } } From 9fe2d69b06497efd672b48391c90c5ec45f2b588 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 14 Feb 2012 13:01:00 -0700 Subject: [PATCH 6/9] improve seed generation in java.util.Random The previous code caused frequent seed collisions for successive calls to the no-arg constructor, even for single threaded workloads. This patch should avoid such collisions in both single and multi-threaded cases. --- classpath/java/util/Random.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/classpath/java/util/Random.java b/classpath/java/util/Random.java index 856f30424a..311230f538 100644 --- a/classpath/java/util/Random.java +++ b/classpath/java/util/Random.java @@ -13,7 +13,9 @@ package java.util; public class Random { private static final long Mask = 0x5DEECE66DL; - private static long nextSeed = 0; + private static final long InitialSeed = 123456789987654321L; + + private static long nextSeed = InitialSeed; private long seed; @@ -22,7 +24,13 @@ public class Random { } public Random() { - setSeed((nextSeed++) ^ System.currentTimeMillis()); + synchronized (Random.class) { + setSeed(nextSeed ^ System.currentTimeMillis()); + nextSeed *= 123456789987654321L; + if (nextSeed == 0) { + nextSeed = InitialSeed; + } + } } public void setSeed(long seed) { From e849d8f9c928fbaea037aa89c436581b9c59e20b Mon Sep 17 00:00:00 2001 From: Seth Goings Date: Mon, 20 Feb 2012 16:25:37 -0700 Subject: [PATCH 7/9] Updates to .gitignore to get rid of any possibility of checking in binaries in lib/distrib directories, and generalized method of setting location of win32 and win64 libs. --- .gitignore | 2 ++ makefile | 12 +++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 8028923871..201518bb12 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ build .project .settings bin +/lib +/distrib diff --git a/makefile b/makefile index 218216f537..67d6b49b66 100755 --- a/makefile +++ b/makefile @@ -51,6 +51,8 @@ test-build = $(build)/test src = src classpath-src = classpath test = test +win32 ?= $(root)/win32 +win64 ?= $(root)/win64 classpath = avian @@ -361,8 +363,8 @@ endif ifeq ($(platform),windows) bootimage-cflags += -DTARGET_PLATFORM_WINDOWS - inc = "$(root)/win32/include" - lib = "$(root)/win32/lib" + inc = "$(win32)/include" + lib = "$(win32)/lib" embed-prefix = c:/avian-embedded @@ -411,8 +413,8 @@ ifeq ($(platform),windows) ar = x86_64-w64-mingw32-ar ranlib = x86_64-w64-mingw32-ranlib strip = x86_64-w64-mingw32-strip - inc = "$(root)/win64/include" - lib = "$(root)/win64/lib" + inc = "$(win64)/include" + lib = "$(win64)/lib" endif endif @@ -469,7 +471,7 @@ build-ld := $(build-cc) ifdef msvc windows-java-home := $(shell cygpath -m "$(JAVA_HOME)") - zlib := $(shell cygpath -m "$(root)/win32/msvc") + zlib := $(shell cygpath -m "$(win32)/msvc") cxx = "$(msvc)/BIN/cl.exe" cc = $(cxx) ld = "$(msvc)/BIN/link.exe" From b5fda8ee13979f16621d541a41dfdff9ddabe42f Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 27 Feb 2012 13:38:47 -0700 Subject: [PATCH 8/9] use avian.http.Handler for http(s) URLs, not avian.file.Handler --- classpath/avian/http/Handler.java | 26 ++++++++++++++++++++++++++ classpath/java/net/URL.java | 6 ++---- makefile | 2 +- 3 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 classpath/avian/http/Handler.java diff --git a/classpath/avian/http/Handler.java b/classpath/avian/http/Handler.java new file mode 100644 index 0000000000..70e7cea519 --- /dev/null +++ b/classpath/avian/http/Handler.java @@ -0,0 +1,26 @@ +/* Copyright (c) 2012, 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.http; + +import java.net.URL; +import java.net.URLStreamHandler; +import java.net.URLConnection; +import java.io.IOException; +import java.io.FileNotFoundException; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; + +public class Handler extends URLStreamHandler { + protected URLConnection openConnection(URL url) { + throw new UnsupportedOperationException(); + } +} diff --git a/classpath/java/net/URL.java b/classpath/java/net/URL.java index 6cd8e92095..d1c97450ec 100644 --- a/classpath/java/net/URL.java +++ b/classpath/java/net/URL.java @@ -81,10 +81,8 @@ public final class URL { private static URLStreamHandler findHandler(String protocol) throws MalformedURLException { - if ("http".equals(protocol)) { - return new avian.file.Handler(); - } else if ("https".equals(protocol)) { - return new avian.file.Handler(); + if ("http".equals(protocol) || "https".equals(protocol)) { + return new avian.http.Handler(); } else if ("resource".equals(protocol)) { return new avian.resource.Handler(); } else if ("file".equals(protocol)) { diff --git a/makefile b/makefile index f72b091054..147bb6f3de 100755 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ -#MAKEFLAGS = -s +MAKEFLAGS = -s name = avian version = 0.5 From c6ac66e45ad9a08f6de48047ee9c57d406e86f98 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 27 Feb 2012 18:16:01 -0700 Subject: [PATCH 9/9] fix bug in isAssignableFrom such that primitive array types were considered to be subclasses of the Object array type --- src/machine.cpp | 7 +++++-- src/machine.h | 2 ++ test/Misc.java | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/machine.cpp b/src/machine.cpp index 33d1599f20..f05ba92d39 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -869,9 +869,10 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) parsePoolEntry(t, s, index, pool, ci); parsePoolEntry(t, s, index, pool, nti); - + object class_ = referenceName(t, singletonObject(t, pool, ci)); object nameAndType = singletonObject(t, pool, nti); + object value = makeReference (t, class_, pairFirst(t, nameAndType), pairSecond(t, nameAndType)); set(t, pool, SingletonBody + (i * BytesPerWord), value); @@ -3228,7 +3229,9 @@ isAssignableFrom(Thread* t, object a, object b) return isAssignableFrom (t, classStaticTable(t, a), classStaticTable(t, b)); } - } else { + } else if ((classVmFlags(t, a) & PrimitiveFlag) + == (classVmFlags(t, b) & PrimitiveFlag)) + { for (; b; b = classSuper(t, b)) { if (b == a) { return true; diff --git a/src/machine.h b/src/machine.h index 96c853624f..83ea2577a4 100644 --- a/src/machine.h +++ b/src/machine.h @@ -2164,6 +2164,8 @@ hashTaken(Thread*, object o) inline unsigned baseSize(Thread* t, object o, object class_) { + assert(t, classFixedSize(t, class_) >= BytesPerWord); + return ceiling(classFixedSize(t, class_), BytesPerWord) + ceiling(classArrayElementSize(t, class_) * cast(o, classFixedSize(t, class_) - BytesPerWord), diff --git a/test/Misc.java b/test/Misc.java index 7ff2f25378..450f23d2b0 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -235,5 +235,7 @@ public class Misc { System.out.println(75.62); System.out.println(75.62d); System.out.println(new char[] { 'h', 'i' }); + + expect(! (((Object) new int[0]) instanceof Object[])); } }