--- a/hotspot/src/share/vm/classfile/javaClasses.cpp Fri Jul 11 09:14:21 2014 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Sat Jul 12 01:26:13 2014 -0700
@@ -1239,6 +1239,16 @@
}
+// Return Symbol for detailed_message or NULL
+Symbol* java_lang_Throwable::detail_message(oop throwable) {
+ PRESERVE_EXCEPTION_MARK; // Keep original exception
+ oop detailed_message = java_lang_Throwable::message(throwable);
+ if (detailed_message != NULL) {
+ return java_lang_String::as_symbol(detailed_message, THREAD);
+ }
+ return NULL;
+}
+
void java_lang_Throwable::set_message(oop throwable, oop value) {
throwable->obj_field_put(detailMessage_offset, value);
}
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp Fri Jul 11 09:14:21 2014 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp Sat Jul 12 01:26:13 2014 -0700
@@ -520,6 +520,7 @@
static oop message(oop throwable);
static oop message(Handle throwable);
static void set_message(oop throwable, oop value);
+ static Symbol* detail_message(oop throwable);
static void print_stack_element(outputStream *st, Handle mirror, int method,
int version, int bci);
static void print_stack_element(outputStream *st, methodHandle method, int bci);
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Fri Jul 11 09:14:21 2014 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Sat Jul 12 01:26:13 2014 -0700
@@ -430,9 +430,18 @@
// tracing
if (TraceExceptions) {
- ttyLocker ttyl;
ResourceMark rm(thread);
- tty->print_cr("Exception <%s> (" INTPTR_FORMAT ")", h_exception->print_value_string(), (address)h_exception());
+ Symbol* message = java_lang_Throwable::detail_message(h_exception());
+ ttyLocker ttyl; // Lock after getting the detail message
+ if (message != NULL) {
+ tty->print_cr("Exception <%s: %s> (" INTPTR_FORMAT ")",
+ h_exception->print_value_string(), message->as_C_string(),
+ (address)h_exception());
+ } else {
+ tty->print_cr("Exception <%s> (" INTPTR_FORMAT ")",
+ h_exception->print_value_string(),
+ (address)h_exception());
+ }
tty->print_cr(" thrown in interpreter method <%s>", h_method->print_value_string());
tty->print_cr(" at bci %d for thread " INTPTR_FORMAT, current_bci, thread);
}
--- a/hotspot/src/share/vm/interpreter/oopMapCache.cpp Fri Jul 11 09:14:21 2014 -0700
+++ b/hotspot/src/share/vm/interpreter/oopMapCache.cpp Sat Jul 12 01:26:13 2014 -0700
@@ -244,10 +244,8 @@
method()->print_value();
tty->print(" @ %d = [%d] { ", bci(), n);
for (int i = 0; i < n; i++) {
-#ifdef ENABLE_ZAP_DEAD_LOCALS
if (is_dead(i)) tty->print("%d+ ", i);
else
-#endif
if (is_oop(i)) tty->print("%d ", i);
}
tty->print_cr("}");
@@ -402,13 +400,11 @@
value |= (mask << oop_bit_number );
}
- #ifdef ENABLE_ZAP_DEAD_LOCALS
// set dead bit
if (!cell->is_live()) {
value |= (mask << dead_bit_number);
assert(!cell->is_reference(), "dead value marked as oop");
}
- #endif
}
// make sure last word is stored
--- a/hotspot/src/share/vm/interpreter/oopMapCache.hpp Fri Jul 11 09:14:21 2014 -0700
+++ b/hotspot/src/share/vm/interpreter/oopMapCache.hpp Sat Jul 12 01:26:13 2014 -0700
@@ -66,19 +66,15 @@
public:
enum {
- N = 2, // the number of words reserved
+ N = 4, // the number of words reserved
// for inlined mask storage
small_mask_limit = N * BitsPerWord, // the maximum number of bits
// available for small masks,
// small_mask_limit can be set to 0
// for testing bit_mask allocation
-#ifdef ENABLE_ZAP_DEAD_LOCALS
bits_per_entry = 2,
dead_bit_number = 1,
-#else
- bits_per_entry = 1,
-#endif
oop_bit_number = 0
};
@@ -119,10 +115,6 @@
void set_expression_stack_size(int sz) { _expression_stack_size = sz; }
-#ifdef ENABLE_ZAP_DEAD_LOCALS
- bool is_dead(int offset) const { return (entry_at(offset) & (1 << dead_bit_number)) != 0; }
-#endif
-
// Lookup
bool match(methodHandle method, int bci) const { return _method == method() && _bci == bci; }
bool is_empty() const;
@@ -144,6 +136,7 @@
void print() const;
int number_of_entries() const { return mask_size() / bits_per_entry; }
+ bool is_dead(int offset) const { return (entry_at(offset) & (1 << dead_bit_number)) != 0; }
bool is_oop (int offset) const { return (entry_at(offset) & (1 << oop_bit_number )) != 0; }
int expression_stack_size() const { return _expression_stack_size; }
--- a/hotspot/src/share/vm/oops/constantPool.cpp Fri Jul 11 09:14:21 2014 -0700
+++ b/hotspot/src/share/vm/oops/constantPool.cpp Sat Jul 12 01:26:13 2014 -0700
@@ -520,13 +520,9 @@
Symbol* ConstantPool::exception_message(constantPoolHandle this_cp, int which, constantTag tag, oop pending_exception) {
// Dig out the detailed message to reuse if possible
- Symbol* message = NULL;
- oop detailed_message = java_lang_Throwable::message(pending_exception);
- if (detailed_message != NULL) {
- message = java_lang_String::as_symbol_or_null(detailed_message);
- if (message != NULL) {
- return message;
- }
+ Symbol* message = java_lang_Throwable::detail_message(pending_exception);
+ if (message != NULL) {
+ return message;
}
// Return specific message for the tag
--- a/hotspot/src/share/vm/prims/jvmtiImpl.cpp Fri Jul 11 09:14:21 2014 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiImpl.cpp Sat Jul 12 01:26:13 2014 -0700
@@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "classfile/systemDictionary.hpp"
#include "interpreter/interpreter.hpp"
+#include "interpreter/oopMapCache.hpp"
#include "jvmtifiles/jvmtiEnv.hpp"
#include "memory/resourceArea.hpp"
#include "oops/instanceKlass.hpp"
@@ -744,6 +745,13 @@
}
void VM_GetOrSetLocal::doit() {
+ InterpreterOopMap oop_mask;
+ _jvf->method()->mask_for(_jvf->bci(), &oop_mask);
+ if (oop_mask.is_dead(_index)) {
+ // The local can be invalid and uninitialized in the scope of current bci
+ _result = JVMTI_ERROR_INVALID_SLOT;
+ return;
+ }
if (_set) {
// Force deoptimization of frame if compiled because it's
// possible the compiler emitted some locals as constant values,
--- a/hotspot/src/share/vm/runtime/atomic.hpp Fri Jul 11 09:14:21 2014 -0700
+++ b/hotspot/src/share/vm/runtime/atomic.hpp Sat Jul 12 01:26:13 2014 -0700
@@ -35,6 +35,18 @@
// can provide an alternative action if not - see supports_cx8() for
// a means to test availability.
+ // The memory operations that are mentioned with each of the atomic
+ // function families come from src/share/vm/runtime/orderAccess.hpp,
+ // e.g., <fence> is described in that file and is implemented by the
+ // OrderAccess::fence() function. See that file for the gory details
+ // on the Memory Access Ordering Model.
+
+ // All of the atomic operations that imply a read-modify-write action
+ // guarantee a two-way memory barrier across that operation. Historically
+ // these semantics reflect the strength of atomic operations that are
+ // provided on SPARC/X86. We assume that strength is necessary unless
+ // we can prove that a weaker form is sufficiently safe.
+
// Atomically store to a location
inline static void store (jbyte store_value, jbyte* dest);
inline static void store (jshort store_value, jshort* dest);
@@ -55,7 +67,8 @@
// See comment above about using jlong atomics on 32-bit platforms
inline static jlong load(volatile jlong* src);
- // Atomically add to a location, return updated value
+ // Atomically add to a location. Returns updated value. add*() provide:
+ // <fence> add-value-to-dest <membar StoreLoad|StoreStore>
inline static jint add (jint add_value, volatile jint* dest);
inline static size_t add (size_t add_value, volatile size_t* dest);
inline static intptr_t add_ptr(intptr_t add_value, volatile intptr_t* dest);
@@ -63,30 +76,35 @@
// See comment above about using jlong atomics on 32-bit platforms
static jlong add (jlong add_value, volatile jlong* dest);
- // Atomically increment location
+ // Atomically increment location. inc*() provide:
+ // <fence> increment-dest <membar StoreLoad|StoreStore>
inline static void inc (volatile jint* dest);
static void inc (volatile jshort* dest);
inline static void inc (volatile size_t* dest);
inline static void inc_ptr(volatile intptr_t* dest);
inline static void inc_ptr(volatile void* dest);
- // Atomically decrement a location
+ // Atomically decrement a location. dec*() provide:
+ // <fence> decrement-dest <membar StoreLoad|StoreStore>
inline static void dec (volatile jint* dest);
static void dec (volatile jshort* dest);
inline static void dec (volatile size_t* dest);
inline static void dec_ptr(volatile intptr_t* dest);
inline static void dec_ptr(volatile void* dest);
- // Performs atomic exchange of *dest with exchange_value. Returns old prior value of *dest.
+ // Performs atomic exchange of *dest with exchange_value. Returns old
+ // prior value of *dest. xchg*() provide:
+ // <fence> exchange-value-with-dest <membar StoreLoad|StoreStore>
inline static jint xchg(jint exchange_value, volatile jint* dest);
static unsigned int xchg(unsigned int exchange_value, volatile unsigned int* dest);
inline static intptr_t xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest);
inline static void* xchg_ptr(void* exchange_value, volatile void* dest);
- // Performs atomic compare of *dest and compare_value, and exchanges *dest with exchange_value
- // if the comparison succeeded. Returns prior value of *dest. Guarantees a two-way memory
- // barrier across the cmpxchg. I.e., it's really a 'fence_cmpxchg_acquire'.
+ // Performs atomic compare of *dest and compare_value, and exchanges
+ // *dest with exchange_value if the comparison succeeded. Returns prior
+ // value of *dest. cmpxchg*() provide:
+ // <fence> compare-and-exchange <membar StoreLoad|StoreStore>
static jbyte cmpxchg (jbyte exchange_value, volatile jbyte* dest, jbyte compare_value);
inline static jint cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value);
// See comment above about using jlong atomics on 32-bit platforms
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/TraceExceptionsTest.java Sat Jul 12 01:26:13 2014 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, 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 8048933
+ * @summary TraceExceptions output should have the exception message - useful for ClassNotFoundExceptions especially
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.*;
+
+public class TraceExceptionsTest {
+ public static void main(String[] args) throws Exception {
+
+ if (!Platform.isDebugBuild()) {
+ System.out.println("Skip the test on product builds since XX:+TraceExceptions is not available on product builds");
+ return;
+ }
+
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+ "-XX:+TraceExceptions", "NoClassFound");
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldContain("<a 'java/lang/ClassNotFoundException': NoClassFound>");
+ output.shouldNotContain("<a 'java/lang/ClassNotFoundException'>");
+ output.shouldHaveExitValue(1);
+ }
+}