java gc机制新区域旧屋_Java 内存回收机制——GC机制-Go语言中文社区

一、Java GC 概念说明

Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代码,对内存泄露和溢出的问题,也不需要像C程序员那样战战兢兢。这是因为在Java虚拟机中,存在自动内存管理和垃圾清扫机制。概括地说,该机制对JVM(Java Virtual Machine)中的内存进行标记,并确定哪些内存需要回收,根据一定的回收策略,自动的回收内存,永不停息(Nerver Stop)的保证JVM中的内存空间,防止出现内存泄露和溢出问题。

Java GC机制主要完成3件事:确定哪些内存需要回收,确定什么时候需要执行GC,如何执行GC。下面我们将从4个方面学习Java GC机制,1,内存是如何分配的;2,如何保证内存不被错误回收(即:哪些内存需要回收);3,在什么情况下执行GC以及执行GC的方式;4,如何监控和优化GC机制。

二、Java内存区域划分

了解Java GC机制,必须先清楚在JVM中内存区域的划分。在Java运行时的数据区里,由JVM管理的内存区域分为下图几个模块:

837a88465abe5ae15882c22792251115.png

1. 程序计数器(Program Counter Register)

程序计数器是一个比较小的内存区域,用于指示当前线程所执行的字节码执行到了第几行,可以理解为是当前线程的行号指示器。字节码解释器在工作时,会通过改变这个计数器的值来取下一条语句指令。

每个程序计数器只用来记录一个线程的行号,所以它是线程私有(一个线程就有一个程序计数器)的。

如果程序执行的是一个Java方法,则计数器记录的是正在执行的虚拟机字节码指令地址;如果正在执行的是一个本地(native,由C语言编写完成)方法,则计数器的值为Undefined,由于程序计数器只是记录当前指令地址,所以不存在内存溢出的情况,因此,程序计数器也是所有JVM内存区域中唯一一个没有定义OutOfMemoryError的区域。

2. Java虚拟机栈(Java Virtual Machine Stacks)

一个线程的每个方法在执行的同时,都会创建一个栈帧(Statck Frame),栈帧中存储的有局部变量表、操作站、动态链接、方法出口等,当方法被调用时,栈帧在JVM栈中入栈,当方法执行完成时,栈帧出栈。

局部变量表中存储着方法的相关局部变量,包括各种基本数据类型,对象的引用,返回地址等。在局部变量表中,只有long和double类型会占用2个局部变量空间(Slot,对于32位机器,一个Slot就是32个bit),其它都是1个Slot。需要注意的是,局部变量表是在编译时就已经确定好的,方法运行所需要分配的空间在栈帧中是完全确定的,在方法的生命周期内都不会改变。

虚拟机栈中定义了两种异常,如果线程调用的栈深度大于虚拟机允许的最大深度,则抛出StatckOverFlowError(栈溢出);不过多数Java虚拟机都允许动态扩展虚拟机栈的大小(有少部分是固定长度的),所以线程可以一直申请栈,直到内存不足,此时,会抛出OutOfMemoryError(内存溢出)。

每个线程对应着一个虚拟机栈,因此虚拟机栈也是线程私有的。

3. 本地方法栈(Native Method Stacks)

本地方法栈在作用,运行机制,异常类型等方面都与虚拟机栈相同,唯一的区别是:虚拟机栈是执行Java方法的,而本地方法栈是用来执行native方法的,在很多虚拟机中(如Sun的JDK默认的HotSpot虚拟机),会将本地方法栈与虚拟机栈放在一起使用。

本地方法栈也是线程私有的。

4. 堆区(Heap) (新生代和旧生代)

堆区是理解Java GC机制最重要的区域,没有之一。在JVM所管理的内存中,堆区是最大的一块,堆区也是Java GC机制所管理的主要内存区域,堆区由所有线程共享,在虚拟机启动时创建。堆区的存在是为了存储对象实例,原则上讲,所有的对象都在堆区上分配内存(不过现代技术里,也不是这么绝对的,也有栈上直接分配的)。

一般的,根据Java虚拟机规范规定,堆内存需要在逻辑上是连续的(在物理上不需要),在实现时,可以是固定大小的,也可以是可扩展的,目前主流的虚拟机都是可扩展的。如果在执行垃圾回收之后,仍没有足够的内存分配,也不能再扩展,将会抛出OutOfMemoryError:Java heap space异常。

5. 方法区(Method Area)(永久代)

方法区是各个线程共享的区域,用于存储已经被虚拟机加载的类信息(即加载类时需要加载的信息,包括版本、field、方法、接口等信息)、final常量、静态变量、编译器即时编译的代码等。

方法区在物理上也不需要是连续的,可以选择固定大小或可扩展大小,并且方法区比堆还多了一个限制:可以选择是否执行垃圾收集。一般的,方法区上执行的垃圾收集是很少的。但这也不代表着在方法区上完全没有垃圾收集,其上的垃圾收集主要是针对常量池的内存回收和对已加载类的卸载。

