Mercurial > hg > release > icedtea7-forest-2.5 > hotspot
changeset 5692:cc04abb12fea icedtea-2.5.4pre01
Merge jdk7u71-b14
author | andrew |
---|---|
date | Thu, 16 Oct 2014 16:01:21 +0100 |
parents | 4dc4b096589a (current diff) ad909197a1ce (diff) |
children | 0c2c813ea665 |
files | .hgtags make/hotspot_version src/share/vm/adlc/formssel.cpp src/share/vm/classfile/classFileParser.cpp src/share/vm/classfile/verifier.cpp src/share/vm/classfile/verifier.hpp src/share/vm/interpreter/linkResolver.cpp src/share/vm/opto/graphKit.cpp src/share/vm/opto/graphKit.hpp src/share/vm/opto/library_call.cpp src/share/vm/opto/reg_split.cpp src/share/vm/opto/type.hpp src/share/vm/prims/jvm.cpp src/share/vm/prims/jvm.h src/share/vm/runtime/arguments.cpp src/share/vm/runtime/globals.hpp test/testlibrary/OutputAnalyzerTest.java |
diffstat | 24 files changed, 1525 insertions(+), 274 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Tue Oct 14 21:12:32 2014 +0100 +++ b/.hgtags Thu Oct 16 16:01:21 2014 +0100 @@ -648,6 +648,9 @@ 8175599864880938d68d0a515fa561043d7d5fd0 jdk7u55-b31 ba9270b8fb1f4852ff1d9dab15571eb9e0714495 jdk7u55-b32 0901a8cf66a0494b55bf104c9666d4e3c6ff93f0 jdk7u55-b33 +278d7e230b297a4632b94ddc07d591e74736e039 jdk7u55-b34 +db88943dba0b7672a09e22974934022fbe8ba8dd jdk7u55-b35 +b3e388601b0fc0922b311e2cc68b9417cedd16ef jdk7u55-b36 ae4adc1492d1c90a70bd2d139a939fc0c8329be9 jdk7u60-b00 af1fc2868a2b919727bfbb0858449bd991bbee4a jdk7u40-b60 cc83359f5e5eb46dd9176b0a272390b1a0a51fdc hs24.60-b01 @@ -688,6 +691,10 @@ f106b1f551d7ae8ef8d493b87818ada0f0bcdd8f icedtea-2.5pre07 5dc3dd2819c8066197d931a213b3cf23b2758e6c icedtea-2.5pre08 5dc3dd2819c8066197d931a213b3cf23b2758e6c icedtea-2.5.0 +13f561930b3e80a94e2baddc51dfc6c43c5ca601 jdk7u60-b30 +35b2dbe7f7c69ea0f2feb1e66fe8651511a5fb6d jdk7u60-b31 +f166d2e391993f1b12b4ad1685baf999c78e6372 jdk7u60-b32 +cc1fea28c886ef100632247a708eac0c83640914 jdk7u60-b33 eb797fab50d3b440b17b3e7c5d83f42bfa73655e jdk7u65-b02 bb00df28ecdbd0da89ab4ed81f6f2b732fa512da jdk7u65-b03 848481af9003067546c7f34c166bb8d745b95d5f jdk7u65-b04 @@ -712,3 +719,34 @@ 9f719e4c80af23dc6574df3e431ad85c29a1937d icedtea-2.5.3pre01 7ce2690d2182cf6643b9860cdd64cc0c7ed72826 icedtea-2.5.3pre02 1d0d98e7c98104a48513aa684b85e5dfdf77c7f0 icedtea-2.5.3 +c43b0b843f897a4d8cf0a3566b017b87230dd3b4 jdk7u65-b32 +d3c9265e12fa115052f18d1e3d379143b56bbf63 jdk7u65-b20 +39776d90970221dd260187acb4c37631e41a66a9 jdk7u67-b01 +1d8226b3e9896656451801393eb3ae394faeb638 jdk7u65-b40 +cf8b3a090e597e59177c5f67d44cdec12309777f jdk7u65-b31 +df855c3f4d31dd7db081d68e3054518380127893 jdk7u65-b33 +6b37a189944aaa09e81d97d394496464d16bee42 jdk7u66-b00 +121dc94194d9234e2b13c867d875e23e1bdd6abd jdk7u66-b01 +f28ea516eb0b9e99f1e342954ab4642456af4da1 jdk7u66-b09 +3dc6ae1972a45ba563518cc0e51f09885258f69d jdk7u66-b10 +8d2b3f7d5b3001d019832476d684679ca6be0c8d jdk7u66-b11 +5ee19b64ef208daaef91f063d800aa162427f8f6 jdk7u66-b12 +a1e6f9c4c1f47be1b0edef6bd92399f8f07b7d15 jdk7u66-b13 +b44baba406f2de6eeccc57dbfae653cf124b527b jdk7u66-b14 +d20b495c96d3f8899a64657aba0fc72799773cb3 jdk7u66-b15 +3bbfed065c601187449d319fd70bba6ae1ebb707 jdk7u66-b16 +4abb71ff14b2e6cf932e5c61900f480d5e1afedb jdk7u66-b17 +4ceb9c03fe8ee6b93d22854780ef8c737edd14b2 jdk7u71-b00 +f95d6d32e08006209f1798f82b60d7d05767a3e8 jdk7u71-b01 +1c760efe2d0795f4ce8260ec655b8870bfd77ca1 jdk7u71-b02 +0cb0b5abd0b5aa25fc8bd5920c8d61c5b85a10c6 jdk7u71-b03 +a491e5e52998c23502ebb1340955e3e726d44ad6 jdk7u71-b04 +c93efe6377ffd7484c50cba9a88a37bebf525114 jdk7u71-b05 +f95fa655cc119659686ba68c7242497fd209f9e1 jdk7u71-b06 +7f32b65fde34db41bf951ed81374240840ef88f4 jdk7u71-b07 +4e17bd4fb2304d068023d9d805e86d6b592d4230 jdk7u71-b08 +1ffc702334d960aa4015e5cc6f4fb9e971952b54 jdk7u71-b09 +9a17c184bcb99f13dc6ab714ad98976410429637 jdk7u71-b10 +d6cb97651f0bd8d61f4d22aa7550145bbe6fb051 jdk7u71-b11 +959b4e5d2e3111920c198187f3bc66eba3e457f1 jdk7u71-b12 +608f470d22689bab17bab0ea1dbee3e1a0802d5b jdk7u71-b13
--- a/make/hotspot_version Tue Oct 14 21:12:32 2014 +0100 +++ b/make/hotspot_version Thu Oct 16 16:01:21 2014 +0100 @@ -34,8 +34,8 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2014 HS_MAJOR_VER=24 -HS_MINOR_VER=65 -HS_BUILD_NUMBER=04 +HS_MINOR_VER=71 +HS_BUILD_NUMBER=01 JDK_MAJOR_VER=1 JDK_MINOR_VER=7
--- a/make/windows/makefiles/trace.make Tue Oct 14 21:12:32 2014 +0100 +++ b/make/windows/makefiles/trace.make Thu Oct 16 16:01:21 2014 +0100 @@ -40,8 +40,7 @@ traceEventIds.hpp \ traceTypes.hpp - -!if "$(OPENJDK)" != "true" +!if EXISTS($(TraceAltSrcDir)) TraceGeneratedNames = $(TraceGeneratedNames) \ traceRequestables.hpp \ traceEventControl.hpp \ @@ -56,7 +55,7 @@ $(TraceOutDir)/traceEventIds.hpp \ $(TraceOutDir)/traceTypes.hpp -!if "$(OPENJDK)" != "true" +!if EXISTS($(TraceAltSrcDir)) TraceGeneratedFiles = $(TraceGeneratedFiles) \ $(TraceOutDir)/traceRequestables.hpp \ $(TraceOutDir)/traceEventControl.hpp \ @@ -68,7 +67,7 @@ XML_DEPS = $(TraceSrcDir)/trace.xml $(TraceSrcDir)/tracetypes.xml \ $(TraceSrcDir)/trace.dtd $(TraceSrcDir)/xinclude.mod -!if "$(OPENJDK)" != "true" +!if EXISTS($(TraceAltSrcDir)) XML_DEPS = $(XML_DEPS) $(TraceAltSrcDir)/traceevents.xml !endif @@ -87,7 +86,7 @@ @echo Generating $@ @$(XSLT) -IN $(TraceSrcDir)/trace.xml -XSL $(TraceSrcDir)/traceTypes.xsl -OUT $(TraceOutDir)/traceTypes.hpp -!if "$(OPENJDK)" == "true" +!if !EXISTS($(TraceAltSrcDir)) $(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventClasses.xsl $(XML_DEPS) @echo Generating $@
--- a/src/share/vm/classfile/verifier.cpp Tue Oct 14 21:12:32 2014 +0100 +++ b/src/share/vm/classfile/verifier.cpp Thu Oct 16 16:01:21 2014 +0100 @@ -2222,6 +2222,181 @@ } } +// Look at the method's handlers. If the bci is in the handler's try block +// then check if the handler_pc is already on the stack. If not, push it. +void ClassVerifier::push_handlers(ExceptionTable* exhandlers, + GrowableArray<u4>* handler_stack, + u4 bci) { + int exlength = exhandlers->length(); + for(int x = 0; x < exlength; x++) { + if (bci >= exhandlers->start_pc(x) && bci < exhandlers->end_pc(x)) { + handler_stack->append_if_missing(exhandlers->handler_pc(x)); + } + } +} + +// Return TRUE if all code paths starting with start_bc_offset end in +// bytecode athrow or loop. +bool ClassVerifier::ends_in_athrow(u4 start_bc_offset) { + ResourceMark rm; + // Create bytecode stream. + RawBytecodeStream bcs(method()); + u4 code_length = method()->code_size(); + bcs.set_start(start_bc_offset); + u4 target; + // Create stack for storing bytecode start offsets for if* and *switch. + GrowableArray<u4>* bci_stack = new GrowableArray<u4>(30); + // Create stack for handlers for try blocks containing this handler. + GrowableArray<u4>* handler_stack = new GrowableArray<u4>(30); + // Create list of visited branch opcodes (goto* and if*). + GrowableArray<u4>* visited_branches = new GrowableArray<u4>(30); + ExceptionTable exhandlers(_method()); + + while (true) { + if (bcs.is_last_bytecode()) { + // if no more starting offsets to parse or if at the end of the + // method then return false. + if ((bci_stack->is_empty()) || ((u4)bcs.end_bci() == code_length)) + return false; + // Pop a bytecode starting offset and scan from there. + bcs.set_start(bci_stack->pop()); + } + Bytecodes::Code opcode = bcs.raw_next(); + u4 bci = bcs.bci(); + + // If the bytecode is in a TRY block, push its handlers so they + // will get parsed. + push_handlers(&exhandlers, handler_stack, bci); + + switch (opcode) { + case Bytecodes::_if_icmpeq: + case Bytecodes::_if_icmpne: + case Bytecodes::_if_icmplt: + case Bytecodes::_if_icmpge: + case Bytecodes::_if_icmpgt: + case Bytecodes::_if_icmple: + case Bytecodes::_ifeq: + case Bytecodes::_ifne: + case Bytecodes::_iflt: + case Bytecodes::_ifge: + case Bytecodes::_ifgt: + case Bytecodes::_ifle: + case Bytecodes::_if_acmpeq: + case Bytecodes::_if_acmpne: + case Bytecodes::_ifnull: + case Bytecodes::_ifnonnull: + target = bcs.dest(); + if (visited_branches->contains(bci)) { + if (bci_stack->is_empty()) return true; + // Pop a bytecode starting offset and scan from there. + bcs.set_start(bci_stack->pop()); + } else { + if (target > bci) { // forward branch + if (target >= code_length) return false; + // Push the branch target onto the stack. + bci_stack->push(target); + // then, scan bytecodes starting with next. + bcs.set_start(bcs.next_bci()); + } else { // backward branch + // Push bytecode offset following backward branch onto the stack. + bci_stack->push(bcs.next_bci()); + // Check bytecodes starting with branch target. + bcs.set_start(target); + } + // Record target so we don't branch here again. + visited_branches->append(bci); + } + break; + + case Bytecodes::_goto: + case Bytecodes::_goto_w: + target = (opcode == Bytecodes::_goto ? bcs.dest() : bcs.dest_w()); + if (visited_branches->contains(bci)) { + if (bci_stack->is_empty()) return true; + // Been here before, pop new starting offset from stack. + bcs.set_start(bci_stack->pop()); + } else { + if (target >= code_length) return false; + // Continue scanning from the target onward. + bcs.set_start(target); + // Record target so we don't branch here again. + visited_branches->append(bci); + } + break; + + // Check that all switch alternatives end in 'athrow' bytecodes. Since it + // is difficult to determine where each switch alternative ends, parse + // each switch alternative until either hit a 'return', 'athrow', or reach + // the end of the method's bytecodes. This is gross but should be okay + // because: + // 1. tableswitch and lookupswitch byte codes in handlers for ctor explicit + // constructor invocations should be rare. + // 2. if each switch alternative ends in an athrow then the parsing should be + // short. If there is no athrow then it is bogus code, anyway. + case Bytecodes::_lookupswitch: + case Bytecodes::_tableswitch: + { + address aligned_bcp = (address) round_to((intptr_t)(bcs.bcp() + 1), jintSize); + u4 default_offset = Bytes::get_Java_u4(aligned_bcp) + bci; + int keys, delta; + if (opcode == Bytecodes::_tableswitch) { + jint low = (jint)Bytes::get_Java_u4(aligned_bcp + jintSize); + jint high = (jint)Bytes::get_Java_u4(aligned_bcp + 2*jintSize); + // This is invalid, but let the regular bytecode verifier + // report this because the user will get a better error message. + if (low > high) return true; + keys = high - low + 1; + delta = 1; + } else { + keys = (int)Bytes::get_Java_u4(aligned_bcp + jintSize); + delta = 2; + } + // Invalid, let the regular bytecode verifier deal with it. + if (keys < 0) return true; + + // Push the offset of the next bytecode onto the stack. + bci_stack->push(bcs.next_bci()); + + // Push the switch alternatives onto the stack. + for (int i = 0; i < keys; i++) { + u4 target = bci + (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize); + if (target > code_length) return false; + bci_stack->push(target); + } + + // Start bytecode parsing for the switch at the default alternative. + if (default_offset > code_length) return false; + bcs.set_start(default_offset); + break; + } + + case Bytecodes::_return: + return false; + + case Bytecodes::_athrow: + { + if (bci_stack->is_empty()) { + if (handler_stack->is_empty()) { + return true; + } else { + // Parse the catch handlers for try blocks containing athrow. + bcs.set_start(handler_stack->pop()); + } + } else { + // Pop a bytecode offset and starting scanning from there. + bcs.set_start(bci_stack->pop()); + } + } + break; + + default: + ; + } // end switch + } // end while loop + + return false; +} + void ClassVerifier::verify_invoke_init( RawBytecodeStream* bcs, u2 ref_class_index, VerificationType ref_class_type, StackMapFrame* current_frame, u4 code_length, bool *this_uninit, @@ -2249,10 +2424,20 @@ ExceptionTable exhandlers(_method()); int exlength = exhandlers.length(); for(int i = 0; i < exlength; i++) { - if (bci >= exhandlers.start_pc(i)) { - verify_error(ErrorContext::bad_code(bci), - "Bad <init> method call from after the start of a try block"); - return; + u2 start_pc = exhandlers.start_pc(i); + u2 end_pc = exhandlers.end_pc(i); + + if (bci >= start_pc && bci < end_pc) { + if (!ends_in_athrow(exhandlers.handler_pc(i))) { + verify_error(ErrorContext::bad_code(bci), + "Bad <init> method call from after the start of a try block"); + return; + } else if (VerboseVerification) { + ResourceMark rm; + tty->print_cr( + "Survived call to ends_in_athrow(): %s", + current_class()->name()->as_C_string()); + } } }
--- a/src/share/vm/classfile/verifier.hpp Tue Oct 14 21:12:32 2014 +0100 +++ b/src/share/vm/classfile/verifier.hpp Thu Oct 16 16:01:21 2014 +0100 @@ -30,6 +30,7 @@ #include "oops/klass.hpp" #include "oops/methodOop.hpp" #include "runtime/handles.hpp" +#include "utilities/growableArray.hpp" #include "utilities/exceptions.hpp" // The verifier class @@ -301,6 +302,16 @@ StackMapFrame* current_frame, u4 code_length, bool* this_uninit, constantPoolHandle cp, TRAPS); + // Used by ends_in_athrow() to push all handlers that contain bci onto + // the handler_stack, if the handler is not already on the stack. + void push_handlers(ExceptionTable* exhandlers, + GrowableArray<u4>* handler_stack, + u4 bci); + + // Returns true if all paths starting with start_bc_offset end in athrow + // bytecode or loop. + bool ends_in_athrow(u4 start_bc_offset); + void verify_invoke_instructions( RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame, bool* this_uninit, VerificationType return_type,
--- a/src/share/vm/opto/graphKit.cpp Tue Oct 14 21:12:32 2014 +0100 +++ b/src/share/vm/opto/graphKit.cpp Thu Oct 16 16:01:21 2014 +0100 @@ -1121,6 +1121,17 @@ } return _gvn.transform( new (C) ConvI2LNode(offset)); } + +Node* GraphKit::ConvI2UL(Node* offset) { + juint offset_con = (juint) find_int_con(offset, Type::OffsetBot); + if (offset_con != (juint) Type::OffsetBot) { + return longcon((julong) offset_con); + } + Node* conv = _gvn.transform( new (C) ConvI2LNode(offset)); + Node* mask = _gvn.transform( ConLNode::make(C, (julong) max_juint) ); + return _gvn.transform( new (C) AndLNode(conv, mask) ); +} + Node* GraphKit::ConvL2I(Node* offset) { // short-circuit a common case jlong offset_con = find_long_con(offset, (jlong)Type::OffsetBot);
--- a/src/share/vm/opto/graphKit.hpp Tue Oct 14 21:12:32 2014 +0100 +++ b/src/share/vm/opto/graphKit.hpp Thu Oct 16 16:01:21 2014 +0100 @@ -338,6 +338,7 @@ // Convert between int and long, and size_t. // (See macros ConvI2X, etc., in type.hpp for ConvI2X, etc.) Node* ConvI2L(Node* offset); + Node* ConvI2UL(Node* offset); Node* ConvL2I(Node* offset); // Find out the klass of an object. Node* load_object_klass(Node* object);
--- a/src/share/vm/opto/library_call.cpp Tue Oct 14 21:12:32 2014 +0100 +++ b/src/share/vm/opto/library_call.cpp Thu Oct 16 16:01:21 2014 +0100 @@ -2438,7 +2438,7 @@ case T_ADDRESS: // Cast to an int type. p = _gvn.transform(new (C) CastP2XNode(NULL, p)); - p = ConvX2L(p); + p = ConvX2UL(p); break; default: fatal(err_msg_res("unexpected type %d: %s", type, type2name(type)));
--- a/src/share/vm/opto/type.hpp Tue Oct 14 21:12:32 2014 +0100 +++ b/src/share/vm/opto/type.hpp Thu Oct 16 16:01:21 2014 +0100 @@ -1351,6 +1351,7 @@ #define ConvL2X(x) (x) #define ConvX2I(x) ConvL2I(x) #define ConvX2L(x) (x) +#define ConvX2UL(x) (x) #else @@ -1395,6 +1396,7 @@ #define ConvL2X(x) ConvL2I(x) #define ConvX2I(x) (x) #define ConvX2L(x) ConvI2L(x) +#define ConvX2UL(x) ConvI2UL(x) #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/6653795/UnsafeGetAddressTest.java Thu Oct 16 16:01:21 2014 +0100 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6653795 + * @summary C2 intrinsic for Unsafe.getAddress performs pointer sign extension on 32-bit systems + * @run main UnsafeGetAddressTest + * + */ + +import sun.misc.Unsafe; +import java.lang.reflect.*; + +public class UnsafeGetAddressTest { + private static Unsafe unsafe; + + public static void main(String[] args) throws Exception { + Class c = UnsafeGetAddressTest.class.getClassLoader().loadClass("sun.misc.Unsafe"); + Field f = c.getDeclaredField("theUnsafe"); + f.setAccessible(true); + unsafe = (Unsafe)f.get(c); + + long address = unsafe.allocateMemory(unsafe.addressSize()); + unsafe.putAddress(address, 0x0000000080000000L); + // from sun.misc.Unsafe.getAddress' documentation: + // "If the native pointer is less than 64 bits wide, it is + // extended as an unsigned number to a Java long." + result = unsafe.getAddress(address); + System.out.printf("1: was 0x%x, expected 0x%x\n", result, + 0x0000000080000000L); + for (int i = 0; i < 1000000; i++) { + result = unsafe.getAddress(address); + } + + // The code has got compiled, check the result now + System.out.printf("2: was 0x%x, expected 0x%x\n", result, + 0x0000000080000000L); + if (result != 0x0000000080000000L) { + System.out.println("Test Failed"); + System.exit(97); + } else { + System.out.println("Test Passed"); + } + } + static volatile long result; +} +
--- a/test/compiler/7141637/SpreadNullArg.java Tue Oct 14 21:12:32 2014 +0100 +++ b/test/compiler/7141637/SpreadNullArg.java Thu Oct 16 16:01:21 2014 +0100 @@ -46,13 +46,17 @@ mh_spread_target = MethodHandles.lookup().findStatic(SpreadNullArg.class, "target_spread_arg", mt_ref_arg); result = (int) mh_spreadInvoker.invokeExact(mh_spread_target, (Object[]) null); - } catch(NullPointerException e) { - // Expected exception - do nothing! - } catch(Throwable e) { + throw new Error("Expected IllegalArgumentException was not thrown"); + } catch (IllegalArgumentException e) { + System.out.println("Expected exception : " + e); + } catch (Throwable e) { throw new Error(e); } - if (result != 42) throw new Error("Expected NullPointerException was not thrown"); + if (result != 42) { + throw new Error("result [" + result + + "] != 42 : Expected IllegalArgumentException was not thrown?"); + } } public static int target_spread_arg(Integer i1) {
--- a/test/testlibrary/ClassFileInstaller.java Tue Oct 14 21:12:32 2014 +0100 +++ b/test/testlibrary/ClassFileInstaller.java Thu Oct 16 16:01:21 2014 +0100 @@ -45,7 +45,9 @@ // Create the class file's package directory Path p = Paths.get(pathName); - Files.createDirectories(p.getParent()); + if (pathName.contains("/")) { + Files.createDirectories(p.getParent()); + } // Create the class file Files.copy(is, p, StandardCopyOption.REPLACE_EXISTING); }
--- a/test/testlibrary/OutputAnalyzerTest.java Tue Oct 14 21:12:32 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,193 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @summary Test the OutputAnalyzer utility class - * @library /testlibrary - */ - -import com.oracle.java.testlibrary.OutputAnalyzer; - -public class OutputAnalyzerTest { - - public static void main(String args[]) throws Exception { - - String stdout = "aaaaaa"; - String stderr = "bbbbbb"; - - // Regexps used for testing pattern matching of the test input - String stdoutPattern = "[a]"; - String stderrPattern = "[b]"; - String nonExistingPattern = "[c]"; - - OutputAnalyzer output = new OutputAnalyzer(stdout, stderr); - - if (!stdout.equals(output.getStdout())) { - throw new Exception("getStdout() returned '" + output.getStdout() + "', expected '" + stdout + "'"); - } - - if (!stderr.equals(output.getStderr())) { - throw new Exception("getStderr() returned '" + output.getStderr() + "', expected '" + stderr + "'"); - } - - try { - output.shouldContain(stdout); - output.stdoutShouldContain(stdout); - output.shouldContain(stderr); - output.stderrShouldContain(stderr); - } catch (RuntimeException e) { - throw new Exception("shouldContain() failed", e); - } - - try { - output.shouldContain("cccc"); - throw new Exception("shouldContain() failed to throw exception"); - } catch (RuntimeException e) { - // expected - } - - try { - output.stdoutShouldContain(stderr); - throw new Exception("stdoutShouldContain() failed to throw exception"); - } catch (RuntimeException e) { - // expected - } - - try { - output.stderrShouldContain(stdout); - throw new Exception("stdoutShouldContain() failed to throw exception"); - } catch (RuntimeException e) { - // expected - } - - try { - output.shouldNotContain("cccc"); - output.stdoutShouldNotContain("cccc"); - output.stderrShouldNotContain("cccc"); - } catch (RuntimeException e) { - throw new Exception("shouldNotContain() failed", e); - } - - try { - output.shouldNotContain(stdout); - throw new Exception("shouldContain() failed to throw exception"); - } catch (RuntimeException e) { - // expected - } - - try { - output.stdoutShouldNotContain(stdout); - throw new Exception("shouldContain() failed to throw exception"); - } catch (RuntimeException e) { - // expected - } - - try { - output.stderrShouldNotContain(stderr); - throw new Exception("shouldContain() failed to throw exception"); - } catch (RuntimeException e) { - // expected - } - - // Should match - try { - output.shouldMatch(stdoutPattern); - output.stdoutShouldMatch(stdoutPattern); - output.shouldMatch(stderrPattern); - output.stderrShouldMatch(stderrPattern); - } catch (RuntimeException e) { - throw new Exception("shouldMatch() failed", e); - } - - try { - output.shouldMatch(nonExistingPattern); - throw new Exception("shouldMatch() failed to throw exception"); - } catch (RuntimeException e) { - // expected - } - - try { - output.stdoutShouldMatch(stderrPattern); - throw new Exception( - "stdoutShouldMatch() failed to throw exception"); - } catch (RuntimeException e) { - // expected - } - - try { - output.stderrShouldMatch(stdoutPattern); - throw new Exception( - "stderrShouldMatch() failed to throw exception"); - } catch (RuntimeException e) { - // expected - } - - // Should not match - try { - output.shouldNotMatch(nonExistingPattern); - output.stdoutShouldNotMatch(nonExistingPattern); - output.stderrShouldNotMatch(nonExistingPattern); - } catch (RuntimeException e) { - throw new Exception("shouldNotMatch() failed", e); - } - - try { - output.shouldNotMatch(stdoutPattern); - throw new Exception("shouldNotMatch() failed to throw exception"); - } catch (RuntimeException e) { - // expected - } - - try { - output.stdoutShouldNotMatch(stdoutPattern); - throw new Exception("shouldNotMatch() failed to throw exception"); - } catch (RuntimeException e) { - // expected - } - - try { - output.stderrShouldNotMatch(stderrPattern); - throw new Exception("shouldNotMatch() failed to throw exception"); - } catch (RuntimeException e) { - // expected - } - - { - String aaaa = "aaaa"; - String result = output.firstMatch(aaaa); - if (!aaaa.equals(result)) { - throw new Exception("firstMatch(String) faild to match. Expected: " + aaaa + " got: " + result); - } - } - - { - String aa = "aa"; - String aa_grouped_aa = aa + "(" + aa + ")"; - String result = output.firstMatch(aa_grouped_aa, 1); - if (!aa.equals(result)) { - throw new Exception("firstMatch(String, int) failed to match. Expected: " + aa + " got: " + result); - } - } - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/com/oracle/java/testlibrary/Asserts.java Thu Oct 16 16:01:21 2014 +0100 @@ -0,0 +1,395 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.java.testlibrary; + +/** + * Asserts that can be used for verifying assumptions in tests. + * + * An assertion will throw a {@link RuntimeException} if the assertion isn't + * valid. All the asserts can be imported into a test by using a static + * import: + * + * <pre> + * {@code + * import static com.oracle.java.testlibrary.Asserts.*; + * } + * + * Always provide a message describing the assumption if the line number of the + * failing assertion isn't enough to understand why the assumption failed. For + * example, if the assertion is in a loop or in a method that is called + * multiple times, then the line number won't provide enough context to + * understand the failure. + * </pre> + */ +public class Asserts { + + /** + * Shorthand for {@link #assertLessThan(T, T)}. + * + * @see #assertLessThan(T, T) + */ + public static <T extends Comparable<T>> void assertLT(T lhs, T rhs) { + assertLessThan(lhs, rhs); + } + + /** + * Shorthand for {@link #assertLessThan(T, T, String)}. + * + * @see #assertLessThan(T, T, String) + */ + public static <T extends Comparable<T>> void assertLT(T lhs, T rhs, String msg) { + assertLessThan(lhs, rhs, msg); + } + + /** + * Calls {@link #assertLessThan(T, T, String)} with a default message. + * + * @see #assertLessThan(T, T, String) + */ + public static <T extends Comparable<T>> void assertLessThan(T lhs, T rhs) { + String msg = "Expected that " + format(lhs) + " < " + format(rhs); + assertLessThan(lhs, rhs, msg); + } + + /** + * Asserts that {@code lhs} is less than {@code rhs}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption. + * @throws RuntimeException if the assertion isn't valid. + */ + public static <T extends Comparable<T>>void assertLessThan(T lhs, T rhs, String msg) { + assertTrue(compare(lhs, rhs, msg) < 0, msg); + } + + /** + * Shorthand for {@link #assertLessThanOrEqual(T, T)}. + * + * @see #assertLessThanOrEqual(T, T) + */ + public static <T extends Comparable<T>> void assertLTE(T lhs, T rhs) { + assertLessThanOrEqual(lhs, rhs); + } + + /** + * Shorthand for {@link #assertLessThanOrEqual(T, T, String)}. + * + * @see #assertLessThanOrEqual(T, T, String) + */ + public static <T extends Comparable<T>> void assertLTE(T lhs, T rhs, String msg) { + assertLessThanOrEqual(lhs, rhs, msg); + } + + /** + * Calls {@link #assertLessThanOrEqual(T, T, String)} with a default message. + * + * @see #assertLessThanOrEqual(T, T, String) + */ + public static <T extends Comparable<T>> void assertLessThanOrEqual(T lhs, T rhs) { + String msg = "Expected that " + format(lhs) + " <= " + format(rhs); + assertLessThanOrEqual(lhs, rhs, msg); + } + + /** + * Asserts that {@code lhs} is less than or equal to {@code rhs}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption. + * @throws RuntimeException if the assertion isn't valid. + */ + public static <T extends Comparable<T>> void assertLessThanOrEqual(T lhs, T rhs, String msg) { + assertTrue(compare(lhs, rhs, msg) <= 0, msg); + } + + /** + * Shorthand for {@link #assertEquals(T, T)}. + * + * @see #assertEquals(T, T) + */ + public static void assertEQ(Object lhs, Object rhs) { + assertEquals(lhs, rhs); + } + + /** + * Shorthand for {@link #assertEquals(T, T, String)}. + * + * @see #assertEquals(T, T, String) + */ + public static void assertEQ(Object lhs, Object rhs, String msg) { + assertEquals(lhs, rhs, msg); + } + + /** + * Calls {@link #assertEquals(T, T, String)} with a default message. + * + * @see #assertEquals(T, T, String) + */ + public static void assertEquals(Object lhs, Object rhs) { + String msg = "Expected " + format(lhs) + " to equal " + format(rhs); + assertEquals(lhs, rhs, msg); + } + + /** + * Asserts that {@code lhs} is equal to {@code rhs}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption. + * @throws RuntimeException if the assertion isn't valid. + */ + public static void assertEquals(Object lhs, Object rhs, String msg) { + if (lhs == null) { + if (rhs != null) { + error(msg); + } + } else { + assertTrue(lhs.equals(rhs), msg); + } + } + + /** + * Shorthand for {@link #assertGreaterThanOrEqual(T, T)}. + * + * @see #assertGreaterThanOrEqual(T, T) + */ + public static <T extends Comparable<T>> void assertGTE(T lhs, T rhs) { + assertGreaterThanOrEqual(lhs, rhs); + } + + /** + * Shorthand for {@link #assertGreaterThanOrEqual(T, T, String)}. + * + * @see #assertGreaterThanOrEqual(T, T, String) + */ + public static <T extends Comparable<T>> void assertGTE(T lhs, T rhs, String msg) { + assertGreaterThanOrEqual(lhs, rhs, msg); + } + + /** + * Calls {@link #assertGreaterThanOrEqual(T, T, String)} with a default message. + * + * @see #assertGreaterThanOrEqual(T, T, String) + */ + public static <T extends Comparable<T>> void assertGreaterThanOrEqual(T lhs, T rhs) { + String msg = "Expected that " + format(lhs) + " >= " + format(rhs); + assertGreaterThanOrEqual(lhs, rhs, msg); + } + + /** + * Asserts that {@code lhs} is greater than or equal to {@code rhs}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption. + * @throws RuntimeException if the assertion isn't valid. + */ + public static <T extends Comparable<T>> void assertGreaterThanOrEqual(T lhs, T rhs, String msg) { + assertTrue(compare(lhs, rhs, msg) >= 0, msg); + } + + /** + * Shorthand for {@link #assertGreaterThan(T, T)}. + * + * @see #assertGreaterThan(T, T) + */ + public static <T extends Comparable<T>> void assertGT(T lhs, T rhs) { + assertGreaterThan(lhs, rhs); + } + + /** + * Shorthand for {@link #assertGreaterThan(T, T, String)}. + * + * @see #assertGreaterThan(T, T, String) + */ + public static <T extends Comparable<T>> void assertGT(T lhs, T rhs, String msg) { + assertGreaterThan(lhs, rhs, msg); + } + + /** + * Calls {@link #assertGreaterThan(T, T, String)} with a default message. + * + * @see #assertGreaterThan(T, T, String) + */ + public static <T extends Comparable<T>> void assertGreaterThan(T lhs, T rhs) { + String msg = "Expected that " + format(lhs) + " > " + format(rhs); + assertGreaterThan(lhs, rhs, msg); + } + + /** + * Asserts that {@code lhs} is greater than {@code rhs}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption. + * @throws RuntimeException if the assertion isn't valid. + */ + public static <T extends Comparable<T>> void assertGreaterThan(T lhs, T rhs, String msg) { + assertTrue(compare(lhs, rhs, msg) > 0, msg); + } + + /** + * Shorthand for {@link #assertNotEquals(T, T)}. + * + * @see #assertNotEquals(T, T) + */ + public static void assertNE(Object lhs, Object rhs) { + assertNotEquals(lhs, rhs); + } + + /** + * Shorthand for {@link #assertNotEquals(T, T, String)}. + * + * @see #assertNotEquals(T, T, String) + */ + public static void assertNE(Object lhs, Object rhs, String msg) { + assertNotEquals(lhs, rhs, msg); + } + + /** + * Calls {@link #assertNotEquals(T, T, String)} with a default message. + * + * @see #assertNotEquals(T, T, String) + */ + public static void assertNotEquals(Object lhs, Object rhs) { + String msg = "Expected " + format(lhs) + " to not equal " + format(rhs); + assertNotEquals(lhs, rhs, msg); + } + + /** + * Asserts that {@code lhs} is not equal to {@code rhs}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption. + * @throws RuntimeException if the assertion isn't valid. + */ + public static void assertNotEquals(Object lhs, Object rhs, String msg) { + if (lhs == null) { + if (rhs == null) { + error(msg); + } + } else { + assertFalse(lhs.equals(rhs), msg); + } + } + + /** + * Calls {@link #assertNull(Object, String)} with a default message. + * + * @see #assertNull(Object, String) + */ + public static void assertNull(Object o) { + assertNull(o, "Expected " + format(o) + " to be null"); + } + + /** + * Asserts that {@code o} is null. + * + * @param o The reference assumed to be null. + * @param msg A description of the assumption. + * @throws RuntimeException if the assertion isn't valid. + */ + public static void assertNull(Object o, String msg) { + assertEquals(o, null, msg); + } + + /** + * Calls {@link #assertNotNull(Object, String)} with a default message. + * + * @see #assertNotNull(Object, String) + */ + public static void assertNotNull(Object o) { + assertNotNull(o, "Expected non null reference"); + } + + /** + * Asserts that {@code o} is <i>not</i> null. + * + * @param o The reference assumed <i>not</i> to be null, + * @param msg A description of the assumption. + * @throws RuntimeException if the assertion isn't valid. + */ + public static void assertNotNull(Object o, String msg) { + assertNotEquals(o, null, msg); + } + + /** + * Calls {@link #assertFalse(boolean, String)} with a default message. + * + * @see #assertFalse(boolean, String) + */ + public static void assertFalse(boolean value) { + assertFalse(value, "Expected value to be false"); + } + + /** + * Asserts that {@code value} is {@code false}. + * + * @param value The value assumed to be false. + * @param msg A description of the assumption. + * @throws RuntimeException if the assertion isn't valid. + */ + public static void assertFalse(boolean value, String msg) { + assertTrue(!value, msg); + } + + /** + * Calls {@link #assertTrue(boolean, String)} with a default message. + * + * @see #assertTrue(boolean, String) + */ + public static void assertTrue(boolean value) { + assertTrue(value, "Expected value to be true"); + } + + /** + * Asserts that {@code value} is {@code true}. + * + * @param value The value assumed to be true. + * @param msg A description of the assumption. + * @throws RuntimeException if the assertion isn't valid. + */ + public static void assertTrue(boolean value, String msg) { + if (!value) { + error(msg); + } + } + + private static <T extends Comparable<T>> int compare(T lhs, T rhs, String msg) { + assertNotNull(lhs, msg); + assertNotNull(rhs, msg); + return lhs.compareTo(rhs); + } + + private static String format(Object o) { + return o == null? "null" : o.toString(); + } + + private static void error(String msg) { + throw new RuntimeException(msg); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/com/oracle/java/testlibrary/ByteCodeLoader.java Thu Oct 16 16:01:21 2014 +0100 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.java.testlibrary; + +import java.security.SecureClassLoader; + +/** + * {@code ByteCodeLoader} can be used for easy loading of byte code already + * present in memory. + * + * {@code InMemoryCompiler} can be used for compiling source code in a string + * into byte code, which then can be loaded with {@code ByteCodeLoader}. + * + * @see InMemoryCompiler + */ +public class ByteCodeLoader extends SecureClassLoader { + private final String className; + private final byte[] byteCode; + + /** + * Creates a new {@code ByteCodeLoader} ready to load a class with the + * given name and the given byte code. + * + * @param className The name of the class + * @param byteCode The byte code of the class + */ + public ByteCodeLoader(String className, byte[] byteCode) { + this.className = className; + this.byteCode = byteCode; + } + + @Override + protected Class<?> findClass(String name) throws ClassNotFoundException { + if (!name.equals(className)) { + throw new ClassNotFoundException(name); + } + + return defineClass(name, byteCode, 0, byteCode.length); + } + + /** + * Utility method for creating a new {@code ByteCodeLoader} and then + * directly load the given byte code. + * + * @param className The name of the class + * @param byteCode The byte code for the class + * @throws ClassNotFoundException if the class can't be loaded + * @return A {@see Class} object representing the class + */ + public static Class<?> load(String className, byte[] byteCode) throws ClassNotFoundException { + return new ByteCodeLoader(className, byteCode).loadClass(className); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/com/oracle/java/testlibrary/InMemoryJavaCompiler.java Thu Oct 16 16:01:21 2014 +0100 @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.java.testlibrary; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import java.net.URI; +import java.util.Arrays; + +import javax.tools.ForwardingJavaFileManager; +import javax.tools.ForwardingJavaFileManager; +import javax.tools.FileObject; +import javax.tools.JavaCompiler; +import javax.tools.JavaCompiler.CompilationTask; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import javax.tools.JavaFileObject.Kind; +import javax.tools.SimpleJavaFileObject; +import javax.tools.ToolProvider; + +/** + * {@code InMemoryJavaCompiler} can be used for compiling a {@link + * CharSequence} to a {@code byte[]}. + * + * The compiler will not use the file system at all, instead using a {@link + * ByteArrayOutputStream} for storing the byte code. For the source code, any + * kind of {@link CharSequence} can be used, e.g. {@link String}, {@link + * StringBuffer} or {@link StringBuilder}. + * + * The {@code InMemoryCompiler} can easily be used together with a {@code + * ByteClassLoader} to easily compile and load source code in a {@link String}: + * + * <pre> + * {@code + * import com.oracle.java.testlibrary.InMemoryJavaCompiler; + * import com.oracle.java.testlibrary.ByteClassLoader; + * + * class Example { + * public static void main(String[] args) { + * String className = "Foo"; + * String sourceCode = "public class " + className + " {" + + * " public void bar() {" + + * " System.out.println("Hello from bar!");" + + * " }" + + * "}"; + * byte[] byteCode = InMemoryJavaCompiler.compile(className, sourceCode); + * Class fooClass = ByteClassLoader.load(className, byteCode); + * } + * } + * } + * </pre> + */ +public class InMemoryJavaCompiler { + private static class MemoryJavaFileObject extends SimpleJavaFileObject { + private final String className; + private final CharSequence sourceCode; + private final ByteArrayOutputStream byteCode; + + public MemoryJavaFileObject(String className, CharSequence sourceCode) { + super(URI.create("string:///" + className.replace('.','/') + Kind.SOURCE.extension), Kind.SOURCE); + this.className = className; + this.sourceCode = sourceCode; + this.byteCode = new ByteArrayOutputStream(); + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return sourceCode; + } + + @Override + public OutputStream openOutputStream() throws IOException { + return byteCode; + } + + public byte[] getByteCode() { + return byteCode.toByteArray(); + } + + public String getClassName() { + return className; + } + } + + private static class FileManagerWrapper extends ForwardingJavaFileManager { + private MemoryJavaFileObject file; + + public FileManagerWrapper(MemoryJavaFileObject file) { + super(getCompiler().getStandardFileManager(null, null, null)); + this.file = file; + } + + @Override + public JavaFileObject getJavaFileForOutput(Location location, String className, + Kind kind, FileObject sibling) + throws IOException { + if (!file.getClassName().equals(className)) { + throw new IOException("Expected class with name " + file.getClassName() + + ", but got " + className); + } + return file; + } + } + + /** + * Compiles the class with the given name and source code. + * + * @param className The name of the class + * @param sourceCode The source code for the class with name {@code className} + * @throws RuntimeException if the compilation did not succeed + * @return The resulting byte code from the compilation + */ + public static byte[] compile(String className, CharSequence sourceCode) { + MemoryJavaFileObject file = new MemoryJavaFileObject(className, sourceCode); + CompilationTask task = getCompilationTask(file); + + if(!task.call()) { + throw new RuntimeException("Could not compile " + className + " with source code " + sourceCode); + } + + return file.getByteCode(); + } + + private static JavaCompiler getCompiler() { + return ToolProvider.getSystemJavaCompiler(); + } + + private static CompilationTask getCompilationTask(MemoryJavaFileObject file) { + return getCompiler().getTask(null, new FileManagerWrapper(file), null, null, null, Arrays.asList(file)); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/com/oracle/java/testlibrary/InputArguments.java Thu Oct 16 16:01:21 2014 +0100 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.java.testlibrary; + +import java.lang.management.RuntimeMXBean; +import java.lang.management.ManagementFactory; +import java.util.List; + +/** + * This class provides access to the input arguments to the VM. + */ +public class InputArguments { + private static final List<String> args; + + static { + RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean(); + args = runtimeMxBean.getInputArguments(); + } + + /** + * Returns true if {@code arg} is an input argument to the VM. + * + * This is useful for checking boolean flags such as -XX:+UseSerialGC or + * -XX:-UsePerfData. + * + * @param arg The name of the argument. + * @return {@code true} if the given argument is an input argument, + * otherwise {@code false}. + */ + public static boolean contains(String arg) { + return args.contains(arg); + } + + /** + * Returns true if {@code prefix} is the start of an input argument to the + * VM. + * + * This is useful for checking if flags describing a quantity, such as + * -XX:+MaxMetaspaceSize=100m, is set without having to know the quantity. + * To check if the flag -XX:MaxMetaspaceSize is set, use + * {@code InputArguments.containsPrefix("-XX:MaxMetaspaceSize")}. + * + * @param prefix The start of the argument. + * @return {@code true} if the given argument is the start of an input + * argument, otherwise {@code false}. + */ + public static boolean containsPrefix(String prefix) { + for (String arg : args) { + if (arg.startsWith(prefix)) { + return true; + } + } + return false; + } +}
--- a/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java Tue Oct 14 21:12:32 2014 +0100 +++ b/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java Thu Oct 16 16:01:21 2014 +0100 @@ -23,28 +23,84 @@ package com.oracle.java.testlibrary; -import java.io.File; +import java.io.FileNotFoundException; +import java.nio.file.Path; +import java.nio.file.Paths; public final class JDKToolFinder { - private JDKToolFinder() { - } + private JDKToolFinder() { + } + + /** + * Returns the full path to an executable in jdk/bin based on System + * property {@code test.jdk} or {@code compile.jdk} (both are set by the jtreg test suite) + * + * @return Full path to an executable in jdk/bin + */ + public static String getJDKTool(String tool) { - /** - * Returns the full path to an executable in jdk/bin based on System property - * test.jdk (set by jtreg test suite) - * - * @return Full path to an executable in jdk/bin - */ - public static String getJDKTool(String tool) { - String binPath = System.getProperty("test.jdk"); - if (binPath == null) { - throw new RuntimeException("System property 'test.jdk' not set. This property is normally set by jtreg. " - + "When running test separately, set this property using '-Dtest.jdk=/path/to/jdk'."); + // First try to find the executable in test.jdk + try { + return getTool(tool, "test.jdk"); + } catch (FileNotFoundException e) { + + } + + // Now see if it's available in compile.jdk + try { + return getTool(tool, "compile.jdk"); + } catch (FileNotFoundException e) { + throw new RuntimeException("Failed to find " + tool + + ", looked in test.jdk (" + System.getProperty("test.jdk") + + ") and compile.jdk (" + System.getProperty("compile.jdk") + ")"); + } } - binPath += File.separatorChar + "bin" + File.separatorChar + tool; + /** + * Returns the full path to an executable in jdk/bin based on System + * property {@code compile.jdk} + * + * @return Full path to an executable in jdk/bin + */ + public static String getCompileJDKTool(String tool) { + try { + return getTool(tool, "compile.jdk"); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + } - return binPath; - } + /** + * Returns the full path to an executable in jdk/bin based on System + * property {@code test.jdk} + * + * @return Full path to an executable in jdk/bin + */ + public static String getTestJDKTool(String tool) { + try { + return getTool(tool, "test.jdk"); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + } + + private static String getTool(String tool, String property) throws FileNotFoundException { + String jdkPath = System.getProperty(property); + + if (jdkPath == null) { + throw new RuntimeException( + "System property '" + property + "' not set. This property is normally set by jtreg. " + + "When running test separately, set this property using '-D" + property + "=/path/to/jdk'."); + } + + Path toolName = Paths.get("bin", tool + (Platform.isWindows() ? ".exe" : "")); + + Path jdkTool = Paths.get(jdkPath, toolName.toString()); + if (!jdkTool.toFile().exists()) { + throw new FileNotFoundException("Could not find file " + jdkTool.toAbsolutePath()); + } + + return jdkTool.toAbsolutePath().toString(); + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/com/oracle/java/testlibrary/JDKToolLauncher.java Thu Oct 16 16:01:21 2014 +0100 @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.java.testlibrary; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * A utility for constructing command lines for starting JDK tool processes. + * + * The JDKToolLauncher can in particular be combined with a + * java.lang.ProcessBuilder to easily run a JDK tool. For example, the following + * code run {@code jmap -heap} against a process with GC logging turned on for + * the {@code jmap} process: + * + * <pre> + * {@code + * JDKToolLauncher jmap = JDKToolLauncher.create("jmap") + * .addVMArg("-XX:+PrintGC"); + * .addVMArg("-XX:+PrintGCDetails") + * .addToolArg("-heap") + * .addToolArg(pid); + * ProcessBuilder pb = new ProcessBuilder(jmap.getCommand()); + * Process p = pb.start(); + * } + * </pre> + */ +public class JDKToolLauncher { + private final String executable; + private final List<String> vmArgs = new ArrayList<String>(); + private final List<String> toolArgs = new ArrayList<String>(); + + private JDKToolLauncher(String tool, boolean useCompilerJDK) { + if (useCompilerJDK) { + executable = JDKToolFinder.getJDKTool(tool); + } else { + executable = JDKToolFinder.getTestJDKTool(tool); + } + vmArgs.addAll(Arrays.asList(ProcessTools.getPlatformSpecificVMArgs())); + } + + /** + * Creates a new JDKToolLauncher for the specified tool. Using tools path + * from the compiler JDK. + * + * @param tool + * The name of the tool + * @return A new JDKToolLauncher + */ + public static JDKToolLauncher create(String tool) { + return new JDKToolLauncher(tool, true); + } + + /** + * Creates a new JDKToolLauncher for the specified tool in the Tested JDK. + * + * @param tool + * The name of the tool + * + * @return A new JDKToolLauncher + */ + public static JDKToolLauncher createUsingTestJDK(String tool) { + return new JDKToolLauncher(tool, false); + } + + /** + * Adds an argument to the JVM running the tool. + * + * The JVM arguments are passed to the underlying JVM running the tool. + * Arguments will automatically be prepended with "-J". + * + * Any platform specific arguments required for running the tool are + * automatically added. + * + * + * @param arg + * The argument to VM running the tool + * @return The JDKToolLauncher instance + */ + public JDKToolLauncher addVMArg(String arg) { + vmArgs.add(arg); + return this; + } + + /** + * Adds an argument to the tool. + * + * @param arg + * The argument to the tool + * @return The JDKToolLauncher instance + */ + public JDKToolLauncher addToolArg(String arg) { + toolArgs.add(arg); + return this; + } + + /** + * Returns the command that can be used for running the tool. + * + * @return An array whose elements are the arguments of the command. + */ + public String[] getCommand() { + List<String> command = new ArrayList<String>(); + command.add(executable); + // Add -J in front of all vmArgs + for (String arg : vmArgs) { + command.add("-J" + arg); + } + command.addAll(toolArgs); + return command.toArray(new String[command.size()]); + } +}
--- a/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java Tue Oct 14 21:12:32 2014 +0100 +++ b/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java Thu Oct 16 16:01:21 2014 +0100 @@ -76,7 +76,8 @@ */ public void shouldContain(String expectedString) { if (!stdout.contains(expectedString) && !stderr.contains(expectedString)) { - throw new RuntimeException("'" + expectedString + "' missing from stdout/stderr: [" + stdout + stderr + "]\n"); + reportDiagnosticSummary(); + throw new RuntimeException("'" + expectedString + "' missing from stdout/stderr \n"); } } @@ -88,7 +89,8 @@ */ public void stdoutShouldContain(String expectedString) { if (!stdout.contains(expectedString)) { - throw new RuntimeException("'" + expectedString + "' missing from stdout: [" + stdout + "]\n"); + reportDiagnosticSummary(); + throw new RuntimeException("'" + expectedString + "' missing from stdout \n"); } } @@ -100,7 +102,8 @@ */ public void stderrShouldContain(String expectedString) { if (!stderr.contains(expectedString)) { - throw new RuntimeException("'" + expectedString + "' missing from stderr: [" + stderr + "]\n"); + reportDiagnosticSummary(); + throw new RuntimeException("'" + expectedString + "' missing from stderr \n"); } } @@ -112,10 +115,12 @@ */ public void shouldNotContain(String notExpectedString) { if (stdout.contains(notExpectedString)) { - throw new RuntimeException("'" + notExpectedString + "' found in stdout: [" + stdout + "]\n"); + reportDiagnosticSummary(); + throw new RuntimeException("'" + notExpectedString + "' found in stdout \n"); } if (stderr.contains(notExpectedString)) { - throw new RuntimeException("'" + notExpectedString + "' found in stderr: [" + stderr + "]\n"); + reportDiagnosticSummary(); + throw new RuntimeException("'" + notExpectedString + "' found in stderr \n"); } } @@ -127,7 +132,8 @@ */ public void stdoutShouldNotContain(String notExpectedString) { if (stdout.contains(notExpectedString)) { - throw new RuntimeException("'" + notExpectedString + "' found in stdout: [" + stdout + "]\n"); + reportDiagnosticSummary(); + throw new RuntimeException("'" + notExpectedString + "' found in stdout \n"); } } @@ -139,7 +145,8 @@ */ public void stderrShouldNotContain(String notExpectedString) { if (stderr.contains(notExpectedString)) { - throw new RuntimeException("'" + notExpectedString + "' found in stderr: [" + stderr + "]\n"); + reportDiagnosticSummary(); + throw new RuntimeException("'" + notExpectedString + "' found in stderr \n"); } } @@ -154,9 +161,9 @@ Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout); Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); if (!stdoutMatcher.find() && !stderrMatcher.find()) { + reportDiagnosticSummary(); throw new RuntimeException("'" + pattern - + "' missing from stdout/stderr: [" + stdout + stderr - + "]\n"); + + "' missing from stdout/stderr \n"); } } @@ -170,8 +177,9 @@ public void stdoutShouldMatch(String pattern) { Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout); if (!matcher.find()) { + reportDiagnosticSummary(); throw new RuntimeException("'" + pattern - + "' missing from stdout: [" + stdout + "]\n"); + + "' missing from stdout \n"); } } @@ -185,8 +193,9 @@ public void stderrShouldMatch(String pattern) { Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); if (!matcher.find()) { + reportDiagnosticSummary(); throw new RuntimeException("'" + pattern - + "' missing from stderr: [" + stderr + "]\n"); + + "' missing from stderr \n"); } } @@ -200,13 +209,15 @@ public void shouldNotMatch(String pattern) { Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout); if (matcher.find()) { + reportDiagnosticSummary(); throw new RuntimeException("'" + pattern - + "' found in stdout: [" + stdout + "]\n"); + + "' found in stdout: '" + matcher.group() + "' \n"); } matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); if (matcher.find()) { + reportDiagnosticSummary(); throw new RuntimeException("'" + pattern - + "' found in stderr: [" + stderr + "]\n"); + + "' found in stderr: '" + matcher.group() + "' \n"); } } @@ -220,8 +231,9 @@ public void stdoutShouldNotMatch(String pattern) { Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout); if (matcher.find()) { + reportDiagnosticSummary(); throw new RuntimeException("'" + pattern - + "' found in stdout: [" + stdout + "]\n"); + + "' found in stdout \n"); } } @@ -235,8 +247,9 @@ public void stderrShouldNotMatch(String pattern) { Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); if (matcher.find()) { + reportDiagnosticSummary(); throw new RuntimeException("'" + pattern - + "' found in stderr: [" + stderr + "]\n"); + + "' found in stderr \n"); } } @@ -279,10 +292,31 @@ */ public void shouldHaveExitValue(int expectedExitValue) { if (getExitValue() != expectedExitValue) { - throw new RuntimeException("Exit value " + getExitValue() + " , expected to get " + expectedExitValue); + reportDiagnosticSummary(); + throw new RuntimeException("Expected to get exit value of [" + + expectedExitValue + "]\n"); } } + + /** + * Report summary that will help to diagnose the problem + * Currently includes: + * - standard input produced by the process under test + * - standard output + * - exit code + * Note: the command line is printed by the ProcessTools + */ + private void reportDiagnosticSummary() { + String msg = + " stdout: [" + stdout + "];\n" + + " stderr: [" + stderr + "]\n" + + " exitValue = " + getExitValue() + "\n"; + + System.err.println(msg); + } + + /** * Get the contents of the output buffer (stdout and stderr) *
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/com/oracle/java/testlibrary/PerfCounter.java Thu Oct 16 16:01:21 2014 +0100 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.java.testlibrary; + +import sun.jvmstat.monitor.Monitor; + +/** + * Represents a performance counter in the JVM. + * + * See http://openjdk.java.net/groups/hotspot/docs/Serviceability.html#bjvmstat + * for more details about performance counters. + */ +public class PerfCounter { + private final Monitor monitor; + private final String name; + + PerfCounter(Monitor monitor, String name) { + this.monitor = monitor; + this.name = name; + } + + /** + * Returns the value of this performance counter as a long. + * + * @return The long value of this performance counter + * @throws RuntimeException If the value of the performance counter isn't a long + */ + public long longValue() { + Object value = monitor.getValue(); + if (value instanceof Long) { + return ((Long) value).longValue(); + } + throw new RuntimeException("Expected " + monitor.getName() + " to have a long value"); + } + + /** + * Returns the name of the performance counter. + * + * @return The name of the performance counter. + */ + public String getName() { + return name; + } + + @Override + public String toString() { + return name; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/com/oracle/java/testlibrary/PerfCounters.java Thu Oct 16 16:01:21 2014 +0100 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.java.testlibrary; + +import sun.jvmstat.monitor.Monitor; +import sun.jvmstat.monitor.MonitorException; +import sun.jvmstat.monitor.MonitoredHost; +import sun.jvmstat.monitor.MonitoredVm; +import sun.jvmstat.monitor.VmIdentifier; + +/** + * PerfCounters can be used to get a performance counter from the currently + * executing VM. + * + * Throws a runtime exception if an error occurs while communicating with the + * currently executing VM. + */ +public class PerfCounters { + private final static MonitoredVm vm; + + static { + try { + String pid = Integer.toString(ProcessTools.getProcessId()); + VmIdentifier vmId = new VmIdentifier(pid); + MonitoredHost host = MonitoredHost.getMonitoredHost(vmId); + vm = host.getMonitoredVm(vmId); + } catch (Exception e) { + throw new RuntimeException("Could not connect to the VM"); + } + } + + /** + * Returns the performance counter with the given name. + * + * @param name The name of the performance counter. + * @throws IllegalArgumentException If no counter with the given name exists. + * @throws MonitorException If an error occurs while communicating with the VM. + * @return The performance counter with the given name. + */ + public static PerfCounter findByName(String name) + throws MonitorException, IllegalArgumentException { + Monitor m = vm.findByName(name); + if (m == null) { + throw new IllegalArgumentException("Did not find a performance counter with name " + name); + } + return new PerfCounter(m, name); + } +}
--- a/test/testlibrary/com/oracle/java/testlibrary/Platform.java Tue Oct 14 21:12:32 2014 +0100 +++ b/test/testlibrary/com/oracle/java/testlibrary/Platform.java Thu Oct 16 16:01:21 2014 +0100 @@ -24,39 +24,80 @@ package com.oracle.java.testlibrary; public class Platform { - private static final String osName = System.getProperty("os.name"); - private static final String dataModel = System.getProperty("sun.arch.data.model"); - private static final String vmVersion = System.getProperty("java.vm.version"); + private static final String osName = System.getProperty("os.name"); + private static final String dataModel = System.getProperty("sun.arch.data.model"); + private static final String vmVersion = System.getProperty("java.vm.version"); + private static final String osArch = System.getProperty("os.arch"); - public static boolean is64bit() { - return dataModel.equals("64"); - } + public static boolean is32bit() { + return dataModel.equals("32"); + } + + public static boolean is64bit() { + return dataModel.equals("64"); + } + + public static boolean isSolaris() { + return isOs("sunos"); + } - public static boolean isSolaris() { - return osName.toLowerCase().startsWith("sunos"); - } + public static boolean isWindows() { + return isOs("win"); + } + + public static boolean isOSX() { + return isOs("mac"); + } - public static boolean isWindows() { - return osName.toLowerCase().startsWith("win"); - } + public static boolean isLinux() { + return isOs("linux"); + } + + private static boolean isOs(String osname) { + return osName.toLowerCase().startsWith(osname.toLowerCase()); + } + + public static String getOsName() { + return osName; + } - public static boolean isOSX() { - return osName.toLowerCase().startsWith("mac"); - } + public static boolean isDebugBuild() { + return vmVersion.toLowerCase().contains("debug"); + } + + public static String getVMVersion() { + return vmVersion; + } - public static boolean isLinux() { - return osName.toLowerCase().startsWith("linux"); - } + // Returns true for sparc and sparcv9. + public static boolean isSparc() { + return isArch("sparc"); + } + + public static boolean isARM() { + return isArch("arm"); + } - public static String getOsName() { - return osName; - } + public static boolean isPPC() { + return isArch("ppc"); + } + + public static boolean isX86() { + // On Linux it's 'i386', Windows 'x86' + return (isArch("i386") || isArch("x86")); + } - public static boolean isDebugBuild() { - return vmVersion.toLowerCase().contains("debug"); - } + public static boolean isX64() { + // On OSX it's 'x86_64' and on other (Linux, Windows and Solaris) platforms it's 'amd64' + return (isArch("amd64") || isArch("x86_64")); + } - public static String getVMVersion() { - return vmVersion; - } + private static boolean isArch(String archname) { + return osArch.toLowerCase().startsWith(archname.toLowerCase()); + } + + public static String getOsArch() { + return osArch; + } + }
--- a/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java Tue Oct 14 21:12:32 2014 +0100 +++ b/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java Thu Oct 16 16:01:21 2014 +0100 @@ -31,6 +31,7 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; +import java.util.List; import sun.management.VMManagement; @@ -107,15 +108,29 @@ } /** + * Get the string containing input arguments passed to the VM + * + * @return arguments + */ + public static String getVmInputArguments() { + RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); + + List<String> args = runtime.getInputArguments(); + StringBuilder result = new StringBuilder(); + for (String arg : args) + result.append(arg).append(' '); + + return result.toString(); + } + + /** * Get platform specific VM arguments (e.g. -d64 on 64bit Solaris) * * @return String[] with platform specific arguments, empty if there are none */ public static String[] getPlatformSpecificVMArgs() { - String osName = System.getProperty("os.name"); - String dataModel = System.getProperty("sun.arch.data.model"); - if (osName.equals("SunOS") && dataModel.equals("64")) { + if (Platform.is64bit() && Platform.isSolaris()) { return new String[] { "-d64" }; } @@ -134,8 +149,13 @@ Collections.addAll(args, getPlatformSpecificVMArgs()); Collections.addAll(args, command); + // Reporting + StringBuilder cmdLine = new StringBuilder(); + for (String cmd : args) + cmdLine.append(cmd).append(' '); + System.out.println("Command line: [" + cmdLine.toString() + "]"); + return new ProcessBuilder(args.toArray(new String[args.size()])); - } }