--- a/hotspot/make/test/JtregNative.gmk Thu May 14 12:05:32 2015 -0700
+++ b/hotspot/make/test/JtregNative.gmk Sat May 16 13:19:11 2015 -0700
@@ -42,6 +42,8 @@
# Add more directories here when needed.
BUILD_HOTSPOT_JTREG_NATIVE_SRC := \
$(HOTSPOT_TOPDIR)/test/native_sanity \
+ $(HOTSPOT_TOPDIR)/test/runtime/jni/8025979 \
+ $(HOTSPOT_TOPDIR)/test/runtime/jni/8033445 \
#
BUILD_HOTSPOT_JTREG_OUTPUT_DIR := $(BUILD_OUTPUT)/support/test/hotspot/jtreg/native
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp Thu May 14 12:05:32 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp Sat May 16 13:19:11 2015 -0700
@@ -1035,8 +1035,7 @@
// rdx, c_rarg1: BasicObjectLock to be used for locking
//
// Kills:
-// rax
-// rscratch1 (scratch regs)
+// rax, rbx
void InterpreterMacroAssembler::lock_object(Register lock_reg) {
assert(lock_reg == LP64_ONLY(c_rarg1) NOT_LP64(rdx),
"The argument is only for looks. It must be c_rarg1");
@@ -1049,6 +1048,8 @@
Label done;
const Register swap_reg = rax; // Must use rax for cmpxchg instruction
+ const Register tmp_reg = rbx; // Will be passed to biased_locking_enter to avoid a
+ // problematic case where tmp_reg = no_reg.
const Register obj_reg = LP64_ONLY(c_rarg3) NOT_LP64(rcx); // Will contain the oop
const int obj_offset = BasicObjectLock::obj_offset_in_bytes();
@@ -1062,7 +1063,7 @@
movptr(obj_reg, Address(lock_reg, obj_offset));
if (UseBiasedLocking) {
- biased_locking_enter(lock_reg, obj_reg, swap_reg, rscratch1, false, done, &slow_case);
+ biased_locking_enter(lock_reg, obj_reg, swap_reg, tmp_reg, false, done, &slow_case);
}
// Load immediate 1 into swap_reg %rax
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Thu May 14 12:05:32 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Sat May 16 13:19:11 2015 -0700
@@ -1069,15 +1069,8 @@
BiasedLockingCounters* counters) {
assert(UseBiasedLocking, "why call this otherwise?");
assert(swap_reg == rax, "swap_reg must be rax for cmpxchgq");
- LP64_ONLY( assert(tmp_reg != noreg, "tmp_reg must be supplied"); )
- bool need_tmp_reg = false;
- if (tmp_reg == noreg) {
- need_tmp_reg = true;
- tmp_reg = lock_reg;
- assert_different_registers(lock_reg, obj_reg, swap_reg);
- } else {
- assert_different_registers(lock_reg, obj_reg, swap_reg, tmp_reg);
- }
+ assert(tmp_reg != noreg, "tmp_reg must be supplied");
+ assert_different_registers(lock_reg, obj_reg, swap_reg, tmp_reg);
assert(markOopDesc::age_shift == markOopDesc::lock_bits + markOopDesc::biased_lock_bits, "biased locking makes assumptions about bit layout");
Address mark_addr (obj_reg, oopDesc::mark_offset_in_bytes());
Address saved_mark_addr(lock_reg, 0);
@@ -1097,15 +1090,9 @@
null_check_offset = offset();
movptr(swap_reg, mark_addr);
}
- if (need_tmp_reg) {
- push(tmp_reg);
- }
movptr(tmp_reg, swap_reg);
andptr(tmp_reg, markOopDesc::biased_lock_mask_in_place);
cmpptr(tmp_reg, markOopDesc::biased_lock_pattern);
- if (need_tmp_reg) {
- pop(tmp_reg);
- }
jcc(Assembler::notEqual, cas_label);
// The bias pattern is present in the object's header. Need to check
// whether the bias owner and the epoch are both still current.
@@ -1117,9 +1104,6 @@
// simpler.
movptr(saved_mark_addr, swap_reg);
#endif
- if (need_tmp_reg) {
- push(tmp_reg);
- }
if (swap_reg_contains_mark) {
null_check_offset = offset();
}
@@ -1135,9 +1119,6 @@
Register header_reg = swap_reg;
#endif
andptr(header_reg, ~((int) markOopDesc::age_mask_in_place));
- if (need_tmp_reg) {
- pop(tmp_reg);
- }
if (counters != NULL) {
cond_inc32(Assembler::zero,
ExternalAddress((address) counters->biased_lock_entry_count_addr()));
@@ -1180,9 +1161,6 @@
NOT_LP64( movptr(swap_reg, saved_mark_addr); )
andptr(swap_reg,
markOopDesc::biased_lock_mask_in_place | markOopDesc::age_mask_in_place | markOopDesc::epoch_mask_in_place);
- if (need_tmp_reg) {
- push(tmp_reg);
- }
#ifdef _LP64
movptr(tmp_reg, swap_reg);
orptr(tmp_reg, r15_thread);
@@ -1194,9 +1172,6 @@
lock();
}
cmpxchgptr(tmp_reg, mark_addr); // compare tmp_reg and swap_reg
- if (need_tmp_reg) {
- pop(tmp_reg);
- }
// If the biasing toward our thread failed, this means that
// another thread succeeded in biasing it toward itself and we
// need to revoke that bias. The revocation will occur in the
@@ -1220,9 +1195,6 @@
//
// FIXME: due to a lack of registers we currently blow away the age
// bits in this situation. Should attempt to preserve them.
- if (need_tmp_reg) {
- push(tmp_reg);
- }
load_prototype_header(tmp_reg, obj_reg);
#ifdef _LP64
orptr(tmp_reg, r15_thread);
@@ -1235,9 +1207,6 @@
lock();
}
cmpxchgptr(tmp_reg, mark_addr); // compare tmp_reg and swap_reg
- if (need_tmp_reg) {
- pop(tmp_reg);
- }
// If the biasing toward our thread failed, then another thread
// succeeded in biasing it toward itself and we need to revoke that
// bias. The revocation will occur in the runtime in the slow case.
@@ -1263,17 +1232,11 @@
// FIXME: due to a lack of registers we currently blow away the age
// bits in this situation. Should attempt to preserve them.
NOT_LP64( movptr(swap_reg, saved_mark_addr); )
- if (need_tmp_reg) {
- push(tmp_reg);
- }
load_prototype_header(tmp_reg, obj_reg);
if (os::is_MP()) {
lock();
}
cmpxchgptr(tmp_reg, mark_addr); // compare tmp_reg and swap_reg
- if (need_tmp_reg) {
- pop(tmp_reg);
- }
// Fall through to the normal CAS-based lock, because no matter what
// the result of the above CAS, some thread must have succeeded in
// removing the bias bit from the object's header.
--- a/hotspot/src/os/linux/vm/os_linux.cpp Thu May 14 12:05:32 2015 -0700
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Sat May 16 13:19:11 2015 -0700
@@ -5878,14 +5878,6 @@
extern char** environ;
-#ifndef __NR_fork
- #define __NR_fork IA32_ONLY(2) IA64_ONLY(not defined) AMD64_ONLY(57) AARCH64_ONLY(1079)
-#endif
-
-#ifndef __NR_execve
- #define __NR_execve IA32_ONLY(11) IA64_ONLY(1033) AMD64_ONLY(59) AARCH64_ONLY(221)
-#endif
-
// Run the specified command in a separate process. Return its exit value,
// or -1 on failure (e.g. can't fork a new process).
// Unlike system(), this function can be called from signal handler. It
@@ -5893,13 +5885,7 @@
int os::fork_and_exec(char* cmd) {
const char * argv[4] = {"sh", "-c", cmd, NULL};
- // fork() in LinuxThreads/NPTL is not async-safe. It needs to run
- // pthread_atfork handlers and reset pthread library. All we need is a
- // separate process to execve. Make a direct syscall to fork process.
- // On IA64 there's no fork syscall, we have to use fork() and hope for
- // the best...
- pid_t pid = NOT_IA64(syscall(__NR_fork);)
- IA64_ONLY(fork();)
+ pid_t pid = fork();
if (pid < 0) {
// fork failed
@@ -5908,15 +5894,7 @@
} else if (pid == 0) {
// child process
- // execve() in LinuxThreads will call pthread_kill_other_threads_np()
- // first to kill every thread on the thread list. Because this list is
- // not reset by fork() (see notes above), execve() will instead kill
- // every thread in the parent process. We know this is the only thread
- // in the new process, so make a system call directly.
- // IA64 should use normal execve() from glibc to match the glibc fork()
- // above.
- NOT_IA64(syscall(__NR_execve, "/bin/sh", argv, environ);)
- IA64_ONLY(execve("/bin/sh", (char* const*)argv, environ);)
+ execve("/bin/sh", (char* const*)argv, environ);
// execve failed
_exit(-1);
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp Thu May 14 12:05:32 2015 -0700
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp Sat May 16 13:19:11 2015 -0700
@@ -1587,6 +1587,26 @@
result.set_handle(resolved_method, resolved_appendix, resolved_method_type, CHECK);
}
+static void wrap_invokedynamic_exception(TRAPS) {
+ if (HAS_PENDING_EXCEPTION) {
+ if (TraceMethodHandles) {
+ tty->print_cr("invokedynamic throws BSME for " INTPTR_FORMAT, p2i((void *)PENDING_EXCEPTION));
+ PENDING_EXCEPTION->print();
+ }
+ if (PENDING_EXCEPTION->is_a(SystemDictionary::BootstrapMethodError_klass())) {
+ // throw these guys, since they are already wrapped
+ return;
+ }
+ if (!PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) {
+ // intercept only LinkageErrors which might have failed to wrap
+ return;
+ }
+ // See the "Linking Exceptions" section for the invokedynamic instruction in the JVMS.
+ Handle nested_exception(THREAD, PENDING_EXCEPTION);
+ CLEAR_PENDING_EXCEPTION;
+ THROW_CAUSE(vmSymbols::java_lang_BootstrapMethodError(), nested_exception)
+ }
+}
void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
//resolve_pool(<resolved_klass>, method_name, method_signature, current_klass, pool, index, CHECK);
@@ -1600,7 +1620,8 @@
ConstantPoolCacheEntry* cpce = pool->invokedynamic_cp_cache_entry_at(index);
if (cpce->is_f1_null()) {
int pool_index = cpce->constant_pool_index();
- oop bsm_info = pool->resolve_bootstrap_specifier_at(pool_index, CHECK);
+ oop bsm_info = pool->resolve_bootstrap_specifier_at(pool_index, THREAD);
+ wrap_invokedynamic_exception(CHECK);
assert(bsm_info != NULL, "");
// FIXME: Cache this once per BootstrapMethods entry, not once per CONSTANT_InvokeDynamic.
bootstrap_specifier = Handle(THREAD, bsm_info);
@@ -1609,7 +1630,8 @@
methodHandle method( THREAD, cpce->f1_as_method());
Handle appendix( THREAD, cpce->appendix_if_resolved(pool));
Handle method_type(THREAD, cpce->method_type_if_resolved(pool));
- result.set_handle(method, appendix, method_type, CHECK);
+ result.set_handle(method, appendix, method_type, THREAD);
+ wrap_invokedynamic_exception(CHECK);
return;
}
@@ -1640,25 +1662,9 @@
&resolved_appendix,
&resolved_method_type,
THREAD);
- if (HAS_PENDING_EXCEPTION) {
- if (TraceMethodHandles) {
- tty->print_cr("invokedynamic throws BSME for " INTPTR_FORMAT, p2i((void *)PENDING_EXCEPTION));
- PENDING_EXCEPTION->print();
- }
- if (PENDING_EXCEPTION->is_a(SystemDictionary::BootstrapMethodError_klass())) {
- // throw these guys, since they are already wrapped
- return;
- }
- if (!PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) {
- // intercept only LinkageErrors which might have failed to wrap
- return;
- }
- // See the "Linking Exceptions" section for the invokedynamic instruction in the JVMS.
- Handle nested_exception(THREAD, PENDING_EXCEPTION);
- CLEAR_PENDING_EXCEPTION;
- THROW_CAUSE(vmSymbols::java_lang_BootstrapMethodError(), nested_exception)
- }
- result.set_handle(resolved_method, resolved_appendix, resolved_method_type, CHECK);
+ wrap_invokedynamic_exception(CHECK);
+ result.set_handle(resolved_method, resolved_appendix, resolved_method_type, THREAD);
+ wrap_invokedynamic_exception(CHECK);
}
//------------------------------------------------------------------------------------------------------------------------
--- a/hotspot/src/share/vm/utilities/vmError.cpp Thu May 14 12:05:32 2015 -0700
+++ b/hotspot/src/share/vm/utilities/vmError.cpp Sat May 16 13:19:11 2015 -0700
@@ -1062,7 +1062,9 @@
out.print_raw (cmd);
out.print_raw_cr("\" ...");
- os::fork_and_exec(cmd);
+ if (os::fork_and_exec(cmd) < 0) {
+ out.print_cr("os::fork_and_exec failed: %s (%d)", strerror(errno), errno);
+ }
}
// done with OnError
@@ -1147,7 +1149,9 @@
#endif
tty->print_cr("\"%s\"...", cmd);
- os::fork_and_exec(cmd);
+ if (os::fork_and_exec(cmd) < 0) {
+ tty->print_cr("os::fork_and_exec failed: %s (%d)", strerror(errno), errno);
+ }
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/ErrorHandling/TestOnError.java Sat May 16 13:19:11 2015 -0700
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test TestOnError
+ * @summary Test using -XX:OnError=<cmd>
+ * @library /testlibrary
+ * @build TestOnError
+ * @run main TestOnError
+ * @bug 8078470
+ */
+
+import jdk.test.lib.*;
+
+public class TestOnError {
+
+ public static void main(String[] args) throws Exception {
+ if (!Platform.isDebugBuild()) {
+ System.out.println("Test requires a non-product build - skipping");
+ return;
+ }
+
+ String msg = "Test Succeeded";
+
+ // Execute the VM so that a
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+ "-XX:-TransmitErrorReport",
+ "-XX:ErrorHandlerTest=12", // trigger potential SEGV
+ "-XX:OnError=echo " + msg,
+ TestOnError.class.getName());
+
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+ /* Actual output will include:
+ #
+ # -XX:OnError="echo Test Succeeded"
+ # Executing /bin/sh -c "echo Test Succeeded"...
+ Test Succeeded
+
+ So we don't want to match on the "# Executing ..." line, and they
+ both get written to stdout.
+ */
+ output.stdoutShouldMatch("^" + msg); // match start of line only
+ System.out.println("PASSED");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/ErrorHandling/TestOnOutOfMemoryError.java Sat May 16 13:19:11 2015 -0700
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test TestOnOutOfMemoryError
+ * @summary Test using -XX:OnOutOfMemoryError=<cmd>
+ * @library /testlibrary
+ * @build TestOnOutOfMemoryError
+ * @run main TestOnOutOfMemoryError
+ * @bug 8078470
+ */
+
+import jdk.test.lib.*;
+
+public class TestOnOutOfMemoryError {
+
+ public static void main(String[] args) throws Exception {
+ if (args.length == 1) {
+ // This should guarantee to throw:
+ // java.lang.OutOfMemoryError: Requested array size exceeds VM limit
+ Object[] oa = new Object[Integer.MAX_VALUE];
+ return;
+ }
+
+ // else this is the main test
+ String msg = "Test Succeeded";
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+ "-XX:OnOutOfMemoryError=echo " + msg,
+ TestOnOutOfMemoryError.class.getName(),
+ "throwOOME");
+
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+ /* Actual output should look like this:
+ #
+ # java.lang.OutOfMemoryError: Requested array size exceeds VM limit
+ # -XX:OnOutOfMemoryError="echo Test Succeeded"
+ # Executing /bin/sh -c "echo Test Succeeded"...
+ Test Succeeded
+ Exception in thread "main" java.lang.OutOfMemoryError: Requested array size exceeds VM limit
+ at OOME.main(OOME.java:3)
+
+ So we don't want to match on the "# Executing ..." line, and they
+ both get written to stdout.
+ */
+ output.shouldContain("Requested array size exceeds VM limit");
+ output.stdoutShouldMatch("^" + msg); // match start of line only
+ System.out.println("PASSED");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/invokedynamic/BootstrapMethodErrorTest.java Sat May 16 13:19:11 2015 -0700
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8051045
+ * @summary Test that exceptions from invokedynamic are wrapped in BootstrapMethodError
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * @run main BootstrapMethodErrorTest
+ */
+
+import java.lang.reflect.Method;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Handle;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+import jdk.internal.org.objectweb.asm.Opcodes;
+
+public class BootstrapMethodErrorTest extends ClassLoader implements Opcodes {
+
+ @Override
+ public Class findClass(String name) throws ClassNotFoundException {
+ byte[] b;
+ try {
+ b = loadClassData(name);
+ } catch (Throwable th) {
+ throw new ClassNotFoundException("Loading error", th);
+ }
+ return defineClass(name, b, 0, b.length);
+ }
+
+ private byte[] loadClassData(String name) throws Exception {
+ ClassWriter cw = new ClassWriter(0);
+ MethodVisitor mv;
+
+ if (name.equals("C")) {
+ cw.visit(52, ACC_SUPER | ACC_PUBLIC, "C", null, "java/lang/Object", null);
+ {
+ mv = cw.visitMethod(ACC_PRIVATE | ACC_STATIC, "m", "()V", null, null);
+ mv.visitCode();
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(0, 1);
+ mv.visitEnd();
+ }
+ cw.visitEnd();
+ return cw.toByteArray();
+ } else if (name.equals("Exec")) {
+ cw.visit(52, ACC_SUPER | ACC_PUBLIC, "Exec", null, "java/lang/Object", null);
+ {
+ mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "invokeRef", "()V", null, null);
+ mv.visitCode();
+ Handle h = new Handle(H_INVOKESTATIC, "C", "m", "()V");
+ mv.visitInvokeDynamicInsn("C", "()V", h);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+ }
+ cw.visitEnd();
+ return cw.toByteArray();
+ }
+ return null;
+ }
+
+ public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, NoSuchMethodException {
+ new BootstrapMethodErrorTest().test();
+ }
+
+ public void test() throws ClassNotFoundException, IllegalAccessException, NoSuchMethodException {
+ Class.forName("C", true, this);
+ Class<?> exec = Class.forName("Exec", true, this);
+
+ try {
+ exec.getMethod("invokeRef").invoke(null);
+ } catch (Throwable e) {
+ Throwable c = e.getCause();
+ if (c == null) {
+ throw new RuntimeException(
+ "Expected BootstrapMethodError wrapped in an InvocationTargetException but it wasn't wrapped", e);
+ } else if (c instanceof BootstrapMethodError) {
+ // Only way to pass test, all else should throw
+ return;
+ } else {
+ throw new RuntimeException(
+ "Expected BootstrapMethodError but got another Error: "
+ + c.getClass().getName(),
+ c);
+ }
+ }
+ throw new RuntimeException("Expected BootstrapMethodError but no Error at all was thrown");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/jni/8025979/UninitializedStrings.java Sat May 16 13:19:11 2015 -0700
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8025979
+ * @summary
+ * regression tests for 8025922, verify uninitialized strings reference.
+ * Affects:
+ * GetStringLength
+ * GetStringChars
+ * GetStringUTFLength
+ * GetStringUTFChars
+ * @run main/native UninitializedStrings all
+ */
+
+public class UninitializedStrings {
+
+ static {
+ System.loadLibrary("UninitializedStrings");
+ }
+
+ native static void lengthTest();
+
+ native static void charsTest();
+
+ native static void utfLengthTest();
+
+ native static void utfCharsTest();
+
+ /**
+ * @param args the command line arguments
+ * @throws java.lang.Exception
+ */
+ public static void main(String[] args) throws Exception {
+ if (args.length != 1) {
+ throw new RuntimeException("invalid number of input arguments");
+ }
+
+ switch (args[0]) {
+ case "length":
+ lengthTest();
+ break;
+ case "chars":
+ charsTest();
+ break;
+ case "utf_length":
+ utfLengthTest();
+ break;
+ case "utf_chars":
+ utfCharsTest();
+ break;
+ default:
+ lengthTest();
+ charsTest();
+ utfLengthTest();
+ utfCharsTest();
+ break;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/jni/8025979/libUninitializedStrings.c Sat May 16 13:19:11 2015 -0700
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+
+//Method to verify expression and throw java/lang/Exception if it is FALSE
+void Assert(JNIEnv *jni_env, jint expr, const char* message) {
+ if(expr == 0){ //if expr is false
+ (*jni_env)->FatalError(jni_env, message);
+ }
+}
+
+//Method to allocate a java/lang/String object and return jstring as a result
+jstring AllocateString(JNIEnv *jni_env) {
+ jclass classString = NULL;
+ jstring allocatedString = NULL;
+ classString = (*jni_env)->FindClass(jni_env, "java/lang/String");
+ //NULL check
+ Assert(jni_env, (classString != NULL), "class String not found");
+ //allocate object of type java/lang/String
+ allocatedString = (jstring) (*jni_env)->AllocObject(jni_env, classString);
+ //NULL check
+ Assert(jni_env, (allocatedString != NULL), "allocated string is NULL");
+ return allocatedString;
+}
+
+//GetStringLength test
+JNIEXPORT void JNICALL Java_UninitializedStrings_lengthTest
+(JNIEnv *jni_env, jclass cl) {
+ jint stringLength = 0;
+ jstring allocatedString = NULL;
+ //allocate object of type java/lang/String
+ allocatedString = AllocateString(jni_env);
+
+ stringLength = (*jni_env)->GetStringLength(jni_env, allocatedString);
+ Assert(jni_env, (stringLength == 0), "string length must be 0");
+}
+
+//GetStringChars test
+JNIEXPORT void JNICALL Java_UninitializedStrings_charsTest
+(JNIEnv *jni_env, jclass cl) {
+ jint compareRes = 0;
+ const jchar* stringChars = NULL;
+ jstring allocatedString = NULL;
+ //allocate object of type java/lang/String
+ allocatedString = AllocateString(jni_env);
+
+ stringChars = (*jni_env)->GetStringChars(jni_env, allocatedString, NULL);
+ compareRes = (stringChars == NULL);
+ //release stringChars pointer
+ (*jni_env)->ReleaseStringChars(jni_env, allocatedString, stringChars);
+ Assert(jni_env, compareRes, "string chars must be NULL");
+}
+
+//GetStringUTFLength test
+JNIEXPORT void JNICALL Java_UninitializedStrings_utfLengthTest
+(JNIEnv *jni_env, jclass cl) {
+ jint stringLength = 0;
+ jstring allocatedString = NULL;
+ //allocate object of type java/lang/String
+ allocatedString = AllocateString(jni_env);
+
+ stringLength = (*jni_env)->GetStringUTFLength(jni_env, allocatedString);
+ Assert(jni_env, (stringLength == 0), "string utf length must be 0");
+}
+
+//GetStringUTFChars test
+JNIEXPORT void JNICALL Java_UninitializedStrings_utfCharsTest
+(JNIEnv *jni_env, jclass cl) {
+ jint compareRes = 0;
+ const char* stringUtfChars = NULL;
+ jstring allocatedString = NULL;
+ //allocate object of type java/lang/String
+ allocatedString = AllocateString(jni_env);
+
+ stringUtfChars = (*jni_env)->GetStringUTFChars(jni_env, allocatedString, NULL);
+ compareRes = (stringUtfChars == NULL);
+ //release stringUtfChars pointer
+ (*jni_env)->ReleaseStringUTFChars(jni_env, allocatedString, stringUtfChars);
+ Assert(jni_env, compareRes, "string utf chars must be NULL");
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/jni/8033445/DefaultMethods.java Sat May 16 13:19:11 2015 -0700
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8033445
+ * @summary regression tests for 8033445, verify default methods call from JNI
+ * @run main/native DefaultMethods
+ */
+
+interface A {
+
+ default int getOne() {
+ return 1;
+ }
+}
+
+interface B extends A {
+
+}
+
+interface C extends B {
+
+ @Override
+ default int getOne() {
+ return 2;
+ }
+}
+
+abstract class Abstract implements C {
+}
+
+class Impl extends Abstract {
+
+ @Override
+ public int getOne() {
+ return 3;
+ }
+}
+
+class Impl2 extends Impl {
+
+ public static final int expectedValue = 4;
+
+ @Override
+ public int getOne() {
+ return expectedValue;
+ }
+}
+
+public class DefaultMethods {
+
+ static {
+ System.loadLibrary("DefaultMethods");
+ }
+
+ static native int callAndVerify(Impl impl, String className, int expectedResult, int implExpectedResult);
+
+ /**
+ * @param args the command line arguments
+ */
+ public static void main(String[] args) {
+ Impl2 impl2 = new Impl2();
+ if (args.length == 0) {
+ callAndVerify(impl2, "A", 1, Impl2.expectedValue);
+ callAndVerify(impl2, "B", 1, Impl2.expectedValue);
+ callAndVerify(impl2, "C", 2, Impl2.expectedValue);
+ callAndVerify(impl2, "Abstract", 2, Impl2.expectedValue);
+ callAndVerify(impl2, "Impl", 3, Impl2.expectedValue);
+ callAndVerify(impl2, "Impl2", 4, Impl2.expectedValue);
+ } else {
+ verifyAndRun(args, impl2, Impl2.expectedValue);
+ }
+ }
+
+ //Method to verify input arguments and run a specific test with an expected result provided in the args array
+ static void verifyAndRun(String[] args, Impl2 impl, int expectedValue) {
+ if (args.length != 2) {
+ throw new RuntimeException("invalid number of input arguments");
+ }
+
+ String className = args[0];
+ int expectedResult = Integer.parseInt(args[1]);
+
+ callAndVerify(impl, className, expectedResult, expectedValue);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/jni/8033445/libDefaultMethods.c Sat May 16 13:19:11 2015 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <jni.h>
+
+//Default methods call test
+JNIEXPORT void JNICALL
+Java_DefaultMethods_callAndVerify(JNIEnv *env, jclass unused, jobject impl, jstring klass_name, jint expected_result, jint impl_expected_result) {
+
+ jmethodID getOne_id = NULL;
+ jint res = 0;
+ jclass clazz = NULL;
+ const char* class_name = NULL;
+
+ class_name = (*env)->GetStringUTFChars(env, klass_name, NULL);
+
+ clazz = (*env)->FindClass(env, class_name);
+ (*env)->ReleaseStringUTFChars(env, klass_name, class_name);
+ if (clazz == NULL) {
+ (*env)->FatalError(env, "could not find class");
+ }
+
+ getOne_id = (*env)->GetMethodID(env, clazz, "getOne", "()I");
+ if (getOne_id == NULL) {
+ (*env)->FatalError(env, "could not find method");
+ }
+
+ res = (*env)->CallNonvirtualIntMethod(env, impl, clazz, getOne_id);
+
+ if (res != expected_result) {
+ (*env)->FatalError(env, "wrong return value");
+ }
+
+ res = (*env)->CallIntMethod(env, impl, getOne_id);
+
+ if (res != impl_expected_result) {
+ (*env)->FatalError(env, "wrong return value");
+ }
+}