This commit is contained in:
Jesper Wilhelmsson 2021-12-16 00:26:36 +00:00
commit e6b28e05c6
27 changed files with 329 additions and 72 deletions

View file

@ -191,7 +191,8 @@ CodeEmitInfo::CodeEmitInfo(ValueStack* stack, XHandlers* exception_handlers, boo
, _oop_map(NULL) , _oop_map(NULL)
, _stack(stack) , _stack(stack)
, _is_method_handle_invoke(false) , _is_method_handle_invoke(false)
, _deoptimize_on_exception(deoptimize_on_exception) { , _deoptimize_on_exception(deoptimize_on_exception)
, _force_reexecute(false) {
assert(_stack != NULL, "must be non null"); assert(_stack != NULL, "must be non null");
} }
@ -203,7 +204,8 @@ CodeEmitInfo::CodeEmitInfo(CodeEmitInfo* info, ValueStack* stack)
, _oop_map(NULL) , _oop_map(NULL)
, _stack(stack == NULL ? info->_stack : stack) , _stack(stack == NULL ? info->_stack : stack)
, _is_method_handle_invoke(info->_is_method_handle_invoke) , _is_method_handle_invoke(info->_is_method_handle_invoke)
, _deoptimize_on_exception(info->_deoptimize_on_exception) { , _deoptimize_on_exception(info->_deoptimize_on_exception)
, _force_reexecute(info->_force_reexecute) {
// deep copy of exception handlers // deep copy of exception handlers
if (info->_exception_handlers != NULL) { if (info->_exception_handlers != NULL) {
@ -215,7 +217,8 @@ CodeEmitInfo::CodeEmitInfo(CodeEmitInfo* info, ValueStack* stack)
void CodeEmitInfo::record_debug_info(DebugInformationRecorder* recorder, int pc_offset) { void CodeEmitInfo::record_debug_info(DebugInformationRecorder* recorder, int pc_offset) {
// record the safepoint before recording the debug info for enclosing scopes // record the safepoint before recording the debug info for enclosing scopes
recorder->add_safepoint(pc_offset, _oop_map->deep_copy()); recorder->add_safepoint(pc_offset, _oop_map->deep_copy());
_scope_debug_info->record_debug_info(recorder, pc_offset, true/*topmost*/, _is_method_handle_invoke); bool reexecute = _force_reexecute || _scope_debug_info->should_reexecute();
_scope_debug_info->record_debug_info(recorder, pc_offset, reexecute, _is_method_handle_invoke);
recorder->end_safepoint(pc_offset); recorder->end_safepoint(pc_offset);
} }

View file

@ -232,16 +232,15 @@ class IRScopeDebugInfo: public CompilationResourceObj {
//Whether we should reexecute this bytecode for deopt //Whether we should reexecute this bytecode for deopt
bool should_reexecute(); bool should_reexecute();
void record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool topmost, bool is_method_handle_invoke = false) { void record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool reexecute, bool is_method_handle_invoke = false) {
if (caller() != NULL) { if (caller() != NULL) {
// Order is significant: Must record caller first. // Order is significant: Must record caller first.
caller()->record_debug_info(recorder, pc_offset, false/*topmost*/); caller()->record_debug_info(recorder, pc_offset, false/*reexecute*/);
} }
DebugToken* locvals = recorder->create_scope_values(locals()); DebugToken* locvals = recorder->create_scope_values(locals());
DebugToken* expvals = recorder->create_scope_values(expressions()); DebugToken* expvals = recorder->create_scope_values(expressions());
DebugToken* monvals = recorder->create_monitor_values(monitors()); DebugToken* monvals = recorder->create_monitor_values(monitors());
// reexecute allowed only for the topmost frame // reexecute allowed only for the topmost frame
bool reexecute = topmost ? should_reexecute() : false;
bool return_oop = false; // This flag will be ignored since it used only for C2 with escape analysis. bool return_oop = false; // This flag will be ignored since it used only for C2 with escape analysis.
bool rethrow_exception = false; bool rethrow_exception = false;
bool is_opt_native = false; bool is_opt_native = false;
@ -264,6 +263,7 @@ class CodeEmitInfo: public CompilationResourceObj {
ValueStack* _stack; // used by deoptimization (contains also monitors ValueStack* _stack; // used by deoptimization (contains also monitors
bool _is_method_handle_invoke; // true if the associated call site is a MethodHandle call site. bool _is_method_handle_invoke; // true if the associated call site is a MethodHandle call site.
bool _deoptimize_on_exception; bool _deoptimize_on_exception;
bool _force_reexecute; // force the reexecute flag on, used for patching stub
FrameMap* frame_map() const { return scope()->compilation()->frame_map(); } FrameMap* frame_map() const { return scope()->compilation()->frame_map(); }
Compilation* compilation() const { return scope()->compilation(); } Compilation* compilation() const { return scope()->compilation(); }
@ -290,7 +290,11 @@ class CodeEmitInfo: public CompilationResourceObj {
bool is_method_handle_invoke() const { return _is_method_handle_invoke; } bool is_method_handle_invoke() const { return _is_method_handle_invoke; }
void set_is_method_handle_invoke(bool x) { _is_method_handle_invoke = x; } void set_is_method_handle_invoke(bool x) { _is_method_handle_invoke = x; }
bool force_reexecute() const { return _force_reexecute; }
void set_force_reexecute() { _force_reexecute = true; }
int interpreter_frame_size() const; int interpreter_frame_size() const;
}; };

View file

@ -43,6 +43,7 @@ void LIR_Assembler::patching_epilog(PatchingStub* patch, LIR_PatchCode patch_cod
while ((intx) _masm->pc() - (intx) patch->pc_start() < NativeGeneralJump::instruction_size) { while ((intx) _masm->pc() - (intx) patch->pc_start() < NativeGeneralJump::instruction_size) {
_masm->nop(); _masm->nop();
} }
info->set_force_reexecute();
patch->install(_masm, patch_code, obj, info); patch->install(_masm, patch_code, obj, info);
append_code_stub(patch); append_code_stub(patch);

View file

@ -117,9 +117,11 @@ ciMethod::ciMethod(const methodHandle& h_m, ciInstanceKlass* holder) :
if (h_m->method_holder()->is_linked()) { if (h_m->method_holder()->is_linked()) {
_can_be_statically_bound = h_m->can_be_statically_bound(); _can_be_statically_bound = h_m->can_be_statically_bound();
_can_omit_stack_trace = h_m->can_omit_stack_trace();
} else { } else {
// Have to use a conservative value in this case. // Have to use a conservative value in this case.
_can_be_statically_bound = false; _can_be_statically_bound = false;
_can_omit_stack_trace = true;
} }
// Adjust the definition of this condition to be more useful: // Adjust the definition of this condition to be more useful:
@ -176,6 +178,7 @@ ciMethod::ciMethod(ciInstanceKlass* holder,
_intrinsic_id( vmIntrinsics::_none), _intrinsic_id( vmIntrinsics::_none),
_instructions_size(-1), _instructions_size(-1),
_can_be_statically_bound(false), _can_be_statically_bound(false),
_can_omit_stack_trace(true),
_liveness( NULL) _liveness( NULL)
#if defined(COMPILER2) #if defined(COMPILER2)
, ,
@ -766,6 +769,20 @@ bool ciMethod::can_be_statically_bound(ciInstanceKlass* context) const {
return (holder() == context) && can_be_statically_bound(); return (holder() == context) && can_be_statically_bound();
} }
// ------------------------------------------------------------------
// ciMethod::can_omit_stack_trace
//
// Tries to determine whether a method can omit stack trace in throw in compiled code.
bool ciMethod::can_omit_stack_trace() const {
if (!StackTraceInThrowable) {
return true; // stack trace is switched off.
}
if (!OmitStackTraceInFastThrow) {
return false; // Have to provide stack trace.
}
return _can_omit_stack_trace;
}
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// ciMethod::resolve_invoke // ciMethod::resolve_invoke
// //

View file

@ -92,6 +92,7 @@ class ciMethod : public ciMetadata {
bool _is_c2_compilable; bool _is_c2_compilable;
bool _can_be_parsed; bool _can_be_parsed;
bool _can_be_statically_bound; bool _can_be_statically_bound;
bool _can_omit_stack_trace;
bool _has_reserved_stack_access; bool _has_reserved_stack_access;
bool _is_overpass; bool _is_overpass;
@ -364,6 +365,8 @@ class ciMethod : public ciMetadata {
bool can_be_statically_bound(ciInstanceKlass* context) const; bool can_be_statically_bound(ciInstanceKlass* context) const;
bool can_omit_stack_trace() const;
// Replay data methods // Replay data methods
static void dump_name_as_ascii(outputStream* st, Method* method); static void dump_name_as_ascii(outputStream* st, Method* method);
void dump_name_as_ascii(outputStream* st); void dump_name_as_ascii(outputStream* st);

View file

@ -142,6 +142,7 @@
template(java_util_Iterator, "java/util/Iterator") \ template(java_util_Iterator, "java/util/Iterator") \
template(java_lang_Record, "java/lang/Record") \ template(java_lang_Record, "java/lang/Record") \
template(sun_instrument_InstrumentationImpl, "sun/instrument/InstrumentationImpl") \ template(sun_instrument_InstrumentationImpl, "sun/instrument/InstrumentationImpl") \
template(sun_invoke_util_ValueConversions, "sun/invoke/util/ValueConversions") \
\ \
template(jdk_internal_loader_NativeLibraries, "jdk/internal/loader/NativeLibraries") \ template(jdk_internal_loader_NativeLibraries, "jdk/internal/loader/NativeLibraries") \
template(jdk_internal_loader_BuiltinClassLoader, "jdk/internal/loader/BuiltinClassLoader") \ template(jdk_internal_loader_BuiltinClassLoader, "jdk/internal/loader/BuiltinClassLoader") \

View file

@ -202,7 +202,7 @@ static void prepare_for_resolution() {
static bool stack_trace_precondition(const ObjectSample* sample) { static bool stack_trace_precondition(const ObjectSample* sample) {
assert(sample != NULL, "invariant"); assert(sample != NULL, "invariant");
return sample->has_stack_trace_id() && !sample->is_dead(); return sample->has_stack_trace_id() && !sample->is_dead() && !sample->stacktrace().valid();
} }
class StackTraceBlobInstaller { class StackTraceBlobInstaller {
@ -249,7 +249,7 @@ void StackTraceBlobInstaller::install(ObjectSample* sample) {
writer.write_type(TYPE_STACKTRACE); writer.write_type(TYPE_STACKTRACE);
writer.write_count(1); writer.write_count(1);
ObjectSampleCheckpoint::write_stacktrace(stack_trace, writer); ObjectSampleCheckpoint::write_stacktrace(stack_trace, writer);
blob = writer.copy(); blob = writer.move();
_cache.put(sample, blob); _cache.put(sample, blob);
sample->set_stacktrace(blob); sample->set_stacktrace(blob);
} }
@ -278,7 +278,7 @@ void ObjectSampleCheckpoint::on_rotation(const ObjectSampler* sampler) {
} }
static bool is_klass_unloaded(traceid klass_id) { static bool is_klass_unloaded(traceid klass_id) {
assert(ClassLoaderDataGraph_lock->owned_by_self(), "invariant"); assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
return JfrKlassUnloading::is_unloaded(klass_id); return JfrKlassUnloading::is_unloaded(klass_id);
} }
@ -381,6 +381,12 @@ void ObjectSampleCheckpoint::write(const ObjectSampler* sampler, EdgeStore* edge
assert(sampler != NULL, "invariant"); assert(sampler != NULL, "invariant");
assert(edge_store != NULL, "invariant"); assert(edge_store != NULL, "invariant");
assert(thread != NULL, "invariant"); assert(thread != NULL, "invariant");
{
// First install stacktrace blobs for the most recently added candidates.
MutexLocker lock(SafepointSynchronize::is_at_safepoint() ? nullptr : ClassLoaderDataGraph_lock);
// the lock is needed to ensure the unload lists do not grow in the middle of inspection.
install_stack_traces(sampler);
}
write_sample_blobs(sampler, emit_all, thread); write_sample_blobs(sampler, emit_all, thread);
// write reference chains // write reference chains
if (!edge_store->is_empty()) { if (!edge_store->is_empty()) {

View file

@ -232,6 +232,7 @@ int write__klass(JfrCheckpointWriter* writer, const void* k) {
int write__klass__leakp(JfrCheckpointWriter* writer, const void* k) { int write__klass__leakp(JfrCheckpointWriter* writer, const void* k) {
assert(k != NULL, "invariant"); assert(k != NULL, "invariant");
KlassPtr klass = (KlassPtr)k; KlassPtr klass = (KlassPtr)k;
CLEAR_LEAKP(klass);
return write_klass(writer, klass, true); return write_klass(writer, klass, true);
} }
@ -835,7 +836,7 @@ class MethodIteratorHost {
private: private:
MethodCallback _method_cb; MethodCallback _method_cb;
KlassCallback _klass_cb; KlassCallback _klass_cb;
MethodUsedPredicate<leakp> _method_used_predicate; MethodUsedPredicate _method_used_predicate;
MethodFlagPredicate<leakp> _method_flag_predicate; MethodFlagPredicate<leakp> _method_flag_predicate;
public: public:
MethodIteratorHost(JfrCheckpointWriter* writer, MethodIteratorHost(JfrCheckpointWriter* writer,

View file

@ -146,16 +146,12 @@ class SymbolPredicate {
} }
}; };
template <bool leakp>
class MethodUsedPredicate { class MethodUsedPredicate {
bool _current_epoch; bool _current_epoch;
public: public:
MethodUsedPredicate(bool current_epoch) : _current_epoch(current_epoch) {} MethodUsedPredicate(bool current_epoch) : _current_epoch(current_epoch) {}
bool operator()(const Klass* klass) { bool operator()(const Klass* klass) {
if (_current_epoch) { return _current_epoch ? METHOD_USED_THIS_EPOCH(klass) : METHOD_USED_PREVIOUS_EPOCH(klass);
return leakp ? IS_LEAKP(klass) : METHOD_USED_THIS_EPOCH(klass);
}
return leakp ? IS_LEAKP(klass) : METHOD_USED_PREVIOUS_EPOCH(klass);
} }
}; };

View file

@ -818,6 +818,18 @@ bool Method::can_be_statically_bound(InstanceKlass* context) const {
return (method_holder() == context) && can_be_statically_bound(); return (method_holder() == context) && can_be_statically_bound();
} }
/**
* Returns false if this is one of specially treated methods for
* which we have to provide stack trace in throw in compiled code.
* Returns true otherwise.
*/
bool Method::can_omit_stack_trace() {
if (klass_name() == vmSymbols::sun_invoke_util_ValueConversions()) {
return false; // All methods in sun.invoke.util.ValueConversions
}
return true;
}
bool Method::is_accessor() const { bool Method::is_accessor() const {
return is_getter() || is_setter(); return is_getter() || is_setter();
} }

View file

@ -600,6 +600,9 @@ public:
bool can_be_statically_bound(InstanceKlass* context) const; bool can_be_statically_bound(InstanceKlass* context) const;
bool can_be_statically_bound(AccessFlags class_access_flags) const; bool can_be_statically_bound(AccessFlags class_access_flags) const;
// true if method can omit stack trace in throw in compiled code.
bool can_omit_stack_trace();
// returns true if the method has any backward branches. // returns true if the method has any backward branches.
bool has_loops() { bool has_loops() {
return access_flags().loops_flag_init() ? access_flags().has_loops() : compute_has_loops_flag(); return access_flags().loops_flag_init() ? access_flags().has_loops() : compute_has_loops_flag();

View file

@ -560,8 +560,7 @@ void GraphKit::builtin_throw(Deoptimization::DeoptReason reason, Node* arg) {
// let us handle the throw inline, with a preconstructed instance. // let us handle the throw inline, with a preconstructed instance.
// Note: If the deopt count has blown up, the uncommon trap // Note: If the deopt count has blown up, the uncommon trap
// runtime is going to flush this nmethod, not matter what. // runtime is going to flush this nmethod, not matter what.
if (treat_throw_as_hot if (treat_throw_as_hot && method()->can_omit_stack_trace()) {
&& (!StackTraceInThrowable || OmitStackTraceInFastThrow)) {
// If the throw is local, we use a pre-existing instance and // If the throw is local, we use a pre-existing instance and
// punt on the backtrace. This would lead to a missing backtrace // punt on the backtrace. This would lead to a missing backtrace
// (a repeat of 4292742) if the backtrace object is ever asked // (a repeat of 4292742) if the backtrace object is ever asked

View file

@ -798,6 +798,7 @@ JRT_LEAF(BasicType, Deoptimization::unpack_frames(JavaThread* thread, int exec_m
// at an uncommon trap for an invoke (where the compiler // at an uncommon trap for an invoke (where the compiler
// generates debug info before the invoke has executed) // generates debug info before the invoke has executed)
Bytecodes::Code cur_code = str.next(); Bytecodes::Code cur_code = str.next();
Bytecodes::Code next_code = Bytecodes::_shouldnotreachhere;
if (Bytecodes::is_invoke(cur_code)) { if (Bytecodes::is_invoke(cur_code)) {
Bytecode_invoke invoke(mh, iframe->interpreter_frame_bci()); Bytecode_invoke invoke(mh, iframe->interpreter_frame_bci());
cur_invoke_parameter_size = invoke.size_of_parameters(); cur_invoke_parameter_size = invoke.size_of_parameters();
@ -806,7 +807,7 @@ JRT_LEAF(BasicType, Deoptimization::unpack_frames(JavaThread* thread, int exec_m
} }
} }
if (str.bci() < max_bci) { if (str.bci() < max_bci) {
Bytecodes::Code next_code = str.next(); next_code = str.next();
if (next_code >= 0) { if (next_code >= 0) {
// The interpreter oop map generator reports results before // The interpreter oop map generator reports results before
// the current bytecode has executed except in the case of // the current bytecode has executed except in the case of
@ -854,6 +855,10 @@ JRT_LEAF(BasicType, Deoptimization::unpack_frames(JavaThread* thread, int exec_m
// Print out some information that will help us debug the problem // Print out some information that will help us debug the problem
tty->print_cr("Wrong number of expression stack elements during deoptimization"); tty->print_cr("Wrong number of expression stack elements during deoptimization");
tty->print_cr(" Error occurred while verifying frame %d (0..%d, 0 is topmost)", i, cur_array->frames() - 1); tty->print_cr(" Error occurred while verifying frame %d (0..%d, 0 is topmost)", i, cur_array->frames() - 1);
tty->print_cr(" Current code %s", Bytecodes::name(cur_code));
if (try_next_mask) {
tty->print_cr(" Next code %s", Bytecodes::name(next_code));
}
tty->print_cr(" Fabricated interpreter frame had %d expression stack elements", tty->print_cr(" Fabricated interpreter frame had %d expression stack elements",
iframe->interpreter_frame_expression_stack_size()); iframe->interpreter_frame_expression_stack_size());
tty->print_cr(" Interpreter oop map had %d expression stack elements", mask.expression_stack_size()); tty->print_cr(" Interpreter oop map had %d expression stack elements", mask.expression_stack_size());

View file

@ -1313,7 +1313,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi {
return super.engineGetAttributes(alias); return super.engineGetAttributes(alias);
} }
Entry entry = entries.get(alias.toLowerCase(Locale.ENGLISH)); Entry entry = entries.get(alias.toLowerCase(Locale.ENGLISH));
return getAttributes(entry); return Collections.unmodifiableSet(new HashSet<>(getAttributes(entry)));
} }
/** /**

View file

@ -55,7 +55,7 @@ import java.util.Optional;
* {@linkplain #downcallHandle(FunctionDescriptor) Linking a foreign function} is a process which requires a function descriptor, * {@linkplain #downcallHandle(FunctionDescriptor) Linking a foreign function} is a process which requires a function descriptor,
* a set of memory layouts which, together, specify the signature of the foreign function to be linked, and returns, * a set of memory layouts which, together, specify the signature of the foreign function to be linked, and returns,
* when complete, a downcall method handle, that is, a method handle that can be used to invoke the target native function. * when complete, a downcall method handle, that is, a method handle that can be used to invoke the target native function.
* The Java {@link java.lang.invoke.MethodType method type} associated with the returned method handle is * The Java {@linkplain java.lang.invoke.MethodType method type} associated with the returned method handle is
* {@linkplain #downcallType(FunctionDescriptor) derived} from the argument and return layouts in the function descriptor. * {@linkplain #downcallType(FunctionDescriptor) derived} from the argument and return layouts in the function descriptor.
* More specifically, given each layout {@code L} in the function descriptor, a corresponding carrier {@code C} is inferred, * More specifically, given each layout {@code L} in the function descriptor, a corresponding carrier {@code C} is inferred,
* as described below: * as described below:
@ -69,7 +69,8 @@ import java.util.Optional;
* <li>or, if {@code L} is a {@link GroupLayout}, then {@code C} is set to {@code MemorySegment.class}</li> * <li>or, if {@code L} is a {@link GroupLayout}, then {@code C} is set to {@code MemorySegment.class}</li>
* </ul> * </ul>
* <p> * <p>
* The downcall method handle type, derived as above, might be decorated by additional leading parameters: * The downcall method handle type, derived as above, might be decorated by additional leading parameters,
* in the given order if both are present:
* <ul> * <ul>
* <li>If the downcall method handle is created {@linkplain #downcallHandle(FunctionDescriptor) without specifying a native symbol}, * <li>If the downcall method handle is created {@linkplain #downcallHandle(FunctionDescriptor) without specifying a native symbol},
* the downcall method handle type features a leading parameter of type {@link NativeSymbol}, from which the * the downcall method handle type features a leading parameter of type {@link NativeSymbol}, from which the
@ -91,7 +92,7 @@ import java.util.Optional;
* handle and a function descriptor; in this case, the set of memory layouts in the function descriptor * handle and a function descriptor; in this case, the set of memory layouts in the function descriptor
* specify the signature of the function pointer associated with the upcall stub. * specify the signature of the function pointer associated with the upcall stub.
* <p> * <p>
* The type of the provided method handle has to match the Java {@link java.lang.invoke.MethodType method type} * The type of the provided method handle has to match the Java {@linkplain java.lang.invoke.MethodType method type}
* associated with the upcall stub, which is derived from the argument and return layouts in the function descriptor. * associated with the upcall stub, which is derived from the argument and return layouts in the function descriptor.
* More specifically, given each layout {@code L} in the function descriptor, a corresponding carrier {@code C} is inferred, as described below: * More specifically, given each layout {@code L} in the function descriptor, a corresponding carrier {@code C} is inferred, as described below:
* <ul> * <ul>
@ -109,7 +110,7 @@ import java.util.Optional;
* *
* <h2>System lookup</h2> * <h2>System lookup</h2>
* *
* This class implements the {@link SymbolLookup} interface; as such clients can {@linkplain #lookup(String) lookup} symbols * This class implements the {@link SymbolLookup} interface; as such clients can {@linkplain #lookup(String) look up} symbols
* in the standard libraries associated with this linker. The set of symbols available for lookup is unspecified, * in the standard libraries associated with this linker. The set of symbols available for lookup is unspecified,
* as it depends on the platform and on the operating system. * as it depends on the platform and on the operating system.
* *
@ -163,7 +164,7 @@ public sealed interface CLinker extends SymbolLookup permits Windowsx64Linker, S
} }
/** /**
* Lookup a symbol in the standard libraries associated with this linker. * Look up a symbol in the standard libraries associated with this linker.
* The set of symbols available for lookup is unspecified, as it depends on the platform and on the operating system. * The set of symbols available for lookup is unspecified, as it depends on the platform and on the operating system.
* @return a symbol in the standard libraries associated with this linker. * @return a symbol in the standard libraries associated with this linker.
*/ */

View file

@ -29,14 +29,16 @@ package jdk.incubator.foreign;
import jdk.internal.foreign.MemoryAddressImpl; import jdk.internal.foreign.MemoryAddressImpl;
import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.CallerSensitive;
import java.lang.invoke.MethodHandle;
import java.nio.ByteOrder; import java.nio.ByteOrder;
/** /**
* A memory address models a reference into a memory location. Memory addresses are typically obtained in three ways: * A memory address models a reference into a memory location. Memory addresses are typically obtained in one of the following ways:
* <ul> * <ul>
* <li>By calling {@link Addressable#address()} on an instance of type {@link Addressable} (e.g. a memory segment);</li> * <li>By calling {@link Addressable#address()} on an instance of type {@link Addressable} (e.g. a memory segment);</li>
* <li>By invoking a {@linkplain CLinker#downcallHandle(FunctionDescriptor) downcall method handle} which returns a pointer;</li> * <li>By invoking a {@linkplain CLinker#downcallHandle(FunctionDescriptor) downcall method handle} which returns a pointer;</li>
* <li>By reading an address from memory, e.g. via {@link MemorySegment#get(ValueLayout.OfAddress, long)}.</li> * <li>By reading an address from memory, e.g. via {@link MemorySegment#get(ValueLayout.OfAddress, long)}.</li>
* <li>By the invocation of an {@linkplain CLinker#upcallStub(MethodHandle, FunctionDescriptor, ResourceScope) upcall stub} which accepts a pointer.
* </ul> * </ul>
* A memory address is backed by a raw machine pointer, expressed as a {@linkplain #toRawLongValue() long value}. * A memory address is backed by a raw machine pointer, expressed as a {@linkplain #toRawLongValue() long value}.
* *

View file

@ -56,7 +56,7 @@ import java.util.stream.Stream;
* A memory segment models a contiguous region of memory. A memory segment is associated with both spatial * A memory segment models a contiguous region of memory. A memory segment is associated with both spatial
* and temporal bounds (e.g. a {@link ResourceScope}). Spatial bounds ensure that memory access operations on a memory segment cannot affect a memory location * and temporal bounds (e.g. a {@link ResourceScope}). Spatial bounds ensure that memory access operations on a memory segment cannot affect a memory location
* which falls <em>outside</em> the boundaries of the memory segment being accessed. Temporal bounds ensure that memory access * which falls <em>outside</em> the boundaries of the memory segment being accessed. Temporal bounds ensure that memory access
* operations on a segment cannot occur after the resource scope associated with a memory segment has been closed (see {@link ResourceScope#close()}). * operations on a segment cannot occur <em>after</em> the resource scope associated with a memory segment has been closed (see {@link ResourceScope#close()}).
* <p> * <p>
* All implementations of this interface must be <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>; * All implementations of this interface must be <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>;
* programmers should treat instances that are {@linkplain Object#equals(Object) equal} as interchangeable and should not * programmers should treat instances that are {@linkplain Object#equals(Object) equal} as interchangeable and should not
@ -157,7 +157,7 @@ import java.util.stream.Stream;
* scope, it can only be accessed by the thread which owns the scope. * scope, it can only be accessed by the thread which owns the scope.
* <p> * <p>
* Heap and buffer segments are always associated with a <em>global</em>, shared scope. This scope cannot be closed, * Heap and buffer segments are always associated with a <em>global</em>, shared scope. This scope cannot be closed,
* and can be considered as <em>always alive</em>. * and segments associated with it can be considered as <em>always alive</em>.
* *
* <h2>Memory segment views</h2> * <h2>Memory segment views</h2>
* *
@ -217,11 +217,11 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
* The returned spliterator splits this segment according to the specified element layout; that is, * The returned spliterator splits this segment according to the specified element layout; that is,
* if the supplied layout has size N, then calling {@link Spliterator#trySplit()} will result in a spliterator serving * if the supplied layout has size N, then calling {@link Spliterator#trySplit()} will result in a spliterator serving
* approximately {@code S/N/2} elements (depending on whether N is even or not), where {@code S} is the size of * approximately {@code S/N/2} elements (depending on whether N is even or not), where {@code S} is the size of
* this segment. As such, splitting is possible as long as {@code S/N >= 2}. The spliterator returns segments that feature the same * this segment. As such, splitting is possible as long as {@code S/N >= 2}. The spliterator returns segments that
* scope as this given segment. * are associated with the same scope as this segment.
* <p> * <p>
* The returned spliterator effectively allows to slice this segment into disjoint sub-segments, which can then * The returned spliterator effectively allows to slice this segment into disjoint {@linkplain #asSlice(long, long) slices},
* be processed in parallel by multiple threads. * which can then be processed in parallel by multiple threads.
* *
* @param elementLayout the layout to be used for splitting. * @param elementLayout the layout to be used for splitting.
* @return the element spliterator for this segment * @return the element spliterator for this segment
@ -679,7 +679,7 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
/** /**
* Creates a new array memory segment that models the memory associated with a given heap-allocated byte array. * Creates a new array memory segment that models the memory associated with a given heap-allocated byte array.
* The returned segment's resource scope is set to the {@linkplain ResourceScope#globalScope() global} resource scope. * The returned segment is associated with the {@linkplain ResourceScope#globalScope() global} resource scope.
* *
* @param arr the primitive array backing the array memory segment. * @param arr the primitive array backing the array memory segment.
* @return a new array memory segment. * @return a new array memory segment.
@ -690,7 +690,7 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
/** /**
* Creates a new array memory segment that models the memory associated with a given heap-allocated char array. * Creates a new array memory segment that models the memory associated with a given heap-allocated char array.
* The returned segment's resource scope is set to the {@linkplain ResourceScope#globalScope() global} resource scope. * The returned segment is associated with the {@linkplain ResourceScope#globalScope() global} resource scope.
* *
* @param arr the primitive array backing the array memory segment. * @param arr the primitive array backing the array memory segment.
* @return a new array memory segment. * @return a new array memory segment.
@ -701,7 +701,7 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
/** /**
* Creates a new array memory segment that models the memory associated with a given heap-allocated short array. * Creates a new array memory segment that models the memory associated with a given heap-allocated short array.
* The returned segment's resource scope is set to the {@linkplain ResourceScope#globalScope() global} resource scope. * The returned segment is associated with the {@linkplain ResourceScope#globalScope() global} resource scope.
* *
* @param arr the primitive array backing the array memory segment. * @param arr the primitive array backing the array memory segment.
* @return a new array memory segment. * @return a new array memory segment.
@ -712,7 +712,7 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
/** /**
* Creates a new array memory segment that models the memory associated with a given heap-allocated int array. * Creates a new array memory segment that models the memory associated with a given heap-allocated int array.
* The returned segment's resource scope is set to the {@linkplain ResourceScope#globalScope() global} resource scope. * The returned segment is associated with the {@linkplain ResourceScope#globalScope() global} resource scope.
* *
* @param arr the primitive array backing the array memory segment. * @param arr the primitive array backing the array memory segment.
* @return a new array memory segment. * @return a new array memory segment.
@ -723,7 +723,7 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
/** /**
* Creates a new array memory segment that models the memory associated with a given heap-allocated float array. * Creates a new array memory segment that models the memory associated with a given heap-allocated float array.
* The returned segment's resource scope is set to the {@linkplain ResourceScope#globalScope() global} resource scope. * The returned segment is associated with the {@linkplain ResourceScope#globalScope() global} resource scope.
* *
* @param arr the primitive array backing the array memory segment. * @param arr the primitive array backing the array memory segment.
* @return a new array memory segment. * @return a new array memory segment.
@ -734,7 +734,7 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
/** /**
* Creates a new array memory segment that models the memory associated with a given heap-allocated long array. * Creates a new array memory segment that models the memory associated with a given heap-allocated long array.
* The returned segment's resource scope is set to the {@linkplain ResourceScope#globalScope() global} resource scope. * The returned segment is associated with the {@linkplain ResourceScope#globalScope() global} resource scope.
* *
* @param arr the primitive array backing the array memory segment. * @param arr the primitive array backing the array memory segment.
* @return a new array memory segment. * @return a new array memory segment.
@ -745,7 +745,7 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
/** /**
* Creates a new array memory segment that models the memory associated with a given heap-allocated double array. * Creates a new array memory segment that models the memory associated with a given heap-allocated double array.
* The returned segment's resource scope is set to the {@linkplain ResourceScope#globalScope() global} resource scope. * The returned segment is associated with the {@linkplain ResourceScope#globalScope() global} resource scope.
* *
* @param arr the primitive array backing the array memory segment. * @param arr the primitive array backing the array memory segment.
* @return a new array memory segment. * @return a new array memory segment.

View file

@ -456,7 +456,6 @@ public interface SegmentAllocator {
* Returns a native allocator which allocates segments in independent {@linkplain ResourceScope#newImplicitScope() implicit scopes}. * Returns a native allocator which allocates segments in independent {@linkplain ResourceScope#newImplicitScope() implicit scopes}.
* Equivalent to (but likely more efficient than) the following code: * Equivalent to (but likely more efficient than) the following code:
* {@snippet lang=java : * {@snippet lang=java :
* ResourceScope scope = ...
* SegmentAllocator implicitAllocator = (size, align) -> MemorySegment.allocateNative(size, align, ResourceScope.newImplicitScope()); * SegmentAllocator implicitAllocator = (size, align) -> MemorySegment.allocateNative(size, align, ResourceScope.newImplicitScope());
* } * }
* *

View file

@ -59,7 +59,8 @@ import java.util.function.Consumer;
sealed public interface VaList extends Addressable permits WinVaList, SysVVaList, LinuxAArch64VaList, MacOsAArch64VaList, SharedUtils.EmptyVaList { sealed public interface VaList extends Addressable permits WinVaList, SysVVaList, LinuxAArch64VaList, MacOsAArch64VaList, SharedUtils.EmptyVaList {
/** /**
* Reads the next value as an {@code int} and advances this variable argument list's position. * Reads the next value as an {@code int} and advances this variable argument list's position. The behavior of this
* method is equivalent to the C {@code va_arg} function.
* *
* @param layout the layout of the value to be read. * @param layout the layout of the value to be read.
* @return the {@code int} value read from this variable argument list. * @return the {@code int} value read from this variable argument list.
@ -69,7 +70,8 @@ sealed public interface VaList extends Addressable permits WinVaList, SysVVaList
int nextVarg(ValueLayout.OfInt layout); int nextVarg(ValueLayout.OfInt layout);
/** /**
* Reads the next value as a {@code long} and advances this variable argument list's position. * Reads the next value as a {@code long} and advances this variable argument list's position. The behavior of this
* method is equivalent to the C {@code va_arg} function.
* *
* @param layout the layout of the value to be read. * @param layout the layout of the value to be read.
* @return the {@code long} value read from this variable argument list. * @return the {@code long} value read from this variable argument list.
@ -79,7 +81,8 @@ sealed public interface VaList extends Addressable permits WinVaList, SysVVaList
long nextVarg(ValueLayout.OfLong layout); long nextVarg(ValueLayout.OfLong layout);
/** /**
* Reads the next value as a {@code double} and advances this variable argument list's position. * Reads the next value as a {@code double} and advances this variable argument list's position. The behavior of this
* method is equivalent to the C {@code va_arg} function.
* *
* @param layout the layout of the value * @param layout the layout of the value
* @return the {@code double} value read from this variable argument list. * @return the {@code double} value read from this variable argument list.
@ -89,7 +92,8 @@ sealed public interface VaList extends Addressable permits WinVaList, SysVVaList
double nextVarg(ValueLayout.OfDouble layout); double nextVarg(ValueLayout.OfDouble layout);
/** /**
* Reads the next value as a {@code MemoryAddress} and advances this variable argument list's position. * Reads the next value as a {@code MemoryAddress} and advances this variable argument list's position. The behavior of this
* method is equivalent to the C {@code va_arg} function.
* *
* @param layout the layout of the value to be read. * @param layout the layout of the value to be read.
* @return the {@code MemoryAddress} value read from this variable argument list. * @return the {@code MemoryAddress} value read from this variable argument list.
@ -99,7 +103,13 @@ sealed public interface VaList extends Addressable permits WinVaList, SysVVaList
MemoryAddress nextVarg(ValueLayout.OfAddress layout); MemoryAddress nextVarg(ValueLayout.OfAddress layout);
/** /**
* Reads the next value as a {@code MemorySegment}, and advances this variable argument list's position. * Reads the next value as a {@code MemorySegment}, and advances this variable argument list's position. The behavior of this
* method is equivalent to the C {@code va_arg} function. The provided group layout must correspond to a C struct or union
* type.
* <p>
* How the value is read in the returned segment is ABI-dependent: calling this method on a group layout
* with member layouts {@code L_1, L_2, ... L_n} is not guaranteed to be semantically equivalent to perform distinct
* calls to {@code nextVarg} for each of the layouts in {@code L_1, L_2, ... L_n}.
* <p> * <p>
* The memory segment returned by this method will be allocated using the given {@link SegmentAllocator}. * The memory segment returned by this method will be allocated using the given {@link SegmentAllocator}.
* *
@ -129,9 +139,12 @@ sealed public interface VaList extends Addressable permits WinVaList, SysVVaList
/** /**
* Copies this variable argument list at its current position into a new variable argument list associated * Copies this variable argument list at its current position into a new variable argument list associated
* with the same scope as this variable argument list. Copying is useful to * with the same scope as this variable argument list. The behavior of this method is equivalent to the C
* traverse the variable argument list elements, starting from the current position, without affecting the state * {@code va_copy} function.
* of the original variable argument list, essentially allowing the elements to be traversed multiple times. * <p>
* Copying is useful to traverse the variable argument list elements, starting from the current position,
* without affecting the state of the original variable argument list, essentially allowing the elements to be
* traversed multiple times.
* *
* @return a copy of this variable argument list. * @return a copy of this variable argument list.
* @throws IllegalStateException if the scope associated with this variable argument list has been closed, or if access occurs from * @throws IllegalStateException if the scope associated with this variable argument list has been closed, or if access occurs from
@ -187,8 +200,8 @@ sealed public interface VaList extends Addressable permits WinVaList, SysVVaList
* of the underlying variable argument list. * of the underlying variable argument list.
* @param scope scope the scope to be associated with the new variable arity list. * @param scope scope the scope to be associated with the new variable arity list.
* @return a new variable argument list. * @return a new variable argument list.
* @throws IllegalStateException if the scope associated with {@code allocator} has been already closed, * @throws IllegalStateException if {@code scope} has been already closed, or if access occurs from a thread other
* or if access occurs from a thread other than the thread owning that scope. * than the thread owning {@code scope}.
*/ */
static VaList make(Consumer<Builder> actions, ResourceScope scope) { static VaList make(Consumer<Builder> actions, ResourceScope scope) {
Objects.requireNonNull(actions); Objects.requireNonNull(actions);

View file

@ -41,7 +41,7 @@ import java.util.OptionalLong;
/** /**
* A value layout. A value layout is used to model the memory layout associated with values of basic data types, such as <em>integral</em> types * A value layout. A value layout is used to model the memory layout associated with values of basic data types, such as <em>integral</em> types
* (either signed or unsigned) and <em>floating-point</em> types. Each value layout has a size, a {@linkplain ByteOrder byte order}) * (either signed or unsigned) and <em>floating-point</em> types. Each value layout has a size, an alignment, a {@linkplain ByteOrder byte order})
* and a <em>carrier</em>, that is, the Java type that should be used when {@linkplain MemorySegment#get(OfInt, long) accessing} * and a <em>carrier</em>, that is, the Java type that should be used when {@linkplain MemorySegment#get(OfInt, long) accessing}
* a memory region using the value layout. * a memory region using the value layout.
* <p> * <p>

View file

@ -86,7 +86,7 @@
* <h3><a id="safety"></a>Safety</h3> * <h3><a id="safety"></a>Safety</h3>
* *
* This API provides strong safety guarantees when it comes to memory access. First, when dereferencing a memory segment, * This API provides strong safety guarantees when it comes to memory access. First, when dereferencing a memory segment,
* the access coordinates are validated (upon access), to make sure that access does not occur at an address which resides * the access coordinates are validated (upon access), to make sure that access does not occur at any address which resides
* <em>outside</em> the boundaries of the memory segment used by the dereference operation. We call this guarantee <em>spatial safety</em>; * <em>outside</em> the boundaries of the memory segment used by the dereference operation. We call this guarantee <em>spatial safety</em>;
* in other words, access to memory segments is bounds-checked, in the same way as array access is, as described in * in other words, access to memory segments is bounds-checked, in the same way as array access is, as described in
* Section {@jls 15.10.4} of <cite>The Java Language Specification</cite>. * Section {@jls 15.10.4} of <cite>The Java Language Specification</cite>.
@ -99,10 +99,10 @@
* <h2>Foreign function access</h2> * <h2>Foreign function access</h2>
* The key abstractions introduced to support foreign function access are {@link jdk.incubator.foreign.SymbolLookup}, * The key abstractions introduced to support foreign function access are {@link jdk.incubator.foreign.SymbolLookup},
* {@link jdk.incubator.foreign.MemoryAddress} and {@link jdk.incubator.foreign.CLinker}. * {@link jdk.incubator.foreign.MemoryAddress} and {@link jdk.incubator.foreign.CLinker}.
* The first is used to lookup symbols inside native libraries; the second is used to model native addresses (more on that later), * The first is used to look up symbols inside native libraries; the second is used to model native addresses (more on that later),
* while the third provides linking capabilities which allows modelling foreign functions as {@link java.lang.invoke.MethodHandle} instances, * while the third provides linking capabilities which allows modelling foreign functions as {@link java.lang.invoke.MethodHandle} instances,
* so that clients can perform foreign function calls directly in Java, without the need for intermediate layers of native * so that clients can perform foreign function calls directly in Java, without the need for intermediate layers of native
* code (as it's the case with the <a href="{@docRoot}/../specs/jni/index.html">Java Native Interface (JNI)</a>). * code (as is the case with the <a href="{@docRoot}/../specs/jni/index.html">Java Native Interface (JNI)</a>).
* <p> * <p>
* For example, to compute the length of a string using the C standard library function {@code strlen} on a Linux x64 platform, * For example, to compute the length of a string using the C standard library function {@code strlen} on a Linux x64 platform,
* we can use the following code: * we can use the following code:
@ -122,7 +122,7 @@
* } * }
* *
* Here, we obtain a {@linkplain jdk.incubator.foreign.CLinker#systemCLinker() linker instance} and we use it * Here, we obtain a {@linkplain jdk.incubator.foreign.CLinker#systemCLinker() linker instance} and we use it
* to {@linkplain jdk.incubator.foreign.CLinker#lookup(java.lang.String) lookup} the {@code strlen} symbol in the * to {@linkplain jdk.incubator.foreign.CLinker#lookup(java.lang.String) look up} the {@code strlen} symbol in the
* standard C library; a <em>downcall method handle</em> targeting said symbol is subsequently * standard C library; a <em>downcall method handle</em> targeting said symbol is subsequently
* {@linkplain jdk.incubator.foreign.CLinker#downcallHandle(jdk.incubator.foreign.FunctionDescriptor) obtained}. * {@linkplain jdk.incubator.foreign.CLinker#downcallHandle(jdk.incubator.foreign.FunctionDescriptor) obtained}.
* To complete the linking successfully, we must provide a {@link jdk.incubator.foreign.FunctionDescriptor} instance, * To complete the linking successfully, we must provide a {@link jdk.incubator.foreign.FunctionDescriptor} instance,
@ -138,9 +138,9 @@
* <h3>Foreign addresses</h3> * <h3>Foreign addresses</h3>
* *
* When a memory segment is created from Java code, the segment properties (spatial bounds, temporal bounds and confinement) * When a memory segment is created from Java code, the segment properties (spatial bounds, temporal bounds and confinement)
* are fully known at segment creation. But when interacting with native libraries, clients will often receive <em>raw</em> pointers; * are fully known at segment creation. But when interacting with native libraries, clients will often receive <em>raw</em> pointers.
* such pointers have no spatial bounds (example: does the C type {@code char*} refer to a single {@code char} value, * Such pointers have no spatial bounds. For example, the C type {@code char*} can refer to a single {@code char} value,
* or an array of {@code char} values, of given size?), no notion of temporal bounds, nor thread-confinement. * or an array of {@code char} values, of given size. Nor do said pointers have any notion of temporal bounds or thread-confinement.
* <p> * <p>
* Raw pointers are modelled using the {@link jdk.incubator.foreign.MemoryAddress} class. When clients receive a * Raw pointers are modelled using the {@link jdk.incubator.foreign.MemoryAddress} class. When clients receive a
* memory address instance from a foreign function call, they can perform memory dereference on it directly, * memory address instance from a foreign function call, they can perform memory dereference on it directly,
@ -167,7 +167,7 @@
* } * }
* *
* <h3>Upcalls</h3> * <h3>Upcalls</h3>
* The {@link jdk.incubator.foreign.CLinker} interface also allows to turn an existing method handle (which might point * The {@link jdk.incubator.foreign.CLinker} interface also allows clients to turn an existing method handle (which might point
* to a Java method) into a memory address, so that Java code can effectively be passed to other foreign functions. * to a Java method) into a memory address, so that Java code can effectively be passed to other foreign functions.
* For instance, we can write a method that compares two integer values, as follows: * For instance, we can write a method that compares two integer values, as follows:
* *
@ -193,7 +193,7 @@
* As before, we need to create a {@link jdk.incubator.foreign.FunctionDescriptor} instance, this time describing the signature * As before, we need to create a {@link jdk.incubator.foreign.FunctionDescriptor} instance, this time describing the signature
* of the function pointer we want to create. The descriptor can be used to * of the function pointer we want to create. The descriptor can be used to
* {@linkplain jdk.incubator.foreign.CLinker#upcallType(jdk.incubator.foreign.FunctionDescriptor) derive} a method type * {@linkplain jdk.incubator.foreign.CLinker#upcallType(jdk.incubator.foreign.FunctionDescriptor) derive} a method type
* that can be used to lookup the method handle for {@code IntComparator.intCompare}. * that can be used to look up the method handle for {@code IntComparator.intCompare}.
* <p> * <p>
* Now that we have a method handle instance, we can turn it into a fresh function pointer, * Now that we have a method handle instance, we can turn it into a fresh function pointer,
* using the {@link jdk.incubator.foreign.CLinker} interface, as follows: * using the {@link jdk.incubator.foreign.CLinker} interface, as follows:

View file

@ -191,7 +191,7 @@ public class IOUtils {
PrintStream consumer, boolean writeOutputToFile, long timeout) PrintStream consumer, boolean writeOutputToFile, long timeout)
throws IOException { throws IOException {
exec(pb, testForPresenceOnly, consumer, writeOutputToFile, exec(pb, testForPresenceOnly, consumer, writeOutputToFile,
Executor.INFINITE_TIMEOUT, false); timeout, false);
} }
static void exec(ProcessBuilder pb, boolean testForPresenceOnly, static void exec(ProcessBuilder pb, boolean testForPresenceOnly,

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -30,6 +30,16 @@
* @run main BSMCalledTwice * @run main BSMCalledTwice
*/ */
/*
* @test
* @bug 8262134
* @library /test/lib
* @requires vm.debug
* @modules java.base/jdk.internal.org.objectweb.asm
* @compile -XDignore.symbol.file BSMCalledTwice.java
* @run main/othervm -Xcomp -XX:CompileCommand=compileonly,TestC::* -XX:+DeoptimizeALot -XX:+VerifyStack BSMCalledTwice
*/
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.util.*; import java.util.*;

View file

@ -834,9 +834,6 @@ jdk/jfr/api/consumer/streaming/TestLatestEvent.java 8268297 windows-
# jdk_jpackage # jdk_jpackage
tools/jpackage/share/IconTest.java 8278233 macosx-x64
tools/jpackage/share/MultiNameTwoPhaseTest.java 8278233 macosx-x64
############################################################################ ############################################################################
# Client manual tests # Client manual tests

View file

@ -0,0 +1,111 @@
/*
* Copyright (c) 2021, 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 8277964
* @summary Test IllegalArgumentException be thrown when an argument is invalid
* @run testng/othervm IllegalArgumentsTest
*/
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import org.testng.annotations.Test;
public class IllegalArgumentsTest {
static class T {
public T(int i) {}
public static void m(int i) {}
public void m1(String s) {}
}
@Test
public void wrongArgumentType() throws ReflectiveOperationException {
for (int i = 0; i < 100_000; ++i) {
try {
Constructor<T> ctor = T.class.getConstructor(int.class);
ctor.newInstance(int.class); // wrong argument type
throw new RuntimeException("Expected IAE not thrown");
} catch (IllegalArgumentException e) {}
}
for (int i = 0; i < 100_000; ++i) {
try {
Method method = T.class.getMethod("m", int.class);
method.invoke(null, int.class); // wrong argument type
throw new RuntimeException("Expected IAE not thrown");
} catch (IllegalArgumentException e) {}
}
}
@Test
public void nullArguments() throws ReflectiveOperationException {
for (int i = 0; i < 100_000; ++i) {
try {
Constructor<T> ctor = T.class.getConstructor(int.class);
ctor.newInstance(new Object[] {null});
throw new RuntimeException("Expected IAE not thrown");
} catch (IllegalArgumentException e) {}
}
for (int i = 0; i < 100_000; ++i) {
try {
Method method = T.class.getMethod("m", int.class);
method.invoke(null, new Object[] {null});
throw new RuntimeException("Expected IAE not thrown");
} catch (IllegalArgumentException e) {}
}
}
@Test
public void illegalArguments() throws ReflectiveOperationException {
for (int i = 0; i < 100_000; ++i) {
try {
Constructor<T> ctor = T.class.getConstructor(int.class);
ctor.newInstance(new Object[] { 10, 20});
throw new RuntimeException("Expected IAE not thrown");
} catch (IllegalArgumentException e) {}
}
for (int i = 0; i < 100_000; ++i) {
try {
Method method = T.class.getMethod("m", int.class);
method.invoke(null, new Object[] { 10, 20});
throw new RuntimeException("Expected IAE not thrown");
} catch (IllegalArgumentException e) {}
}
}
@Test
public void wrongReceiver() throws ReflectiveOperationException {
for (int i = 0; i < 100_000; ++i) {
try {
Method method = T.class.getMethod("m1", String.class);
method.invoke(this, "bad receiver");
throw new RuntimeException("Expected IAE not thrown");
} catch (IllegalArgumentException e) {}
}
}
}

View file

@ -0,0 +1,64 @@
/*
* Copyright (c) 2021, 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 8278744
* @summary KeyStore:getAttributes() not returning unmodifiable Set
* @library /test/lib
*/
import jdk.test.lib.SecurityTools;
import jdk.test.lib.Utils;
import java.io.File;
import java.security.KeyStore;
public class UnmodifiableAttributes {
public static final void main(String[] args) throws Exception {
var oneAttr = new KeyStore.Entry.Attribute() {
@Override
public String getName() {
return "1.2.3";
}
@Override
public String getValue() {
return "testVal";
}
};
char[] pass = "changeit".toCharArray();
SecurityTools.keytool("-keystore ks -storepass changeit -genkeypair -alias a -dname CN=A -keyalg EC")
.shouldHaveExitValue(0);
KeyStore ks = KeyStore.getInstance(new File("ks"), pass);
var attrs = ks.getAttributes("a");
Utils.runAndCheckException(() -> attrs.add(oneAttr), UnsupportedOperationException.class);
var attrs2 = ks.getEntry("a", new KeyStore.PasswordProtection(pass)).getAttributes();
Utils.runAndCheckException(() -> attrs2.add(oneAttr), UnsupportedOperationException.class);
}
}

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -51,10 +51,10 @@ import jdk.test.lib.jfr.Events;
*/ */
public final class TestHiddenMethod { public final class TestHiddenMethod {
public static void main(String[] args) throws Throwable { // Must call in separate thread because JTREG uses reflection
try (Recording recording = new Recording()) { // to invoke main method, which uses hidden methods.
recording.enable(MyEvent.class).withThreshold(Duration.ofMillis(0)); public static class TestThread extends Thread {
recording.start(); public void run() {
// doPrivileged calls a method that has the @Hidden // doPrivileged calls a method that has the @Hidden
// annotation // annotation
AccessController.doPrivileged(new PrivilegedAction<Void>() { AccessController.doPrivileged(new PrivilegedAction<Void>() {
@ -65,8 +65,19 @@ public final class TestHiddenMethod {
return null; return null;
} }
}); });
MyEvent event = new MyEvent(); MyEvent event = new MyEvent();
event.commit(); event.commit();
}
}
public static void main(String[] args) throws Throwable {
try (Recording recording = new Recording()) {
recording.enable(MyEvent.class).withThreshold(Duration.ofMillis(0));
recording.start();
Thread t = new TestThread();
t.start();
t.join();
recording.stop(); recording.stop();
List<RecordedEvent> events = Events.fromRecording(recording); List<RecordedEvent> events = Events.fromRecording(recording);
@ -78,9 +89,7 @@ public final class TestHiddenMethod {
System.out.println("visibleEvent:" + visibleEvent); System.out.println("visibleEvent:" + visibleEvent);
assertTrue(hasHiddenStackFrame(hiddenEvent), "No hidden frame in hidden event: " + hiddenEvent); assertTrue(hasHiddenStackFrame(hiddenEvent), "No hidden frame in hidden event: " + hiddenEvent);
assertFalse(hasHiddenStackFrame(visibleEvent), "Hidden frame in visible event: " + visibleEvent);
// Temporary disable this test until JDK-8272064 is resolved.
// assertFalse(hasHiddenStackFrame(visibleEvent), "Hidden frame in visible event: " + visibleEvent);
} }
} }