Java内存结构

Java内存结构:堆、栈、方法区、程序计数器、本地方法栈

java内存的基本结构图:
这里写图片描述

《深入理解Java虚拟机(第二版)》中的结构图:
这里写图片描述

Java中内存分配:

Java程序在运行时,需要在内存中的分配空间。为了提高运算效率,就对数据进行了不同空间的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
重点关注前三个:
1.栈:存放局部变量(线程创建的时候 被创建)
2.堆:存放所有创建(new)出来的对象(堆空间是所有线程共享,虚拟机启动的时候建立)
3.方法区:被虚拟机加载的类信息、常量、静态常量等。是共享的
4.程序计数器(和系统相关)
5.本地方法栈

1. 栈
虚拟机栈,也是线程私有的,它也是随着线程的创建而创建,同生共死。既然是一个栈,自然就拥有栈的数据结构,它由一个个栈帧组成。每一帧里面保存的是每个线程中执行方法的相关信息,包括一个方法的局部变量,常量池指针,方法出口等信息。就像栈的基本操作一样,每次线程调用一个方法的时候,就会形成一个栈帧,并压入栈中,当方法执行完成,则执行出栈操作。方法调用的过程正好和栈的先入后出过程相似。

在Java虚拟机规范中,对这个区域规定了两种异常情况:
(1)如果线程请求的栈深度太深,超出了虚拟机所允许的深度,就会出现StackOverFlowError(比如无限递归。因为每一层栈帧都占用一定空间,而 Xss 规定了栈的最大空间,超出这个值就会报错)
(2)虚拟机栈可以动态扩展,如果扩展到无法申请足够的内存空间,会出现OOM

2. 堆
垃圾回收的主要区域
堆是JVM中最大的一块内存区域,而且被所有的线程所共享,几乎所有的对象实例都放在这里(简单点说,就是我们new出来的对象啦)这里有很多面试经常考察的知识点,比如:垃圾回收算法(堆是JVM进行垃圾回收的主要区域),什么情况下会报出OutOfMemoryError异常,堆的划分区域,以及每个区域是如何进行垃圾回收的(可以分为新生代和老年代,新生代又可以分为Eden空间、From Survivor空间、To Survivor空间等)
不同种类的垃圾回收器异同点

3. 方法区

方法区,也被称作永久代,和堆一样,是所有线程内存共享的区域
主要用来保存被虚拟机加载的类信息,静态变量,常量等。
这里还专门开辟了一块称之为运行时常量池的区域,不仅用来存放普通常量池中有关编译期间生成的各种字面量和符号引用,还可以在程序执行期间动态加入新的常量(比如通过String.intern()方法)

每一块堆内存空间彼此独立,但是会同时使用同一块方法区。说明了方法区的共享性

4.程序计数器
程序计数器,也就是我们常说的PC寄存器。
每个线程刚创建时,会创建一个程序计数器,它的生命周期跟随线程而变,同生共死。
主要作用:当前线程所执行程序的字节码的行号指示器,通过它可以获取下一条需要执行的字节码指令。

程序计数器(Program Counter Register)是JVM中一块较小的内存区域,保存着当前线程执行的虚拟机字节码指令的内存地址。Java多线程的实现,其实是通过线程间的轮流切换并分配处理器执行时间的方式来实现的,在任何时刻,处理器都只会执行一个线程中的指令。在多线程场景下,为了保证线程切换回来后,还能恢复到原先状态,找到原先执行的指令,所以每个线程都会设立一个程序计数器,并且各个线程之间不会互相影响,程序计数器为”线程私有”的内存区域。
  如果当前线程正在执行Java方法,则程序计数器保存的是虚拟机字节码的内存地址,如果正在执行的是Native方法(非Java方法,JVM底层有许多非Java编写的函数实现),计数器则为空。程序计数器是唯一一个在Java规范中没有规定任何OutOfMemory场景的区域。

5.本地方法栈
本地方法栈(Native Method Stack)和虚拟机栈的作用相似,不过虚拟机栈是为Java方法服务的,而本地方法栈是为Native方法服务的。

垃圾收集器:是JAVA的核心。
没有任何栈内存指向的堆内存空间,会被GC进行回收。

总结内存结构:
1. 栈,堆,方法区(方法区 共享)
2. 注意引用类型的赋值问题 。 引用类型的赋值也叫引用传递,指一块堆内存空间被多个栈内存空间所指向。
3. 注意:每一块堆内存空间彼此独立,但是会同时使用同一块方法内存区
4. 垃圾空间:没有任何栈内存指向的堆内存空间,会被GC进行回收。

看了几个技术博客总结出来的,都很简略

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java内存结构主要可以分为以下几个部分: 1. (Heap):用于存储对象实例,是Java程序中最大的一块内存空间,可通过“new”关键字创建对象时,将对象存储在上。 2. (Stack):用于存储局部变量和方法调用,每个线程都会创建一个中的数据是线程私有的,只有当前线程可以访问。 3. 方法区(Method Area):用于存储类信息、常量、静态变量和即时编译器编译后的代码等数据,是各个线程共享的内存区域。 4. 本地方法(Native Method Stack):用于存储Java调用本地方法时的参数和返回值,以及本地方法的调用和返回状态。 Java程序中最基本的内存结构是用来存储对象实例的,它是Java程序中最大的一块内存空间。内存是由JVM管理的,可以通过“new”关键字创建对象时,将对象存储在上。内存的大小可以通过JVM参数进行配置,如果内存不足,会抛出OutOfMemoryError异常。 是用来存储局部变量和方法调用的,每个线程都会创建一个中的数据是线程私有的,只有当前线程可以访问。内存是由操作系统管理的,它的大小是有限制的,如果内存不足,会抛出StackOverflowError异常。 在方法调用时,JVM会为每个方法调用创建一个帧,帧包含了局部变量表、操作数、动态链接、方法返回地址等信息。当方法调用结束时,这个帧会被弹出。 总之,Java程序中最基本的内存结构用于存储对象实例,用于存储局部变量和方法调用。它们的使用方式和内存管理方式都有所不同,程序员需要根据具体情况来选择合适的数据结构内存管理策略。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值