JVM内存结构主要包括两个子系统和两个组件。
两个子系统分别是Classloader子系统和Executionengine(执行引擎)子系统;两个组件分别是Runtimedataarea(运行时数据区域)组件和Nativeinterface(本地接口)组件。
Classloader子系统:装载class信息到运行时数据区
Executionengine(执行引擎)子系统:执行Class的地方
Runtimedataarea(运行时数据区域)组件:经常说的JVM内存,分为5个区域
(1)heap(堆):存放new 出来的对象和数组,由GC管理内存,每个JVM实例一个堆
(2)javastack(栈):每个线程一个javastack,只有压栈和出栈2个动作,以桢为单位
(3)methodarea(方法区):每个JVM实例一个,存储类信息,静态的变量
(4)ProgramCounter:每个线程都有一个PC寄存器,记录线程执行的下个地址
(5)nativemethodstack:保存本地方法进去区域的地址
这里heap和methodarea是所有线程共享,而其他3个则是以线程为粒度隔离的。
Nativeinterface(本地接口)组件:与本地lib交互,是与其他语言交互的接口,当调用native方法时,不受JVM限制,可能会抛nativeheapOutOfMemory
栈是JVM的内存指令区,JAVA基本类型,JAVA指令代码,常量都保存在stack中,存取速度快,数据可以共享,缺点是栈中的数据大小和生命周期是确定的,不灵活
堆是JVM的内存数据区,对象实例包括他的属性都作为数据存储在heap中,对象实例在heap中分配好后,需要在stack中保存4个字节的heap内存地址,用来定位该对象在heap的位置,找到该实例,可以动态的分配内存大小,生存期不需要告诉编译器,但是存取慢。
例子:对象的方法和属性保存在哪里?
方法信息在方法区中,属性在heap中
另外,对象的静态属性在方法区中。
非静态方法和静态方法:
实例方法有一个隐含的传入参数,该参数就是this,也就是当前对象实例在stack中的地址指针,因为调用非静态方法时,都要先new出来。
静态方法无此隐含参数,不需要new 对象,只要class文件被ClassLoader加载到JVM的stack中,静态方法就能被调用,当然,静态方法取不到heap中的对象属性,因为还没对象呢。。。