Java Jvm GC简单理解

关于Java JVM 的一些简单理解

JVM主要是对java程序提供一个运行环境,包括类的加载、内存分配、垃圾回收,JVM将内存划分为堆,虚拟机栈,线程计数器,本地方法栈,方法区五个内存区域。执行顺序为先加载.class字节码文件,然后管理并分配内存,执行垃圾回收。
1、java8虚拟机和之前的变化更新:
撤销了永久带,引入了元空间。jkd1.6时,将方法区设计为永久带,使得GC的工作区域可以拓展到方法区,但回收条件苛刻、效果不好。1.8之后引入了元空间,元空间中类与其相关的元数据与类加载器生命周期一致,每个类加载器有专门的存储空间,不会单独回收某个类。
2、java类加载机制
沙箱安全机制
Java安全模型的核心就是Java沙箱.
字节码校验器
类装载器:双亲委派机制模式
双亲委派机制:类加载器收到类加载的请求–>将这个请求向上委托给父类加载器去完成,一直向上委托,直到启动类加载器–>启动加载器检查是否能够加载当前类,能加载就结束,使用当前类加载器,否则抛出异常,通知子加载器进行加载–>重复步骤3
级别:BootstrapClassLoader(启动类加载器),C++编写–>ExtClassLoader (标准扩展类加载器)–>AppClassLoader(系统类加载器)–>CustomClassLoader(用户自定义类加载器)
启动类加载器:加载JDK\jre\lib下被虚拟机识别的类,无法被java程序直接引用;
扩展类加载器:加载JDK\jre\lib\ext的类,可直接使用;
应用程序类加载器:加载用户类路径所指定的类,如果没定义类加载器,这个是默认的;
自定义类加载器:自定义。
3、缓存机制
所有加载过得class文件都会被缓存,当程序中使用某个class时,类加载器先从缓存区寻找该class,只有缓存区不存在,系统才会读取该类对应的二进制数据,并将其转为class文件存在缓存区。这就是为什么修改了class后,重启JVM才会生效。
4、内存结构:堆内存,方法区,栈(虚拟机栈,本地方法栈,程序计数器)
堆内存(heap):所有通过new创建的对象都在堆,大小可以通过-Xmx和-Xms来控制,一个jvm只有一个堆内存。类加载器读取了类文件后,将类、方法、常量、变量,所有引用类型的真实对象放在堆中。
方法区:存储类信息,常量,静态变量等数据,是线程共享的区域。静态变量、常量、类信息(构造方法,接口定义)、运行时的常量池放在方法区中,但是实例变量存在堆内存中,和方法区无关。(static、final、Class、常量池)
栈:主要用于方法的执行。8大基本类型+对象的引用+实例的方法。栈主管程序的运行,生命周期和线程同步。线程结束,栈内存也就释放,不存在垃圾回收问题。栈的运行原理:栈帧,每个方法都有一个栈帧,正在运行的方法一定在栈的顶部。
堆和方法区出现异常,抛出OutOfMemoryError错误;栈出现异常,抛出StackOverflowError错误
5、垃圾回收GC
年轻代:
  在新生代中,使用“停止-复制”算法进行清理,将新生代内存分为2部分,1部分 Eden区较大,1部分Survivor比较小,并被划分为两个等量的部分。每次进行清理时,将Eden区和一个Survivor中仍然存活的对象拷贝到 另一个Survivor中,然后清理掉Eden和刚才的Survivor。
  这里也可以发现,停止复制算法中,用来复制的两部分并不总是相等的(传统的停止复制算法两部分内存相等,但新生代中使用1个大的Eden区和2个小的Survivor区来避免这个问题)

由于绝大部分的对象都是短命的,甚至存活不到Survivor中,所以,Eden区与Survivor的比例较大,HotSpot默认是 8:1,即分别占新生代的80%,10%,10%。如果一次回收中,Survivor+Eden中存活下来的内存超过了10%,则需要将一部分对象分配到 老年代。用-XX:SurvivorRatio参数来配置Eden区域Survivor区的容量比值,默认是8,代表Eden:Survivor1:Survivor2=8:1:1.

