--- a/src/hotspot/share/interpreter/bytecodeUtils.cpp Wed Apr 10 08:15:45 2019 +0200
+++ b/src/hotspot/share/interpreter/bytecodeUtils.cpp Wed Apr 10 08:26:23 2019 +0200
@@ -32,22 +32,10 @@
#include "utilities/events.hpp"
/*
- * Returns the name of the klass that is described at constant pool
+ * Prints the name of the method that is described at constant pool
* index cp_index in the constant pool of method 'method'.
*/
-char const* MethodBytecodePrinter::get_klass_name(Method* method, int cp_index) {
- ConstantPool* cp = method->constants();
- int class_index = cp->klass_ref_index_at(cp_index);
- Symbol* klass = cp->klass_at_noresolve(class_index);
-
- return klass->as_klass_external_name();
-}
-
-/*
- * Returns the name of the method that is described at constant pool
- * index cp_index in the constant pool of method 'method'.
- */
-char const* MethodBytecodePrinter::get_method_name(Method* method, int cp_index) {
+static void print_method_name(outputStream *os, Method* method, int cp_index) {
ConstantPool* cp = method->constants();
int class_index = cp->klass_ref_index_at(cp_index);
Symbol* klass = cp->klass_at_noresolve(class_index);
@@ -58,16 +46,17 @@
Symbol* name = cp->symbol_at(name_index);
Symbol* signature = cp->symbol_at(type_index);
- stringStream ss;
- ss.print("%s.%s%s", klass->as_klass_external_name(), name->as_C_string(), signature->as_C_string());
- return ss.as_string();
+ signature->print_as_signature_external_return_type(os);
+ os->print(" %s.%s(", klass->as_klass_external_name(), name->as_C_string());
+ signature->print_as_signature_external_parameters(os);
+ os->print(")");
}
/*
- * Returns the name of the field that is described at constant pool
+ * Prints the name of the field that is described at constant pool
* index cp_index in the constant pool of method 'method'.
*/
-char const* MethodBytecodePrinter::get_field_and_class(Method* method, int cp_index) {
+static void print_field_and_class(outputStream *os, Method* method, int cp_index) {
ConstantPool* cp = method->constants();
int class_index = cp->klass_ref_index_at(cp_index);
Symbol* klass = cp->klass_at_noresolve(class_index);
@@ -76,16 +65,14 @@
int name_index = cp->name_ref_index_at(name_and_type_index);
Symbol* name = cp->symbol_at(name_index);
- stringStream ss;
- ss.print("%s.%s", klass->as_klass_external_name(), name->as_C_string());
- return ss.as_string();
+ os->print("%s.%s", klass->as_klass_external_name(), name->as_C_string());
}
/*
* Returns the name of the field that is described at constant pool
* index cp_index in the constant pool of method 'method'.
*/
-char const* MethodBytecodePrinter::get_field_name(Method* method, int cp_index) {
+static char const* get_field_name(Method* method, int cp_index) {
ConstantPool* cp = method->constants();
int name_and_type_index = cp->name_and_type_ref_index_at(cp_index);
int name_index = cp->name_ref_index_at(name_and_type_index);
@@ -93,6 +80,54 @@
return name->as_C_string();
}
+static void print_local_var(outputStream *os, int bci, Method* method, int slot) {
+ if (method->has_localvariable_table()) {
+ for (int i = 0; i < method->localvariable_table_length(); i++) {
+ LocalVariableTableElement* elem = method->localvariable_table_start() + i;
+ int start = elem->start_bci;
+ int end = start + elem->length;
+
+ if ((bci >= start) && (bci < end) && (elem->slot == slot)) {
+ ConstantPool* cp = method->constants();
+ char *var = cp->symbol_at(elem->name_cp_index)->as_C_string();
+ os->print("%s", var);
+
+ return;
+ }
+ }
+ }
+
+ // Handle at least some cases we know.
+ if (!method->is_static() && (slot == 0)) {
+ os->print("this");
+ } else {
+ int curr = method->is_static() ? 0 : 1;
+ SignatureStream ss(method->signature());
+ int param_index = 0;
+ bool found = false;
+
+ for (SignatureStream ss(method->signature()); !ss.is_done(); ss.next()) {
+ if (ss.at_return_type()) {
+ continue;
+ }
+ int size = type2size[ss.type()];
+ if ((slot >= curr) && (slot < curr + size)) {
+ found = true;
+ break;
+ }
+ param_index += 1;
+ curr += size;
+ }
+
+ if (found) {
+ os->print("<parameter%d>", 1 + param_index);
+ } else {
+ // This is the best we can do.
+ os->print("<local%d>", slot);
+ }
+ }
+}
+
TrackingStackEntry::TrackingStackEntry(BasicType type) : _entry(INVALID + type * SCALE) { }
TrackingStackEntry::TrackingStackEntry(int bci, BasicType type) : _entry(bci + type * SCALE) {
@@ -105,7 +140,7 @@
}
BasicType TrackingStackEntry::get_type() {
- return BasicType (_entry / SCALE);
+ return BasicType(_entry / SCALE);
}
TrackingStackEntry TrackingStackEntry::merge(TrackingStackEntry other) {
@@ -184,120 +219,6 @@
return _stack.at(get_size() - slot - 1);
}
-
-
-static TrackingStackSource createInvalidSource(int bci) {
- return TrackingStackSource(TrackingStackSource::INVALID, bci, "invalid");
-}
-
-static TrackingStackSource createLocalVarSource(int bci, Method* method, int slot) {
- // We assume outermost caller has ResourceMark.
- stringStream reason;
-
- if (method->has_localvariable_table()) {
- for (int i = 0; i < method->localvariable_table_length(); i++) {
- LocalVariableTableElement* elem = method->localvariable_table_start() + i;
- int start = elem->start_bci;
- int end = start + elem->length;
-
- if ((bci >= start) && (bci < end) && (elem->slot == slot)) {
- ConstantPool* cp = method->constants();
- char *var = cp->symbol_at(elem->name_cp_index)->as_C_string();
- if (strlen(var) == 4 && strcmp(var, "this") == 0) {
- reason.print("this");
- } else {
- reason.print("%s", var);
- }
-
- return TrackingStackSource(TrackingStackSource::LOCAL_VAR, bci, reason.as_string());
- }
- }
- }
-
- // Handle at least some cases we know.
- if (!method->is_static() && (slot == 0)) {
- reason.print("this");
- } else {
- int curr = method->is_static() ? 0 : 1;
- SignatureStream ss(method->signature());
- int param_index = 0;
- bool found = false;
-
- for (SignatureStream ss(method->signature()); !ss.is_done(); ss.next()) {
- if (ss.at_return_type()) {
- continue;
- }
-
- int size = type2size[ss.type()];
-
- if ((slot >= curr) && (slot < curr + size)) {
- found = true;
- break;
- }
-
- param_index += 1;
- curr += size;
- }
-
- if (found) {
- reason.print("<parameter%d>", 1 + param_index);
- } else {
- // This is the best we can do.
- reason.print("<local%d>", slot);
- }
- }
-
- return TrackingStackSource(TrackingStackSource::LOCAL_VAR, bci, reason.as_string());
-}
-
-
-static TrackingStackSource createConstantSource(int bci, const char *text) {
- return TrackingStackSource(TrackingStackSource::CONSTANT, bci, text);
-}
-
-static TrackingStackSource createArraySource(int bci, TrackingStackSource const& array_source,
- TrackingStackSource const& index_source) {
- // We assume outermost caller has ResourceMark.
- stringStream reason;
-
- if (array_source.get_type() != TrackingStackSource::INVALID) {
- reason.print("%s", array_source.as_string());
- } else {
- reason.print("array");
- }
- if (index_source.get_type() != TrackingStackSource::INVALID) {
- reason.print("[%s]", index_source.as_string());
- } else {
- reason.print("[...]");
- }
-
- return TrackingStackSource(TrackingStackSource::ARRAY_ELEM, bci, reason.as_string());
-}
-
-static TrackingStackSource createFieldSource(int bci, Method* method, int cp_index,
- TrackingStackSource const& object_source) {
- // We assume outermost caller has ResourceMark.
- stringStream reason;
-
- // GLGL We could also print the type of the field. Should we do that?
- //MethodBytecodePrinter::get_klass_name(method, cp_index)
- if (object_source.get_type() != TrackingStackSource::INVALID) {
- reason.print("%s.", object_source.as_string());
- }
- reason.print("%s", MethodBytecodePrinter::get_field_name(method, cp_index));
-
- return TrackingStackSource(TrackingStackSource::FIELD_ELEM, bci, reason.as_string());
-}
-
-static TrackingStackSource createStaticFieldSource(int bci, Method* method, int cp_index) {
- // We assume outermost caller has ResourceMark.
- stringStream reason;
- reason.print("static %s",
- MethodBytecodePrinter::get_field_and_class(method, cp_index));
-
- return TrackingStackSource(TrackingStackSource::FIELD_ELEM, bci, reason.as_string());
-}
-
TrackingStackCreator::TrackingStackCreator(Method* method, int bci) : _method(method) {
ConstMethod* const_method = method->constMethod();
@@ -912,128 +833,27 @@
return len;
}
-TrackingStackSource TrackingStackCreator::get_source(int bci, int slot, int max_detail) {
- assert(bci >= 0, "BCI too low");
- assert(bci < get_size(), "BCI to large");
-
- if (max_detail <= 0) {
- return createInvalidSource(bci);
- }
-
- if (_stacks->at(bci) == NULL) {
- return createInvalidSource(bci);
+int TrackingStackCreator::get_NPE_null_slot(int bci) {
+ // If this NPE was created via reflection, we have no real NPE.
+ if (_method->method_holder() == SystemDictionary::reflect_NativeConstructorAccessorImpl_klass()) {
+ return -2;
}
-
- TrackingStack* stack = _stacks->at(bci);
- assert(slot >= 0, "Slot nr. too low");
- assert(slot < stack->get_size(), "Slot nr. too large");
-
- TrackingStackEntry entry = stack->get_entry(slot);
-
- if (!entry.has_bci()) {
- return createInvalidSource(bci);
- }
-
// Get the bytecode.
- int source_bci = entry.get_bci();
address code_base = _method->constMethod()->code_base();
- Bytecodes::Code code = Bytecodes::java_code_at(_method, code_base + source_bci);
- bool is_wide = false;
- int pos = source_bci + 1;
-
+ Bytecodes::Code code = Bytecodes::java_code_at(_method, code_base + bci);
+ int pos = bci + 1;
if (code == Bytecodes::_wide) {
- is_wide = true;
- code = Bytecodes::java_code_at(_method, code_base + source_bci + 1);
+ code = Bytecodes::java_code_at(_method, code_base + bci + 1);
pos += 1;
}
switch (code) {
- case Bytecodes::_iload:
- case Bytecodes::_lload:
- case Bytecodes::_fload:
- case Bytecodes::_dload:
- case Bytecodes::_aload: {
- int index;
-
- if (is_wide) {
- index = Bytes::get_Java_u2(code_base + source_bci + 2);
- } else {
- index = *(uint8_t*) (code_base + source_bci + 1);
- }
-
- return createLocalVarSource(source_bci, _method, index);
- }
-
- case Bytecodes::_iload_0:
- case Bytecodes::_lload_0:
- case Bytecodes::_fload_0:
- case Bytecodes::_dload_0:
- case Bytecodes::_aload_0:
- return createLocalVarSource(source_bci, _method, 0);
-
- case Bytecodes::_iload_1:
- case Bytecodes::_lload_1:
- case Bytecodes::_fload_1:
- case Bytecodes::_dload_1:
- case Bytecodes::_aload_1:
- return createLocalVarSource(source_bci, _method, 1);
-
- case Bytecodes::_iload_2:
- case Bytecodes::_lload_2:
- case Bytecodes::_fload_2:
- case Bytecodes::_dload_2:
- case Bytecodes::_aload_2:
- return createLocalVarSource(source_bci, _method, 2);
-
- case Bytecodes::_lload_3:
- case Bytecodes::_iload_3:
- case Bytecodes::_fload_3:
- case Bytecodes::_dload_3:
- case Bytecodes::_aload_3:
- return createLocalVarSource(source_bci, _method, 3);
-
- case Bytecodes::_aconst_null:
- return createConstantSource(source_bci, "null");
- case Bytecodes::_iconst_m1:
- return createConstantSource(source_bci, "-1");
- case Bytecodes::_iconst_0:
- return createConstantSource(source_bci, "0");
- case Bytecodes::_iconst_1:
- return createConstantSource(source_bci, "1");
- case Bytecodes::_iconst_2:
- return createConstantSource(source_bci, "2");
- case Bytecodes::_iconst_3:
- return createConstantSource(source_bci, "3");
- case Bytecodes::_iconst_4:
- return createConstantSource(source_bci, "4");
- case Bytecodes::_iconst_5:
- return createConstantSource(source_bci, "5");
- case Bytecodes::_lconst_0:
- return createConstantSource(source_bci, "0L");
- case Bytecodes::_lconst_1:
- return createConstantSource(source_bci, "1L");
- case Bytecodes::_fconst_0:
- return createConstantSource(source_bci, "0.0f");
- case Bytecodes::_fconst_1:
- return createConstantSource(source_bci, "1.0f");
- case Bytecodes::_fconst_2:
- return createConstantSource(source_bci, "2.0f");
- case Bytecodes::_dconst_0:
- return createConstantSource(source_bci, "0.0");
- case Bytecodes::_dconst_1:
- return createConstantSource(source_bci, "1.0");
- case Bytecodes::_bipush: {
- jbyte con = *(jbyte*) (code_base + source_bci + 1);
- stringStream ss;
- ss.print("%d", con);
- return createConstantSource(source_bci, ss.as_string());
- }
- case Bytecodes::_sipush: {
- u2 con = Bytes::get_Java_u2(code_base + source_bci + 1);
- stringStream ss;
- ss.print("%d", con);
- return createConstantSource(source_bci, ss.as_string());
- }
+ case Bytecodes::_getfield:
+ case Bytecodes::_arraylength:
+ case Bytecodes::_athrow:
+ case Bytecodes::_monitorenter:
+ case Bytecodes::_monitorexit:
+ return 0;
case Bytecodes::_iaload:
case Bytecodes::_faload:
case Bytecodes::_aaload:
@@ -1041,259 +861,26 @@
case Bytecodes::_caload:
case Bytecodes::_saload:
case Bytecodes::_laload:
- case Bytecodes::_daload: {
- TrackingStackSource array_source = get_source(source_bci, 1, max_detail - 1);
- TrackingStackSource index_source = get_source(source_bci, 0, max_detail - 1);
- return createArraySource(source_bci, array_source, index_source);
- }
-
- case Bytecodes::_invokevirtual:
- case Bytecodes::_invokespecial:
- case Bytecodes::_invokestatic:
- case Bytecodes::_invokeinterface: {
- int cp_index = Bytes::get_native_u2(code_base + pos) DEBUG_ONLY(+ ConstantPool::CPCACHE_INDEX_TAG);
- // We assume outermost caller has ResourceMark.
- stringStream reason;
- if (max_detail == 5 /* Todo: introduce a constant ... */) {
- reason.print("The return value of '%s'", MethodBytecodePrinter::get_method_name(_method, cp_index));
- } else {
- reason.print("%s", MethodBytecodePrinter::get_method_name(_method, cp_index));
- }
- return TrackingStackSource(TrackingStackSource::METHOD, source_bci, reason.as_string());
- }
-
- case Bytecodes::_getstatic:
- return createStaticFieldSource(source_bci, _method,
- Bytes::get_native_u2(code_base + pos) + ConstantPool::CPCACHE_INDEX_TAG);
-
- case Bytecodes::_getfield: {
- int cp_index = Bytes::get_native_u2(code_base + pos) + ConstantPool::CPCACHE_INDEX_TAG;
- TrackingStackSource object_source = get_source(source_bci, 0, max_detail - 1);
- return createFieldSource(source_bci, _method, cp_index, object_source);
- }
-
- default:
- return createInvalidSource(bci);
- }
-}
-
-int TrackingStackCreator::get_null_pointer_slot(int bci, char const** reason) {
- // If this NPE was created via reflection, we have no real NPE.
- if (_method->method_holder() == SystemDictionary::reflect_NativeConstructorAccessorImpl_klass()) {
- return -2;
- }
-
- // Get the bytecode.
- address code_base = _method->constMethod()->code_base();
- Bytecodes::Code code = Bytecodes::java_code_at(_method, code_base + bci);
- int pos = bci + 1;
-
- if (code == Bytecodes::_wide) {
- code = Bytecodes::java_code_at(_method, code_base + bci + 1);
- pos += 1;
- }
-
- int result = -1;
-
- switch (code) {
- case Bytecodes::_iaload:
- if (reason != NULL) {
- *reason = "Can not load from null int array.";
- }
-
- result = 1;
- break;
-
- case Bytecodes::_faload:
- if (reason != NULL) {
- *reason = "Can not load from null float array.";
- }
-
- result = 1;
- break;
-
- case Bytecodes::_aaload:
- if (reason != NULL) {
- *reason = "Can not load from null object array.";
- }
-
- result = 1;
- break;
-
- case Bytecodes::_baload:
- if (reason != NULL) {
- *reason = "Can not load from null byte/boolean array.";
- }
-
- result = 1;
- break;
-
- case Bytecodes::_caload:
- if (reason != NULL) {
- *reason = "Can not load from null char array.";
- }
-
- result = 1;
- break;
-
- case Bytecodes::_saload:
- if (reason != NULL) {
- *reason = "Can not load from null short array.";
- }
-
- result = 1;
- break;
-
- case Bytecodes::_laload:
- if (reason != NULL) {
- *reason = "Can not load from null long array.";
- }
-
- result = 1;
- break;
-
case Bytecodes::_daload:
- if (reason != NULL) {
- *reason = "Can not load from null double array.";
- }
-
- result = 1;
- break;
-
+ return 1;
case Bytecodes::_iastore:
- if (reason != NULL) {
- *reason = "Can not store to null int array.";
- }
-
- result = 2;
- break;
-
- case Bytecodes::_lastore:
- if (reason != NULL) {
- *reason = "Can not store to null long array.";
- }
-
- result = 3;
- break;
-
case Bytecodes::_fastore:
- if (reason != NULL) {
- *reason = "Can not store to null float array.";
- }
-
- result = 2;
- break;
-
- case Bytecodes::_dastore:
- if (reason != NULL) {
- *reason = "Can not store to null double array.";
- }
-
- result = 3;
- break;
-
case Bytecodes::_aastore:
- if (reason != NULL) {
- *reason = "Can not store to null object array.";
- }
-
- result = 2;
- break;
-
case Bytecodes::_bastore:
- if (reason != NULL) {
- *reason = "Can not store to to null byte/boolean array.";
- }
-
- result = 2;
- break;
-
case Bytecodes::_castore:
- if (reason != NULL) {
- *reason = "Can not store to to null char array.";
- }
-
- result = 2;
- break;
-
case Bytecodes::_sastore:
- if (reason != NULL) {
- *reason = "Can not store to null short array.";
- }
-
- result = 2;
- break;
-
- case Bytecodes::_getfield:
- {
- if (reason != NULL) {
- int cp_index = Bytes::get_native_u2(code_base + pos) DEBUG_ONLY(+ ConstantPool::CPCACHE_INDEX_TAG);
- ConstantPool* cp = _method->constants();
- int name_and_type_index = cp->name_and_type_ref_index_at(cp_index);
- int name_index = cp->name_ref_index_at(name_and_type_index);
- Symbol* name = cp->symbol_at(name_index);
- stringStream ss;
- ss.print("Can not read field '%s'.", name->as_C_string());
- *reason = ss.as_string();
- }
-
- result = 0;
- }
-
- break;
-
- case Bytecodes::_arraylength:
- if (reason != NULL) {
- *reason = "Can not read the array length.";
- }
-
- result = 0;
- break;
-
- case Bytecodes::_athrow:
- if (reason != NULL) {
- *reason = "Can not throw a null exception object.";
- }
-
- result = 0;
- break;
-
- case Bytecodes::_monitorenter:
- if (reason != NULL) {
- *reason = "Can not enter a null monitor.";
- }
-
- result = 0;
- break;
-
- case Bytecodes::_monitorexit:
- if (reason != NULL) {
- *reason = "Can not exit a null monitor.";
- }
-
- result = 0;
- break;
-
- case Bytecodes::_putfield:
- {
+ return 2;
+ case Bytecodes::_lastore:
+ case Bytecodes::_dastore:
+ return 3;
+ case Bytecodes::_putfield: {
int cp_index = Bytes::get_native_u2(code_base + pos) DEBUG_ONLY(+ ConstantPool::CPCACHE_INDEX_TAG);
ConstantPool* cp = _method->constants();
int name_and_type_index = cp->name_and_type_ref_index_at(cp_index);
int type_index = cp->signature_ref_index_at(name_and_type_index);
Symbol* signature = cp->symbol_at(type_index);
-
- if (reason != NULL) {
- stringStream ss;
- ss.print("Can not write field '%s'.",
- MethodBytecodePrinter::get_field_name(_method, cp_index));
- *reason = ss.as_string();
- }
-
- result = type2size[char2type((char) signature->char_at(0))];
+ return type2size[char2type((char) signature->char_at(0))];
}
-
- break;
-
case Bytecodes::_invokevirtual:
case Bytecodes::_invokespecial:
case Bytecodes::_invokeinterface:
@@ -1310,26 +897,332 @@
// (which is true in Java). This is mainly used to avoid generating wrong
// messages for NullPointerExceptions created explicitly by new in Java code.
if (name != vmSymbols::object_initializer_name()) {
- if (reason != NULL) {
- stringStream ss;
- ss.print("Can not invoke method '%s'.",
- MethodBytecodePrinter::get_method_name(_method, cp_index));
- *reason = ss.as_string();
- }
-
- result = ArgumentSizeComputer(signature).size();
- }
- else {
- result = -2;
+ return ArgumentSizeComputer(signature).size();
+ } else {
+ return -2;
}
}
- break;
-
default:
break;
}
- return result;
+ return -1;
+}
+
+const int TrackingStackCreator::_max_cause_detail = 5;
+
+void TrackingStackCreator::TrackingStackCreator::print_NPE_cause(outputStream *os, int bci, int slot) {
+ if (print_NPE_cause0(os, bci, slot, _max_cause_detail, "'")) {
+ os->print("' is null. ");
+ }
}
+/* Recursively print what was null.
+ *
+ * Go the the bytecode that pushed slot 'slot' on the operant stack
+ * at bytecode 'bci'. Compute a message for that bytecode. If
+ * necessary (array, field), recur further.
+ * At most do max_detail recursions.
+ *
+ * Returns true if something was printed.
+ */
+bool TrackingStackCreator::TrackingStackCreator::print_NPE_cause0(outputStream *os, int bci, int slot,
+ int max_detail, const char *prefix) {
+ assert(bci >= 0, "BCI too low");
+ assert(bci < get_size(), "BCI to large");
+
+ if (max_detail <= 0) {
+ return false;
+ }
+
+ if (_stacks->at(bci) == NULL) {
+ return false;
+ }
+
+ TrackingStack* stack = _stacks->at(bci);
+ assert(slot >= 0, "Slot nr. too low");
+ assert(slot < stack->get_size(), "Slot nr. too large");
+
+ TrackingStackEntry entry = stack->get_entry(slot);
+
+ if (!entry.has_bci()) {
+ return false;
+ }
+
+ // Get the bytecode.
+ int source_bci = entry.get_bci();
+ address code_base = _method->constMethod()->code_base();
+ Bytecodes::Code code = Bytecodes::java_code_at(_method, code_base + source_bci);
+ bool is_wide = false;
+ int pos = source_bci + 1;
+
+ if (code == Bytecodes::_wide) {
+ is_wide = true;
+ code = Bytecodes::java_code_at(_method, code_base + source_bci + 1);
+ pos += 1;
+ }
+
+ if (max_detail == _max_cause_detail &&
+ prefix != NULL &&
+ code != Bytecodes::_invokevirtual &&
+ code != Bytecodes::_invokespecial &&
+ code != Bytecodes::_invokestatic &&
+ code != Bytecodes::_invokeinterface) {
+ os->print("%s", prefix);
+ }
+
+ switch (code) {
+ case Bytecodes::_iload_0:
+ //case Bytecodes::_lload_0: // ?
+ //case Bytecodes::_fload_0: // ?
+ //case Bytecodes::_dload_0: // ?
+ case Bytecodes::_aload_0:
+ print_local_var(os, source_bci, _method, 0);
+ return true;
+
+ case Bytecodes::_iload_1:
+ //case Bytecodes::_lload_1: // ?
+ //case Bytecodes::_fload_1: // ?
+ //case Bytecodes::_dload_1: // ?
+ case Bytecodes::_aload_1:
+ print_local_var(os, source_bci, _method, 1);
+ return true;
+
+ case Bytecodes::_iload_2:
+ //case Bytecodes::_lload_2: // ?
+ //case Bytecodes::_fload_2: // ?
+ //case Bytecodes::_dload_2: // ?
+ case Bytecodes::_aload_2:
+ print_local_var(os, source_bci, _method, 2);
+ return true;
+
+ case Bytecodes::_iload_3:
+ //case Bytecodes::_lload_3: // ?
+ //case Bytecodes::_fload_3: // ?
+ //case Bytecodes::_dload_3: // ?
+ case Bytecodes::_aload_3:
+ print_local_var(os, source_bci, _method, 3);
+ return true;
+
+ case Bytecodes::_iload:
+ //case Bytecodes::_lload: // ?
+ //case Bytecodes::_fload: // ?
+ //case Bytecodes::_dload: // ?
+ case Bytecodes::_aload: {
+ int index;
+
+ if (is_wide) {
+ index = Bytes::get_Java_u2(code_base + source_bci + 2);
+ } else {
+ index = *(uint8_t*) (code_base + source_bci + 1);
+ }
+
+ print_local_var(os, source_bci, _method, index);
+ return true;
+ }
+
+ case Bytecodes::_aconst_null:
+ os->print("null");
+ return true;
+ case Bytecodes::_iconst_m1:
+ os->print("-1");
+ return true;
+ case Bytecodes::_iconst_0:
+ os->print("0");
+ return true;
+ case Bytecodes::_iconst_1:
+ os->print("1");
+ return true;
+ case Bytecodes::_iconst_2:
+ os->print("2");
+ return true;
+ case Bytecodes::_iconst_3:
+ os->print("3");
+ return true;
+ case Bytecodes::_iconst_4:
+ os->print("4");
+ return true;
+ case Bytecodes::_iconst_5:
+ os->print("5");
+ return true;
+ /*
+ case Bytecodes::_lconst_0: // ?
+ os->print("0L");
+ return true;
+ case Bytecodes::_lconst_1: // ?
+ os->print("1L");
+ return true;
+ case Bytecodes::_fconst_0: // ?
+ os->print("0.0f");
+ return true;
+ case Bytecodes::_fconst_1: // ?
+ os->print("1.0f");
+ return true;
+ case Bytecodes::_fconst_2: // ?
+ os->print("2.0f");
+ return true;
+ case Bytecodes::_dconst_0: // ?
+ os->print("0.0");
+ return true;
+ case Bytecodes::_dconst_1: // ?
+ os->print("1.0");
+ return true;
+ */
+ case Bytecodes::_bipush: {
+ jbyte con = *(jbyte*) (code_base + source_bci + 1);
+ os->print("%d", con);
+ return true;
+ }
+ case Bytecodes::_sipush: {
+ u2 con = Bytes::get_Java_u2(code_base + source_bci + 1);
+ os->print("%d", con);
+ return true;
+ }
+ case Bytecodes::_iaload:
+ //case Bytecodes::_faload: // ?
+ case Bytecodes::_aaload: {
+ //case Bytecodes::_baload: // ?
+ //case Bytecodes::_caload: // ?
+ //case Bytecodes::_saload: // ?
+ //case Bytecodes::_laload: // ?
+ //case Bytecodes::_daload: { // ?
+
+ // Print the 'name' of the array. Go back to the bytecode that
+ // pushed the array reference on the operand stack.
+ if (!print_NPE_cause0(os, source_bci, 1, max_detail-1)) {
+ // Returned false. Max recursion depth was reached. Print dummy.
+ os->print("<array>");
+ }
+ os->print("[");
+ // Print the index expression. Go back to the bytecode that
+ // pushed the index on the operand stack.
+ // Don't decrement maxdetail so we get a value here and only
+ // cancel out on the dereference.
+ if (!print_NPE_cause0(os, source_bci, 0, max_detail)) {
+ // Returned false. We don't print complex array index expressions. Print placeholder.
+ os->print("...");
+ }
+ os->print("]");
+ return true;
+ }
+
+ case Bytecodes::_getstatic: {
+ int cp_index = Bytes::get_native_u2(code_base + pos) + ConstantPool::CPCACHE_INDEX_TAG;
+ os->print("static ");
+ print_field_and_class(os, _method, cp_index);
+ return true;
+ }
+
+ case Bytecodes::_getfield: {
+ // Print the sender. Go back to the bytecode that
+ // pushed the sender on the operand stack.
+ if (print_NPE_cause0(os, source_bci, 0, max_detail - 1)) {
+ os->print(".");
+ }
+ int cp_index = Bytes::get_native_u2(code_base + pos) + ConstantPool::CPCACHE_INDEX_TAG;
+ os->print("%s", get_field_name(_method, cp_index));
+ return true;
+ }
+
+ case Bytecodes::_invokevirtual:
+ case Bytecodes::_invokespecial:
+ case Bytecodes::_invokestatic:
+ case Bytecodes::_invokeinterface: {
+ int cp_index = Bytes::get_native_u2(code_base + pos) DEBUG_ONLY(+ ConstantPool::CPCACHE_INDEX_TAG);
+ if (max_detail == _max_cause_detail) {
+ os->print("The return value of '");
+ }
+ print_method_name(os, _method, cp_index);
+ return true;
+ }
+
+ default: break;
+ }
+ return false;
+}
+
+void TrackingStackCreator::print_NPE_failedAction(outputStream *os, int bci) {
+ // If this NPE was created via reflection, we have no real NPE.
+ assert(_method->method_holder() != SystemDictionary::reflect_NativeConstructorAccessorImpl_klass(),
+ "We should have checked for reflection in get_NPE_null_slot().");
+
+ // Get the bytecode.
+ address code_base = _method->constMethod()->code_base();
+ Bytecodes::Code code = Bytecodes::java_code_at(_method, code_base + bci);
+ int pos = bci + 1;
+ if (code == Bytecodes::_wide) {
+ code = Bytecodes::java_code_at(_method, code_base + bci + 1);
+ pos += 1;
+ }
+
+ switch (code) {
+ case Bytecodes::_iaload:
+ os->print("Can not load from null int array."); break;
+ case Bytecodes::_faload:
+ os->print("Can not load from null float array."); break;
+ case Bytecodes::_aaload:
+ os->print("Can not load from null object array."); break;
+ case Bytecodes::_baload:
+ os->print("Can not load from null byte/boolean array."); break;
+ case Bytecodes::_caload:
+ os->print("Can not load from null char array."); break;
+ case Bytecodes::_saload:
+ os->print("Can not load from null short array."); break;
+ case Bytecodes::_laload:
+ os->print("Can not load from null long array."); break;
+ case Bytecodes::_daload:
+ os->print("Can not load from null double array."); break;
+
+ case Bytecodes::_iastore:
+ os->print("Can not store to null int array."); break;
+ case Bytecodes::_fastore:
+ os->print("Can not store to null float array."); break;
+ case Bytecodes::_aastore:
+ os->print("Can not store to null object array."); break;
+ case Bytecodes::_bastore:
+ os->print("Can not store to null byte/boolean array."); break;
+ case Bytecodes::_castore:
+ os->print("Can not store to null char array."); break;
+ case Bytecodes::_sastore:
+ os->print("Can not store to null short array."); break;
+ case Bytecodes::_lastore:
+ os->print("Can not store to null long array."); break;
+ case Bytecodes::_dastore:
+ os->print("Can not store to null double array."); break;
+
+ case Bytecodes::_arraylength:
+ os->print("Can not read the array length."); break;
+ case Bytecodes::_athrow:
+ os->print("Can not throw a null exception object."); break;
+ case Bytecodes::_monitorenter:
+ os->print("Can not enter a null monitor."); break;
+ case Bytecodes::_monitorexit:
+ os->print("Can not exit a null monitor."); break;
+ case Bytecodes::_getfield: {
+ int cp_index = Bytes::get_native_u2(code_base + pos) DEBUG_ONLY(+ ConstantPool::CPCACHE_INDEX_TAG);
+ ConstantPool* cp = _method->constants();
+ int name_and_type_index = cp->name_and_type_ref_index_at(cp_index);
+ int name_index = cp->name_ref_index_at(name_and_type_index);
+ Symbol* name = cp->symbol_at(name_index);
+ os->print("Can not read field '%s'.", name->as_C_string());
+ } break;
+ case Bytecodes::_putfield: {
+ int cp_index = Bytes::get_native_u2(code_base + pos) DEBUG_ONLY(+ ConstantPool::CPCACHE_INDEX_TAG);
+ os->print("Can not write field '%s'.", get_field_name(_method, cp_index));
+ } break;
+ case Bytecodes::_invokevirtual:
+ case Bytecodes::_invokespecial:
+ case Bytecodes::_invokeinterface: {
+ int cp_index = Bytes::get_native_u2(code_base+ pos) DEBUG_ONLY(+ ConstantPool::CPCACHE_INDEX_TAG);
+ os->print("Can not invoke method '");
+ print_method_name(os, _method, cp_index);
+ os->print("'.");
+ } break;
+
+ default:
+ assert(0, "We should have checked this bytecode in get_NPE_null_slot().");
+ break;
+ }
+}
+
--- a/test/hotspot/jtreg/runtime/exceptionMsgs/NullPointerException/NullPointerExceptionTest.java Wed Apr 10 08:15:45 2019 +0200
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/NullPointerException/NullPointerExceptionTest.java Wed Apr 10 08:26:23 2019 +0200
@@ -27,6 +27,8 @@
* @summary Test extended NullPointerException message for class
* files generated without debugging information. The message lists
* detailed information about the entity that is null.
+ * @modules java.base/java.lang:open
+ * java.base/jdk.internal.org.objectweb.asm
* @library /test/lib
* @compile NullPointerExceptionTest.java
* @run main NullPointerExceptionTest
@@ -36,9 +38,11 @@
* @summary Test extended NullPointerException message for
* classfiles generated with debug information. In this case the name
* of the variable containing the array is printed.
+ * @modules java.base/java.lang:open
+ * java.base/jdk.internal.org.objectweb.asm
* @library /test/lib
* @compile -g NullPointerExceptionTest.java
- * @run main/othervm -XX:+WizardMode -DhasDebugInfo NullPointerExceptionTest
+ * @run main/othervm -XX:+WizardMode NullPointerExceptionTest hasDebugInfo
*/
import java.io.ByteArrayInputStream;
@@ -49,10 +53,22 @@
import jdk.test.lib.Asserts;
+import java.lang.reflect.*;
+import java.lang.invoke.MethodHandles.Lookup;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodHandles.Lookup.*;
+
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+import jdk.internal.org.objectweb.asm.Type;
+import jdk.internal.org.objectweb.asm.Label;
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+
/**
* Tests NullPointerExceptions
*/
public class NullPointerExceptionTest {
+
// Some fields used in the test.
static Object nullStaticField;
NullPointerExceptionTest nullInstanceField;
@@ -61,15 +77,9 @@
DoubleArrayGen dag;
ArrayList<String> names = new ArrayList<>();
ArrayList<String> curr;
- static boolean hasDebugInfo = true;
+ static boolean hasDebugInfo = false;
static {
- try {
- hasDebugInfo = System.getProperty("hasDebugInfo") != null;
- } catch (Throwable t) {
- throw new RuntimeException(t);
- }
-
staticArray = new int[1][][][];
staticArray[0] = new int[1][][];
staticArray[0][0] = new int[1][];
@@ -80,58 +90,537 @@
System.out.println();
System.out.println(" source code: " + expression);
System.out.println(" thrown msg: " + obtainedMsg);
- //System.out.println("expected msg: " + expectedMsg);
- //Asserts.assertEquals(obtainedMsg, expectedMsg);
+ if (obtainedMsg.equals(expectedMsg)) return;
+ System.out.println("expected msg: " + expectedMsg);
+ Asserts.assertEquals(obtainedMsg, expectedMsg);
}
public static void main(String[] args) throws Exception {
NullPointerExceptionTest t = new NullPointerExceptionTest();
- t.testPointerChasing();
- t.testArrayChasing();
- t.testMethodChasing();
- t.testMixedChasing();
+ if (args.length > 0) {
+ hasDebugInfo = true;
+ }
+
+ // Test the message printed for the failed action.
+ t.testFailedAction();
+
+ // Test the method printed for the null entity.
+ t.testNullEntity();
+
+ // Test that no message is printed for exceptions
+ // allocated explicitly.
+ t.testCreation();
+
+ // Test that no message is printed for exceptions
+ // thrown in native methods.
+ t.testNative();
+
+ // Test that two calls to getMessage() return the same
+ // message.
+ // It is a design decision that it returns two different
+ // String objects.
t.testSameMessage();
- t.testCreationViaNew();
- t.testCreationViaReflection();
- t.testCreationViaSerialization();
- t.testLoadedFromLocalVariable1();
- t.testLoadedFromLocalVariable2();
- t.testLoadedFromLocalVariable3();
- t.testLoadedFromLocalVariable4();
- t.testLoadedFromLocalVariable5();
- t.testLoadedFromLocalVariable6();
- t.testLoadedFromLocalVariable7();
- t.testLoadedFromMethod1();
- t.testLoadedFromMethod2();
- t.testLoadedFromMethod3();
- t.testLoadedFromMethod4();
- t.testLoadedFromMethod5();
- t.testLoadedFromMethod6();
- t.testLoadedFromMethod7();
- t.testLoadedFromStaticField1();
- t.testLoadedFromStaticField2();
- t.testLoadedFromStaticField3();
- t.testLoadedFromStaticField4(0, 0);
- t.testLoadedFromStaticField5();
- t.testLoadedFromStaticField5a();
- t.testLoadedFromStaticField5b();
- t.testLoadedFromStaticField6();
- t.testLoadedFromInstanceField1();
- t.testLoadedFromInstanceField2();
- t.testLoadedFromInstanceField3();
- t.testLoadedFromInstanceField4();
- t.testLoadedFromInstanceField5();
- t.testLoadedFromInstanceField6();
- t.testInNative();
- t.testMissingLocalVariableTable();
- t.testNullMessages();
+
+ // Test serialization.
+ // It is a design decision that after serialization the
+ // the message is lost.
+ t.testSerialization();
+
+ // Test that messages are printed for code generated
+ // on-the-fly.
+ t.testGeneratedCode();
+
+
+ // Some more interesting complex messages.
+ t.testComplexMessages();
+ }
+
+ // Helper method to cause test case.
+ private double callWithTypes(String[][] dummy1, int[][][] dummy2, float dummy3, long dummy4, short dummy5,
+ boolean dummy6, byte dummy7, double dummy8, char dummy9) {
+ return 0.0;
}
+ public void testFailedAction() {
+ int[] ia1 = null;
+ float[] fa1 = null;
+ Object[] oa1 = null;
+ boolean[] za1 = null;
+ byte[] ba1 = null;
+ char[] ca1 = null;
+ short[] sa1 = null;
+ long[] la1 = null;
+ double[] da1 = null;
+
+ // iaload
+ try {
+ System.out.println(ia1[0]);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("ia1[0]", e.getMessage(),
+ (hasDebugInfo ? "'ia1'" : "'<local1>'") + " is null. " +
+ "Can not load from null int array.");
+ }
+ // faload
+ try {
+ System.out.println(fa1[0]);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("fa1[0]", e.getMessage(),
+ (hasDebugInfo ? "'fa1'" : "'<local2>'") + " is null. " +
+ "Can not load from null float array.");
+ }
+ // aaload
+ try {
+ System.out.println(oa1[0]);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("oa1[0]", e.getMessage(),
+ (hasDebugInfo ? "'oa1'" : "'<local3>'") + " is null. " +
+ "Can not load from null object array.");
+ }
+ // baload (boolean)
+ try {
+ System.out.println(za1[0]);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("za1[0]", e.getMessage(),
+ (hasDebugInfo ? "'za1'" : "'<local4>'") + " is null. " +
+ "Can not load from null byte/boolean array.");
+ }
+ // baload (byte)
+ try {
+ System.out.println(ba1[0]);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("ba1[0]", e.getMessage(),
+ (hasDebugInfo ? "'ba1'" : "'<local5>'") + " is null. " +
+ "Can not load from null byte/boolean array.");
+ }
+ // caload
+ try {
+ System.out.println(ca1[0]);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("ca1[0]", e.getMessage(),
+ (hasDebugInfo ? "'ca1'" : "'<local6>'") + " is null. " +
+ "Can not load from null char array.");
+ }
+ // saload
+ try {
+ System.out.println(sa1[0]);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("sa1[0]", e.getMessage(),
+ (hasDebugInfo ? "'sa1'" : "'<local7>'") + " is null. " +
+ "Can not load from null short array.");
+ }
+ // laload
+ try {
+ System.out.println(la1[0]);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("la1[0]", e.getMessage(),
+ (hasDebugInfo ? "'la1'" : "'<local8>'") + " is null. " +
+ "Can not load from null long array.");
+ }
+ // daload
+ try {
+ System.out.println(da1[0]);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("da1[0]", e.getMessage(),
+ (hasDebugInfo ? "'da1'" : "'<local9>'") + " is null. " +
+ "Can not load from null double array.");
+ }
+
+ // iastore
+ try {
+ System.out.println(ia1[0] = 0);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("ia1[0] = 0", e.getMessage(),
+ (hasDebugInfo ? "'ia1'" : "'<local1>'") + " is null. " +
+ "Can not store to null int array.");
+ }
+ // fastore
+ try {
+ System.out.println(fa1[0] = 0.7f);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("fa1[0] = false", e.getMessage(),
+ (hasDebugInfo ? "'fa1'" : "'<local2>'") + " is null. " +
+ "Can not store to null float array.");
+ }
+ // aastore
+ try {
+ System.out.println(oa1[0] = null);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("oa1[0] = null", e.getMessage(),
+ (hasDebugInfo ? "'oa1'" : "'<local3>'") + " is null. " +
+ "Can not store to null object array.");
+ }
+ // bastore (boolean)
+ try {
+ System.out.println(za1[0] = false);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("za1[0] = false", e.getMessage(),
+ (hasDebugInfo ? "'za1'" : "'<local4>'") + " is null. " +
+ "Can not store to null byte/boolean array.");
+ }
+ // bastore (byte)
+ try {
+ System.out.println(ba1[0] = 0);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("ba1[0] = 0", e.getMessage(),
+ (hasDebugInfo ? "'ba1'" : "'<local5>'") + " is null. " +
+ "Can not store to null byte/boolean array.");
+ }
+ // castore
+ try {
+ System.out.println(ca1[0] = 0);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("ca1[0] = 0", e.getMessage(),
+ (hasDebugInfo ? "'ca1'" : "'<local6>'") + " is null. " +
+ "Can not store to null char array.");
+ }
+ // sastore
+ try {
+ System.out.println(sa1[0] = 0);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("sa1[0] = 0", e.getMessage(),
+ (hasDebugInfo ? "'sa1'" : "'<local7>'") + " is null. " +
+ "Can not store to null short array.");
+ }
+ // lastore
+ try {
+ System.out.println(la1[0] = 0);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("la1[0] = 0", e.getMessage(),
+ (hasDebugInfo ? "'la1'" : "'<local8>'") + " is null. " +
+ "Can not store to null long array.");
+ }
+ // dastore
+ try {
+ System.out.println(da1[0] = 0);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("da1[0] = 0", e.getMessage(),
+ (hasDebugInfo ? "'da1'" : "'<local9>'") + " is null. " +
+ "Can not store to null double array.");
+ }
+
+ // arraylength
+ try {
+ System.out.println(za1.length);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("za1.length", e.getMessage(),
+ (hasDebugInfo ? "'za1'" : "'<local4>'") + " is null. " +
+ "Can not read the array length.");
+ }
+ // athrow
+ try {
+ throw null;
+ } catch (NullPointerException e) {
+ checkMessage("throw null", e.getMessage(),
+ "'null' is null. " +
+ "Can not throw a null exception object.");
+ }
+ // monitorenter
+ try {
+ synchronized (nullInstanceField) {
+ // desired
+ }
+ } catch (NullPointerException e) {
+ checkMessage("synchronized (nullInstanceField)", e.getMessage(),
+ "'this.nullInstanceField' is null. " +
+ "Can not enter a null monitor.");
+ }
+ // monitorexit
+ // No test available
+
+ // getfield
+ try {
+ System.out.println(nullInstanceField.nullInstanceField);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("nullInstanceField.nullInstanceField", e.getMessage(),
+ "'this.nullInstanceField' is null. " +
+ "Can not read field 'nullInstanceField'.");
+ }
+ // putfield
+ try {
+ System.out.println(nullInstanceField.nullInstanceField = null);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("nullInstanceField.nullInstanceField = null", e.getMessage(),
+ "'this.nullInstanceField' is null. " +
+ "Can not write field 'nullInstanceField'.");
+ }
+ // invoke
+ try {
+ nullInstanceField.toString();
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("nullInstanceField.toString()", e.getMessage(),
+ "'this.nullInstanceField' is null. " +
+ "Can not invoke method 'java.lang.String java.lang.Object.toString()'.");
+ }
+ // Test parameter and return types
+ try {
+ Asserts.assertTrue(nullInstanceField.callWithTypes(null, null, 0.0f, 0L, (short)0, false, (byte)0, 0.0, 'x') == 0.0);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("nullInstanceField.callWithTypes(null, null, 0.0f, 0L, (short)0, false, (byte)0, 0.0, 'x')", e.getMessage(),
+ "'this.nullInstanceField' is null. " +
+ "Can not invoke method 'double NullPointerExceptionTest.callWithTypes(java.lang.String[][], int[][][], float, long, short, boolean, byte, double, char)'.");
+ }
+ }
+
+ static void test_iload() {
+ int i0 = 0;
+ int i1 = 1;
+ int i2 = 2;
+ int i3 = 3;
+ int i4 = 4;
+ int i5 = 5;
+
+ int[][] a = new int[6][];
+
+ // iload_0
+ try {
+ a[i0][0] = 77;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("a[i0][0]", e.getMessage(),
+ (hasDebugInfo ? "'a[i0]'" : "'<local6>[<local0>]'") + " is null. " +
+ "Can not store to null int array.");
+ }
+ // iload_1
+ try {
+ a[i1][0] = 77;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("a[i1][0]", e.getMessage(),
+ (hasDebugInfo ? "'a[i1]'" : "'<local6>[<local1>]'") + " is null. " +
+ "Can not store to null int array.");
+ }
+ // iload_2
+ try {
+ a[i2][0] = 77;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("a[i2][0]", e.getMessage(),
+ (hasDebugInfo ? "'a[i2]'" : "'<local6>[<local2>]'") + " is null. " +
+ "Can not store to null int array.");
+ }
+ // iload_3
+ try {
+ a[i3][0] = 77;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("a[i3][0]", e.getMessage(),
+ (hasDebugInfo ? "'a[i3]'" : "'<local6>[<local3>]'") + " is null. " +
+ "Can not store to null int array.");
+ }
+ // iload
+ try {
+ a[i5][0] = 77;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("a[i5][0]", e.getMessage(),
+ (hasDebugInfo ? "'a[i5]'" : "'<local6>[<local5>]'") + " is null. " +
+ "Can not store to null int array.");
+ }
+ }
+
+ // Other datatyes than int are not needed.
+ // If we implement l2d and similar bytecodes, we can print
+ // long expressions as array indexes. Then these here could
+ // be used.
+ static void test_lload() {
+ long l0 = 0L;
+ long l1 = 1L;
+ long l2 = 2L;
+ long l3 = 3L;
+ long l4 = 4L;
+ long l5 = 5L;
+
+ int[][] a = new int[6][];
+
+ // lload_0
+ try {
+ a[(int)l0][0] = 77;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("a[(int)l0][0]", e.getMessage(),
+ (hasDebugInfo ? "'a[...]'" : "'<local12>[...]'") + " is null. " +
+ "Can not store to null int array.");
+ }
+ // lload_1
+ try {
+ a[(int)l1][0] = 77;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("a[(int)l1][0]", e.getMessage(),
+ (hasDebugInfo ? "'a[...]'" : "'<local12>[...]'") + " is null. " +
+ "Can not store to null int array.");
+ }
+ // lload_2
+ try {
+ a[(int)l2][0] = 77;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("a[(int)l2][0]", e.getMessage(),
+ (hasDebugInfo ? "'a[...]'" : "'<local12>[...]'") + " is null. " +
+ "Can not store to null int array.");
+ }
+ // lload_3
+ try {
+ a[(int)l3][0] = 77;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("a[(int)l3][0]", e.getMessage(),
+ (hasDebugInfo ? "'a[...]'" : "'<local12>[...]'") + " is null. " +
+ "Can not store to null int array.");
+ }
+ // lload
+ try {
+ a[(int)l5][0] = 77;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("a[(int)l5][0]", e.getMessage(),
+ (hasDebugInfo ? "'a[...]'" : "'<local12>[...]'") + " is null. " +
+ "Can not store to null int array.");
+ }
+ }
+
+ static void test_fload() {
+ float f0 = 0.0f;
+ float f1 = 1.0f;
+ float f2 = 2.0f;
+ float f3 = 3.0f;
+ float f4 = 4.0f;
+ float f5 = 5.0f;
+
+ int[][] a = new int[6][];
+
+ // fload_0
+ try {
+ a[(int)f0][0] = 77;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("a[(int)f0][0]", e.getMessage(),
+ (hasDebugInfo ? "'a[...]'" : "'<local6>[...]'") + " is null. " +
+ "Can not store to null int array.");
+ }
+ // fload_1
+ try {
+ a[(int)f1][0] = 77;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("a[(int)f1][0]", e.getMessage(),
+ (hasDebugInfo ? "'a[...]'" : "'<local6>[...]'") + " is null. " +
+ "Can not store to null int array.");
+ }
+ // fload_2
+ try {
+ a[(int)f2][0] = 77;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("a[(int)f2][0]", e.getMessage(),
+ (hasDebugInfo ? "'a[...]'" : "'<local6>[...]'") + " is null. " +
+ "Can not store to null int array.");
+ }
+ // fload_3
+ try {
+ a[(int)f3][0] = 77;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("a[(int)f3][0]", e.getMessage(),
+ (hasDebugInfo ? "'a[...]'" : "'<local6>[...]'") + " is null. " +
+ "Can not store to null int array.");
+ }
+ // fload
+ try {
+ a[(int)f5][0] = 77;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("a[(int)f5][0]", e.getMessage(),
+ (hasDebugInfo ? "'a[...]'" : "'<local6>[...]'") + " is null. " +
+ "Can not store to null int array.");
+ }
+ }
+
+ static void test_aload() {
+ F f0 = null;
+ F f1 = null;
+ F f2 = null;
+ F f3 = null;
+ F f4 = null;
+ F f5 = null;
+
+ // aload_0
+ try {
+ f0.i = 33;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("f0.i", e.getMessage(),
+ (hasDebugInfo ? "'f0'" : "'<local0>'") + " is null. " +
+ "Can not write field 'i'.");
+ }
+ // aload_1
+ try {
+ f1.i = 33;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("f1.i", e.getMessage(),
+ (hasDebugInfo ? "'f1'" : "'<local1>'") + " is null. " +
+ "Can not write field 'i'.");
+ }
+ // aload_2
+ try {
+ f2.i = 33;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("f2.i", e.getMessage(),
+ (hasDebugInfo ? "'f2'" : "'<local2>'") + " is null. " +
+ "Can not write field 'i'.");
+ }
+ // aload_3
+ try {
+ f3.i = 33;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("f3.i", e.getMessage(),
+ (hasDebugInfo ? "'f3'" : "'<local3>'") + " is null. " +
+ "Can not write field 'i'.");
+ }
+ // aload
+ try {
+ f5.i = 33;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("f5.i", e.getMessage(),
+ (hasDebugInfo ? "'f5'" : "'<local5>'") + " is null. " +
+ "Can not write field 'i'.");
+ }
+ }
+
+ // Helper class for test cases.
class A {
public B to_b;
public B getB() { return to_b; }
}
+ // Helper class for test cases.
class B {
public C to_c;
public B to_b;
@@ -139,16 +628,83 @@
public B getBfromB() { return to_b; }
}
+ // Helper class for test cases.
class C {
public D to_d;
public D getD() { return to_d; }
}
+ // Helper class for test cases.
class D {
public int num;
public int[][] ar;
}
+
+ public void testArrayChasing() {
+ int[][][][][][] a = null;
+ try {
+ a[0][0][0][0][0][0] = 99;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("int[0][0][0][0][0] = 99 // a is null", e.getMessage(),
+ (hasDebugInfo ? "'a'" : "'<local1>'") + " is null. " +
+ "Can not load from null object array.");
+ }
+ a = new int[1][][][][][];
+ try {
+ a[0][0][0][0][0][0] = 99;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("int[0][0][0][0][0] = 99 // a[0] is null", e.getMessage(),
+ (hasDebugInfo ? "'a[0]'" : "'<local1>[0]'") + " is null. " +
+ "Can not load from null object array.");
+ }
+ a[0] = new int[1][][][][];
+ try {
+ a[0][0][0][0][0][0] = 99;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("int[0][0][0][0][0] = 99 // a[0][0] is null", e.getMessage(),
+ (hasDebugInfo ? "'a[0][0]'" : "'<local1>[0][0]'") + " is null. " +
+ "Can not load from null object array.");
+ }
+ a[0][0] = new int[1][][][];
+ try {
+ a[0][0][0][0][0][0] = 99;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("int[0][0][0][0][0] = 99 // a[0][0][0] is null", e.getMessage(),
+ (hasDebugInfo ? "'a[0][0][0]'" : "'<local1>[0][0][0]'") + " is null. " +
+ "Can not load from null object array.");
+ }
+ a[0][0][0] = new int[1][][];
+ try {
+ a[0][0][0][0][0][0] = 99;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("int[0][0][0][0][0] = 99 // a[0][0][0][0] is null", e.getMessage(),
+ (hasDebugInfo ? "'a[0][0][0][0]'" : "'<local1>[0][0][0][0]'") + " is null. " +
+ "Can not load from null object array.");
+ }
+ a[0][0][0][0] = new int[1][];
+ // Reaching max recursion depth. Prints <array>.
+ try {
+ a[0][0][0][0][0][0] = 99;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("int[0][0][0][0][0] = 99 // a[0][0][0][0][0] is null", e.getMessage(),
+ "'<array>[0][0][0][0][0]' is null. " +
+ "Can not store to null int array.");
+ }
+ a[0][0][0][0][0] = new int[1];
+ try {
+ a[0][0][0][0][0][0] = 99;
+ } catch (NullPointerException e) {
+ Asserts.fail();
+ }
+ }
+
public void testPointerChasing() {
A a = null;
try {
@@ -156,8 +712,8 @@
Asserts.fail();
} catch (NullPointerException e) {
checkMessage("a.to_b.to_c.to_d.num = 99 // a is null", e.getMessage(),
- "while trying to read the field 'to_b' of a null object loaded from " +
- (hasDebugInfo ? "local variable 'a'" : "a local variable at slot 1"));
+ (hasDebugInfo ? "'a'" : "'<local1>'") + " is null. " +
+ "Can not read field 'to_b'.");
}
a = new A();
try {
@@ -165,8 +721,8 @@
Asserts.fail();
} catch (NullPointerException e) {
checkMessage("a.to_b.to_c.to_d.num = 99 // a.to_b is null", e.getMessage(),
- "while trying to read the field 'to_c' of a null object loaded from field 'NullPointerExceptionTest$A.to_b' of an object loaded from " +
- (hasDebugInfo ? "local variable 'a'" : "a local variable at slot 1"));
+ (hasDebugInfo ? "'a.to_b'" : "'<local1>.to_b'") + " is null. " +
+ "Can not read field 'to_c'.");
}
a.to_b = new B();
try {
@@ -174,7 +730,8 @@
Asserts.fail();
} catch (NullPointerException e) {
checkMessage("a.to_b.to_c.to_d.num = 99 // a.to_b.to_c is null", e.getMessage(),
- "while trying to read the field 'to_d' of a null object loaded from field 'NullPointerExceptionTest$B.to_c' of an object loaded from field 'NullPointerExceptionTest$A.to_b' of an object");
+ (hasDebugInfo ? "'a.to_b.to_c'" : "'<local1>.to_b.to_c'") + " is null. " +
+ "Can not read field 'to_d'.");
}
a.to_b.to_c = new C();
try {
@@ -182,59 +739,8 @@
Asserts.fail();
} catch (NullPointerException e) {
checkMessage("a.to_b.to_c.to_d.num = 99 // a.to_b.to_c.to_d is null", e.getMessage(),
- "while trying to write the field 'NullPointerExceptionTest$D.num' of a null object loaded from field 'NullPointerExceptionTest$C.to_d' of an object loaded from field 'NullPointerExceptionTest$B.to_c' of an object");
- }
- }
-
- public void testArrayChasing() {
- int[][][][][] a = null;
- try {
- a[0][0][0][0][0] = 99;
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("int[0][0][0][0][0] = 99 // a is null", e.getMessage(),
- "while trying to load from a null object array loaded from " +
- (hasDebugInfo ? "local variable 'a'" : "a local variable at slot 1"));
- }
- a = new int[1][][][][];
- try {
- a[0][0][0][0][0] = 99;
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("int[0][0][0][0][0] = 99 // a[0] is null", e.getMessage(),
- "while trying to load from a null object array loaded from an array (which itself was loaded from " +
- (hasDebugInfo ? "local variable 'a'" : "a local variable at slot 1") +
- ") with an index loaded from a constant");
- }
- a[0] = new int[1][][][];
- try {
- a[0][0][0][0][0] = 99;
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("int[0][0][0][0][0] = 99 // a[0][0] is null", e.getMessage(),
- "while trying to load from a null object array loaded from an array (which itself was loaded from an array) with an index loaded from a constant");
- }
- a[0][0] = new int[1][][];
- try {
- a[0][0][0][0][0] = 99;
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("int[0][0][0][0][0] = 99 // a[0][0][0] is null", e.getMessage(),
- "while trying to load from a null object array loaded from an array (which itself was loaded from an array) with an index loaded from a constant");
- }
- a[0][0][0] = new int[1][];
- try {
- a[0][0][0][0][0] = 99;
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("int[0][0][0][0][0] = 99 // a[0][0][0][0] is null", e.getMessage(),
- "while trying to store to a null int array loaded from an array (which itself was loaded from an array) with an index loaded from a constant");
- }
- a[0][0][0][0] = new int[1];
- try {
- a[0][0][0][0][0] = 99;
- } catch (NullPointerException e) {
- Asserts.fail();
+ (hasDebugInfo ? "'a.to_b.to_c.to_d'" : "'<local1>.to_b.to_c.to_d'") + " is null. " +
+ "Can not write field 'num'.");
}
}
@@ -245,8 +751,8 @@
Asserts.fail();
} catch (NullPointerException e) {
checkMessage("a.getB().getBfromB().getC().getD().num = 99 // a is null", e.getMessage(),
- "while trying to invoke the method 'NullPointerExceptionTest$A.getB()LNullPointerExceptionTest$B;' on a null reference loaded from " +
- (hasDebugInfo ? "local variable 'a'" : "a local variable at slot 1"));
+ (hasDebugInfo ? "'a" : "'<local1>") + "' is null. " +
+ "Can not invoke method 'NullPointerExceptionTest$B NullPointerExceptionTest$A.getB()'.");
}
a = new A();
try {
@@ -254,7 +760,8 @@
Asserts.fail();
} catch (NullPointerException e) {
checkMessage("a.getB().getBfromB().getC().getD().num = 99 // a.getB() is null", e.getMessage(),
- "while trying to invoke the method 'NullPointerExceptionTest$B.getBfromB()LNullPointerExceptionTest$B;' on a null reference returned from 'NullPointerExceptionTest$A.getB()LNullPointerExceptionTest$B;'");
+ "The return value of 'NullPointerExceptionTest$B NullPointerExceptionTest$A.getB()' is null. " +
+ "Can not invoke method 'NullPointerExceptionTest$B NullPointerExceptionTest$B.getBfromB()'.");
}
a.to_b = new B();
try {
@@ -262,7 +769,8 @@
Asserts.fail();
} catch (NullPointerException e) {
checkMessage("a.getB().getBfromB().getC().getD().num = 99 // a.getB().getBfromB() is null", e.getMessage(),
- "while trying to invoke the method 'NullPointerExceptionTest$B.getC()LNullPointerExceptionTest$C;' on a null reference returned from 'NullPointerExceptionTest$B.getBfromB()LNullPointerExceptionTest$B;'");
+ "The return value of 'NullPointerExceptionTest$B NullPointerExceptionTest$B.getBfromB()' is null. " +
+ "Can not invoke method 'NullPointerExceptionTest$C NullPointerExceptionTest$B.getC()'.");
}
a.to_b.to_b = new B();
try {
@@ -270,7 +778,8 @@
Asserts.fail();
} catch (NullPointerException e) {
checkMessage("a.getB().getBfromB().getC().getD().num = 99 // a.getB().getBfromB().getC() is null", e.getMessage(),
- "while trying to invoke the method 'NullPointerExceptionTest$C.getD()LNullPointerExceptionTest$D;' on a null reference returned from 'NullPointerExceptionTest$B.getC()LNullPointerExceptionTest$C;'");
+ "The return value of 'NullPointerExceptionTest$C NullPointerExceptionTest$B.getC()' is null. " +
+ "Can not invoke method 'NullPointerExceptionTest$D NullPointerExceptionTest$C.getD()'.");
}
a.to_b.to_b.to_c = new C();
try {
@@ -278,7 +787,8 @@
Asserts.fail();
} catch (NullPointerException e) {
checkMessage("a.getB().getBfromB().getC().getD().num = 99 // a.getB().getBfromB().getC().getD() is null", e.getMessage(),
- "while trying to write the field 'NullPointerExceptionTest$D.num' of a null object returned from 'NullPointerExceptionTest$C.getD()LNullPointerExceptionTest$D;'");
+ "The return value of 'NullPointerExceptionTest$D NullPointerExceptionTest$C.getD()' is null. " +
+ "Can not write field 'num'.");
}
}
@@ -289,8 +799,8 @@
Asserts.fail();
} catch (NullPointerException e) {
checkMessage("a.getB().getBfromB().to_c.to_d.ar[0][0] = 99; // a is null", e.getMessage(),
- "while trying to invoke the method 'NullPointerExceptionTest$A.getB()LNullPointerExceptionTest$B;' on a null reference loaded from " +
- (hasDebugInfo ? "local variable 'a'" : "a local variable at slot 1"));
+ (hasDebugInfo ? "'a'" : "'<local1>'") + " is null. " +
+ "Can not invoke method 'NullPointerExceptionTest$B NullPointerExceptionTest$A.getB()'.");
}
a = new A();
try {
@@ -298,7 +808,8 @@
Asserts.fail();
} catch (NullPointerException e) {
checkMessage("a.getB().getBfromB().to_c.to_d.ar[0][0] = 99; // a.getB() is null", e.getMessage(),
- "while trying to invoke the method 'NullPointerExceptionTest$B.getBfromB()LNullPointerExceptionTest$B;' on a null reference returned from 'NullPointerExceptionTest$A.getB()LNullPointerExceptionTest$B;'");
+ "The return value of 'NullPointerExceptionTest$B NullPointerExceptionTest$A.getB()' is null. " +
+ "Can not invoke method 'NullPointerExceptionTest$B NullPointerExceptionTest$B.getBfromB()'.");
}
a.to_b = new B();
try {
@@ -306,7 +817,8 @@
Asserts.fail();
} catch (NullPointerException e) {
checkMessage("a.getB().getBfromB().to_c.to_d.ar[0][0] = 99; // a.getB().getBfromB() is null", e.getMessage(),
- "while trying to read the field 'to_c' of a null object returned from 'NullPointerExceptionTest$B.getBfromB()LNullPointerExceptionTest$B;'");
+ "The return value of 'NullPointerExceptionTest$B NullPointerExceptionTest$B.getBfromB()' is null. " +
+ "Can not read field 'to_c'.");
}
a.to_b.to_b = new B();
try {
@@ -314,7 +826,8 @@
Asserts.fail();
} catch (NullPointerException e) {
checkMessage("a.getB().getBfromB().to_c.to_d.ar[0][0] = 99; // a.getB().getBfromB().to_c is null", e.getMessage(),
- "while trying to read the field 'to_d' of a null object loaded from field 'NullPointerExceptionTest$B.to_c' of an object returned from 'NullPointerExceptionTest$B.getBfromB()LNullPointerExceptionTest$B;'");
+ "'NullPointerExceptionTest$B NullPointerExceptionTest$B.getBfromB().to_c' is null. " +
+ "Can not read field 'to_d'.");
}
a.to_b.to_b.to_c = new C();
try {
@@ -322,7 +835,8 @@
Asserts.fail();
} catch (NullPointerException e) {
checkMessage("a.getB().getBfromB().to_c.to_d.ar[0][0] = 99; // a.getB().getBfromB().to_c.to_d is null", e.getMessage(),
- "while trying to read the field 'ar' of a null object loaded from field 'NullPointerExceptionTest$C.to_d' of an object loaded from field 'NullPointerExceptionTest$B.to_c' of an object");
+ "'NullPointerExceptionTest$B NullPointerExceptionTest$B.getBfromB().to_c.to_d' is null. " +
+ "Can not read field 'ar'.");
}
a.to_b.to_b.to_c.to_d = new D();
try {
@@ -330,14 +844,16 @@
Asserts.fail();
} catch (NullPointerException e) {
checkMessage("a.getB().getBfromB().to_c.to_d.ar[0][0] = 99; // a.getB().getBfromB().to_c.to_d.ar is null", e.getMessage(),
- "while trying to load from a null object array loaded from field 'NullPointerExceptionTest$D.ar' of an object loaded from field 'NullPointerExceptionTest$C.to_d' of an object");
+ "'NullPointerExceptionTest$B NullPointerExceptionTest$B.getBfromB().to_c.to_d.ar' is null. " +
+ "Can not load from null object array.");
}
try {
a.getB().getBfromB().getC().getD().ar[0][0] = 99;
Asserts.fail();
} catch (NullPointerException e) {
checkMessage("a.getB().getBfromB().getC().getD().ar[0][0] = 99; // a.getB().getBfromB().getC().getD().ar is null", e.getMessage(),
- "while trying to load from a null object array loaded from field 'NullPointerExceptionTest$D.ar' of an object returned from 'NullPointerExceptionTest$C.getD()LNullPointerExceptionTest$D;'");
+ "'NullPointerExceptionTest$D NullPointerExceptionTest$C.getD().ar' is null. " +
+ "Can not load from null object array.");
}
a.to_b.to_b.to_c.to_d.ar = new int[1][];
try {
@@ -345,25 +861,255 @@
Asserts.fail();
} catch (NullPointerException e) {
checkMessage("a.getB().getBfromB().to_c.to_d.ar[0][0] = 99; // a.getB().getBfromB().to_c.to_d.ar[0] is null", e.getMessage(),
- "while trying to store to a null int array loaded from an array (which itself was loaded from field 'NullPointerExceptionTest$D.ar' of an object) with an index loaded from a constant");
+ "'NullPointerExceptionTest$B NullPointerExceptionTest$B.getBfromB().to_c.to_d.ar[0]' is null. " +
+ "Can not store to null int array.");
}
try {
a.getB().getBfromB().getC().getD().ar[0][0] = 99;
Asserts.fail();
} catch (NullPointerException e) {
checkMessage("a.getB().getBfromB().getC().getD().ar[0][0] = 99; // a.getB().getBfromB().getC().getD().ar[0] is null", e.getMessage(),
- "while trying to store to a null int array loaded from an array (which itself was loaded from field 'NullPointerExceptionTest$D.ar' of an object) with an index loaded from a constant");
+ "'NullPointerExceptionTest$D NullPointerExceptionTest$C.getD().ar[0]' is null. " +
+ "Can not store to null int array.");
+ }
+ }
+
+ // Helper method to cause test case.
+ private Object returnNull(String[][] dummy1, int[][][] dummy2, float dummy3) {
+ return null;
+ }
+
+ // Helper method to cause test case.
+ private NullPointerExceptionTest returnMeAsNull(Throwable dummy1, int dummy2, char dummy3) {
+ return null;
+ }
+
+ // Helper interface for test cases.
+ static interface DoubleArrayGen {
+ public double[] getArray();
+ }
+
+ // Helper class for test cases.
+ static class DoubleArrayGenImpl implements DoubleArrayGen {
+ @Override
+ public double[] getArray() {
+ return null;
+ }
+ }
+
+ // Helper class for test cases.
+ static class NullPointerGenerator {
+ public static Object nullReturner(boolean dummy1) {
+ return null;
+ }
+
+ public Object returnMyNull(double dummy1, long dummy2, short dummy3) {
+ return null;
+ }
+ }
+
+ // Helper method to cause test case.
+ public void ImplTestLoadedFromMethod(DoubleArrayGen gen) {
+ try {
+ (gen.getArray())[0] = 1.0;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("(gen.getArray())[0]", e.getMessage(),
+ "The return value of 'double[] NullPointerExceptionTest$DoubleArrayGen.getArray()' is null. Can not store to null double array.");
}
}
+ public void testNullEntity() {
+ int[][] a = new int[820][];
+
+ test_iload();
+ test_lload();
+ test_fload();
+ // test_dload();
+ test_aload();
+ // aload_0: 'this'
+ try {
+ this.nullInstanceField.nullInstanceField = null;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("this.nullInstanceField.nullInstanceField = null", e.getMessage(),
+ "'this.nullInstanceField' is null. Can not write field 'nullInstanceField'.");
+ }
+
+ // aconst_null
+ try {
+ throw null;
+ } catch (NullPointerException e) {
+ checkMessage("throw null", e.getMessage(),
+ "'null' is null. Can not throw a null exception object.");
+ }
+ // iconst_0
+ try {
+ a[0][0] = 77;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("a[0][0]", e.getMessage(),
+ (hasDebugInfo ? "'a[0]'" : "'<local1>[0]'") + " is null. " +
+ "Can not store to null int array.");
+ }
+ // iconst_1
+ try {
+ a[1][0] = 77;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("a[1][0]", e.getMessage(),
+ (hasDebugInfo ? "'a[1]'" : "'<local1>[1]'") + " is null. " +
+ "Can not store to null int array.");
+ }
+ // iconst_2
+ try {
+ a[2][0] = 77;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("a[2][0]", e.getMessage(),
+ (hasDebugInfo ? "'a[2]'" : "'<local1>[2]'") + " is null. " +
+ "Can not store to null int array.");
+ }
+ // iconst_3
+ try {
+ a[3][0] = 77;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("a[3][0]", e.getMessage(),
+ (hasDebugInfo ? "'a[3]'" : "'<local1>[3]'") + " is null. " +
+ "Can not store to null int array.");
+ }
+ // iconst_4
+ try {
+ a[4][0] = 77;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("a[4][0]", e.getMessage(),
+ (hasDebugInfo ? "'a[4]'" : "'<local1>[4]'") + " is null. " +
+ "Can not store to null int array.");
+ }
+ // iconst_5
+ try {
+ a[5][0] = 77;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("a[5][0]", e.getMessage(),
+ (hasDebugInfo ? "'a[5]'" : "'<local1>[5]'") + " is null. " +
+ "Can not store to null int array.");
+ }
+ // long --> iconst
+ try {
+ a[(int)0L][0] = 77;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("a[(int)0L][0]", e.getMessage(),
+ (hasDebugInfo ? "'a[0]'" : "'<local1>[0]'") + " is null. " +
+ "Can not store to null int array.");
+ }
+ // bipush
+ try {
+ a[139 /*0x77*/][0] = 77;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("a[139][0]", e.getMessage(),
+ (hasDebugInfo ? "'a[139]'" : "'<local1>[139]'") + " is null. " +
+ "Can not store to null int array.");
+ }
+ // sipush
+ try {
+ a[819 /*0x333*/][0] = 77;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("a[819][0]", e.getMessage(),
+ (hasDebugInfo ? "'a[819]'" : "'<local1>[819]'") + " is null. " +
+ "Can not store to null int array.");
+ }
+
+ // aaload, with recursive descend.
+ testArrayChasing();
+
+ // getstatic
+ try {
+ Asserts.assertTrue(((float[]) nullStaticField)[0] == 1.0f);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("((float[]) nullStaticField)[0]", e.getMessage(),
+ "'static NullPointerExceptionTest.nullStaticField' is null. Can not load from null float array.");
+ }
+
+ // getfield, with recursive descend.
+ testPointerChasing();
+
+ // invokestatic
+ try {
+ Asserts.assertTrue(((char[]) NullPointerGenerator.nullReturner(false))[0] == 'A');
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("((char[]) NullPointerGenerator.nullReturner(false))[0]", e.getMessage(),
+ "The return value of 'java.lang.Object NullPointerExceptionTest$NullPointerGenerator.nullReturner(boolean)' is null. Can not load from null char array.");
+ }
+ // invokevirtual
+ try {
+ Asserts.assertTrue(((char[]) (new NullPointerGenerator().returnMyNull(1, 1, (short) 1)))[0] == 'a');
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("((char[]) (new NullPointerGenerator().returnMyNull(1, 1, (short) 1)))[0]", e.getMessage(),
+ "The return value of 'java.lang.Object NullPointerExceptionTest$NullPointerGenerator.returnMyNull(double, long, short)' is null. Can not load from null char array.");
+ }
+ // Call with array arguments.
+ try {
+ Asserts.assertTrue(((double[]) returnNull(null, null, 1f))[0] == 1.0);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("((double[]) returnNull(null, null, 1f))[0] ", e.getMessage(),
+ "The return value of 'java.lang.Object NullPointerExceptionTest.returnNull(java.lang.String[][], int[][][], float)' is null. Can not load from null double array.");
+ }
+ // invokeinterface
+ ImplTestLoadedFromMethod(new DoubleArrayGenImpl());
+ try {
+ returnMeAsNull(null, 1, 'A').dag = null;
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ checkMessage("returnMeAsNull(null, 1, 'A').dag = null", e.getMessage(),
+ "The return value of 'NullPointerExceptionTest NullPointerExceptionTest.returnMeAsNull(java.lang.Throwable, int, char)' is null. Can not write field 'dag'.");
+ }
+ testMethodChasing();
+
+ // Mixed recursive descend.
+ testMixedChasing();
+
+ }
+
+
+ public void testCreation() throws Exception {
+ // If allocated with new, the message should not be generated.
+ Asserts.assertNull(new NullPointerException().getMessage());
+ String msg = new String("A pointless message.");
+ Asserts.assertTrue(new NullPointerException(msg).getMessage() == msg);
+
+ // If created via reflection, the message should not be generated.
+ Exception ex = NullPointerException.class.getDeclaredConstructor().newInstance();
+ Asserts.assertNull(ex.getMessage());
+ }
+
+ public void testNative() throws Exception {
+ // If NPE is thrown in a native method, the message should
+ // not be generated.
+ try {
+ Class.forName(null);
+ Asserts.fail();
+ } catch (NullPointerException e) {
+ Asserts.assertNull(e.getMessage());
+ }
+
+ }
// Test we get the same message calling npe.getMessage() twice.
public void testSameMessage() throws Exception {
Object null_o = null;
String expectedMsg =
- "while trying to invoke the method 'java.lang.Object.hashCode()I'" +
- " on a null reference loaded from " +
- (hasDebugInfo ? "local variable 'null_o'" : "a local variable at slot 1");
+ (hasDebugInfo ? "'null_o" : "'<local1>") + "' is null. " +
+ "Can not invoke method 'int java.lang.Object.hashCode()'.";
try {
null_o.hashCode();
@@ -374,30 +1120,13 @@
String msg2 = npe.getMessage();
Asserts.assertTrue(msg1.equals(msg2));
// It was decided that getMessage should generate the
- // message anew on every call, so this does not hold any more.
+ // message anew on every call, so this does not hold.
+ //Asserts.assertTrue(msg1 == msg2);
Asserts.assertFalse(msg1 == msg2);
}
}
- /**
- *
- */
- public void testCreationViaNew() {
- Asserts.assertNull(new NullPointerException().getMessage());
- }
-
- /**
- * @throws Exception
- */
- public void testCreationViaReflection() throws Exception {
- Exception ex = NullPointerException.class.getDeclaredConstructor().newInstance();
- Asserts.assertNull(ex.getMessage());
- }
-
- /**
- * @throws Exception
- */
- public void testCreationViaSerialization() throws Exception {
+ public void testSerialization() throws Exception {
// NPE without message.
Object o1 = new NullPointerException();
ByteArrayOutputStream bos1 = new ByteArrayOutputStream();
@@ -429,9 +1158,9 @@
} catch (NullPointerException npe3) {
o3 = npe3;
msg3 = npe3.getMessage();
- checkMessage("null_o3.hashCode()", msg3, "while trying to invoke the method 'java.lang.Object.hashCode()I'" +
- " on a null reference loaded from " +
- (hasDebugInfo ? "local variable 'null_o3'" : "a local variable at slot 14"));
+ checkMessage("null_o3.hashCode()", msg3,
+ (hasDebugInfo ? "'null_o3'" : "'<local14>'") + " is null. " +
+ "Can not invoke method 'int java.lang.Object.hashCode()'.");
}
ByteArrayOutputStream bos3 = new ByteArrayOutputStream();
ObjectOutputStream oos3 = new ObjectOutputStream(bos3);
@@ -446,791 +1175,124 @@
Asserts.assertEquals(ex3.getMessage(), null);
}
- /**
- *
- */
- @SuppressWarnings("null")
- public void testLoadedFromLocalVariable1() {
- Object o = null;
-
- try {
- o.hashCode();
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("o.hashCode()", e.getMessage(), "while trying to invoke the method 'java.lang.Object.hashCode()I' on a null reference loaded from " + (hasDebugInfo ? "local variable 'o'" : "a local variable at slot 1"));
- }
- }
-
- /**
- *
- */
- @SuppressWarnings("null")
- public void testLoadedFromLocalVariable2() {
- Exception[] myVariable = null;
-
- try {
- Asserts.assertNull(myVariable[0]);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("myVariable[0]", e.getMessage(), "while trying to load from a null object array loaded from " + (hasDebugInfo ? "local variable 'myVariable'" : "a local variable at slot 1"));
- }
- }
-
- /**
- *
- */
- @SuppressWarnings("null")
- public void testLoadedFromLocalVariable3() {
- Exception[] myVariable = null;
-
- try {
- myVariable[0] = null;
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("myVariable[0] = null", e.getMessage(), "while trying to store to a null object array loaded from " + (hasDebugInfo ? "local variable 'myVariable'" : "a local variable at slot 1"));
- }
- }
-
- /**
- *
- */
- @SuppressWarnings("null")
- public void testLoadedFromLocalVariable4() {
- Exception[] myVariable\u0096 = null;
-
- try {
- Asserts.assertTrue(myVariable\u0096.length == 0);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("myVariable\u0096.length", e.getMessage(), "while trying to get the length of a null array loaded from " + (hasDebugInfo ? "local variable 'myVariable'" : "a local variable at slot 1"));
- }
- }
-
- /**
- * @throws Exception
- */
- @SuppressWarnings("null")
- public void testLoadedFromLocalVariable5() throws Exception {
- Exception myException = null;
-
- try {
- throw myException;
- } catch (NullPointerException e) {
- checkMessage("throw myException", e.getMessage(), "while trying to throw a null exception object loaded from " + (hasDebugInfo ? "local variable 'myException'" : "a local variable at slot 1"));
- }
- }
-
- /**
- *
- */
- @SuppressWarnings("null")
- public void testLoadedFromLocalVariable6() {
- byte[] myVariable = null;
- int my_index = 1;
-
- try {
- Asserts.assertTrue(myVariable[my_index] == 0);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("myVariable[my_index]", e.getMessage(), "while trying to load from a null byte (or boolean) array loaded from " + (hasDebugInfo ? "local variable 'myVariable'" : "a local variable at slot 1"));
- }
- }
-
- /**
- *
- */
- @SuppressWarnings("null")
- public void testLoadedFromLocalVariable7() {
- byte[] myVariable = null;
-
- try {
- myVariable[System.out.hashCode()] = (byte) 0;
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("myVariable[System.out.hashCode()]", e.getMessage(), "while trying to store to a null byte (or boolean) array loaded from " + (hasDebugInfo ? "local variable 'myVariable'" : "a local variable at slot 1"));
- }
- }
-
- /**
- *
- */
- public void testLoadedFromMethod1() {
- try {
- Asserts.assertTrue(((char[]) NullPointerGenerator.nullReturner(false))[0] == 'A');
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("((char[]) NullPointerGenerator.nullReturner(false))[0]", e.getMessage(), "while trying to load from a null char array returned from 'NullPointerExceptionTest$NullPointerGenerator.nullReturner(Z)Ljava/lang/Object;'");
- }
- }
-
- /**
- *
- */
- public void testLoadedFromMethod2() {
- try {
- Asserts.assertTrue(((char[]) (new NullPointerGenerator().returnMyNull(1, 1, (short) 1)))[0] == 'a');
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("((char[]) (new NullPointerGenerator().returnMyNull(1, 1, (short) 1)))[0]", e.getMessage(), "while trying to load from a null char array returned from 'NullPointerExceptionTest$NullPointerGenerator.returnMyNull(DJS)Ljava/lang/Object;'");
- }
- }
-
- /**
- *
- */
- public void testLoadedFromMethod3() {
- try {
- Asserts.assertTrue(((double[]) returnNull(null, null, 1f))[0] == 1.0);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("((double[]) returnNull(null, null, 1f))[0] ", e.getMessage(), "while trying to load from a null double array returned from 'NullPointerExceptionTest.returnNull([[Ljava/lang/String;[[[IF)Ljava/lang/Object;'");
- }
- }
-
- /**
- *
- */
- public void testLoadedFromMethod4() {
- ImplTestLoadedFromMethod4(new DoubleArrayGenImpl());
- }
-
- /**
- * @param gen
- */
- public void ImplTestLoadedFromMethod4(DoubleArrayGen gen) {
- try {
- (gen.getArray())[0] = 1.0;
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("(gen.getArray())[0]", e.getMessage(), "while trying to store to a null double array returned from 'NullPointerExceptionTest$DoubleArrayGen.getArray()[D'");
- }
- }
-
- /**
- *
- */
- public void testLoadedFromMethod5() {
- try {
- returnMeAsNull(null, 1, 'A').dag = null;
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("returnMeAsNull(null, 1, 'A').dag = null", e.getMessage(), "while trying to write the field 'NullPointerExceptionTest.dag' of a null object returned from 'NullPointerExceptionTest.returnMeAsNull(Ljava/lang/Throwable;IC)LNullPointerExceptionTest;'");
- }
- /*
- try {
- returnMeAsNull(null, 1, 'A').dag.dag = null;
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("returnMeAsNull(null, 1, 'A').dag.dag = null", e.getMessage(), "while trying to write the field 'NullPointerExceptionTest.dag' of a null object returned from 'NullPointerExceptionTest.returnMeAsNull(Ljava/lang/Throwable;IC)LNullPointerExceptionTest;'");
- }
- */
- }
-
- /**
- *
- */
- @SuppressWarnings("null")
- public void testLoadedFromMethod6() {
- short[] sa = null;
-
- try {
- Asserts.assertTrue(sa[0] == (short) 1);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("sa[0]", e.getMessage(), "while trying to load from a null short array loaded from " + (hasDebugInfo ? "local variable 'sa'" : "a local variable at slot 1"));
- }
- }
-
- /**
- *
- */
- @SuppressWarnings("null")
- public void testLoadedFromMethod7() {
- short[] sa = null;
-
- try {
- sa[0] = 1;
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("sa[0] = 1", e.getMessage(), "while trying to store to a null short array loaded from " + (hasDebugInfo ? "local variable 'sa'" : "a local variable at slot 1"));
- }
- }
-
- /**
- *
- */
- public void testLoadedFromStaticField1() {
- try {
- Asserts.assertTrue(((float[]) nullStaticField)[0] == 1.0f);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("((float[]) nullStaticField)[0]", e.getMessage(), "while trying to load from a null float array loaded from static field 'NullPointerExceptionTest.nullStaticField'");
- }
- }
-
- /**
- *
- */
- public void testLoadedFromStaticField2() {
- try {
- ((float[]) nullStaticField)[0] = 1.0f;
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("((float[]) nullStaticField)[0] = 1.0f", e.getMessage(), "while trying to store to a null float array loaded from static field 'NullPointerExceptionTest.nullStaticField'");
- }
- }
-
- /**
- *
- */
- public void testLoadedFromStaticField3() {
- try {
- Asserts.assertTrue(staticArray[0][0][0][0] == 1);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("staticArray[0][0][0][0] // staticArray[0][0][0] is null.", e.getMessage(), "while trying to load from a null int array loaded from an array (which itself was loaded from an array) with an index loaded from a constant");
- }
- }
-
- /**
- *
- */
- public void testLoadedFromStaticField4(int myIdx, int pos) {
- try {
- staticArray[0][0][pos][myIdx] = 2;
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage(" staticArray[0][0][pos][myIdx] = 2", e.getMessage(), "while trying to store to a null int array loaded from an array (which itself was loaded from an array) with an index loaded from " + (hasDebugInfo ? "local variable 'pos'" : "the parameter nr. 2 of the method"));
- }
- }
-
- /**
- *
- */
- public void testLoadedFromStaticField5() {
- try {
- Asserts.assertTrue(staticLongArray[0][0] == 1L);
- } catch (NullPointerException e) {
- checkMessage("staticLongArray[0][0]", e.getMessage(), "while trying to load from a null long array loaded from an array (which itself was loaded from static field 'NullPointerExceptionTest.staticLongArray') with an index loaded from a constant");
- }
- }
-
- /**
- * Test bipush for index.
- */
- public void testLoadedFromStaticField5a() {
- try {
- Asserts.assertTrue(staticLongArray[139 /*0x77*/][0] == 1L);
- } catch (NullPointerException e) {
- checkMessage("staticLongArray[139][0]", e.getMessage(), "while trying to load from a null long array loaded from an array (which itself was loaded from static field 'NullPointerExceptionTest.staticLongArray') with an index loaded from a constant");
- }
- }
-
- /**
- * Test sipush for index.
- */
- public void testLoadedFromStaticField5b() {
- try {
- Asserts.assertTrue(staticLongArray[819 /*0x333*/][0] == 1L);
- } catch (NullPointerException e) {
- checkMessage("staticLongArray[819][0]", e.getMessage(), "while trying to load from a null long array loaded from an array (which itself was loaded from static field 'NullPointerExceptionTest.staticLongArray') with an index loaded from a constant");
- }
- }
-
- /**
- *
- */
- public void testLoadedFromStaticField6() {
+ public void testComplexMessages() {
try {
staticLongArray[0][0] = 2L;
Asserts.fail();
} catch (NullPointerException e) {
- checkMessage("staticLongArray[0][0] = 2L", e.getMessage(), "while trying to store to a null long array loaded from an array (which itself was loaded from static field 'NullPointerExceptionTest.staticLongArray') with an index loaded from a constant");
+ checkMessage("staticLongArray[0][0] = 2L", e.getMessage(),
+ "'static NullPointerExceptionTest.staticLongArray[0]' is null. " +
+ "Can not store to null long array.");
}
- }
- /**
- *
- */
- public void testLoadedFromInstanceField1() {
try {
Asserts.assertTrue(this.nullInstanceField.nullInstanceField == null);
Asserts.fail();
} catch (NullPointerException e) {
- checkMessage("this.nullInstanceField.nullInstanceField", e.getMessage(), "while trying to read the field 'nullInstanceField' of a null object loaded from field 'NullPointerExceptionTest.nullInstanceField' of an object loaded from 'this'");
+ checkMessage("this.nullInstanceField.nullInstanceField", e.getMessage(),
+ "'this.nullInstanceField' is null. " +
+ "Can not read field 'nullInstanceField'.");
}
- }
-
- /**
- *
- */
- public void testLoadedFromInstanceField2() {
- try {
- this.nullInstanceField.nullInstanceField = null;
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("this.nullInstanceField.nullInstanceField = null", e.getMessage(), "while trying to write the field 'NullPointerExceptionTest.nullInstanceField' of a null object loaded from field 'NullPointerExceptionTest.nullInstanceField' of an object loaded from 'this'");
- }
- }
-
- /**
- *
- */
- public void testLoadedFromInstanceField3() {
- NullPointerExceptionTest obj = this;
try {
+ NullPointerExceptionTest obj = this;
Asserts.assertNull(obj.dag.getArray().clone());
Asserts.fail();
} catch (NullPointerException e) {
- checkMessage("obj.dag.getArray().clone()", e.getMessage(), "while trying to invoke the method 'NullPointerExceptionTest$DoubleArrayGen.getArray()[D' on a null reference loaded from field 'NullPointerExceptionTest.dag' of an object loaded from " + (hasDebugInfo ? "local variable 'obj'" : "a local variable at slot 1"));
+ checkMessage("obj.dag.getArray().clone()", e.getMessage(),
+ (hasDebugInfo ? "'obj" : "'<local1>") + ".dag' is null. " +
+ "Can not invoke method 'double[] NullPointerExceptionTest$DoubleArrayGen.getArray()'.");
}
- }
-
- /**
- *
- */
- public void testLoadedFromInstanceField4() {
- int indexes[] = new int[1];
-
- NullPointerExceptionTest[] objs = new NullPointerExceptionTest[] {this};
-
try {
+ int indexes[] = new int[1];
+ NullPointerExceptionTest[] objs = new NullPointerExceptionTest[] {this};
Asserts.assertNull(objs[indexes[0]].nullInstanceField.returnNull(null, null, 1f));
Asserts.fail();
} catch (NullPointerException e) {
- checkMessage("objs[indexes[0]].nullInstanceField.returnNull(null, null, 1f", e.getMessage(), "while trying to invoke the method 'NullPointerExceptionTest.returnNull([[Ljava/lang/String;[[[IF)Ljava/lang/Object;' on a null reference loaded from field 'NullPointerExceptionTest.nullInstanceField' of an object loaded from an array");
+ checkMessage("objs[indexes[0]].nullInstanceField.returnNull(null, null, 1f)", e.getMessage(),
+ (hasDebugInfo ? "'objs[indexes" : "'<local2>[<local1>") + "[0]].nullInstanceField' is null. " +
+ "Can not invoke method 'java.lang.Object NullPointerExceptionTest.returnNull(java.lang.String[][], int[][][], float)'.");
}
- }
-
- /**
- *
- */
- public void testLoadedFromInstanceField5() {
- int indexes[] = new int[1];
-
- NullPointerExceptionTest[] objs = new NullPointerExceptionTest[] {this};
try {
- Asserts.assertNull(objs[indexes[0]].nullInstanceField.toString().toCharArray().clone());
- } catch (NullPointerException e) {
- checkMessage("objs[indexes[0]].nullInstanceField.toString().toCharArray().clone()", e.getMessage(), "while trying to invoke the method 'java.lang.Object.toString()Ljava/lang/String;' on a null reference loaded from field 'NullPointerExceptionTest.nullInstanceField' of an object loaded from an array");
- }
- }
-
- /**
- *
- */
- public void testLoadedFromInstanceField6() {
- int indexes[] = new int[1];
-
- NullPointerExceptionTest[][] objs =
- new NullPointerExceptionTest[][] {new NullPointerExceptionTest[] {this}};
-
- try {
- // Check monitorenter only, since we cannot probe monitorexit from Java.
+ int indexes[] = new int[1];
+ NullPointerExceptionTest[][] objs =
+ new NullPointerExceptionTest[][] {new NullPointerExceptionTest[] {this}};
synchronized (objs[indexes[0]][0].nullInstanceField) {
Asserts.fail();
}
} catch (NullPointerException e) {
- checkMessage("synchronized (objs[indexes[0]][0].nullInstanceField)", e.getMessage(), "while trying to enter a null monitor loaded from field 'NullPointerExceptionTest.nullInstanceField' of an object loaded from an array");
- }
- }
-
- /**
- * @throws ClassNotFoundException
- */
- public void testInNative() throws ClassNotFoundException {
- try {
- Class.forName(null);
- Asserts.fail();
- } catch (NullPointerException e) {
- Asserts.assertNull(e.getMessage());
- }
- }
-
- private Object returnNull(String[][] dummy1, int[][][] dummy2, float dummy3) {
- return null;
- }
-
- private NullPointerExceptionTest returnMeAsNull(Throwable dummy1, int dummy2, char dummy3){
- return null;
- }
-
- static interface DoubleArrayGen {
- public double[] getArray();
- }
-
- static class DoubleArrayGenImpl implements DoubleArrayGen {
- @Override
- public double[] getArray() {
- return null;
- }
- }
-
- static class NullPointerGenerator {
- public static Object nullReturner(boolean dummy1) {
- return null;
- }
-
- public Object returnMyNull(double dummy1, long dummy2, short dummy3) {
- return null;
- }
- }
-
- /**
- *
- */
- public void testMissingLocalVariableTable() {
- doTestMissingLocalVariableTable(names);
-
- String[] expectedHasDebugInfoGoodNames = new String[] {
- "while trying to invoke the method 'java.lang.Object.hashCode()I' on a null reference " +
- "loaded from field 'NullPointerExceptionTest.nullInstanceField' " +
- "of an object loaded from 'this'",
- "while trying to invoke the method 'java.lang.Object.hashCode()I' on a null reference loaded from " +
- "local variable 'a1'",
- "while trying to invoke the method 'java.lang.Object.hashCode()I' on a null reference loaded from " +
- "local variable 'o1'",
- "while trying to invoke the method 'java.lang.Object.hashCode()I' on a null reference loaded from " +
- "local variable 'aa1'"
- };
-
- String[] expectedNoDebugInfoGoodNames = new String[] {
- "while trying to invoke the method 'java.lang.Object.hashCode()I' on a null reference " +
- "loaded from field 'NullPointerExceptionTest.nullInstanceField' " +
- "of an object loaded from 'this'",
- "while trying to invoke the method 'java.lang.Object.hashCode()I' on a null reference loaded from " +
- "the parameter nr. 5 of the method",
- "while trying to invoke the method 'java.lang.Object.hashCode()I' on a null reference loaded from " +
- "the parameter nr. 2 of the method",
- "while trying to invoke the method 'java.lang.Object.hashCode()I' on a null reference loaded from " +
- "the parameter nr. 9 of the method"
- };
-
- String[] expectedNames;
- if (hasDebugInfo) {
- expectedNames = expectedHasDebugInfoGoodNames;
- } else {
- expectedNames = expectedNoDebugInfoGoodNames;
- }
-
- // The two lists of messages should have the same length.
- Asserts.assertEquals(names.size(), expectedNames.length);
-
- for (int i = 0; i < expectedNames.length; ++i) {
- // GLGLGL not for now Asserts.assertEquals(names.get(i), expectedNames[i]);
- }
- }
-
- private void doTestMissingLocalVariableTable(ArrayList<String> names) {
- curr = names;
- doTestMissingLocalVariableTable1();
- doTestMissingLocalVariableTable2(-1, null, false, 0.0, null, 0.1f, (byte) 0, (short) 0, null);
- }
-
- private void doTestMissingLocalVariableTable1() {
- try {
- this.nullInstanceField.hashCode();
- Asserts.fail();
- } catch (NullPointerException e) {
- curr.add(e.getMessage());
- }
- }
-
- private void doTestMissingLocalVariableTable2(long l1, Object o1, boolean z1, double d1, Object[] a1,
- float f1, byte b1, short s1, Object[][] aa1) {
- try {
- a1.hashCode();
- Asserts.fail();
- }
- catch (NullPointerException e) {
- curr.add(e.getMessage());
- }
-
- try {
- o1.hashCode();
- Asserts.fail();
- }
- catch (NullPointerException e) {
- curr.add(e.getMessage());
- }
-
- try {
- aa1.hashCode();
- Asserts.fail();
- }
- catch (NullPointerException e) {
- curr.add(e.getMessage());
+ checkMessage("synchronized (objs[indexes[0]][0].nullInstanceField)", e.getMessage(),
+ (hasDebugInfo ? "'objs[indexes" : "'<local2>[<local1>" ) + "[0]][0].nullInstanceField' is null. " +
+ "Can not enter a null monitor.");
}
}
- /**
- *
- */
- @SuppressWarnings("null")
- public void testNullMessages() {
- boolean[] za1 = null;
- byte[] ba1 = null;
- short[] sa1 = null;
- char[] ca1 = null;
- int[] ia1 = null;
- long[] la1 = null;
- float[] fa1 = null;
- double[] da1 = null;
- Object[] oa1 = null;
-
- Object[][] oa2 = new Object[2][];
- oa2[1] = oa1;
-
- try {
- System.out.println(oa2[1][0]);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("oa2[1][0]", e.getMessage(),
- "while trying to load from a null object array loaded from an array " +
- "(which itself was loaded from " +
- (hasDebugInfo ? "local variable 'oa2'" : "a local variable at slot 10") + ") " +
- "with an index loaded from a constant");
- }
-
-
- try {
- System.out.println(za1[0]);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("za1[0]", e.getMessage(),
- "while trying to load from a null byte (or boolean) array loaded from " +
- (hasDebugInfo ? "local variable 'za1'" : "a local variable at slot 1"));
- }
-
- try {
- System.out.println(ba1[0]);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("ba1[0]", e.getMessage(),
- "while trying to load from a null byte (or boolean) array loaded from " +
- (hasDebugInfo ? "local variable 'ba1'" : "a local variable at slot 2"));
- }
-
- try {
- System.out.println(sa1[0]);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("sa1[0]", e.getMessage(),
- "while trying to load from a null short array loaded from " +
- (hasDebugInfo ? "local variable 'sa1'" : "a local variable at slot 3"));
- }
+ // Generates:
+ // class E implements E0 {
+ // public int throwNPE(F f) {
+ // return f.i;
+ // }
+ // }
+ static byte[] generateTestClass() {
+ ClassWriter cw = new ClassWriter(0);
+ MethodVisitor mv;
- try {
- System.out.println(ca1[0]);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("ca1[0]", e.getMessage(),
- "while trying to load from a null char array loaded from " +
- (hasDebugInfo ? "local variable 'ca1'" : "a local variable at slot 4"));
- }
-
- try {
- System.out.println(ia1[0]);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("ia1[0]", e.getMessage(),
- "while trying to load from a null int array loaded from " +
- (hasDebugInfo ? "local variable 'ia1'" : "a local variable at slot 5"));
- }
-
- try {
- System.out.println(la1[0]);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("la1[0]", e.getMessage(),
- "while trying to load from a null long array loaded from " +
- (hasDebugInfo ? "local variable 'la1'" : "a local variable at slot 6"));
- }
+ cw.visit(57, ACC_SUPER, "E", null, "java/lang/Object", new String[] { "E0" });
- try {
- System.out.println(fa1[0]);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("fa1[0]", e.getMessage(),
- "while trying to load from a null float array loaded from " +
- (hasDebugInfo ? "local variable 'fa1'" : "a local variable at slot 7"));
- }
-
- try {
- System.out.println(da1[0]);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("da1[0]", e.getMessage(),
- "while trying to load from a null double array loaded from " +
- (hasDebugInfo ? "local variable 'da1'" : "a local variable at slot 8"));
- }
-
- try {
- System.out.println(oa1[0]);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("oa1[0]", e.getMessage(),
- "while trying to load from a null object array loaded from " +
- (hasDebugInfo ? "local variable 'oa1'" : "a local variable at slot 9"));
- }
-
- try {
- System.out.println(za1[0] = false);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("za1[0] = false", e.getMessage(),
- "while trying to store to a null byte (or boolean) array loaded from " +
- (hasDebugInfo ? "local variable 'za1'" : "a local variable at slot 1"));
- }
-
- try {
- System.out.println(ba1[0] = 0);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("ba1[0] = 0", e.getMessage(),
- "while trying to store to a null byte (or boolean) array loaded from " +
- (hasDebugInfo ? "local variable 'ba1'" : "a local variable at slot 2"));
+ {
+ mv = cw.visitMethod(0, "<init>", "()V", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
}
- try {
- System.out.println(sa1[0] = 0);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("sa1[0] = 0", e.getMessage(),
- "while trying to store to a null short array loaded from " +
- (hasDebugInfo ? "local variable 'sa1'" : "a local variable at slot 3"));
+ {
+ mv = cw.visitMethod(ACC_PUBLIC, "throwNPE", "(LF;)I", null, null);
+ mv.visitCode();
+ Label label0 = new Label();
+ mv.visitLabel(label0);
+ mv.visitLineNumber(118, label0);
+ mv.visitVarInsn(ALOAD, 1);
+ mv.visitFieldInsn(GETFIELD, "F", "i", "I");
+ mv.visitInsn(IRETURN);
+ Label label1 = new Label();
+ mv.visitLabel(label1);
+ mv.visitLocalVariable("this", "LE;", null, label0, label1, 0);
+ mv.visitLocalVariable("f", "LE;", null, label0, label1, 1);
+ mv.visitMaxs(1, 2);
+ mv.visitEnd();
}
-
- try {
- System.out.println(ca1[0] = 0);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("ca1[0] = 0", e.getMessage(),
- "while trying to store to a null char array loaded from " +
- (hasDebugInfo ? "local variable 'ca1'" : "a local variable at slot 4"));
- }
-
- try {
- System.out.println(ia1[0] = 0);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("ia1[0] = 0", e.getMessage(),
- "while trying to store to a null int array loaded from " +
- (hasDebugInfo ? "local variable 'ia1'" : "a local variable at slot 5"));
- }
+ cw.visitEnd();
- try {
- System.out.println(la1[0] = 0);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("la1[0] = 0", e.getMessage(),
- "while trying to store to a null long array loaded from " +
- (hasDebugInfo ? "local variable 'la1'" : "a local variable at slot 6"));
- }
-
- try {
- System.out.println(fa1[0] = 0);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("fa1[0] = 0", e.getMessage(),
- "while trying to store to a null float array loaded from " +
- (hasDebugInfo ? "local variable 'fa1'" : "a local variable at slot 7"));
- }
+ return cw.toByteArray();
+ }
- try {
- System.out.println(da1[0] = 0);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("da1[0] = 0", e.getMessage(),
- "while trying to store to a null double array loaded from " +
- (hasDebugInfo ? "local variable 'da1'" : "a local variable at slot 8"));
- }
-
- try {
- System.out.println(oa1[0] = null);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("oa1[0] = null", e.getMessage(),
- "while trying to store to a null object array loaded from " +
- (hasDebugInfo ? "local variable 'oa1'" : "a local variable at slot 9"));
- }
-
+ // Tests that a class generated on the fly is handled properly.
+ public void testGeneratedCode() throws Exception {
+ byte[] classBytes = generateTestClass();
+ Lookup lookup = lookup();
+ Class<?> clazz = lookup.defineClass(classBytes);
+ E0 e = (E0) clazz.getDeclaredConstructor().newInstance();
try {
- System.out.println(nullInstanceField.nullInstanceField);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("nullInstanceField.nullInstanceField", e.getMessage(),
- "while trying to read the field 'nullInstanceField' of a null object loaded " +
- "from field 'NullPointerExceptionTest.nullInstanceField' of an object " +
- "loaded from 'this'");
- }
-
- try {
- System.out.println(nullInstanceField.nullInstanceField = null);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("nullInstanceField.nullInstanceField = null", e.getMessage(),
- "while trying to write the field 'NullPointerExceptionTest.nullInstanceField' " +
- "of a null object loaded from field 'NullPointerExceptionTest.nullInstanceField' " +
- "of an object loaded from 'this'");
- }
-
- try {
- System.out.println(za1.length);
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("za1.length", e.getMessage(),
- "while trying to get the length of a null array loaded from " +
- (hasDebugInfo ? "local variable 'za1'" : "a local variable at slot 1"));
- }
-
- try {
- throw null;
- } catch (NullPointerException e) {
- checkMessage("throw null", e.getMessage(),
- "while trying to throw a null exception object loaded " +
- "from a constant");
- }
-
- try {
- synchronized (nullInstanceField) {
- // desired
- }
- } catch (NullPointerException e) {
- checkMessage("synchronized (nullInstanceField)", e.getMessage(),
- "while trying to enter a null monitor loaded from field " +
- "'NullPointerExceptionTest.nullInstanceField' of an object loaded from " +
- "'this'");
- }
-
- try {
- nullInstanceField.testCreationViaNew();
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("nullInstanceField.testCreationViaNew()", e.getMessage(),
- "while trying to invoke the method 'NullPointerExceptionTest.testCreationViaNew()V' on a null reference " +
- "loaded from field 'NullPointerExceptionTest.nullInstanceField' of an " +
- "object loaded from 'this'");
- }
-
- try {
- nullInstanceField.testNullMessages();
- Asserts.fail();
- } catch (NullPointerException e) {
- checkMessage("nullInstanceField.testNullMessages()", e.getMessage(),
- "while trying to invoke the method 'NullPointerExceptionTest.testNullMessages()V' on a null reference " +
- "loaded from field 'NullPointerExceptionTest.nullInstanceField' of an " +
- "object loaded from 'this'");
- }
-
- try {
- // If we can get the value from more than one bci, we cannot know which one.
- (Math.random() < 0.5 ? oa1 : (new Object[1])[0]).equals("");
- } catch (NullPointerException e) {
- checkMessage("(Math.random() < 0.5 ? oa1 : (new Object[1])[0]).equals(\"\")", e.getMessage(),
- "while trying to invoke the method 'java.lang.Object.equals(Ljava/lang/Object;)Z' on a null reference");
+ e.throwNPE(null);
+ } catch (NullPointerException ex) {
+ checkMessage("return f.i;",
+ ex.getMessage(),
+ "'f' is null. Can not read field 'i'.");
}
}
}
+
+// Helper interface for test cases needed for generateTestClass().
+interface E0 {
+ public int throwNPE(F f);
+}
+
+// Helper class for test cases needed for generateTestClass().
+class F {
+ int i;
+}