问:你了解java的内存模型嘛?java
内存简介:
数组
地址空间划分数据结构
- 内核空间(主要是操做系统程序和C运行时的空间,包含连接硬件、调度程序、提供联网、虚拟内存等逻辑和基于C的进程)
- 用户空间(java实际运行时使用的空间,32位系统最多访问3G,内核代码能够访问全部物理内存。64位系统能够访问超过512G,内核代码一样能够访问全部物理内存)
jvm内存模型--jdk8及之后多线程

- 线程私有:程序计数器、虚拟机栈、本地方法栈
- 线程共享:MetaSpace(元空间)、java堆
程序计数器(是一块较小的内存空间,线程私有)jvm
- 当前线程所执行的字节码行号指示器(逻辑)
- 改变计数器的值来选取下一条须要执行的字节码指令(分支、循环、跳转、异常处理、线程恢复等基础功能都须要依赖计数器)
- 和线程是一对一的关系即“线程私有内存”(jvm是多线程运行的,为了确保切换线程后能恢复到每一个线程原来运行的位置就须要私有程序计数器)
- 对java方法技术,若是是Native方法则计数器位Undefined
- 不会发生内存泄漏(由于只是记录了行号)
java虚拟机栈(stack,线程私有)this
- java方法执行的内存模型
- 包含多个栈帧(方法运行的基础数据结构,包含局部变量表、操做栈、动态连接、返回地址等入栈到出栈的过程。栈帧持有局部变量、部分结果、参与方法的调用与返回,方法调用结束时帧才会被销毁。)
局部变量表和操做数栈操作系统
- 局部变量表:包含方法执行过程当中的全部变量(包括this引用、全部方法参数、其余局部变量)
- 操做数栈:入栈、出栈、复制、交换、产生消费变量(在执行字节码指令过程当中被用到,这种方式相似于原生cpu寄存器,大部分jvm字节码把时间花费在操做数栈的操做上,所以局部变量的数组和操做数栈的操做指令经过字节码频繁执行)
实例:线程

编译二进制,再反编译字节码 (这里javac的时候遇到了个小问题,由于中文注释的缘由,GBK不可映射字符 因此加上 -endcoding UTF-8 解决问题)3d


descript:(II)I 表示描述方法:有2个int参数 返回int, flags 标记public的 static的blog
stack=2 操做数栈 深度2 ,locals 本地变量是3 ,args_size参数大小是2个
而后就是一堆进栈出栈的指令
LineNumberTable是代码的行号对应字节码行号
执行add(1,2)过程:

问:递归为何会引起java.lang.StackOverflowError异常?
递归过深,栈帧数超出虚拟栈深度 解决方法就是减小递归次数或者循环替换递归
虚拟机栈过多会引起java.lang.OutOfMemoryError异常
虚拟机栈不须要GC回收,用完就会释放掉
本地方法栈:
- 与虚拟机栈类似,主要做用于标注了native的方法