在方法区上进行垃圾收集,条件苛刻而且相当困难,效果也不令人满意,所以一般不做太多考虑,可以留作以后进一步深入研究时使用。

在方法区上定义了OutOfMemoryError:PermGen space异常,在内存不足时抛出。

6. 新生代、旧生代、永久代

虚拟机中共划分为三个代:新生代、旧生代、永久代。年轻代和年老代的划分是对垃圾收集影响比较大的。

所有新生成的对象首先都是放在新生代的;旧生代中存放的都是一些生命周期较长的对象。永久代用于存放静态文件,如Java类、方法等。永久代对垃圾回收没有显著影响。

三、Java对象的访问方式

一个Java的引用访问涉及到3个内存区域:JVM栈,堆,方法区。

以最简单的本地变量引用:Object obj = new Object()为例:

Object obj表示一个本地引用,存储在JVM栈的本地变量表中,表示一个reference类型数据;

new Object()作为实例对象数据存储在堆中;

堆中还记录了Object类的类型信息(接口、方法、field、对象类型等)的地址,这些地址所执行的数据存储在方法区中;

在Java虚拟机规范中,对于通过reference类型引用访问具体对象的方式并未做规定,目前主流的实现方式主要有两种:

1. 通过句柄访问:

879a2d33ec1896339a59239b539ad0eb.png

通过句柄访问的实现方式中,JVM堆中会专门有一块区域用来作为句柄池,存储相关句柄所执行的实例数据地址(包括在堆中地址和在方法区中的地址)。这种实现方法由于用句柄表示地址,因此十分稳定。

2. 通过直接指针访问:

06c4944196863ac1e506b48d367a5e2d.png

通过直接指针访问的方式中,reference中存储的就是对象在堆中的实际地址,在堆中存储的对象信息中包含了在方法区中的相应类型数据。这种方法最大的优势是速度快,在HotSpot虚拟机中用的就是这种方式。

四、参考资料

1.《JAVA编程思想》第5章

2.《Java深度历险》Java垃圾回收机制与引用类型

3.《深入理解Java虚拟机:JVM高级特效与最佳实现》,第2-3章

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/528557.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java反射 虚拟机优化_面试官问我:Java反射是什么?我回答竟然不上来......

每天凌晨00点00分,第一时间与你相约每日英文We all have moments of desperation. But if we can face them head on, that’s when we find out just how strong we really are.我们都有绝望的时候,只有在勇敢面对时,我们才知道我们有多坚强。每日掏心话…

c java 开发效率高_Java 的开发效率究竟比 C++ 高在哪里?

如果选择C,那C 的难度与JAVA 比,那应该不在一个层次。因为 C 作者及委员会想给你带来足够的抽象能力,让你可以抽象这个世界;给你足够的自由与控制硬件的能力,及零开销的高性能。简单点说,C程序员如同神一般…

java矩阵类_151-矩阵类

