本文源自Recently祝祝,创自Recently祝祝。转载请标注出处。
此解决方式在企业中有所应用,合适Java初级开发学习,参阅。
本文字数与行数,耐心阅读必有收获。
1.运转时办法区说明
JVM中运转时办法区是Java运转环境中的内存区域,运转时办法区包括了堆、虚拟机栈、本地办法栈、办法区(永久代、元空间)、运转时常量池(字符串常量池)、直接内存。
其中这部分内存能够再次划分为线程同享的内存区域、线程独享的内存区域。其中线程同享内存不会随着线程的毁掉而开释。
- 线程同享:堆,办法区
- 线程独享:虚拟机栈、本地办法栈、程序计数器。
还能够划分红虚拟机内部内存和虚拟机外部内存。
- 虚拟机内部内存:虚拟机直接办理的内存
- 虚拟机外部内存:操作系统办理的内存
2.堆、虚拟机栈、本地办法栈、办法区(永久代、元空间)、运转时常量池(字符串常量池)、直接内存
2.1堆
-
JVM中内存最大的区域,寄存目标、目标的引证、数组等数据。
-
堆的结构主要为年青代(Young)、老时代(Old)、元空间(Meta Spase)
-
年青代(Young)又划分红Eden区域、Survivor1区和Survivor0区(简称S0、S1)。
-
年青代保存的是新建的目标,新目标在Eden区域被创立,年青的目标(存活分时刻短的目标),老时代保存的是经历过屡次废物收回任然存活的目标,元空间存储的是元数据:类、办法、字段等数据信息。
-
两个Survivor区域能够削减废物收回的频率和时刻,对存活时刻短的放在年青代,标记的是存活的目标而不是被废物收回的目标,能够削减废物收回的频次,由于存活的目标一般占少数。两部分替换运用,进行废物收回之后,两区域留下的存活目标年龄上加1,相互之间复制,削减了废物收回的时刻,存在Survivor区域的目标比较也比在Eden区域的少,所以需求扫描的目标也削减了,时刻就变快了。
-
堆也是需求进行废物收回的主要区域。
-
堆内存能够经过–xms设置堆初识巨细,–xmx设置堆最大巨细。元空间的巨细取决于硬件,元空间存储在本地,跟虚拟机无关
-
堆内存是线程同享的区域,目标的改变其他线程也能看见
2.2 虚拟机栈
-
虚拟机栈:在虚拟机中给java办法供给服务的区域。履行java办法的一块内存区域
-
办法运转的时分运转的时分运转的是栈帧而不是办法自身,栈帧的存活时刻也便是办法的入栈出栈的一个周期,一个办法的调用完整的进程也是出栈入账的周期时刻内。所以当运转一个开端运转一个办法的时分,栈帧就创立了;办法回来的时分,栈帧就被丢弃了。履行那个办法当时的栈帧便是那个办法的栈帧,当时类也便是当时运转的类。
-
栈的内存结构:先入后出。栈帧运用支持虚拟机进行办法履行的数据结构。栈帧是虚拟机栈的一个根本单元。
-
栈帧存储了局部变量、回来地址、操作栈等信息。
-
栈是存在深度的,如果超越栈的最大深度就会抛出反常,栈溢出。线程过大的时分,内存不行也会抛出反常,内存溢出。
-
虚拟机栈也是线程独享的区域。
2.3本地办法栈
-
履行本地办法的一块内存区域。
-
本地办法栈:在虚拟机中给应用到native办法(也便是java语言以外的语言编写的办法)时供给服务的区域。并不是所有时分都是运用java类编写的办法的,有时分还需求运用原生的办法,也便是native办法。本地便利是跟操作系统跟硬件有关。本地方栈就为本地服务
-
本地办法栈存储了调用本地方的时分所需求的参数、回来值、本地方状况。本地方栈也是一块内存区域,只为本地服务。
-
也能够运用参数来设置-Xss本地方栈的巨细,若超越栈内存巨细,也会抛出栈溢出的反常
-
本地办法栈是线程独享的区域
2.4办法区(永久代、元空间)
- 存储java类编译后的代码的地方,此时的代码已经变成了机器码(本地代码)。也是存储运转时常量池的地方。
- 办法区在1.8jdk之后永久代就修正成了元空间,元空间的运用让办法区更灵活,功能稳定性更强。
- 永久代跟元空间的存储位置不一致,永久代存储在堆中,巨细也受JVM巨细所约束;元数据存储在物理内存区域,也便是本地内存,巨细受硬件、物理内存巨细的约束。
- 元空间跟永久代存储数据不一致,元空间存储的元数据例如类、办法等相关信息。
- 字符串存在永久代中,字符串的数据不断增多,永久代的内存巨细就有或许被占满,永久代的巨细较难指定,而且永久代中的收回效率低,永久代的废物收回跟堆废物收回不同,就会有内存溢出的或许。元数据采用的是本地内存,动态的调节内存巨细,能够削减了废物收回的次数,提高GC效率。
2.5运转时常量池(字符串常量池)
-
字符串常量池保存的所有带有引号的字符串常量。字符串常量池寄存的也是目标地址,而不是具体数据。
-
- 保存在堆中,避免了字符串的重复,加快存取效率,便利调试和剖析。
- 全局都只有一个字符串常量池。
- 字符串本质上便是一个字符数组。编译器的字符串都将存储在字符串常量池中。
- 存储不变的内存空间。
- 字符串常量池的存取是根据哈希表完成的,是StringTable数据结构存储的。加快了查询速度,结构由数组+链表的形式完成,当出现哈希冲突的时分,值的形式就会变成链表。变成链表之后查询速度会变慢,可是增删的速度会增快。
- 字符串常量池中查找数据,回来的是引证,而不是值自身。如果查找的目标不存在,则会创立一个,经过调用intern()办法进行创立目标,而且添加到字符串常量池中,而且回来引证(目标地址)。所以在比较的时分,比较的也是引证的比较,而不是值自身的比较。回来引证也确保了字符串的不行变性。
2.6直接内存
-
直接内存作用在虚拟机之外的一部分内存区域,非堆内存。直接内存在屡次读写操作的情况下,比堆内存要快,究竟不需求再次做转化,虽然转化时刻很快从非直接内存转化本地io的进程,可是频繁的读取的话时刻就会显得尤为明显了。可是直接内存请求空间需求耗费更高的功能,频繁请求的时分也会显示很明显。
-
高频次io更适用于直接内存,不用经过复杂的GC进程。而且生命周期也比堆内存要长。
-
内存地址遭到本级内存地址的约束。
文章全为个人理解,如果发现部分跟你所知道的有出入,欢迎在评论区指出,欢迎探讨。