老年代:
老年代存储的对象比年轻代多得多,而且不乏大对象,对老年代进行内存清理时,如果使用停止-复制算法,则相当低效。一般,老年代用的算法是标记-整理算法,即:标记出仍然存活的对象(存在引用的),将所有存活的对象向一端移动,以保证内存的连续。
在发生Minor GC时,虚拟机会检查每次晋升进入老年代的大小是否大于老年代的剩余空间大小,如果大于,则直接触发一次Full GC,否则,就查看是否设 置了-XX:+HandlePromotionFailure(允许担保失败),如果允许,则只会进行MinorGC,此时可以容忍内存分配失败;如果不 允许,则仍然进行Full GC(这代表着如果设置-XX:+Handle PromotionFailure,则触发MinorGC就会同时触发Full GC,哪怕老年代还有很多内存,所以,最好不要这样做)。

方法区(永久代):
  永久代的回收有两种:常量池中的常量,无用的类信息,常量的回收很简单,没有引用了就可以被回收。对于无用的类进行回收,必须保证3点:
类的所有实例都已经被回收
加载类的ClassLoader已经被回收
类对象的Class对象没有被引用(即没有通过反射引用该类的地方)
永久代的回收并不是必须的,可以通过参数来设置是否对类进行回收。HotSpot提供-Xnoclassgc进行控制
使用-verbose,-XX:+TraceClassLoading、-XX:+TraceClassUnLoading可以查看类加载和卸载信息
-verbose、-XX:+TraceClassLoading可以在Product版HotSpot中使用;
-XX:+TraceClassUnLoading需要fastdebug版HotSpot支持
6、GC算法
复制算法:from–>to,谁空谁是to,主要用于新生区,没有内存碎片,但浪费了内存空间
引用计数法:每个对象计个数
标记->清除->压缩法:扫描对象,对活着的进行标记;没有标记的对象清除,但是扫描两次浪费时间,会产生内存碎片,但不需要额外的空间;再次扫描,向一端移动存活的对象,防止内存碎片产生
分代收集:
当一个对象经历了15次GC的时候还没有死,就会去养老区
7、JVM内存调优
使用jdk提供的JConsole和Java VisualVM工具。
主要目的就是为了减少GC的频率和Full GC的次数,多了的话很占用CPU。
8、native关键字
凡是带了native关键字说明java的作用范围达不到了,会去调用底层C语言的库,会进入本地方法栈,调用本地接口JNI,以拓展java类的使用,融合不同的语言。
9、JMM:Java Memroy Model java内存模型
JMM定义了线程内存和主内存之间的的抽象关系,作用:缓存一致性协议,用于定义数据读写的规则
8中交互操作:
lock (锁定):作用于主内存的变量,把一个变量标识为线程独占状态
unlock (解锁):作用于主内存的变量,它把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定
read (读取):作用于主内存变量,它把一个变量的值从主内存传输到线程的工作内存中,以便随后的load动作使用
load (载入):作用于工作内存的变量,它把read操作从主存中变量放入工作内存中
use (使用):作用于工作内存中的变量,它把工作内存中的变量传输给执行引擎,每当虚拟机遇到一个需要使用到变量的值,就会使用到这个指令
assign (赋值):作用于工作内存中的变量,它把一个从执行引擎中接受到的值放入工作内存的变量副本中
store (存储):作用于主内存中的变量,它把一个从工作内存中一个变量的值传送到主内存中,以便后续的write使用
write  (写入):作用于主内存中的变量,它把store操作从工作内存中得到的变量的值放入主内存的变量中
规则:
1、不允许read和load、store和write操作之一单独出现。即使用了read必须load,使用了store必须write
2、不允许线程丢弃他最近的assign操作,即工作变量的数据改变了之后,必须告知主存
3、不允许一个线程将没有assign的数据从工作内存同步回主内存
4、一个新的变量必须在主内存中诞生,不允许工作内存直接使用一个未被初始化的变量。就是怼变量实施use、store操作之前,必须经过assign和load操作
5、一个变量同一时间只有一个线程能对其进行lock。多次lock后,必须执行相同次数的unlock才能解锁
6、如果对一个变量进行lock操作,会清空所有工作内存中此变量的值,在执行引擎使用这个变量前,必须重新load或assign操作初始化变量的值
7、如果一个变量没有被lock,就不能对其进行unlock操作。也不能unlock一个被其他线程锁住的变量
8、对一个变量进行unlock操作之前,必须把此变量同步回主内存
10、volatile
在java语言中是一个关键字,用于修饰变量。被volatile修饰的变量后,表示这个变量在不同线程中是共享,编译器与运行时都会注意到这个变量是共享的,因此不会对该变量进行重排序。
volatile关键字保证可见性、有序性。但不保证原子性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值