前言

数据库是大家会普遍重视的一个领域,异步通信一般用不到,虚拟机在大部分时候不会出问题,常被人忽视,所以我打算先学习虚拟机,从零单排Java高性能问题。

堆内存存储结构

Java6是以年代来规划内存的,而Java7的G1收集器则相反,这里以Java6为准。

Survivor1和Survivor2是一样大的,必有一个始终为空,容量小于Eden。

垃圾回收机制

年轻代采用复制算法,当回收时,将Eden和Survivor中还存活的对象一次性地复制到另外一块Survivor上,然后清理掉Eden和刚才用过的Survivor空间。每进行一次Minor GC(年轻代回收),对象的年龄就增加1岁(初始为0),当年龄增加到一定程度(默认15岁),就会被移到老年代。老年代的回收算法因篇幅有限在此略过。

从《深入理解Java虚拟机》第二版93页上抄一个例子来做个示范:

package com.jiuyan.mountain.jvm;

public class Test {

  private static final int MB = 1024 * 1024;

  public static void main(String[] args) {
    byte[] bytes1, bytes2, bytes3, bytes4;
    bytes1 = new byte[2 * MB];
    bytes2 = new byte[2 * MB];
    bytes3 = new byte[2 * MB];
    bytes4 = new byte[4 * MB];
  }
}

命令行执行:

java -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 com/jiuyan/mountain/jvm/Test

参数解释:

  1. Xms20M:初始堆20M
  2. Xmx20M:最大堆20M
  3. Xmn10M:年轻代10M
  4. -XX:+PrintGCDetails:打印GC详细信息
  5. -XX:SurvivorRatio=8:Eden和一个Survivor的空间比例是8:1。

输出:

