0、Java 对内存的划分:

Java虚拟机规范将物理内存(主内存和CPU中的缓存、寄存器)划分为程序计数器、Java 虚拟机栈、本地方法栈、Java 堆、方法区五个区域,但并没有规定这些区域的具体实现,在其他地方听到的一些名词(如永久代、元空间等,这些都是方法区的具体实现)可能都是这些区域具体的实现,这点要特别注意,别被这些概念搞晕。

各个区域的特点如下表:

1、类加载器:

类加载器分为Bootstrap、Extension ClassLoader(Java9 中是 Platform ClassLoader)、Application ClassLoader,级别也是从高到低。

可以调用类加载器对象的 getParent() 方法查找该级加载器的上一级加载器,也成为父类加载器。

此处不翻译了,翻译后就变味了,尤其是下面的 Parents Delegation Model 翻译为双亲委派模型很不恰当。

字节码文件加载到内存中,才可以实例化出类,而类加载器就是负责加载 Java 类的。低级别的类加载器在加载一个类时会先询问上一级的类加载器,直到询问到顶级的类加载器(Bootstrap),如果顶级的类加载器可以加载就加载该类,否则向下尝试是否可以加载该类,也即是如果上一级类加载器能加载的就用上一级加载(复用上一级的类加载器),用不了再用自身的类加载器加载,这也就是口口相传却是翻译很不恰当的双亲委派模型。这样做可以使类加载更加安全,避免加载和标准 Java 类同包同名的类破坏虚拟机。

可以根据需要继承 Application ClassLoader 实现自定义类加载器,隔离加载器、修改类的加载方式、扩展加载源、防止源码泄露。

2、类加载的过程:

类加载是将字节码文件实例化成 Class 对象并进行相关初始化的过程。类加载包括类的加载(Load)、类的链接(Link)、类的初始化(init)三个步骤。

类的加载是将字节码文件以二进制流的方式读取到内存中并转化为特定的数据结构,检查 cafe baby 这个魔法数(是不是Java文件的标志),是否有父类等,创建类对应的 Class 对象。

类的链接又分为验证、准备、解析三个阶段,验证阶段是进行更加详细的校验,如类型是否正确,静态变量是否合理等;准备阶段是为类的静态变量分配内存空间,并设定默认值;解析阶段是保证类和类之间相互引用的正确性,完成类在内存中的结构布局。

类的初始化并不是初始化对象,而是根据代码中的值初始化类的静态变量值,类的静态变量的初始化方式也有直接在声明时指定值和在静态代码块中指定值两种方式。

3、访问对象的两种方式:

Java虚拟机栈中的局部变量表存放的数据除了基本的数据类型外,还有对象的引用类型(reference),这关系到如何访问一个对象。

在不同的虚拟机中,对象的访问方式也是不同的,主流的访问方式有使用句柄和直接指针两种。

  • 使用句柄:

使用句柄是在 Java 堆中划分出一块区域作为句柄池,句柄池中存放对象的实例数据和类型数据(类相关的信息)的地址,reference 中存放的是对象对应句柄中的地址,这是一种间接访问对象方式。

  • 直接指针:

直接指针是reference中直接存放对象的地址,但 Java 堆需要考虑如何存放访问对象类型的指针。

两种方式其实各有优劣,如下表:

4、判断对象是否可以回收的算法:

垃圾回收之前需要判断对象是否可以回收,常见的判断算法有引用计数算法和可达性分析算法。

引用计数算法:

每个对象都有对应的引用计数器,当有一个地方引用该对象时,就将引用计数器的值加1,当引用失效时,就将引用计数器的值减1,当计数器的值为0时,表示对象没有引用,可以被回收了。

缺点:看起来简单高效,但是有循环引用问题。如果两个对象中包含对方的引用就会产生循环引用问题,导致垃圾收集器不能回收对象。

可达性分析算法:

如果对象与GC Roots 之间没有直接或间接的应用关系,就可以被回收了。常见的 GC Roots 对象包括虚拟机栈(栈帧本地变量表)中引用的对象、方法区中静态属性引用的对象、方法区常量引用的对象、本地方法栈中(Native 方法)引用的对象。GC Roots,是一个特殊的对象,且绝对不能被其他对象引用,不然也会像引用计数算法那样有循环引用的问题。

5、常见的垃圾回收算法:

  • 标记-清除算法

最基本的垃圾回收算法,后续的算法都是对它的改进。

首先标记出需要回收的对象,再将标记出的区域内容清除。

