JAVA内存模型->JVM基础了解

JVM结构

主要有三部分构成:
一,classload(类加载器)
二,运行时数据区
三,引擎

classload(类加载器)

Java是运行在Java的虚拟机(JVM)中的,但是它是怎么就运行在JVM中了呢?我们在IDE中编写的Java源代码被编译器编译成.class的字节码文件。然后由我们得ClassLoader负责将这些class类加载到JVM中去执行。

JVM中提供了三层的ClassLoader:
Bootstrap classLoader:

主要负责加载核心的类库(java.lang.*等),构造ExtClassLoader和APPClassLoader。

ExtClassLoader:

主要负责加载jre/lib/ext目录下的一些扩展的jar。

AppClassLoader:

主要负责加载应用程序的主函数类

全委派机制:

应用该类的加载器是那个,该类也使用该类加载器

双亲委派机制:

统统向上级类提交AppClassLoader(判断是否已经加载过,加载过的话不再加载)没载过提交到ExtClassLoader,ExtClassLoader(判断是否已经加载过,加载过的话不再加载)提交到顶层Bootstrap classLoader,然后看顶层的Bootstrap classLoader(判断是否已经加载过,加载过的话不再加载)能不能加载类,不能再向下看ExtClassLoader能不那个加载,如果还不能就看AppClassLoader能不能加载,一般是可以加载的,除非你把他删除了,就会报ClassNotFoundException异常
在这里插入图片描述

为什么要用双亲委派机制:

这种设计有个好处是,如果有人想替换系统级别的类:String.java。篡改它的实现,但是在这种机制下这些系统的类已经被Bootstrap classLoader加载过了,所以并不会再去加载,从一定程度上防止了危险代码的植入。

双亲委派机制是可破坏的,可以自己重写它:打破双亲委派机制则不仅要继承ClassLoader类,还要重写loadClass和findClass方法 。不过jdk1.2.版本后一般不推荐这么做

运行时数据区

一般常说的java内存模型代指这里(虽然不是)
在这里插入图片描述

主要分为5个区域:

一和二为公共共享区域,三,四,五为私有区域

一,堆

实例化的对象(new出来的对象),GC(常说的jvm调优就是主要指这里,用来监视full gc的次数)

二,方法区

类信息,常量,静态数据,JITJIT(just in time)即时编译器是sun公司采用了hotspot虚拟机取代其开发的classic vm之后引入的一项技术,目的在于提高java程序的性能,改变人们“java比C/C++慢很多”这一尴尬印象。

三,jvm虚拟栈

每一个类都有私有的栈,里面有栈针,存储局部变量,操作数栈等,相当于jmm的工作区间

四,本地方法栈

每一个类都有私有的由c/c++写的本地方法,每个累都可以单独去调用这些方便放入自己的方法区中

五,pc计数器

存储执行下一条指令的地址(除了此次不会出现内存溢出,其它对方都有可能出现溢出,但是主要的是堆中会出现)

JMM

JAVA在运行时的内存模型-------->JMM

在这里插入图片描述
主内存:内存。共享数据
工作内存:工作空间。私有信息
工作方式:
A.线程修改私有数据,直接在工作空间修改
B.线程修改共享数据,把数据复制到自己的工作空间,在工作空间中修改,修改完成后刷新回主内存中(引用的地址放在工作空间中,也就是虚拟栈,引用的实际对象放在主内存中也就是堆)

JVM内存模型和硬件内存模型的关系

JVM内存模型和硬件内存模型的关系

数据的不一致性

由于JVM内存模型和硬件内存模型的关系(交叉)------------>导致数据的不一致性,和并发问题
解决方案:
A,总线加锁----------------->降低cpu吞吐量
B.缓存的一致协议(MESI)
当cpu在缓存中操作数据时,如果该数据是共享的数据,就会把这个在缓存的数据直接读到寄存器中,同时把缓存中的一个属性LINE置为无效(是一种硬件设置),这样其它的cpu的缓存中也有该数据时就会放弃该数据重新从内存中读取
volatile:在jvm模型上实现MESI协议
synchronized:编译时的moitorenter(进入监控加锁)和monitorexit(退出监控解锁)实现的

并发编程的三个重要特性
一,原子性

原子性即操作不可分割,例:

int i = 10 ;

为原子性

i++:

不为原子性,因为它实际上是由i=i+1完成的,分为两部,中间可以断开不影响结果,所以不是原子性
多个原子合并一起要使还有原子性:
A.synchronized 加锁
B.JUC Lock中的lock 锁

二,可见性

线程只能操作自己工作空间的数据,对其它线程工作空间的数据是看不到的
volatile可以保证可见性同时还可以保证有序性

三,有序性

在编译成过程中不一定是按照程序员写的代码的顺序编译的,它会优化,有编译重排,指令重排,例

int i=1;
Cat cat = new Cat();
int b = 2;

实际上代码编译的时候会重排,会把int b =2;调到new cat对象之前,主要是为了提高效率(单线程重排并不会影响结果,但是多线程的会)

引擎

无了解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值