j***a语言把内存分为,j***a的内存划分

kodinid 23 0

大家好,今天小编关注到一个比较意思的话题,就是关于java语言内存分为的问题,于是小编就整理了4个相关介绍Java语言把内存分为的解答,让我们一起看看吧。

  1. JAVA的内存是如何划分的?
  2. Java运行时区域,哪些区域是线程私有的?哪些是共有的?
  3. java的堆内存是如何被回收的?
  4. 手机(内存)8G秒变12G? 「内存融合」真的这么厉害吗?

JAVA的内存是如何划分的?

谢邀~

关于JVM的知识,一直令很多J***a程序员头疼,不过JVM也是值得我们深入学习内容,下面我就谈谈自己对JVM内存划分的理解。

java语言把内存分为,java的内存划分-第1张图片-安济编程网
图片来源网络,侵删)

学习J***a的朋友应该都知道,J***a程序是在JVM上运行的,所以我们一般谈的J***a内存划分事实上都是指的JVM内存区域的划分。在讨论JVM内存划分之前,我们需要知道J***a程序的执行过程手动画图,有点儿丑):

通过这个可以看到,JVM在执行J***a程序的时候,要用到一块空间来存储运行期间用到的数据,这块区域就是我们经常用的运行时区域,也就是常说的JVM内存。

程序计数器(Program Counter Register)、J***a栈(VM Stack)、本地方法栈(Native Method Stack)、方法区(Method Area)、堆(Heap)。

java语言把内存分为,java的内存划分-第2张图片-安济编程网
(图片来源网络,侵删)

这个是J***a虚拟机规范规定好的,但是具体怎么实现还是由厂商决定的。

运行的时候,每一个区域存的是什么数据的,先看一张图:

保存指令地址,也就是存的是下一条执行所在的存储地址。如果是多线程的时候,因为一个CPU在一个时刻只能执行一条命令,为了能够让每一个线程在切换之后能够恢复切换之前的位置,每个线程就需要有自己的计数器,所以说:程序计数器是每个线程私有的

java语言把内存分为,java的内存划分-第3张图片-安济编程网
(图片来源网络,侵删)

J***a虚拟机在执行J***a程序的过程中会把它所管理的内存划分为若干不同的数据区域,这些区域都有各自的用途以及创建和销毁的时间。J***a虚拟机所管理的内存将会包括以下几个运行时数据区域,如下图(图片来源网上)所示:


下面我们具体就每个场景进行阐述。

运行时数据区域

  1. 方法区:方法区是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息常量静态变量、即时编译器编译后的代码等数据 。方法区包含运行时常量池,是用于存放编译期生成的各种字面量和符号引用的。垃圾收集行为在这个区域比较少出现,但并非数据进了方法区就永久的存在了,这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载,当方法区无法满足内存分配需要时,将抛出OutOfMemoryError异常
  2. 虚拟机栈:J***a虚拟机栈是线程私有的 ,它的生命周期与线程相同。虚拟机栈描述的是J***a方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链表、方法出口信息等。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程,如果扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常。这块内存是线程私有的。
  3. 本地方法栈:本地方法栈与虚拟机栈的作用相似,不同之处在于虚拟机栈为虚拟机执行的J***a方法服务,而本地方法栈则为虚拟机使用到的Native方法服务。会抛出stackOverflowError和OutOfMemoryError异常。这块内存是线程私有的。
  4. 堆:堆是所有线程共享的一块内存区域,在虚拟机启动时创建,此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例以及其属性都在这里分配内存。堆是垃圾收集器管理的主要区域。由于现在收集器基本***用分代回收算法,所以堆还可细分为:新生代和老年代。如果堆中没有内存完成实例分配,并且堆也无法完成扩展时,将会抛出OutOfMemoryError异常。
  5. 程序计数器:可以看做是当前线程所执行的字节码的行号指示器。这块内存是线程私有的。
  6. 直接内存:直接内存不是虚拟机运行时数据区的一部分,在NIO类中引入一种基于通道与缓冲区的IO方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在J***a堆中的DirectByteBuffer对象作为这块内存的引用进行操作

了运行时数据区域相关构成后,下面我们来看看对象的创建过程,如图


