java全局变量_《深入理解Java虚拟机》第二章

首先讲JVM的基本信息

1) 作者站在内存的角度讲了Java以及JVM在内存管理方面的问题,其中重点讲解Java虚拟机在执行Java程序的过程中将内存划分为五个数据区

介绍了五大内存域

1) 程序计数器:负责选取下一条需要执行的字节码指令,方便线程切换后恢复原来状态 ,因为这个原因需要保证各线程之间互补干扰——线程私有内存。另外,正在执行本地方法时,程序计数器为空,是唯一没规定任何OOM(Out of MemoryError)情况的区域

2) Java虚拟机栈:负责存放局部变量表【基本数据类型、句柄(引用变量)/引用指针】、方法调用时形成的栈帧方法1{调用方法2[调用方法3]}...

栈满会出现StackoverflowError,部分虚拟机会动态扩展扩容,申请不到时出现OOM

  • 问:全局变量存在哪?答:全局变量不是存储在栈中的,而是存储在方法区中的,因为它是“某个类的成员”/成员变量。
  • 问: final修饰的变量放哪?答:暂未
  • 问: static final 修饰的变量呢?答:暂未

栈的内存管理也是jvm管理的,只是不是gc而已。栈的管理是因为栈本身数据结构的特性,在函数执行完后,不用的数据自动会出栈的,释放出空间。

4cf901ef8b81afeb66593f7a22a7b119.png

当然在栈中有共享池/常量池概念如下解释说明

a3d2fc51c951686a7cca4b6a97708c18.png
String 
  • -Xss:猜测全称是eXtended ,Stack ,Size。规定了每个线程虚拟机栈及堆栈的大小,一般情况下,256k是足够的,此配置将会影响此进程中并发线程数的大小。
  • java实现的swap交换没效果的很可能原因:是调用swap时,调用swap生成栈帧里拷贝了一份新的变量,跟传入时的变量已经脱轨了

3) 堆:所有线程共享、存放所有对象实例以及数组句柄都在栈中,而数组句柄指向堆中数组的首地址,句柄(引用变量)跟堆对应对象/数组链接后也叫做存放在堆内存中的数组的别名】。

堆内存不够时,会先扩展。若无法扩展,JVM则OOM。

  • 创建一个句柄Person;并不是对象,且存放在Java虚拟机栈中,未连接任何东西要进行初始化,当句柄跟堆内存的对象失去联系时变成了垃圾。

c0c152ae1b226d52c7a48c8b6e7ae759.png

Java堆是垃圾收集器管理的内存区域【GC算法】,Java堆可以在物理存储上是不连续的,逻辑上是连续的。数组大部分被设计成连续内存

  • -Xms:猜测全称是 eXtended Memory Size , 可扩展的内存大小 。一旦对象容量超过了JAVA堆的初始容量,JAVA堆将会自动扩容到-Xmx大小。
  • -Xmx:猜测全称是 eXtended Memory Max size ,最大可分配内存。虽然说堆内存扩容,在很多情况下,通常将-Xms和-Xmx设置成一样的,因为当堆不够用而发生扩容时,会发生内存抖动影响程序运行时的稳定性。
  • 怎么去理解堆共享呢?还记得java内部不同方法运行时可以使用同一个对象进行操作吗?,即就是引用类型,支持在堆里面使用同个数据。如果是栈内部的数据类型传参后修改不是同一个,即没法访问别的栈里面的数据,典型的swap交换实现。【本人参阅资料后总结,以及上面所写的内容】
  • 刚好去面试碰到这样的面试题:String str = new String("abc");创建了几个对象? 并且 abc 字符串之前没有用过。这毫无疑问创建了两个对象,一个是new String 创建的一个新的对象,一个是常量“abc”对象的内容创建出的一个新的String对象,

4) 方法区:采用的是元空间技术【从JVM内存中移到计算机内存中】,且各个线程共享。

主要负责存储加载类信息(接口信息、字段信息、方法信息、类名)、静态成员变量、常量【问号点???!】

若方法区满了,会抛出OOM异常

  • 在1.7以后,HotSpot【我们平时用的JVM】字符串常量池从方法区移到了堆内存中,并且可以被垃圾收集器回收,这个改动降低了字符串常量池OOM风险。而在《深入理解Java虚拟机》中并未说从方法区移至堆中。
  • 常量池还包括整数包装类型-128到127【终于找到这个点的原理 ~ 叹气】
Integer 

5) 本地方法栈:只要调用方法一般用栈,负责本地方法的调用【Java调用C/python】。跟上面的Java虚拟机栈内容相似,栈满都会出现StackOverflowError

下面开始介绍运行常量池、直接内存

首先介绍了运行时常量池【跟HotSpot要区分开来】,他是方法区的一部分

1) 运行时常量池包括Class常量池。用满且无法申请抛出OOM

String 

2) 直接内存也叫堆外内存【物理机内存】,是基于NIO【引入了一种基于通道与缓冲区的IO】,通过使用Native函数直接分配堆外内存,然后通过DirectByteBuffer对象作为**这块内存的引用**进行操作且该对象放堆里面,避免Java堆跟Native堆来回复制数据。【JVM虚拟机也就Java堆能够存储对象数据,想要其他地方能够存储数据则需要在本地扩展】

  • 不受堆的内存大小限制,但受物理机总内存限制

谈谈HotSpot

也就是了解大概普遍虚拟机的模型后,书本在此将针对Hotspot进行展开!!!!爷青回

附录

注意点:不同版本的JVM虚拟机结构不一致,而深入理解Java虚拟机是站在大多数且官方规范来讲解;所以有些知识点在现实跟书本有点差距,特别是HotSpot这个比较活跃、爱出风头、使用量大且改动性大。可能阅读书籍跟博客时会出现很多问号???不慌!!!

  • JAVA 堆栈 堆 方法区 静态区 final static 内存分配 详解(转)
  • Java 内存管理(堆和栈)及 垃圾回收算法
  • JVM参数调优总结 -Xms -Xmx -Xmn -Xss
  • Java 堆内存是线程共享的!面试官:你确定吗?
  • jvm堆和栈的问题?
  • 牛客网Java刷题知识点之全局变量(又称成员变量,分为类变量和实例变量)、局部变量、静态变量(又称为类变量) - 大数据和AI躺过的坑 - 博客园
  • int a = 1,到底存在于JVM的哪里
  • Java中局部变量、实例变量和静态变量在方法区、栈内存、堆内存中的分配_leunging的博客-CSDN博客_java实例变量存放在栈还是堆
  • JAVA堆外内存的简介和使用
  • 堆内内存与堆外内存 - wellDoneGaben - 博客园

补充知识点

1) 用Java命令看编译后的字节码文件各个区域的情况

public 

具体windows 命令行操作如下,可以看到一个大致Class常量池的情况

0ab28a9971c60536bb5de7625928d3d0.png

2) 另外常量池的存储信息

46f56177a37279fc0cc1a271ec164227.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值