java堆栈理解

在这里插入图片描述

在这里插入图片描述

程序计数器(Program Counter Register):当前线程所执行的字节码的行号指示器,字节码解析器的工作是通过改变这个计数器的值,来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能,都需要依赖这个计数器来完成;
Java 虚拟机栈(Java Virtual Machine Stacks):用于存储局部变量表、操作数栈、动态链接、方法出口等信息;
本地方法栈(Native Method Stack):与虚拟机栈的作用是一样的,只不过虚拟机栈是服务 Java 方法的,而本地方法栈是为虚拟机调用 Native 方法服务的;
Java 堆(Java Heap):Java 虚拟机中内存最大的一块,是被所有线程共享的,几乎所有的对象实例都在这里分配内存;
方法区(Methed Area):用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。

物理地址

堆的物理地址分配对对象是不连续的。因此性能慢些。在GC的时候也要考虑到不连续的分配,所以有各种算法。比如,标记-消除,复制,标记-压缩,分代(即新生代使用复制算法,老年代使用标记——压缩)

栈使用的是数据结构中的栈,先进后出的原则,物理地址分配是连续的。所以性能快。

内存分别

堆因为是不连续的,所以分配的内存是在运行期确认的,因此大小不固定。一般堆大小远远大于栈。

栈是连续的,所以分配的内存大小要在编译期就确认,大小是固定的。

存放的内容

堆存放的是对象的实例和数组。因此该区更关注的是数据的存储

栈存放:局部变量,操作数栈,返回结果。该区更关注的是程序方法的执行。

PS:

静态变量放在方法区
静态的对象还是放在堆。

程序的可见度

堆对于整个应用程序都是共享、可见的。

栈只对于线程是可见的。所以也是线程私有。他的生命周期和线程相同。

栈内存:栈内存首先是一片内存区域,存储的都是局部变量,凡是定义在方法中的都是局部变量(方法外的是全局变量),for循环内部定义的也是局部变量,是先加载函数才能进行局部变量的定义,所以方法先进栈,然后再定义变量,变量有自己的作用域,一旦离开作用域,变量就会被释放。栈内存的更新速度很快,因为局部变量的生命周期都很短。

堆内存:存储的是数组和对象(其实数组就是对象),凡是new建立的都是在堆中,堆中存放的都是实体(对象),实体用于封装数据,而且是封装多个(实体的多个属性),如果一个数据消失,这个实体也没有消失,还可以用,所以堆是不会随时释放的,但是栈不一样,栈里存放的都是单个变量,变量被释放了,那就没有了。堆里的实体虽然不会被释放,但是会被当成垃圾,Java有垃圾回收机制不定时的收取。
1.栈内存存储的是局部变量而堆内存存储的是实体;

2.栈内存的更新速度要快于堆内存,因为局部变量的生命周期很短;

3.栈内存存放的变量生命周期一旦结束就会被释放,而堆内存存放的实体会被垃圾回收机制不定时的回收。
扩展理解

链式存储结构(LinkedList)链表指的是用一组任意的存储单元存储线性表中的数据元素,并通过指针域确保数据的逻辑关系
链表中结点的表示必须要用到两个域,其中一个存放数组元素自身的信息,称其为数据域,另一个存放下一个元素的地址或位置,以保证链表的连续性,称其为指针域。
整个可简单如一下理解
堆可理解为数据域;存储变量的具体值(实体)
栈可理解为指针域;存储变量及数据的逻辑关系

数据库表
无群集索引 的表 称为 数据堆 (任意的存储单元 数据不连续)
添加群集索引 后 数据有序存储

实际情况:java堆 分为句柄池(指针) 实例池 (具体值)

整个数据逻辑关系是 :
栈(局部变量 指针的指针)-------> java堆句柄池(实例指针)--------->实例池(具体指)~
java堆句柄池(实例类型指针)------->方法区

查看 jvm 默认值
java -XX:+PrintFlagsFinal

winsows 默认 -client
centos 默认 -server
不显式设置-Xss或-XX:ThreadStackSize时,在baiLinux x64上ThreadStackSize的默认值就是1024KB,给Java线程创建栈会du用这个参数指定的大小。这是zhi前一块代码dao的意思。
如果把-Xss或者-XX:ThreadStackSize设为0,就是使用“系统默认值”。而在Linux x64上HotSpot VM给Java栈定义的“系统默认”大小也是1MB。

VM给Java栈定义的“系统默认”大小也是1MB;

