Java基础篇之Java虚拟机(一)------内存模型和结构; 垃圾回收机制;类加载机制

这次记录内容主要内容包括如下三块内容: html

 内存模型和结构; java

 垃圾回收机制; 算法

 类加载机制; bash

一,Java内存模型与JVM内存结构  微信

JVM内存模型与内存结构是两个大相径庭的东西,你们都知道Java内存分为堆和栈,被问到内存相关都会这样回答,可是今天要弄清楚什么是内存模型什么是内存结构?多线程

 JVM内存模型简称(JMM)是一种抽象的概念,并非像JVM内存结构同样是实际存在的,而是由于Java的多线程之间是经过共享内存进行通讯的,而因为采用共享内存进行通讯,在通讯过程当中会存在一系列如可见性、原子性、顺序性等问题,而JMM就是围绕着多线程通讯以及与其相关的一系列特性而设计创建出来的的模型。oracle

 目的是解决因为多线程经过共享内存进行通讯时候,存在本地内存数据不一致,,编译器对代码重排序,以及处理器对代码乱序执行带来的问题,从而保证Java程序在各类平台下对内存的访问都能保证效果的一致性。  jvm

JVM内存结构是一种实际存在的结构体,由Java虚拟机规范定义,是Java程序执行过程当中,由JVM管理的不一样数据区域,而且各个区域有其特定的功能。学习

 


 二,JVM垃圾回收机制  spa

Java语言通常状况下不须要开发人员本身去处理内存问题,自己存在垃圾回收机制,那么Java的垃圾回收机制究竟是什么?  

在说明垃圾回收机制以前先说一下Java中的内存溢出以及内存泄漏的是怎么回事? 

内存溢出:out of memory,是指在程序申请内存时候,没有足够的空间可供提供,好比加载一个大型游戏出现内存不足,再简单一点就是在仅仅只有Integer大小的空间内放置Long大小的数据,那么就会形成内存溢出。  

内存泄漏:memory leak,是指程序申请到了内存,可是程序没有在不须要内存空间时候即便释放,形成内存空间只会一直减小,这种行为被称为内存泄露,内存泄漏一次没有关系,可是屡次的内存泄漏积累的结果必定会形成内存不足。  

好的咱们开始从如下几点进行逐步了解Java主流虚拟机hotspot的垃圾回收机制,其余类型的虚拟机感兴趣的能够去作更深刻了解。 

 1,什么是垃圾? 

 没有被引用的对象在Java中就被称为垃圾 

 2,怎么判断垃圾?

 判断一个对象是否成为垃圾有如下几种方式 

 引用计数法 :

 为对象添加一个引用计数器,当对象增长一个引用时计数器就加1,引用失效计数器就减1,当引用技术为0时对象可被回收。不过,当两个对象出现循环引用时,两个对象的引用计数器永远不会为0,这样会致使他们没法被回收。 

 引用可达法 

 以 GC Roots 为起始点进行搜索,可达的对象都是存活的,不可达的对象可被回收。 

 GCRoot通常为如下几种: 

  •  虚拟机栈中局部变量表中引用的对象 
  •  本地方法栈中 JNI 中引用的对象 
  •  方法区中类静态属性引用的对象 
  •  方法区中的常量引用的对象 

方法区回收 

方法区存的通常就是永久代(年老代)对象,回收起来比年轻代要更加困难,因此对方法区的回收条件更加严格,主要也是对常量池的回收和类的卸载,知足如下条件才有可能被回收,可是也不必定会被回收。 

 该类全部的实例都已经被回收;

此时堆中不存在该类的任何实例;

 加载该类的 ClassLoader 已经被回收 ;

该类对应的 Class 对象没有在任何地方被引用,也就没法在任何地方经过反射访问该类方法。

finalize() 

 finalize()是Object的方法,存在的意义看似是,当类复写了finalize()方法,能够在对象被回收以前只调一次,来达到所谓的完成最后的功能,可是即便调用了,也不能保证方法会所有执行,可能会在方法执行过程当中被回收

