怎敢精——java内存分配

1、PC寄存器/程序计数器

Program Counter Register,他是线程私有的,每个线程有自己独立的PC寄存器。他所做的事情有如下:分支、循环、跳转、异常处理这些PC寄存器需要跳转位置的时候,以及多线程切换时找到对应挂起的代码位置的时候。他花费的内存空间较小。

在任意时刻,一个jvm线程只会执行一个方法的代码,这个正在被线程所执行的方法称为线程的当前方法current method。

如果当前方法是本地方法,则pc寄存器保存的值就是undefined,如果不是本地方法,保存的就是正在执行的字节码指令的地址。

总结

  • 占用内存小
  • 每个线程拥有独立的PC寄存器(线程私有)
  • 用来记录指令执行的地址。
  • 用于分支,循环,跳转,异常处理,和线程执行到的位置的记录
  • 如果当前方法是本地方法,记录的是undefined,否则记录正在执行的指令地址

2、java虚拟机栈(java virtual machine stacks)

线程私有,与线程同时创建,用于存储栈帧(frame),栈帧中存放局部变量表,操作栈,动态链接,方法出入口等信息,每个方法调用到执行完成就是一个栈帧入栈出栈的过程。详情可以参考开发工具的debug视图。

栈帧的描述:栈帧

扫描二维码关注公众号,回复: 2724901 查看本文章

我个人认为上方的两个蓝色就是栈帧,加在一起就是一个java虚拟机栈。

3、本地方法栈

执行本地方法的栈,和java虚拟机栈类似,有的虚拟机会将两个和在一起。

以上三个为线程私有

下面是线程共享

1、java堆

  • 所有线程共享
  • 虚拟机启动时创建
  • 存放对象实例
  • 几乎所有的对象都在这里分配内存
  • 存放的都是对象,但是对象不一定都在我这里

2、方法区 Method Area

  • 线程共享
  • 存储已经被加载的类信息,常量,静态变量,即时编译器编译后的代码
  • 方法区物理上是java堆的一部分,只不过逻辑上被划分出来了

3、运行时常量池

  • 方法区的一部分
  • 包括在class文件中(除了常量池class文件中还有类版本,字段,方法,接口等描述信息)
  • 常量池存放编译期生成的字面量和符号引用,这部分内容在类加载后存放到方法区的运行时常量池中
  • 不同类的相同字面量对象的地址是一样的,都在常量池中。

测试如下,在两个类里定义了两个string用字面量方式定义"123",结果最后作对比发现二者内存地址相同。hashcode也相同

常量池中的数据不一定是在编译期被放进去的,运行期间也可以向里面加数据。

4、直接内存

  • 使用本机的内存,不受java堆内存限制

猜你喜欢

转载自blog.csdn.net/a397525088/article/details/81452283
今日推荐