JVM总体结构

JVM内存概念

共享内存区域


ce43e3373a8850f028b8eaede1fcb18.png
存储new出来的实例化对象,大多数状况实例化对象会存放在Eden区,当eden区满了以后字节码执行引擎会使用minor gc进行垃圾回收(用gc root寻址法等)。
方法区(元空间/永久带):使用的是物理内存,存放全局的常量,静态变量,类信息(对象在堆中,方法区中存的依旧是指针)java

线程独占内存区域

栈(FILO):先入后出结构
栈帧:每个方法会开辟一个栈帧存储方法内用到的局部变量、操做数栈、动态连接、方法出口c++

  • 局部变量:仅方法内部使用的变量

main方法中若是有new对象,局部变量表中的对象为对象在堆中的地址,相似于指针。segmentfault


  • 操做数栈:存储当前操做的变量,E.x 1+2=3,会将1和2分别压入操做数栈而后将1和2出栈在CPU缓存中进行加法计算,返回结果3从新压入到操做数栈,最后将操做数栈中的结果拿出进行赋值,操做数栈则清空

  • 动态连接:存放程序中调用的非静态方法的内存区位置。E.x user.login() 若是login是非静态方法,则该线程的栈帧中存储的动态连接则是login()在方法区(元空间)中对应的内存地址。

  • 方法出口:方法执行结束后返回的上层方法的位置信息

E.x
user.login(){//方法体}
执行结束后返回调用login()方法的位置继续向下执行。windows

本地方法栈:存放native修饰的方法,由C、C++等语言实现的底层dll文件中的方法,能够实现java语言调用c++等其余语言写的本地方法
程序计数器:每个线程独有的内存空间,用来存储下一条运行代码的位置标识例如汇编代码4:iLoad_1,其中4即为位置标识,每执行完一行代码进行更新。
多线程执行时用来记录当前线程执行的位置,切换回来时在当前位置继续执行。缓存

内存分配:

指针碰撞分配方式:内存依序存储,每次指针向后移动对象大小的空间,指向下一个对象存储的位置多线程

空闲列表分配方式:可能因为GC等问题,内存中的对象不是依序排列,其中有空缺的内存空间,该部分空间会以列表方式进行村存储,后面的对象在列表中找到对应的空闲存储空间进行使用性能

多线程内存争抢问题解决方案:CAS 比较并替换-默认、TLAB(thread local allocation buffer) 线程本地缓存 -XX:+/-UseTLAB 参数设置本地缓存大小。spa

内存调优:

windows下可使用jdk自动监控程序:jvisualvm查看内存中各个区域的状况线程

调优目的:因为GC会触发STW机制,因此要尽可能减小GC,能够适当调整内存的大小分配,以下图
image.png
方法区若是不设置值,该空间初始大小21M,会自动根据GC回收状况进行自动扩容,不然会致使频繁的full GC下降性能
-Xss 栈默认大小为1M,该配置设置的值是针对单个线程设置的栈空间大小,该值越小,单个线程能够调用的方法越少,但能够开启的线程总量会变多。指针

STW目的:避免检测垃圾对象时,对象的状态发生变动,产生对象的错误清理。