3,垃圾怎么回收 ?

 标记清除算法 

 分为两个阶段,先标记出来要回收的区域,而后赞成进行清除。 


 存在问题: 

 1,内存不连续,空间碎片太多 

 2,标记和清除效率低 


 复制算法(新生代) 

 将可用内存分为两等份,每次使用其中一份,进行垃圾回收的时候将,存活对象复制到另外一块没有使用的可用空间上面,而后把使用过的内存空间一次性所有清理。

 优势:简单高效,内存连续 

 不足:内存利用不充分,当对象存活率广泛较高时,因为内存只是用一半,须要屡次执行。 


 标记整理算法(老年代) 

标记整理,与上面的标记清理相似,只是标记整理不是将被标记的进行清除,而是将存活对象移动到一块儿,将剩余外界的进行清理。 


 分代收集算法 

 Java会把Java堆区域分为新生和年老代,而后根据不一样的年代进行不一样算法的回收。  

新生代:大批会被回收,只有少许会继续存活,因此复制算法更加合适。  

老年代:被回收的概率较低,因此适合标记整理,标记清除算法。

 

4,Java不一样类型的引用 

 强引用: 

Object obj = new Object()
复制代码

广泛存在的引用,只要引用还在就永远不会被回收。 

软引用:  

软引用用来描述一些还有用可是非必须的对象,系统在将要发生内存溢出以前,将会把这些对象列进回收范围,并进行第二次回收,若是将弱引用对象及进行回收以后依然没有足够的内存,那么会抛出内存异常。 

 弱引用 :

非必须对象的引用,强度要比软引用更弱,被弱引用指向的对象只能生存到下一次垃圾回收以前。当垃圾回收器工做时候,不管内存是否足够,都会回收掉被弱引用指向的对象。  

虚引用 :

虚引用存在不存在没有太大意义,仅仅是为了这个被虚引用指向的对象在被垃圾回收器回收的时候收到一个系统通知。 

 三,类加载机制 

 什么是类加载机制?  

Class文件中的各类信息,都是须要加载到虚拟机中才能运行,虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验,转换解析和初始化,最终造成能够被虚拟机使用的Java类型,这就是Java虚拟机的类加载机制。 

类加载过程:加载-->验证-->准备-->解析-->初始化-->使用-->卸载 

 双亲委派模型是什么? 

双亲委派模型(Parents Delegation Model)要求除了顶层的启动类加载器,其他加载器都应当有本身的父类加载器,类加载器之间经过组合关系复用。 双亲委派模型工做过程:若是一个类加载器收到类加载请求,他不会本身去加载这个类,而是请求给父类加载器去完成,每一个层次的加载器都是如此,所以全部的加载任务都会传到顶层的启动加载类,只有在父类反馈没法完成加载任务的时候,才会由子类本身去完成加载工做。 

 为何要有双亲委派模型?  

采用双亲委派模型使得Java类随着它的类加载器一块儿具有了一种带有优先级的层次关系。例如类java.lang.Object,它存放在rt.jar中,不管哪一个类加载器要加载这个类,最终都会委派给启动类加载器进行加载,所以Object类在程序的各类类加载器环境中都是同一个类。相反,若是用户本身写了一个名为java.lang.Object的类,并放在程序的Classpath中,那系统中将会出现多个不一样的Object类,java类型体系中最基础的行为也没法保证,应用程序也会变得一片混乱。 


 记录这些也是记录本身学习过程,因此若是您发现不足或者错误之处,敬请雅正、不舍赐教。

若是你也正在学习或者复习中不妨关注微信公众号:【Java成长录】一块儿学习。 


参考文献:

https://www.hollischuang.com/archives/2509)

https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5(Java虚拟机规范) 

周志明. 深刻理解 Java 虚拟机 [M]. 机械工业出版社, 2011.

相关文章
相关标签/搜索