缺点是:标记时的查找效率,清除时产生内存碎片。

  • 标记-复制算法

将内存区域划分为两块,每次只使用一块,垃圾回收时,标记正在使用的内存区域,将存活的对象复制到另一块内存区域,再将原来的那一块内存区域一次性清除。避免了内存碎片的产生,但不适合存活时间长的对象。

缺点:浪费了一半的内存空间,当对象存活率高时,进行大量的复制操作,效率不高。

  • 标记-整理算法

标记过程和标记-除算法相同,垃圾回收时,是将存活的对象向同一端移动,再清除这之外的内存区域,这样就使得对象占用的内存区域连续,避免了内存碎片的产生。

  • 分代收集算法

根据对象存活时间的长短,将堆内存分为新生代和老生代,存活时间短的对象放在新生代区域,存活时间长的大对象(如对象数组)放在老生代区域。新生代和老生代的比例是 1 : 2,新生代又分为一个 Eden 区和两个 Survivor 区。新生代使用标记-复制算法,老生代使用标记-清除算法或标记-整理算法,这样最大发挥各自算法的优势。

6、常见的垃圾回收器:

  • Serial 回收器

Serial 采取 “复制算法” 实现,如果是在单 CPU 环境下,Serial 收集器没有线程交互的开销,理论上是可以获得最高的单线程执行效率,STW 的时间也可以控制在几十到几百毫秒内,这个时间是完全可以接受的。

  • Serial Old (PS MarkSweep)回收器

Serial Old 收集器 是 Serial 收集器的老年代版本,同样也是一个单线程收集器,使用了 “标记-整理算法”。

  • ParNew 回收器

ParNew 收集器实际上就是 Serial 收集器的多线程版本,收集算法、STW、对象分配的规则、回收策略等都与 Serial 收集器完全一样,两者相同的代码很多。ParNew 收集器虽然有多线程优势,但在单 CPU 和多 CPU 环境下,效果并不一定会比 Serial 好,至少在单 CPU 环境下是肯定不如的 Serial 的。

  • Parallel Scavenge 回收器

Parallel Scavenge收集器和 ParNew 收集器很像,也是一个新生代收集器,也是使用复制算法,并且还是并行的多线程的收集器。相比于 ParNew 收集器,Parallel Scavenge收集器可以更加精准的控制 CPU 的吞吐量和 STW 的时间,对于交互不多的任务可以更快地完成。

  • Parallel Old 回收器

Parallel Old 收集器是 Parallel Scavenge 收集器的老年代版本,使用多线程和 “标记-整理算法”。在 Parallel Old 收集器出现之间,选择了 Parallel Scavenge 收集器作为新生代的收集器,就只能选择 Serial Old 收集器作为老生代收集器,这样肯定就是对多 CPU 的浪费,所以 Parallel Scavenge收集器 + Parallel Old 收集器,对于多 CPU 环境吞吐量要求高的环境,算是强强联合。

  • CMS 回收器

CMS (Concurrent Mark Sweep)收集器从英文名字上看就是基于 “标记-清除算法” 实现的,并且还有并发的特点,它是一种以缩短 STW 的时间为目标的收集器,对于一些重视服务响应速度的网站,肯定是 STW 越短,用户体验越好,但是缺点是会在垃圾收集结束后产生大量的空间碎片。

通过初始标记(Initial Mark)、并发标记(Concurrent Mark)、重新标记(Remark)、并发清除(Concurrent Sweep)四个步骤完成垃圾回收。

  • G1 回收器

G1 收集器是目前最先进的收集器,它是基于 “标记-复制算法” 实现的,所以不会产生内存碎片,并且也可以精准地控制 STW 的时间。G1 收集器对于新生代和老年代都是适用的,优先回收垃圾最多的区域。

