JAVA内部模型

JMMJava memory model)学习

Java Java Stack

1、理解定义及原理:先拿出两个栈的生活模型,便于帮助记忆

A.弹匣:

    弹匣装弹理解为入栈,弹匣出单理解为出栈,这样就很好理解了,子弹是先入后出,完美的栈原理模型。栈和弹,有谐音,比便于记忆,要不然过几天又忘记了。

B.撤销:ctrl+z 先修改的文档,最后执行撤销动作。

https://gss1.bdstatic.com/9vo3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike80%2C5%2C5%2C80%2C26/sign=b4cf8cd69925bc313f5009ca3fb6e6d4/8b82b9014a90f603eab7c55f3912b31bb051eda7.jpg

2、优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外,栈数据可以共享。堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据(类似丰巢快递柜中快递员自动清理未被领取的快件)。但缺点是,由于要在运行时动态分配内存,存取速度较慢。

3、栈的存取速度虽然快,但是也不如寄存器的存取速度快,因为寄存器位于CPU内部。寄存器的数量有限,数量的分配受编译器控制,按需分配。                         

  • 堆(heap

同样拿出生活应用模型便于理解记忆

  1. 如果是栈是弹匣,那么堆就应当是弹箱。这个比喻的出发点是,手枪发射子弹的时候,弹匣出弹速度比弹箱要快(存取速度比堆要快,仅次于直接位于CPU中的寄存器,这里不考虑弹匣装弹的速度),因为弹箱中的子弹必须装入弹匣才能发射。数据区域的大小,弹匣的容量比弹箱的容量要小,这个与栈的数据区域大小比堆的数据区域小同理。
  2. 丰巢快递柜:堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据(类似丰巢快递柜中快递员自动清理未被领取的快件)。但缺点是,由于要在运行时动态分配内存,存取速度较慢。

Java heap :对大多数应用来说,java堆是jvm管理的内存中最大的一块,是被所有线程共享的一块数据区域,用来存放java对象实例和数组。

GC:Java堆是垃圾收集器管理的主要区域,因此很多时候也被称作“GC堆”(Garbage Collected heap)根据Java虚拟机规范的规定,Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,就像我们的磁盘空间一样。在实现时,既可以实现固定大小的,也可以是扩展的,不过当前主流的虚拟机都是按照可扩展来实现的。如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。

程序计数器

1、程序计数器的理解:
JVM的多线程是通过CPU时间片轮转(即线程轮流切换并分配处理器执行时间)算法来实现的。

也就是说,某个线程在执行过程中可能会因为时间片耗尽而被挂起,而另一个线程获取到时间片开始执行。当被挂起的线程重新获取到时间片的时候,它要想从被挂起的地方继续执行,就必须知道它上次执行到哪个位置,在JVM中,通过程序计数器来记录某个线程的字节码执行位置。因此,程序计数器是具备线程隔离的特性,也就是说,每个线程工作时都有属于自己的独立计数器。
2、程序计数器的特点:
1.线程隔离性,每个线程工作时都有属于自己的独立计数器。
2.执行java方法时,程序计数器是有值的,且记录的是正在执行的字节码指令的地址(参考上一小节的描述)。
3.执行native本地方法时,程序计数器的值为空(Undefined)。因为native方法是java通过JNI直接调用本地C/C++库(动态链接库),可以近似的认为native方法相当于C/C++暴露给java的一个接口,java通过调用这个接口从而调用到C/C++方法。由于该方法是通过C/C++而不是java进行实现。那么自然无法产生相应的字节码,并且C/C++执行时的内存分配是由自己语言决定的,而不是由JVM决定的。
4.程序计数器占用内存很小,在进行JVM内存计算时,可以忽略不计。
5.程序计数器,是唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError的区域。

总之,简单理解,程序计数器跟java多线程密切相关。

方法区
1.什么是方法区?
方法区(Method Area)与Java堆一样,是各个线程共享的内存区域。
2.方法区(Method Area)存储什么?
它存储已被Java虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等。
(1)static final修饰的成员变量都存储于 方法区(Method Area)中。
(2)静态变量之所以又称为类变量,是因为静态变量和类关联在一起,随着类的加载而存在于方法区(而不是堆中)。
(3)八种基本数据类型(byte、short、int、long、float、double、char、boolean)的静态变量会在方法区开辟空间,并将对应的值存储在方法方法区,对于引用类型的静态变量如果未用new关键字为引用类型的静态变量分配对象(如:static Object obj;)那么对象的引用obj会存储在方法区中,并为其指定默认值null;若,对于引用类型的静态变量如果用new关键字为引用类型的静态变量分配对象(如:static Person person = new Person();),那么对象的引用person 会存储在方法区中,并且该对象在堆中的地址也会存储在方法区中(注意此时静态变量只存储了对象的堆地址,而对象本身仍在堆内存中)。(4)运行时常量池:一个存储了类文件格式中的常量池表的内存空间。这部分空间虽然存在于方法区内,但却在JVM操作中扮演着举足轻重的角色,因此JVM规范单独把这一部分拿出来描述。除了每个类或接口中定义的常量,它还包含了所有对方法和字段的引用。因此当需要一个方法或字段时,JVM通过运行时常量池中的信息从内存空间中来查找其相应的实际地址。(引自https://www.cnblogs.com/enjiex/p/5079338.html
1、 java7之前,方法区位于永久代(PermGen),永久代和堆相互隔离,永久代的大小在启动JVM时可以设置一个固定值,不可变;
2、 java7中,字符串常量池从永久代移到堆中;
3、 java8中,取消永久代,方法区存放于元空间(Metaspace),元空间仍然与堆不相连。
参考网友:https://me.csdn.net/qq_22771739

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值