1.物理内存与虚拟内存
除OS外任何程序都不会直接访问物理内存而是访问虚拟内存。可把虚拟内存等同于物理内存。虚拟内存使得多个进程在同时运行时可以共享物理内存。
2.内核空间与用户空间
内核空间主要是指操作系统运行时所使用的用于程序调度、虚拟内存的使用或者连接硬件资源等的程序逻辑。
换句话:程序使用用户空间,系统使用内核空间。程序通过给定的接口实现内核空间的调用。
3.使用内存的组件:Java 堆
Java 堆是用于存储 Java 对象的内存区域,堆的大小在JVM启动时就一次向操作系统申请完成。一旦分配完成,堆的大小将固定,不能在向操作系统重新申请,也不能归还。
Java 堆中内存空间的管理由JVM来控制,对象创建由 Java 应用程序控制,但是对象所占的空间释放由管理堆内存的垃圾收集器完成。根据垃圾收(GC)算法的不同,内存回收的方式和时机也会不同。
3.1线程
JVM运行的实体是线程,这里说一下线程和进程,一个进程可以有多个线程。进程是cpu资源分配的最小单位,线程是cpu调度的最小单位。
3.2类和类加载器
在 Java 中的类和加载类的类加载器本身同样需要存储空间,任何系统类或通过应用程序类加载器加载的任何应用程序类都不能在运行时释放。
3.3NIO
1.4之后的新的I/O库
优点:调用系统API直接,分配本机内存,不用将数据复制到 Java 内存当中。
3.4JNI
使用本机代码即可调用 Java 方法。
4.JVM 内存结构
运行时数据:
- PC寄存器数据
- Java 栈
- 堆
- 方法区
- 本地方法区
- 运行时常量池
4.1 PC寄存器
它用于保存当前正常执行的程序的内存地址。要知道程序并非真的并行执行,所以当轮流抢占使用内存的时候,停下来时的内存地址一定会被保存下来。
4.2 Java 栈
和线程关联在一起,每当创建一个线程时,JVM就会为这个线程创建一个对应的Java栈。先进后出的原则。
4.3 堆
堆是存储Java对象的地方,它是JVM管理Java对象的核心存储区域。堆是被所有Java线程所共享的,所以对它的访问需要注意同步问题,方法和对应的属性都需要保证一致性。
4.4 方法区
JVM方法区是用于存储类结构信息的地方。其中的常量池、域、方法数据、方法体、构造函数,包括类中的专用方法、实例初始化、接口初始化都存储在这个区域。方法区这个存储区域也属于后面介绍的Java堆中的一部分,也就是我们通常所说的Java堆中的永久区。
方法区不会被频繁的回收。
4.5 运行时常量池
它是方法区的一部分。
JVM 内存分配策略
栈中主要存放一些基本类型的变量数据(int、short、long、byte、float、double、boolean、char)和对象句柄(引用)。
每个Java应用都唯一对应一个JVM实例,每个实例唯一对应一个堆。应用程序在运行中所创建的所有类实例或数组都放在这个堆中,并由应用程序所有的线程共享。
从堆和栈的功能和作用来通俗地比较,堆主要用来存放对象,栈主要用来执行程序,这种不同主要是由堆和栈的特点决定的.
堆耗时,但是可变。栈快速,但是定长。
JVM 内存回收策略
书中的回收策略描述的很详细,我简单的解释就是,在执行代码之前,JVM就会对程序进行检查,如果没有被使用就回收,如果不再被使用,也会被回收,这些都是JVM帮我们考虑的。这就是为什么 Java 强大,但这也恰恰是 Java 为什么那么慢的原因。
Java 对象存储空间是实行时才知道大学,编译时不知道,回收时也是不确定的,只有被检测不再使用才会被回收。