之前看JVM的书有点吃力,最近在看《深入分析java web》感觉里面讲JVM的知识虽然简略,但是容易理解,所以准备将看书过程中的几个要点进行整理概况。

JVM体系结构和工作方式

啥是JVM

计算机系统可以分为一下几个部分(指令集,计算单元,寻址方式,存储器定义,存储单元),其中最主要的是指令集。Java和实体机一样有一套自己的指令集,称为JVM字节码指令集。

JVM体系结构详解

  • 类加载器:三大加载器
  • 执行引擎:Hotspot基于栈,Dalvik基于寄存器
  • 内存区:线程共享(方法区+堆),非共享(栈+PC寄存器),本地方法
  • 本地方法调用:调用C/C++

JVM工作机制

为啥选择基于栈

  1. 要设计成与平台无关的,保证寄存器很少也能执行Java代码;
  2. 为了指令的紧凑型

物理内存和虚拟内存

32位总线最多单次读取4GB的内存。 虚拟内存使得多项进程共享物理内存,注意是空间是上共享,逻辑还是隔离的。

内核空间与用户空间

这种从内核空间到用户空间的数据复制很费时,虽然保住了程序运行的安全性和稳定性,但是也牺牲了一部分效率。

哪些组件需要内存

  1. 堆:-Xms(初始),-Xmx(最大),-Xms()
  2. 线程:每个线程创建时JVM都会为它创建一个堆栈,堆栈的大小根据不同的JVM实现而不同,通常在256KB~ 756KB之间。
  3. 类和类加载器:任何系统类(如java.lang.String)或通过应用程序类加载器加载的任何应用程序类都不能在运行时释放。
  4. NIO:分配的内存使用的是本机内存而不是Java堆上的内存
  5. JNI:JNI也会增加Java运行时的本机内存占用

Java内存结构

  1. PC寄存器:保存当前正常执行的程序的内存地址
  2. 栈:由于Java栈是与Java 线程对应起来的,这个数据不是线程共享的,所以我们不用关心数据一致性问题,也不会存在同步锁的问题
  3. 堆:堆是被所有Java线程所共享的,所以对它的访问需要注意同步问题
  4. 方法区:JVM方法区是用于存儲炎結枸信息的地方(常量池、域、方法数据、方法体、构造函数,包括类中的专用方法、实例初始化、接口初始化)
  5. 本地方法区:为JVM运行Native方法准备的空间
  6. 运行时常量池:它是方法区的部分,所以它的存储也受方法区的规范约束

Java内存分配详解

  1. 栈:栈中主要存放一些基本类型的变量数据( int、short、long、byte、float、 double、boolean、char)和对象句柄(引用)。存取速度比堆要快,仅次于寄存器,栈数据可以共享。缺点是,存在栈中的数据大小与生存期必须是确定的,这也导致缺乏了其灵活性。
  2. 堆:堆的效率非常低。但是堆的优点在于,编译器不必知道要从堆里分配多少存储空间,也不必知道存储的数据要在堆里停留多长时间,因此,用堆保存数据时会得到更大的灵活性。

    Java内存回收策略

静态内存分配和回收

动态内存分配和回收