Skip to main content

VmCapabilitiesNew

Struct VmCapabilitiesNew 

Source
pub struct VmCapabilitiesNew {
    pub can_redefine_classes: bool,
    pub can_add_method: bool,
    pub can_unrestrictedly_redefine_classes: bool,
    pub can_pop_frames: bool,
    pub can_use_instance_filters: bool,
    pub can_get_instance_info: bool,
    pub can_request_monitor_events: bool,
    pub can_get_monitor_frame_info: bool,
}
Expand description

The capabilities VirtualMachine.CapabilitiesNew (command 17) adds on top of VmCapabilities.

The reply repeats the original seven booleans and then adds twenty-five more, of which the last eleven are reserved. Only the ones a feature here turns on are named: decoding a bit nothing consults would be the same uncalled-command mistake IDSizes was deleted for (CLEAN-1, #27).

Asked before hot reload rather than after a failure, per the rule VmCapabilities states: a JVM without canRedefineClasses answers NOT_IMPLEMENTED (99) to the command, and “this JVM cannot HotSwap” is a far more useful report than a bare error code.

Fields§

§can_redefine_classes: bool

Whether redefine_classes will work at all. Every HotSpot this project has met says yes; a JVM in the field may not.

§can_add_method: bool

Whether a redefinition may add a method. HotSpot says no, which is most of why a swap gets refused: method bodies are all it will accept.

§can_unrestrictedly_redefine_classes: bool

Whether the JVM lifts the method-bodies-only restriction entirely. HotSpot says no.

§can_pop_frames: bool

Whether pop_frames will work — the other half of a useful swap, since a frame already on the stack keeps running the code it entered with.

§can_use_instance_filters: bool

Whether a request may carry an InstanceOnly modifier (modKind 11) — position 12.

Decoded in the same change that consults it (FILT-9, #101), per this struct’s rule. It matters more than most bits here because of how the JVM refuses a modifier it cannot honour: not with NOT_IMPLEMENTED, but with INTERNAL (113), which says nothing about which modifier was the problem. Reading the bit first turns that into a sentence.

Measured true on Temurin 17.0.20 — docs/heap-query-measurements.md has the full vector.

§can_get_instance_info: bool

Whether instances and instance_counts will work — position 16, four bits past where this decoder used to stop.

Decoded in the same change that consults it (DISC-10, #84). Positions 13-15 (canGetSourceDebugExtension, canRequestVMDeathEvent, canSetDefaultStratum) are read past rather than named, for the reason this struct’s documentation gives: a bit nothing reads is the mistake IDSizes was deleted for. Position 12 joined the named ones with FILT-9 (#101).

§can_request_monitor_events: bool

Whether set_monitor_request will work — position 17, the very next bit after 16, so DISC-10’s decoder needed no positions skipped to reach it.

Decoded in the same change that consults it (DUMP-7, #96), per this struct’s rule, and consulted at arming time rather than after the fact: a JVM without it answers NOT_IMPLEMENTED (99), and “this JVM cannot report lock contention as it happens, so a lock diagnosis here still needs a suspending debug.thread_dump” is a far more useful report — it names the fallback as well as the refusal.

§can_get_monitor_frame_info: bool

Whether the JVM can say at which stack depth a thread acquired each monitor it owns (ThreadReference.OwnedMonitorsStackDepthInfo) — position 18.

Named although no command here issues that request, which is a deliberate exception to this struct’s rule and needs its justification stated rather than assumed. What consults it is the arming reply for a monitor stop point: a snapshot names the lock, the thread and the location that blocked, and the obvious next question — where in this thread’s stack was the lock taken — is answerable on a JVM with this bit and not on one without. Reporting which of the two a caller is on costs one already-issued command, where leaving it out invites the reading that the tool simply does not report frame depth on any JVM.

That is a consulted bit rather than an implied capability, which is the line IDSizes crossed (CLEAN-1, #27): nothing here claims the frame-depth query exists. If it is ever built, this is the bit it gates on.

Trait Implementations§

Source§

impl Clone for VmCapabilitiesNew

Source§

fn clone(&self) -> VmCapabilitiesNew

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for VmCapabilitiesNew

Source§

impl Debug for VmCapabilitiesNew

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for VmCapabilitiesNew

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Serialize for VmCapabilitiesNew

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more