我们着重看最右边一部分,不同的变量会分配到不同的内存区域里,比如new出来的东西会存放到堆中,而局部变量则是存放在栈中。

总之,了解并掌握这些知识是一个合格的J***a程序员必需的技能,也只有这样才能写出更好的程序,更好地优化程序的性能

J***a运行时区域,哪些区域是线程私有的?哪些是共有的?

1.程序计数器(线程私有)

程序计数器是一块较小的内存空间,可以看作是当前线程所执行字节码的行号指示器。

分支、[_a***_]、跳转、异常处理、线程处理等基础功能都需要依赖这个计数器完成。

由于J***a虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式实现的。为了线程切换后能恢复到正确的执行位置,

每条线程都需要一个独立的程序计数器,各线程之间的计数器互不影响,独立存储。

1.如果线程正在执行的是J***a方法,计数器记录的正在执行的虚拟字节码指令的地址;

2.如果正在执行的是Native方法,这个计数器的值为空。

程序计数器是唯一一个没有规定任何OutOfMemoryError的区域。

2.J***a虚拟机栈(线程私有)

概述

对于 J***a 程序员来说,在虚拟机自动内存管理机制下,不再需要像 C/C++程序开发程序员这样为每一个 new 操作去写对应的 delete/free 操作,不容易出现内存泄漏和内存溢出问题。正是因为 J***a 程序员把内存控制权利交给 J***a 虚拟机,一旦出现内存泄漏和溢出方面的问题,如果不了解虚拟机是怎样使用内存的,那么排查错误将会是一个非常艰巨的任务

运行时数据区域

J***a 虚拟机在执行 J***a 程序的过程中会把它管理的内存划分成若干个不同的数据区域。


线程私有的:

  • 程序计数器

  • 虚拟机栈
  • 本地方法栈

线程共享的:


  • 方法区
  • 直接内存 (非运行时数据区的一部分)

j***a的堆内存是如何被回收的?

J***a的堆内存是由J***a虚拟机(JVM)管理的内存区域,用于存储对象实例。堆内存的回收是由J***a垃圾回收器(GC)来完成的。GC会定期扫描堆内存中的对象,如果发现某个对象已经不再被程序使用,就会将其回收,以释放内存空间。

以常见的CMS收集器进行说明,首先会对堆划分为年轻代和年老代

对象优先分配在年轻代的Edge区,(如果对象过大,可以直接在old区分配,通过jvm参数可以设置这个阈值)

当Edge区塞不下,就需要回收空间腾地方(即触发一次minorGC),(注意此时To Survivor是空的,From Survivor有存活对象)***用的原则是:

- 将Edge区和From Survivor区存活的对象塞到To Survivor区

- 完事之后,表示清空From Survivor和Edge中需要回收的对象,此时From Survivor就变成了新的 To Survivor区

看到这里一个问题就来了,如果To Survivor也塞不下这些数据怎么办?

手机(内存)8G秒变12G? 「内存融合」真的这么厉害吗?

没啥用处,很久以前电脑上就有虚拟内存技术,后来就没有下文了,硬件不行系统优化的不好有啥用只是参数好看,是厂家搞出来的噱头,这一点苹果就从来不堆砌参数,那些宣称内存融合的都是忽悠人的。

内存融合的宣传噱头大于实际体验。

就像挂虚拟内存,如果你缓存没有硬性需求就不要开,开了只会加大你的存储设备使用频率,降低使用寿命。而且虚拟内存速度跟不上你缓存的速度,在遇到高速读写需求的时候,反而会拖慢相应速度。这就是为什么开了内存融合,手机运行某些大型游戏时偶尔出现卡顿的原因。

一般来说,你不打游戏,后台多,内存融合可以开。打游戏的而且8G内存起步的朋友就别开了,开这玩意打游戏,你迟早感受到它给你带来的负影响。

到此,以上就是小编对于j***a语言把内存分为的问题就介绍到这了,希望介绍关于j***a语言把内存分为的4点解答对大家有用。

标签: 内存 线程 j***a

上一个音乐插件编程教程下载,音乐插件编程教程下载安装

下一个python简易计算器学习,python 简易计算器