JVM Stack
Stack
参考SharkStack类,代码:hotspot\src\share\vm\shark\sharkStack.hpp
栈帧
每个方法调用都对应一个栈帧(frame )。包含本地变量表,操作栈(operand stack),当前调用的方法对应类的运行时常量池(run-time constant pool)的引用(reference)。
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.6 写道
A frame may be extended with additional implementation-specific information, such as debugging information.
本地变量表使用一个数组保存每一个本地变量(local variable)。
本地变量表和操作栈 的大小在编译期就已确定。
本地变量表
操作栈
参考SharkState类,代码:hotspot\src\share\vm\shark\sharkState.hpp
参考代码:hotspot\src\share\vm\shark\sharkStateScanner.cpp
void SharkStateScanner::scan(SharkState* state) {
start_frame();
// Expression stack
stack_integrity_checks(state);
start_stack(state->stack_depth());
for (int i = state->stack_depth() - 1; i >= 0; i--) {
process_stack_slot(
i,
state->stack_addr(i),
stack()->stack_slots_offset() +
i + max_stack() - state->stack_depth());
}
end_stack();
// Monitors
start_monitors(state->num_monitors());
for (int i = 0; i < state->num_monitors(); i++) {
process_monitor(
i,
stack()->monitor_offset(i),
stack()->monitor_object_offset(i));
}
end_monitors();
// Frame header
start_frame_header();
process_oop_tmp_slot(
state->oop_tmp_addr(), stack()->oop_tmp_slot_offset());
process_method_slot(state->method_addr(), stack()->method_slot_offset());
process_pc_slot(stack()->pc_slot_offset());
end_frame_header();
// Local variables
locals_integrity_checks(state);
start_locals();
for (int i = 0; i < max_locals(); i++) {
process_local_slot(
i,
state->local_addr(i),
stack()->locals_slots_offset() + max_locals() - 1 - i);
}
end_locals();
end_frame();
}
public static void main(String[] args) {
apply(1);
}
private static void apply(int arg) {
int argc = arg;
try {
apply(++arg);
} catch(Throwable e) {
System.out.println(argc);
System.out.println(e);
}
}
5617
java.lang.StackOverflowError
将System.out.println(e);改成e.printStackTrace();打印出栈信息:
5617
java.lang.StackOverflowError
at sparktest.StackTest.apply(StackTest.java:14)
at sparktest.StackTest.apply(StackTest.java:12)
at sparktest.StackTest.apply(StackTest.java:12)
at sparktest.StackTest.apply(StackTest.java:12)
at sparktest.StackTest.apply(StackTest.java:12)
at sparktest.StackTest.apply(StackTest.java:12)
at sparktest.StackTest.apply(StackTest.java:12)
at sparktest.StackTest.apply(StackTest.java:12)
at sparktest.StackTest.apply(StackTest.java:12)
at sparktest.StackTest.apply(StackTest.java:12)
at sparktest.StackTest.apply(StackTest.java:12)
...
java call
java call包括special,virtual,Static方法调用。这些方法调用都会调用到Low-level的call函数:
static void call(JavaValue* result, methodHandle method, JavaCallArguments* args, TRAPS);
另外还有一个call_helper方法:
static void call_helper(JavaValue* result, methodHandle* method, JavaCallArguments* args, TRAPS);
上面的Low-level的call函数通过java_call_t的函数指针调用call_helper函数。
java_call_t
java_call_t被定义成一个函数指针,用来表示java调用。如调用java的方法,包括virtual方法调用,特定(special)方法调用,静态(static)方法调用。
其中virtual方法,特定(special)方法都是普通的非静态方法。这里的virtual方法,特定(special)方法,静态(static)方法就是java代码编译成字节码后方法调用的地方常见的invokespecial,invokevirtual,invokestatic指令。这些指令参考另一篇文章:https://lobin.iteye.com/blog/2440503。
typedef void (*java_call_t)(JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread);
java call(special)
// call_special
// ------------
// The receiver must be first oop in argument list
static void call_special(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS);
static void call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); // No args
static void call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS);
static void call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS);
java call(virtual)
// virtual call
// ------------
// The receiver must be first oop in argument list
static void call_virtual(JavaValue* result, KlassHandle spec_klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS);
static void call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, TRAPS); // No args
static void call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS);
static void call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS);
java call(Static)
// Static call
// -----------
static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS);
static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS);
static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS);
call_helper函数将java call封装成JavaCallWrapper,然后通过一个调用代理CallStub(调用StubRoutines::call_stub()函数得到这个CallStub调用代理)。
调用代理(CallStub)
StubRoutines::call_stub()函数:
static CallStub call_stub() { return CAST_TO_FN_PTR(CallStub, _call_stub_entry); }
其中:
#define CAST_TO_FN_PTR(func_type, value) ((func_type)(castable_address(value)))
展开后:
static CallStub call_stub() { return ((CallStub)(castable_address(_call_stub_entry)));}
_call_stub_entry由StubGenerator extends StubCodeGenerator初始化,参考generate_call_stub函数,它返回的是调用代理的第一条指令的地址(address),也就是在调用这个调用代理时要跳转到的目标地址,以及调用这个调用代理后要跳转返回的地址,为调用代理(这个调用代理可以理解为一段汇编指令程序,负责代理调用方法)建栈(见__ enter();...__ pop(rbp);),传递参数,方法调用时call指令要跳转到的目标地址。
在看JVM在实现汇编指令等价函数操作时,和汇编指令语法一样,也有它的汇编风格,参考AT&T汇编风格。
调用代理(CallStub)也是一个函数指针
// Calls to Java
typedef void (*CallStub)(
address link,
intptr_t* result,
BasicType result_type,
methodOopDesc* method,
address entry_point,
intptr_t* parameters,
int size_of_parameters,
TRAPS
);
jmethodID -> methodHandle -> JavaCalls::call -> StubRoutines::call_stub -> CallStub ->
CallStub
64位x86 CPU实现:generate_call_stub
参考src\cpu\x86\vm\stubGenerator_x86_64.cpp
address generate_call_stub(address& return_address) {
assert((int)frame::entry_frame_after_call_words == -(int)rsp_after_call_off + 1 &&
(int)frame::entry_frame_call_wrapper_offset == (int)call_wrapper_off,
"adjust this code");
StubCodeMark mark(this, "StubRoutines", "call_stub");
address start = __ pc();
// same as in generate_catch_exception()!
const Address rsp_after_call(rbp, rsp_after_call_off * wordSize);
const Address call_wrapper (rbp, call_wrapper_off * wordSize);
const Address result (rbp, result_off * wordSize);
const Address result_type (rbp, result_type_off * wordSize);
const Address method (rbp, method_off * wordSize);
const Address entry_point (rbp, entry_point_off * wordSize);
const Address parameters (rbp, parameters_off * wordSize);
const Address parameter_size(rbp, parameter_size_off * wordSize);
// same as in generate_catch_exception()!
const Address thread (rbp, thread_off * wordSize);
const Address r15_save(rbp, r15_off * wordSize);
const Address r14_save(rbp, r14_off * wordSize);
const Address r13_save(rbp, r13_off * wordSize);
const Address r12_save(rbp, r12_off * wordSize);
const Address rbx_save(rbp, rbx_off * wordSize);
// stub code
__ enter();
__ subptr(rsp, -rsp_after_call_off * wordSize);
// save register parameters
#ifndef _WIN64
__ movptr(parameters, c_rarg5); // parameters
__ movptr(entry_point, c_rarg4); // entry_point
#endif
__ movptr(method, c_rarg3); // method
__ movl(result_type, c_rarg2); // result type
__ movptr(result, c_rarg1); // result
__ movptr(call_wrapper, c_rarg0); // call wrapper
// save regs belonging to calling function
__ movptr(rbx_save, rbx);
__ movptr(r12_save, r12);
__ movptr(r13_save, r13);
__ movptr(r14_save, r14);
__ movptr(r15_save, r15);
#ifdef _WIN64
for (int i = 6; i <= 15; i++) {
__ movdqu(xmm_save(i), as_XMMRegister(i));
}
const Address rdi_save(rbp, rdi_off * wordSize);
const Address rsi_save(rbp, rsi_off * wordSize);
__ movptr(rsi_save, rsi);
__ movptr(rdi_save, rdi);
#else
const Address mxcsr_save(rbp, mxcsr_off * wordSize);
{
Label skip_ldmx;
__ stmxcsr(mxcsr_save);
__ movl(rax, mxcsr_save);
__ andl(rax, MXCSR_MASK); // Only check control and mask bits
ExternalAddress mxcsr_std(StubRoutines::x86::mxcsr_std());
__ cmp32(rax, mxcsr_std);
__ jcc(Assembler::equal, skip_ldmx);
__ ldmxcsr(mxcsr_std);
__ bind(skip_ldmx);
}
#endif
// Load up thread register
__ movptr(r15_thread, thread);
__ reinit_heapbase();
#ifdef ASSERT
// make sure we have no pending exceptions
{
Label L;
__ cmpptr(Address(r15_thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD);
__ jcc(Assembler::equal, L);
__ stop("StubRoutines::call_stub: entered with pending exception");
__ bind(L);
}
#endif
// pass parameters if any
BLOCK_COMMENT("pass parameters if any");
Label parameters_done;
__ movl(c_rarg3, parameter_size);
__ testl(c_rarg3, c_rarg3);
__ jcc(Assembler::zero, parameters_done);
Label loop;
__ movptr(c_rarg2, parameters); // parameter pointer
__ movl(c_rarg1, c_rarg3); // parameter counter is in c_rarg1
__ BIND(loop);
__ movptr(rax, Address(c_rarg2, 0));// get parameter
__ addptr(c_rarg2, wordSize); // advance to next parameter
__ decrementl(c_rarg1); // decrement counter
__ push(rax); // pass parameter
__ jcc(Assembler::notZero, loop);
// call Java function
__ BIND(parameters_done);
__ movptr(rbx, method); // get methodOop
__ movptr(c_rarg1, entry_point); // get entry_point
__ mov(r13, rsp); // set sender sp
BLOCK_COMMENT("call Java function");
__ call(c_rarg1);
BLOCK_COMMENT("call_stub_return_address:");
return_address = __ pc();
// store result depending on type (everything that is not
// T_OBJECT, T_LONG, T_FLOAT or T_DOUBLE is treated as T_INT)
__ movptr(c_rarg0, result);
Label is_long, is_float, is_double, exit;
__ movl(c_rarg1, result_type);
__ cmpl(c_rarg1, T_OBJECT);
__ jcc(Assembler::equal, is_long);
__ cmpl(c_rarg1, T_LONG);
__ jcc(Assembler::equal, is_long);
__ cmpl(c_rarg1, T_FLOAT);
__ jcc(Assembler::equal, is_float);
__ cmpl(c_rarg1, T_DOUBLE);
__ jcc(Assembler::equal, is_double);
// handle T_INT case
__ movl(Address(c_rarg0, 0), rax);
__ BIND(exit);
// pop parameters
__ lea(rsp, rsp_after_call);
#ifdef ASSERT
// verify that threads correspond
{
Label L, S;
__ cmpptr(r15_thread, thread);
__ jcc(Assembler::notEqual, S);
__ get_thread(rbx);
__ cmpptr(r15_thread, rbx);
__ jcc(Assembler::equal, L);
__ bind(S);
__ jcc(Assembler::equal, L);
__ stop("StubRoutines::call_stub: threads must correspond");
__ bind(L);
}
#endif
// restore regs belonging to calling function
#ifdef _WIN64
for (int i = 15; i >= 6; i--) {
__ movdqu(as_XMMRegister(i), xmm_save(i));
}
#endif
__ movptr(r15, r15_save);
__ movptr(r14, r14_save);
__ movptr(r13, r13_save);
__ movptr(r12, r12_save);
__ movptr(rbx, rbx_save);
#ifdef _WIN64
__ movptr(rdi, rdi_save);
__ movptr(rsi, rsi_save);
#else
__ ldmxcsr(mxcsr_save);
#endif
// restore rsp
__ addptr(rsp, -rsp_after_call_off * wordSize);
// return
__ pop(rbp);
__ ret(0);
// handle return types different from T_INT
__ BIND(is_long);
__ movq(Address(c_rarg0, 0), rax);
__ jmp(exit);
__ BIND(is_float);
__ movflt(Address(c_rarg0, 0), xmm0);
__ jmp(exit);
__ BIND(is_double);
__ movdbl(Address(c_rarg0, 0), xmm0);
__ jmp(exit);
return start;
}
Assembler
MacroAssembler -》Assembler -》AbstractAssembler
AbstractAssembler:
hotspot\src\share\vm\asm\assembler.hpp
x86:
MacroAssembler:
hotspot\src\cpu\x86\vm\assembler_x86.hpp
Assembler:
hotspot\src\cpu\x86\vm\assembler_x86.hpp
sparc:
AbstractAssembler声明如下:
// Instruction boundaries (required when emitting relocatable values).
class InstructionMark: public StackObj {
private:
AbstractAssembler* _assm;
public:
InstructionMark(AbstractAssembler* assm) : _assm(assm) {
assert(assm->inst_mark() == NULL, "overlapping instructions");
_assm->set_inst_mark();
}
~InstructionMark() {
_assm->clear_inst_mark();
}
};
friend class InstructionMark;
#ifdef ASSERT
// Make it return true on platforms which need to verify
// instruction boundaries for some operations.
inline static bool pd_check_instruction_mark();
// Add delta to short branch distance to verify that it still fit into imm8.
int _short_branch_delta;
int short_branch_delta() const { return _short_branch_delta; }
void set_short_branch_delta() { _short_branch_delta = 32; }
void clear_short_branch_delta() { _short_branch_delta = 0; }
class ShortBranchVerifier: public StackObj {
private:
AbstractAssembler* _assm;
public:
ShortBranchVerifier(AbstractAssembler* assm) : _assm(assm) {
assert(assm->short_branch_delta() == 0, "overlapping instructions");
_assm->set_short_branch_delta();
}
~ShortBranchVerifier() {
_assm->clear_short_branch_delta();
}
};
#else
// Dummy in product.
class ShortBranchVerifier: public StackObj {
public:
ShortBranchVerifier(AbstractAssembler* assm) {}
};
#endif
// Label functions
void print(Label& L);
public:
// Creation
AbstractAssembler(CodeBuffer* code);
// save end pointer back to code buf.
void sync();
// ensure buf contains all code (call this before using/copying the code)
void flush();
// min and max values for signed immediate ranges
static int min_simm(int nbits) { return -(intptr_t(1) << (nbits - 1)) ; }
static int max_simm(int nbits) { return (intptr_t(1) << (nbits - 1)) - 1; }
// Define some:
static int min_simm10() { return min_simm(10); }
static int min_simm13() { return min_simm(13); }
static int min_simm16() { return min_simm(16); }
// Test if x is within signed immediate range for nbits
static bool is_simm(intptr_t x, int nbits) { return min_simm(nbits) <= x && x <= max_simm(nbits); }
// Define some:
static bool is_simm5( intptr_t x) { return is_simm(x, 5 ); }
static bool is_simm8( intptr_t x) { return is_simm(x, 8 ); }
static bool is_simm10(intptr_t x) { return is_simm(x, 10); }
static bool is_simm11(intptr_t x) { return is_simm(x, 11); }
static bool is_simm12(intptr_t x) { return is_simm(x, 12); }
static bool is_simm13(intptr_t x) { return is_simm(x, 13); }
static bool is_simm16(intptr_t x) { return is_simm(x, 16); }
static bool is_simm26(intptr_t x) { return is_simm(x, 26); }
static bool is_simm32(intptr_t x) { return is_simm(x, 32); }
// Accessors
CodeBuffer* code() const; // _code_section->outer()
CodeSection* code_section() const { return _code_section; }
int sect() const; // return _code_section->index()
address pc() const { return _code_pos; }
int offset() const { return _code_pos - _code_begin; }
int locator() const; // CodeBuffer::locator(offset(), sect())
OopRecorder* oop_recorder() const { return _oop_recorder; }
void set_oop_recorder(OopRecorder* r) { _oop_recorder = r; }
address inst_mark() const;
void set_inst_mark();
void clear_inst_mark();
// Constants in code
void a_byte(int x);
void a_long(jint x);
void relocate(RelocationHolder const& rspec, int format = 0);
void relocate( relocInfo::relocType rtype, int format = 0) {
if (rtype != relocInfo::none)
relocate(Relocation::spec_simple(rtype), format);
}
static int code_fill_byte(); // used to pad out odd-sized code buffers
// Associate a comment with the current offset. It will be printed
// along with the disassembly when printing nmethods. Currently
// only supported in the instruction section of the code buffer.
void block_comment(const char* comment);
// Label functions
void bind(Label& L); // binds an unbound label L to the current code position
// Move to a different section in the same code buffer.
void set_code_section(CodeSection* cs);
// Inform assembler when generating stub code and relocation info
address start_a_stub(int required_space);
void end_a_stub();
// Ditto for constants.
address start_a_const(int required_space, int required_align = sizeof(double));
void end_a_const();
// constants support
address long_constant(jlong c) {
address ptr = start_a_const(sizeof(c), sizeof(c));
if (ptr != NULL) {
*(jlong*)ptr = c;
_code_pos = ptr + sizeof(c);
end_a_const();
}
return ptr;
}
address double_constant(jdouble c) {
address ptr = start_a_const(sizeof(c), sizeof(c));
if (ptr != NULL) {
*(jdouble*)ptr = c;
_code_pos = ptr + sizeof(c);
end_a_const();
}
return ptr;
}
address float_constant(jfloat c) {
address ptr = start_a_const(sizeof(c), sizeof(c));
if (ptr != NULL) {
*(jfloat*)ptr = c;
_code_pos = ptr + sizeof(c);
end_a_const();
}
return ptr;
}
address address_constant(address c) {
address ptr = start_a_const(sizeof(c), sizeof(c));
if (ptr != NULL) {
*(address*)ptr = c;
_code_pos = ptr + sizeof(c);
end_a_const();
}
return ptr;
}
address address_constant(address c, RelocationHolder const& rspec) {
address ptr = start_a_const(sizeof(c), sizeof(c));
if (ptr != NULL) {
relocate(rspec);
*(address*)ptr = c;
_code_pos = ptr + sizeof(c);
end_a_const();
}
return ptr;
}
// Bootstrapping aid to cope with delayed determination of constants.
// Returns a static address which will eventually contain the constant.
// The value zero (NULL) stands instead of a constant which is still uncomputed.
// Thus, the eventual value of the constant must not be zero.
// This is fine, since this is designed for embedding object field
// offsets in code which must be generated before the object class is loaded.
// Field offsets are never zero, since an object's header (mark word)
// is located at offset zero.
RegisterOrConstant delayed_value(int(*value_fn)(), Register tmp, int offset = 0) {
return delayed_value_impl(delayed_value_addr(value_fn), tmp, offset);
}
RegisterOrConstant delayed_value(address(*value_fn)(), Register tmp, int offset = 0) {
return delayed_value_impl(delayed_value_addr(value_fn), tmp, offset);
}
virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, Register tmp, int offset) = 0;
// Last overloading is platform-dependent; look in assembler_<arch>.cpp.
static intptr_t* delayed_value_addr(int(*constant_fn)());
static intptr_t* delayed_value_addr(address(*constant_fn)());
static void update_delayed_values();
// Bang stack to trigger StackOverflowError at a safe location
// implementation delegates to machine-specific bang_stack_with_offset
void generate_stack_overflow_check( int frame_size_in_bytes );
virtual void bang_stack_with_offset(int offset) = 0;
/**
* A platform-dependent method to patch a jump instruction that refers
* to this label.
*
* @param branch the location of the instruction to patch
* @param masm the assembler which generated the branch
*/
void pd_patch_instruction(address branch, address target);
#ifndef PRODUCT
/**
* Platform-dependent method of printing an instruction that needs to be
* patched.
*
* @param branch the instruction to be patched in the buffer.
*/
static void pd_print_patched_instruction(address branch);
#endif // PRODUCT
};
JVM 处理器体系
参考文档:https://lobin.iteye.com/blog/2438471
x86
寄存器:
Register rax
rcx
rdx
rbx
rsp
rbp
rsi
rdi
r8
r9
r10
r11
r12
r13
r14
r15
XMMRegister xmm0
xmm1
xmm2
xmm3
xmm4
xmm5
xmm6
xmm7
xmm8
xmm9
xmm10
xmm11
xmm12
xmm13
xmm14
xmm15
MMXRegister mmx0
mmx1
mmx2
mmx3
mmx4
mmx5
mmx6
mmx7
源代码参考如下定义:
#define CONSTANT_REGISTER_DECLARATION(type, name, value) \
extern const type name; \
enum { name##_##type##EnumValue = (value) }
以Register rbp为例,
CONSTANT_REGISTER_DECLARATION(Register, rbp, (5));
预处理阶段展开后:
extern const Register rbp;
enum { rbp_RegisterEnumValue = (5) } ;
PC程序计数器
GC
Java Debug调试工具:jdb
>javac -g StackTest.java
>jdb StackTest
> stop at StackTest:6
> run
print StackTest.arg
stop at StackTest:10
list
threads
cont
where 0x1
Java:构建发布JRE&JDK版本:1.6
参考另一篇文章:https://lobin.iteye.com/blog/620153
1、https://www.oracle.com/technetwork/java/javase/tech/index.html
2、http://openjdk.java.net/projects/mlvm/jvmlangsummit/
3、https://www.oracle.com/technetwork/java/javase/memorymanagement-whitepaper-150215.pdf
4、https://download.java.net/openjdk/jdk6
5、http://hg.openjdk.java.net/jdk/jdk/raw-file/tip/doc/building.html
6、http://hg.openjdk.java.net/jdk6/jdk6/raw-file/tip/README-builds.html
7、https://docs.oracle.com/javase/specs/jvms/se8/html/index.html
8、The Java Memory Model, http://www.cs.umd.edu/~pugh/java/memoryModel/
9、http://groups.inf.ed.ac.uk/request/jmmexamples.pdf
10、17.4. Memory Model, https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4
11、JSR 133: JavaTM Memory Model and Thread Specification Revision, https://www.jcp.org/en/jsr/detail?id=133
12、https://docs.oracle.com/javase/7/docs/webnotes/tsg/TSG-VM/html/preface.html
13、Troubleshooting Guide for HotSpot VM, https://docs.oracle.com/javase/7/docs/webnotes/tsg/TSG-VM/html/index.html
14、Java HotSpot VM Options, https://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html
15、https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
16、https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html
相关推荐
Java虚拟机(JVM)是Java程序运行的核心,它负责解释和执行字节码,为Java应用程序提供了一个跨平台的运行环境。JDK(Java Development Kit)包含了开发和运行Java程序所需的所有工具,包括JVM。当我们谈论"jdk,jvm...
标题中提到了JVM原理、JVM调优、JVM内存模型和JAVA并发,这些都是Java虚拟机(JVM)相关的核心概念。JVM是运行Java字节码的虚拟计算机,为Java提供了一个跨平台的环境,确保Java程序可以在不同的操作系统上运行而...
### JVM 详细介绍:掌握 JVM 的各个组成部分与功能 #### 一、Java 源文件编译及执行 Java 应用程序的核心在于源文件的编译与执行。不同于 C/C++ 这类需要针对不同平台进行编译的语言,Java 采用了一种更为灵活的...
SAP JVM 8.1 64位是一个专为SAP系统设计的Java虚拟机,它基于Oracle的Java Development Kit (JDK) 进行优化,以满足SAP应用程序的特定需求。SAP JVM旨在提高性能、可靠性和安全性,同时确保与SAP产品的无缝集成。...
JVM(Java Virtual Machine,Java虚拟机)是运行所有Java程序的假想计算机,是Java程序的运行环境,负责执行指令、管理数据、内存、寄存器等,是实现Java跨平台特性的关键部分。JVM指令手册详细记录了JVM的所有操作...
在Java开发领域,JVM(Java Virtual Machine)是运行所有Java程序的核心,它负责解析字节码并执行程序。深入理解JVM的内核原理、诊断技巧以及优化方法对于提升应用性能至关重要。本教程——“深入JVM内核—原理、...
### JVM必知必会知识点梳理 #### 1. JVM的定义与层次 Java虚拟机(JVM)具有多重含义: - **一套规范**:即Java虚拟机规范,定义了Java虚拟机应该具有的行为。 - **一种实现**:例如HotSpot、J9、JRockit,它们都是...
本系列课程从JVM基础到高级实战,老师手把手教你如何进行JVM调优,思路清晰,没有废话,旨在挑战高薪。 课程亮点: 1、基于阿里arthas进行JVM调优; 2、基于代码排查OOM问题,拒绝空讲; 3、总结JVM通用的调优思路;...
《深入JVM内核—原理、诊断与优化》是一份深度探索Java虚拟机(JVM)的视频教程,旨在帮助开发者全面理解JVM的工作机制,掌握性能诊断技巧,并能进行有效的优化。本教程覆盖了从基础到高级的JVM主题,不仅适用于Java...
R大作为国内JVM领域的权威专家,分享了一系列与JVM相关的知识点,涉及高级语言虚拟机的基础概念、重要书籍推荐、编译器设计与优化等多个方面。这些内容不仅对初学者友好,也为专业人士提供了深入理解JVM机制的机会。...
JVM(Java Virtual Machine)是Java程序运行的核心组件,它负责解释和执行字节码。然而,当JVM出现严重错误或无法恢复的问题时,它可能会崩溃并生成一个崩溃日志,这通常被称为`hs_err_pid.log`文件。这篇内容将深入...
JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。 引入Java语言虚拟机后,Java语言在不同平台...
5. **JVM配置调整**:JProfiler11还可以提供JVM参数建议,帮助开发者正确设置JVM初始堆大小、最大堆大小、内存池等关键参数,确保应用程序稳定运行。 在实际使用中,JProfiler11的详细报告和可视化界面使得问题定位...
在这个压缩包中,"JVM图解.png"可能是对JVM内部结构的可视化表示,"JVM图解"可能是一个详细的文档,解释了JVM的工作原理,而"JVM指令手册 中文版"则提供了JVM可执行的所有指令的详细信息。下面,我们将深入探讨JVM的...
【狂神说JVM探究】是一份集合了多种格式的学习资料,主要涵盖了Java虚拟机(JVM)的基础知识。这份资料出自B站上的【狂神说Java】系列教程,为快速入门JVM提供了详实的笔记。以下是根据这些资源可能包含的一些关键...
Java虚拟机(JVM)是Java程序运行的基础,它是一个抽象的计算机系统,负责执行Java字节码。本文将深入探讨JVM的启动过程及其基本原理。 首先,我们需要理解JVM的基本概念。JVM是Java Virtual Machine的缩写,它是...
SAP JVM 4.1 64位是一个专为SAP系统设计的Java虚拟机,它主要用于运行SAP的应用程序和服务。此版本是为64位操作系统优化的,旨在提供更好的性能和内存管理能力,特别是在处理大数据量和复杂计算场景时。 首先,我们...
### 马士兵JVM调优笔记知识点梳理 #### 一、Java内存结构 Java程序运行时,其内存被划分为几个不同的区域,包括堆内存(Heap)、方法区(Method Area)、栈(Stack)、程序计数器(Program Counter Register)以及...
【JVM运行机制详解】 Java虚拟机(JVM)是Java平台的核心组成部分,它负责执行字节码,为Java程序提供跨平台的运行环境。在深入理解JVM内核的运行机制时,我们需要关注以下几个关键点: 1. **类加载机制**:JVM...
### Java虚拟机(JVM)内存设置与调优详解 #### 引言 在现代软件开发中,Java虚拟机(JVM)作为执行Java字节码的核心组件,其性能直接影响到Java应用的运行效率与稳定性。特别是在大数据处理场景下,合理设置JVM内存...