Heap
 PSYoungGen      total 9216K, used 6799K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 83% used [0x00000000ff600000,0x00000000ffca3f28,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 10240K, used 4096K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  object space 10240K, 40% used [0x00000000fec00000,0x00000000ff000010,0x00000000ff600000)
 PSPermGen       total 21504K, used 2751K [0x00000000f4600000, 0x00000000f5b00000, 0x00000000fec00000)
  object space 21504K, 12% used [0x00000000f4600000,0x00000000f48afc08,0x00000000f5b00000)

JVM没有进行垃圾回收,byte1、byte2、byte3、byte4总共10M内存,而年轻代只有9M内存,不应该啊。结果Eden有6M内存(bytes1,bytes2,bytes3),老年代有4M内存(bytes4),说明bytes4直接被分配到了老年代,因为在Survivor空间中当相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代。

那么我就调用System.gc()来主动触发一次GC。

输出:

[GC-- [PSYoungGen: 6635K->6635K(9216K)] 10731K->14827K(19456K), 0.0035280 secs] [Times: user=0.00 sys=0.01, real=0.00 secs]
[Full GC [PSYoungGen: 6635K->2275K(9216K)] [ParOldGen: 8192K->8192K(10240K)] 14827K->10467K(19456K) [PSPermGen: 2743K->2742K(21504K)], 0.0079080 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
Heap
 PSYoungGen      total 9216K, used 2441K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
  eden space 8192K, 29% used [0x00000000ff600000,0x00000000ff8624d8,0x00000000ffe00000)
  from space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
  to   space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
 ParOldGen       total 10240K, used 8192K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  object space 10240K, 80% used [0x00000000fec00000,0x00000000ff400030,0x00000000ff600000)
 PSPermGen       total 21504K, used 2750K [0x00000000f4600000, 0x00000000f5b00000, 0x00000000fec00000)
  object space 21504K, 12% used [0x00000000f4600000,0x00000000f48af8d0,0x00000000f5b00000)

日志分析:

  • GC和Full GC说明了这次垃圾收集的停顿类型,而不是用来区分年轻代还是老年代的。如果有“Full”,说明这次GC发生了STW(Stop-The-World)。
  • PSYoungGen是采用Parallel Scavenge收集器的年轻代,ParOldGen是采用Parallel Old收集器的老年代,Tenured是采用Serial Old收集器的老年代。
  • [PSYoungGen: 6635K->6635K(9216K)]表示GC前年轻代占用内存6M,GC后占用内存6M,内存区域总容量9M。10731K->14827K(19456K)表示GC前堆占用内存10M,GC后占用内存14M,堆总容量20M。
  • GC过程是把年轻代中的4M内存复制到了老年代,所以才会出现10731K->14827K(19456K),Full GC过程是把年轻代中的4M内存回收掉,所以才会出现PSYoungGen: 6635K->2275K(9216K)。

JVM垃圾回收机制入门的更多相关文章

  1. JVM垃圾回收机制总结:调优方法

    转载: JVM垃圾回收机制总结:调优方法 JVM 优化经验总结 JVM 垃圾回收器工作原理及使用实例介绍

  2. JVM内存管理和JVM垃圾回收机制

    JVM内存管理和JVM垃圾回收机制(1) 这里向大家描述一下JVM学习笔记之JVM内存管理和JVM垃圾回收的概念,JVM内存结构由堆.栈.本地方法栈.方法区等部分组成,另外JVM分别对新生代和旧生代采 ...

  3. JVM垃圾回收机制概述

    JVM垃圾回收机制概述 1.定义 是指JVM用于释放那些不再使用的对象所占用的内存. 2.方式 2.1引用计数(早期) 当引用程序创建引用以及引用超出范围时,JVM必须适当增减引用数.当某个对象的引用 ...

  4. Java虚拟机学习笔记——JVM垃圾回收机制

    Java虚拟机学习笔记——JVM垃圾回收机制 Java垃圾回收基于虚拟机的自动内存管理机制,我们不需要为每一个对象进行释放内存,不容易发生内存泄漏和内存溢出问题. 但是自动内存管理机制不是万能药,我们 ...

  5. JVM基础系列第8讲:JVM 垃圾回收机制

    在第 6 讲中我们说到 Java 虚拟机的内存结构,提到了这部分的规范其实是由<Java 虚拟机规范>指定的,每个 Java 虚拟机可能都有不同的实现.其实涉及到 Java 虚拟机的内存, ...

  6. JVM内存管理、JVM垃圾回收机制、新生代、老年代以及永久代

    内存模型 JVM运行时数据区由程序计数器.堆.虚拟机栈.本地方法栈.方法区部分组成,结构图如下所示. JVM内存结构由程序计数器.堆.栈.本地方法栈.方法区等部分组成,结构图如下所示: 1)程序计数器 ...

  7. JVM 垃圾回收机制和常见算法和 JVM 的内存结构和内存分配(面试题)

    一.JVM 垃圾回收机制和常见算法 Sun 公司只定义了垃圾回收机制规则而不局限于其实现算法,因此不同厂商生产的虚拟机采用的算法也不尽相同.GC(Garbage Collector)在回收对象前首先必 ...

  8. JVM垃圾回收机制和常用算法

    由于疫情的原因,所以目前一直在家远程办公,所以很多时间在刷面试题,发现2019大厂的面试虽然种类很多,但是总结了一下发现主要是这几点:算法和数据结构. JVM.集合.多线程.数据库这几点在面试的时候比 ...

  9. 真的可惜,四面阿里,结果我被JVM垃圾回收机制与 OOM异常卡住了

    前言 为什么需要垃圾回收 首先我们来聊聊为什么会需要垃圾回收,假设我们不进行垃圾回收会造成什么后果,我们举一个简单的例子 我们住在一个房子里面,我们每天都在里面生活,然后垃圾都丢在房子里面,又不打扫, ...

随机推荐

  1. CTE-递归[2]

    在此之前写过一个CTE的递归,取出了所有的子节点,基本上可以满足大多数的需求,这里我们来延伸一下:首先我们回顾下原来的场景 图片的上半部分递归查出某个节点的所有子节点,这个我们已经通过CTE实现了,可 ...

  2. for循环,如何结束多层for循环

    采用标签方式跳出,指定跳出位置, a:for(int i=0;i<n;i++) { b:for(int j=0;j<n;j++) { if(n=0) { break a; } } }

  3. hbase的存储体系

    一.了解hbase的存储体系. hbase的存储体系核心的有Split机制,Flush机制和Compact机制. 1.split机制 每一个hbase的table表在刚刚开始的时候,只有一个regio ...

  4. C++函数二义性问题,我怎么感觉编译器有偷懒嫌疑!!!

    瞎扯一段,讲得不一定对.纯属学习! struct BB{ void a(){ cout << "bb's a()\n"; }}; struct B1 : public ...

  5. Android 新版NDK环境搭建(免Cygwin)

    使用最新ndk,直接抛弃cygwin,以前做Android的项目要用到NDK就必须要下载NDK,下载安装Cygwin(模拟Linux环境用的),下载CDT(Eclipse C/C++开发插件),还要配 ...

  6. 第五篇、 WebSphere8.5的安装

    一.前言 WebSphere Application  Server 是IBM企业级应用服务器,与WAS6,WAS7相比较而言 WAS8发生了很大的改变,其安装介质和以前截然不同,该篇章中对于不同的安 ...

  7. JS判断浏览器是否支持某一个CSS3属性的方法

    var div = document.createElement('div'); console.log(div.style.transition); //如果支持的话, 会输出 "&quo ...

  8. 『重构--改善既有代码的设计』读书笔记----Self Encapsulate Field

    如果你直接访问一个字段,你就会和这个字段直接的耦合关系变得笨拙.也就是说当这个字段权限更改,或者名称更改之后你的客户端代码都需要做相应的改变,此时你可以为这个字段建立设值和取值函数并且只以这些函数来访 ...

  9. 理解Python的*args, **kwargs

    1 # coding=utf-8 2 def speak(*args, **kwargs): 3 print args, kwargs 4 5 6 a = 1 7 b = 2 8 c = 3 9 sp ...

  10. 啊哈,yield

    文章出处:http://www.cnblogs.com/winstic/,请保留此连接 在python编程中,我们经常会看到函数中带有yield关键字,但请注意,此时的函数不再是我们熟知的一般函数,而 ...