浅谈JAVA虚拟机

目录
  1. 为什么要了解JVM
  2. JRE的架构图
  3. Runtime的架构图
  4. 如何判断对象已死
  5. 堆的架构
  6. 堆大小的相关配置参数
  7. 垃圾回收器
  8. 垃圾回收算法
    1. ✔CMS(Concurrent Mark Sweep)并发标记清除垃圾回收器

为什么要了解JVM

个人认为每一个JAVA程序员都要了解一下JAVA虚拟机,这样有利我们知道对象在内存的分布情况,有利于写出健壮的程序,不要动不动就内存溢出,内存泄漏。 深入理解JAVA虚拟机的三种境界,我认为有:

  1. 理解内存发布,垃圾回收,写出健壮的程序
  2. 根据不同的业务场景进行jvm调优
  3. 进行JVM的开发

事实上,个人认为能够达到第二层境界已经非常叼了,第三层境界就是超神了,比如R大

JRE的架构图

JRE JRE全称==JAVA runtime environment== ,JRE上面是运行的JAVA程序,下面是OS和hardware相关。

JRE包括JDK相关的API以及JAVA虚拟机。 JAVA虚拟机包括了:GC(Garbage Collector垃圾回收器),Class loader(类加载器),Runtime(运行时包括执行引擎等),JIT(just in time compiler,即时编译器)。

Runtime的架构图

Runtime 如图所示,运行时数据区有:虚拟机栈,本地方法栈, 堆,方法区,程序计数器。

  • 虚拟机栈,方法执行时会产生一个栈帧,栈帧包括了局部变量表,动态链接,方法出口,操作数栈等,栈帧随着方法的执行而入栈,方法结束后出栈。
  • 本地方法栈:和虚拟机栈一样,只不过存放的native的相关内容。
  • 堆:运行时占的最大的一块区域,堆的作用当然是存放对象。
  • 方法区,主要存放类加载的信息,常量,静态变量,即时编译器编译后的代码。
  • 程序计数器,主要存放执行的指令:分支循环,跳转,异常处理等。

我们可以知道是,虚拟机栈,本地方法栈,程序计数器,都是线程私有的,所以不会线程安全问题。方法区以及堆是线程共享的。

如何判断对象已死

  • 引用计数算法 引用计数算法没办法解决循环引用的死的对象,因为这些循环引用的对象的引用都不为0,但是都是没用的对象,必须从内存里面清除掉。如图中的O3 -> O4 -> O5.
  • 可达性性分析算法 从GC-root出发,如果能够到达的引用的对象认为是存活的对象,没办法到达的对象认为是可以垃圾回收的对象。 可以作为GC-root:
  1. 虚拟机栈引用的对象
  2. 方法区静态变量引用的对象
  3. 方法区常量引用的对象
  4. 本地方法栈引用的对象

堆的架构

堆逻辑分类可以分为新生代,老年代,还有永久代(在方法区)

  • 新生代主要分为Eden区域和survivor区域(分为From和To)。一般新建的对象都会进到Eden区域,当进行minor GC时,没有被垃圾回收的对象就会进入到from区,当度过了多次minor GC就会进入到老年代。from和survivor区域在垃圾回收之后,其中的一个区域总是为空的。新生代采用的垃圾回收算法一般是copying算法。
  • 老年代:主要是存放一些经历了多次GC还没有被回收的对象,一些大对象会直接分配到老年代(超过了新生代的大小),所以写程序的时候切记不要分配过大的朝生夕灭的对象。
  • 永久代:主要是存放这类的信息等,虽然叫永久代,但是还是会回收的,只是回收的概率比较低。

堆大小的相关配置参数

堆配置参数

垃圾回收器

垃圾回收器 一般分为4大类:单线程,多线程并行,并发标记清扫,还有就是GC集大成者G1回收器。 分别在不同年代使用不同垃圾回收器,连线表示可以一起在配合使用。

垃圾回收算法

  • MARK-SWEEP(标记清除算法):好处就是速度快,缺点就是会产生内存碎片。
  • Copying(复制算法):在新生代使用,思想就是把内存分为两块,将存活的对象复制到另一块区域,然后直接清楚死亡对象的那个区域,这就是复制算法,复制算法的有点也是比较简单,缺点就是内存的利用率没有达到100%,不过新生代的对象大部分都是朝生夕灭的,垃圾回收的占比可以达到百分之八九十。所以在新生代非常适合使用复制算法。
  • MARK-COMPACT(标记整理):有三个过程:标记,清除,整理。特点就是不会产生内存碎片,缺点就是效率不如标记清除和复制算法。
  • Generation Collect(分代回收):这是一种思想,根据对象存活的时间进行分代回收。 不同的垃圾回收器使用不同垃圾回收算法: Serial:新生代(Copying),老年代(mark-compact) ParaNew:新生代(Copying),老年代(mark-compact) Parallel scavenge:新生代(Copying) Parallel Old:老年代(mark-compact) CMS:老年代(mark-sweep)

CMS(Concurrent Mark Sweep)并发标记清除垃圾回收器

CMS ##G1(Garbage First回收器)## G! #JAVA程序的生命历程#

缓存之Redis(二)

Redis与Memcache对比

  1. 进程数:首先Redis是单进程的,Memcache是多进程的。
  2. 是否支持数据持久化、主从复制:Redis是支持数据持久化的,有两种方式RDB和AOF;RDB是将数据库的快照以二进制的方式存储到磁盘;AOF是将命令的日志记录到AOF文件。Redis是支持主从复制的。Memcache是不支持持久化的所有数据都放在内存。
  3. 支持的数据类型:Redis除了支持支持key-val,还支持Hash(哈希表),List,SET,ZSET;Memcache只支持简单的key-val。
  4. 性能对比:性能方面,事实上两者的性能都足够高,当然因为Redis是单进程的,Memcache是多进程的,在存储大数据(100k)以上的情况,Memcache略高于Redis,在存储小数据时,Redis性能是要高于Memcache的。