[java]代码库import java.util.Scanner;import java.util.Arrays;public class Main {public static void main(String[] args) {Scanner scan new Scanner(System.in);int r scan.nextInt();int c scan.nextInt();System.out.println("row:"r" column:"…

刻画小狗状态java_JAVA面向接口编程

JAVA面向接口编程小狗在不同环境条件下可能呈现不同的状态,小狗通过调用 cry()方法体现自己的当前的状 态。要求用接口封装小狗的状态。具体要求如下。• 编写一个接口 DogState,该接口有一个名字为 void showState()的方法。• 编写 Dog 类,…

php 图片合成,PHP中多张图片合成一张图片例子

今天分享一段PHP中多张图片合成一张图片的代码实现,我们可以在图片合成,水印,九宫格等需求下使用到类似这样的图片合成效果,下面一起来看看例子吧。今天分享一段PHP中多张图片合成一张图片的代码实现,我们可以在图片合成&#xff…

php的cms是什么意思,phpcms是什么

phpcms是一款具备文章、下载、图片、分类信息、影视、商城、采集、财务等众多功能的强大、易用、可扩展的优秀网站管理软件;该软件采用模块化开发,支持多种分类方式,使其可方便实现个性化网站的设计、开发与维护。phpcms是一款具备文章、下载…

边缘检测滤波matlab,卷积滤波器与边缘检测

频率:对于声音,频率实际上是指声波振荡的速度高低频率高频图像是强度变化很大的图像。并且亮度级别从一个像素到下一个像素快速变化。低频图像可以是亮度相对均匀或变化非常慢的图像。这是一个例子中最容易看到的。大多数图像都有高频和低频成分。在上图…

php 读取 stl 文件,科学网—[转载]【源码】读取ASCII STL文件的STLReader - 刘春静的博文...

读取包含顶点和面的ASCII STL文件,并将其构造为矩阵“顶点”、“颜色”和“面”。之后,使用各小模块在Matlab上建立模型。Read ASCII STL file which contains vertexes and faces and structure it to matrixes "vertexes", "colors&quo…

dsm php,docker dsm是什么?

docker dsm是什么?docker dsm是:从DSM6.0开始如果装了docker的话可以看到下面的图:上图可以看到创建了一个新的DSM,名字为DDSM1,经试验功能和正式DSM一模一样。同时白裙一样可以QuickConnect。然后用Putty登录上去&…

php 5.6 文档,文件存储 | 进阶系列 | Laravel 5.6 中文文档

文件存储由 学院君 创建于3年前, 最后更新于 1年前版本号 #231608 views3 likes0 collects简介Laravel 基于 Frank de Jonge 开发的 PHP 包 Flysystem 提供了强大的文件系统抽象层。Laravel 集成 Flysystem 以便使用不同驱动简化对文件系统的操作,这些驱动包括本地文…

阐述oracle的体系结构,Oracle数据库逻辑体系结构详解

以前对Oracle数据库的了解大多数是集中在mysql,最近工作里面一直使用的是Oracle,虽然说在互联网行业mysql大行其道,但是一些传统行业或者是金融领域还是更加倾向于使用oracle,sqlserver这种大型数据库。为此还是有必要深入了解以下…

linux解锁文件.user.ini,Linux下解决网页服务器权限和.user.ini无法删除的问题

解决网页服务器权限问题在linux环境下搭建Nginx/apache网页服务器,在尝试访问页面时都会遇到这个问题,提示没有写入权限,或者必须访问网页服务器权限。这源自于linux对于权限的限制比较严格。所以网上无数的解决方法,无外乎一个提…

linux内核 lts长期演进,Linux Kernel 4.19 和 5.4 生命周期延长至 6 年

近日,Linux 内核开发及维护者 Greg Kroah-Hartman 宣布将 Linux 内核 4.19 和 5.4 版本的生命周期终止(EOL)支持从两年延长到六年,分别延长至 2024 和 2025 年。在这期间,它们能够继续向后移植 bug 并获得一些重要的安全修复程序。Linux 内核…

linux如何运行qt源码,Linux/Ubuntu下编译Qt4.8.2源码

本人所用的系统为Ubuntu 14,所下载的QT源码版本为4.8.2。以下是编译QT源码的基本步骤:2.解压代码输入指令: tar zxvf qt-everywhere-opensource-src-4.8.2.tar.gz,解压出QT源代码。3.执行./config生成makef…

linux启动过程中内核拷贝,轻松识破linux内核启动过程中的“”套路“”

内核启动流程相关的内容让很多热爱linux的小伙伴既爱又恨,因为这是了解linux系统基本构造的良好过程同时由于其本身复杂且底层,脑子中的脉络不是很清晰,本文就总结了一些优秀博文,以自己的理解来解构一下。本文的环境是CentOS 6.8…

linux wifi ip,Linux环境下使用WIFI模块:使用DHCP工具动态获得IP地址

使用DHCP工具动态获得IP地址实验版本及下载地址DHCP:dhcp-4.4.1.tar.gz链接: [https://www.isc.org/downloads/]编译安装DHCP配置编译选项解压完成后进入DHCP根文件目录,输入配置指令./configure --hostarm-linux ac_cv_file__dev_randomyes --with-rand…

linux创建a1的硬链接a2,Linux命令-重定向和软硬链接

echo功能说明:显示文字. 语 法:echo [-ne][字符串] 或 echo [–help][–version]参数:   -n 不要在最后自动换行重定向>是定向输出到文件,如果文件不存在,就创建文件;如果文件存在,就将其…

linux shell 博客,【博客侠】Linux Shell脚本系列:开始上手(1)

看标题大家应该知道,这是一个关于 Linux Shell 脚本的系列文章。通过本系列文章希望帮助 Linux 初学用户快速开始上手编写 Shell 脚本,能够利索的对脚本进行测试和使用。在接下来的首篇文章中,我们将介绍什么是 Shell,有哪些 Linu…

sql server linux性能,详细了解SQL Server 2008性能和性能优化

在SQL Server 2005或更早的版本中的中,表变量是不能作为存储过程的参数的。当多行数据到SQL Server需要发送多行数据到SQL Server ,开发者要么每次发送一列记录,或想出其他的变通方法,以满足需求。虽然在.net 2.0中提供了个SQLBul…

开发linux显卡驱动,显卡驱动开发DRM入门--Apple的学习笔记

由于之前的blog提及kmscube的源码我没有找到,所以只能在网上搜索了。DRM简介DRM是Linux目前主流的图形显示框架,同时DRM可以统一管理GPU和Display驱动,使得软件架构更为统一,方便管理和维护。而且drm是集成在linux kernel中的。DR…