Jvm内存区域

1、Jvm内存区域

1.1:线程共享区

1.1.1:方法区():

1.1.1.1:存储虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据

类的版本

字段

方法

接口

1.1.1.2:方法区和永代区

1.1.1.3:垃圾回收在方法区的行为

1.1.1.4:异常的定义

 

1.1.2:java堆:存放对象实例,里面存放着新生代、旧生代、Eden空间,同时也是垃圾收集器的主要区域。当堆内存溢出会报:OutOfMemory异常,可通过-Xmx-Xms指定堆内存的大小

1.2:线程独占区

1.2.1:虚拟机栈

1.2.1.1:栈帧:每个方法执行,都会创建一个栈帧, 伴随着方法从创建到执行完成。用于存储局部变量,操作数栈,动态链接,方法出口 等。

1.2.1.2:局部变量表:存放编译期间可知的各种基本数据类型,引用类型,局部变量表的内存空间在编译期完成,当进入一个方法时,这 个方法需要在帧分配多少内存是固定的,在方法运行期间是不会改变局部变量的大小

例如:一个User对象:里面有name属性  对User来说,只是一个对象的引用

重点:每一个放法的调用产生一个栈帧,栈帧都会进入栈内存,方法没结束栈帧会一直存在,然后又有放法调用,又进栈,以此类推,当栈内存不足时,就会报栈内存溢出异常java,lang.StackOverflowError(前提是放法一直没执行完,又有一个方法进来《递归测试》)

1.2.2:本地方法栈:本地方法栈为虚拟机执行native方法服务,虚拟机栈为虚拟机执行java方法程序《本地方法栈和虚拟机栈无多大差异》

1.2.3:程序计数器:记忆程序执行的字节码,例如:ecplice里面记忆了跑到了第几行代码

 

 

重点:

 

第一个这个打印结果会是true

第二个这个打印结果会是false

第三个这个打印结果会是true

 

理由:String为一个抽象数据类型,s1放在栈内存中,及abc为实例存放在堆内存中,s2同理,理应s1s2都是的实例地址应该是不同的地址,但是堆内存中有一个常量池,而常量的  数据类型为hashSetset集合是无序的且不可重复的,当s1存进去之后,s2又存,常量池就不会增加一条abc的数据,s1s2就会指定同一个地址,所以结果为true

  s3是通过new的创建对象的,就不会再考虑常量池了,就会在堆内存开辟一块空间来存储s3的实例,所以s1s3所指向的地址就会不一样,就会返回false

     因为s3使用了intern方法之后,他就会把存储s3那块堆内存区域搬到常量池里面去,导致地址相同,所以结果为true

   s1s2可称之为字节码常量,s3用了intern方法之后称之为运行时常量

 

 

 

 

 

 

 

对象的创建

 

当给分配的内存初始化时,会执行以下顺序

 

 

1.内存分配方式

指针碰撞:内存规则的排序,靠移动指针来分配内存

空闲列表:内存空间无规则混乱,有一张表专门存储空闲的内存区域的地址,当有新的对象要内存时,旧会从空闲表里面拿到该内存的地址,随之该表就减少一条数据

 

内存区域是否规整时由垃圾回收策略决定的

 

2.线程安全性问题

new对象的时候,要给对象在堆内存中分配内存,当使用空闲列表的方式分配时,当一个线程到空闲列表那数据时,数据还没来得及更新,另外一个线程又来那数据,这样就会造成冲突, 形成了线程安全的问题,以下有两种解决方案:

线程同步:当线程A来空闲列表那数据时,给数据表加锁,代数据更新之后再解锁,但这样会造成效率低下的问题。

本地线程分配缓冲:给每一个线程指定一块区域,每次取数据时都去指定的区域拿,这样就不会出现线程不安全的问题,当分配给该线程的区域满了之后,再使用线程同步的方案给该线程分   配一块新的区域,这样就完美解决了

3.初始化对象

就会给对象赋值,基本类型则赋给该基本类型的初始化值,抽象类型都为null

 

4.执行构造方法

然后调用init方法,init方法可以看成一个构造方法

转载请说明出处

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值