Java内存管理知识你需要吗?的更多相关文章

  1. Java进阶2 数组内存和对象的内存管理知识

    Java进阶2 数组内存和对象的内存管理知识 20131028 前言: 在面试的时候,如果是Java的编程语言,也许你认为没有什么可以问的,只能够说明你对于Java了解的太浅了,几乎就是两个星期的节奏 ...

  2. 简单的例子 关于Java内存管理的讲解

    我想做的是,逐行读取文件,然后用该行的电影名去获取电影信息.因为源文件较大,readlines()不能完全读取所有电影名,所以我们逐行读取. 就这段代码,我想要在位置二处使用base64,然后结果呢? ...

  3. java内存管理(堆、栈、方法区)

    java内存管理 简介 首先我们要了解我们为什么要学习java虚拟机的内存管理,不是java的gc垃圾回收机制都帮我们释放了内存了吗?但是在写程序的过程中却也往往因为不懂内存管理而造成了一些不容易察觉 ...

  4. 揭开Java内存管理的面纱

    前言 相对于C.C++这些高性能语言,Java有着让此类程序员羡慕的功能:内存自动管理.似乎这样,Java程序员不用再关心内存,也不用去了解相关知识.但结果真的是这样吗?特别对于我们这种Android ...

  5. Java内存管理-一文掌握虚拟机创建对象的秘密(九)

    勿在流沙筑高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! [福利]JVM系列学习资源无套路赠送 回顾一下: 本文是接着上一篇内容:Java内存管 ...

  6. Java内存管理-掌握虚拟机类加载器(五)

    勿在流沙筑高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 上一篇介绍虚拟机类加载机制,讲解了类加载机制中的三个阶段,分别是:加载.连接(验证.准 ...

  7. Java内存管理-掌握虚拟机类加载机制(四)

    勿在流沙筑高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 上一篇介绍了整个JVM运行时的区域,以及简单对比了JDK7和JDK8中JVM运行时区域 ...

  8. 每个Android开发者必须知道的内存管理知识

    原文:每个Android开发者必须知道的内存管理知识 拷贝在此处,以备后续查看. 相信一步步走过来的Android从业者,每个人都会遇到OOM的情况.如何避免和防范OOM的出现,对于每一个程序员来说确 ...

  9. 你必须了解的java内存管理机制(三)-垃圾标记

    本文在个人技术博客不同步发布,详情可用力戳 亦可扫描屏幕右侧二维码关注个人公众号,公众号内有个人联系方式,等你来撩... 相关链接(注:文章讲解JVM以Hotspot虚拟机为例,jdk版本为1.8) ...

随机推荐

  1. swoole udp

    server.php <?php $server = new swoole_server('127.0.0.1', 9502, SWOOLE_PROCESS, SWOOLE_SOCK_UDP); ...

  2. 2018-2019-2 20165209 《网络对抗技术》 Kali安装

    2018-2019-2 20165209 <网络对抗技术> Kali安装 目录内容 下载 安装 网络 共享 软件源 下载kali kali下载官网地址 我下载的版本(如下图所示) 安装 打 ...

  3. Vert.x

    Vert.x是一个基于JVM.轻量级.高性能的应用平台,非常适用于最新的移动端后台.互联网.企业应用架构.Vert.x基于全异步Java服务器Netty,并扩展出了很多有用的特性. 同时支持多种编程语 ...

  4. Django国际化和本地化

    把django的这篇文档看了一遍,基本弄懂了,讲的也挺详细的 https://docs.djangoproject.com/en/1.6/topics/i18n/ 首先是国际化和本地化概念: 1,国际 ...

  5. 20145101《Java程序设计》第8周学习总结

    20145101<Java程序设计>第8周学习总结 教材学习内容总结 第十四章 NIO与NIO2 NIO使用频道(channel)来衔接数据节点,对数据区的标记提供了clear(),rew ...

  6. 20145206邹京儒《网络对抗》逆向及Bof基础实践

    20145206邹京儒<网络对抗>逆向及Bof基础实践 1 逆向及Bof基础实践说明 1.1 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:ma ...

  7. 20145303刘俊谦《网络攻防》Exp4 Msf基础

    20145303刘俊谦<网络攻防>Exp4 Msf基础 实验目标 • 掌握metasploit的基本应用方式,掌握常用的三种攻击方式的思路. • 一个主动攻击,如ms08_067: • 一 ...

  8. tf.placeholder使用说明

    tf.placeholder(dtype, shape=None, name=None) placeholder,占位符,在tensorflow中类似于函数参数,运行时必须传入值. dtype:数据类 ...

  9. 网络安全、Web安全、渗透测试之笔经面经总结(三)

    本篇文章涉及的知识点有如下几方面: 1.什么是WebShell? 2.什么是网络钓鱼? 3.你获取网络安全知识途径有哪些? 4.什么是CC攻击? 5.Web服务器被入侵后,怎样进行排查? 6.dll文 ...

  10. 【前端】纯html+css+javascript实现楼层跳跃式的页面布局

    实现效果演示: 实现代码及注释: <!DOCTYPE html> <html> <head> <title>楼层跳跃式的页面布局</title&g ...