分代回收器有两个分区:老生代和新生代,NewRatio 默认值是2 新生代默认的空间占比总空间的 1/3,老生代的默认占比是 2/3。

新生代使用的是复制算法,新生代里有 3 个分区:Eden、To Survivor、From Survivor,它们的默认占比是 8:1:1,它的执行流程如下:
官方地址
https://docs.oracle.com/javase/9/gctuning/parallel-collector1.htm#JSGCT-GUID-74BE3BC9-C7ED-4AF8-A202-793255C864C4
/**

  • -Xms 堆内存初始大小,默认内存大小:系统64/1

  • -Xmx 堆内存最大值,默认内存大小:系统4/1

  • -Xmn 堆内存年轻代大小

*/

public static void main(String[] args) {

        long initialHeapSize = Runtime.getRuntime().totalMemory();

        long maxHeapSize = Runtime.getRuntime().maxMemory();

        System.out.println("-Xms = " + initialHeapSize / 1024 + "kb or " + initialHeapSize / 1024 / 1024 + "mb");

        System.out.println("-Xmx = " + maxHeapSize / 1024 + "kb or " + maxHeapSize / 1024 / 1024 + "mb");

 

    }

永久代初始分配空间。默认值是20.75M
通过-XX:PermSize来设置永久代初始分配空间。默认值是20.75M。
-XX:MaxPermSize来设定永久代最大可分配空间。32位机器默认是64M,64位机器默认是84M;
当JVM加载类信息超过这个值,会报异常OutOfMemoryError:PermGen space;

https://blog.csdn.net/xinlingmen/article/details/107482288

import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.log4j.Logger;
public class HelloWorld {
private static Logger LOGGER = Logger.getLogger(HelloWorld.class.getName());
public void sayHello(String message) {
SimpleDateFormat formatter = new SimpleDateFormat("dd.MM.YYYY");
String today = formatter.format(new Date());
LOGGER.info(today + ": " + message);
}
}

在这里插入图片描述

说明:堆区存放的是对象信息,方法区存放的是类信息、常量、静态变量、即时编译后的代码等数据;栈区存放的是线程、参数、变量、行号

java -XX:+PrintCommandLineFlags -version

-XX:+UseParallelGC 新生代使用ParallerGC(复制算法),老年代使用Serial Old(标记压缩(整理)算法)

方法区:永久代 元空间

一句话:方法区JVM规范之一,永久代和元空间(1.8或java8以后)都是对其不同的实现

方法区:是一个JVM规范

方法区是所有线程共享。主要用于存储与类相关的一切信息,如Class、Static与final修饰的变量等。

https://zhuanlan.zhihu.com/p/342337458

对于习惯在HotSpot虚拟机上开发和部署程序的开发者来说,很多人愿意把方法区称为“永久代”(Permanent Generation),本质上两者并不等价,仅仅是因为HotSpot虚拟机的设计团队选择把GC分代收集扩展至方法区,或者说使用永久代来实现方法区而已。
(译者注:Java8中已经移除了永久代,新加了一个叫做元数据区的native内存区)

JVM配置启用几种垃圾收集器的参数说明
https://blog.csdn.net/x763795151/article/details/90348425

如何查看JVM默认使用的垃圾回收器
java -XX:+PrintCommandLineFlags -version

-XX:InitialHeapSize=259247296 -XX:MaxHeapSize=4147956736 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC 
openjdk version "1.8.0_111"
OpenJDK Runtime Environment (build 1.8.0_111-8u111-b14-2~bpo8+1-b14)
OpenJDK 64-Bit Server VM (build 25.111-b14, mixed mode)
-XX:ConcGCThreads=2 -XX:G1ConcRefinementThreads=8 -XX:GCDrainStackTargetSize=64 -XX:InitialHeapSize=253355264 -XX:MarkStackSize=4194304 -XX:MaxHeapSize=4053684224 -XX:MinHeapSize=6815736 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC 
openjdk version "17.0.1" 2021-10-19
OpenJDK Runtime Environment (build 17.0.1+12-39)
OpenJDK 64-Bit Server VM (build 17.0.1+12-39, mixed mode, sharing)
-XX:InitialHeapSize=32768000 -XX:MaxHeapSize=524288000 -XX:MinHeapSize=6815736 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseSerialGC 
openjdk version "17.0.2" 2022-01-18
OpenJDK Runtime Environment (build 17.0.2+8-86)
OpenJDK 64-Bit Server VM (build 17.0.2+8-86, mixed mode, sharing)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值