文档章节

JVM内存管理的机制

Simon丶Ma
 Simon丶Ma
发布于 2016/04/14 14:31
字数 1551
阅读 4
收藏 0

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

1.JVM内存管理的机制

  内存空间划分为:Sun JDK在实现时遵照JVM规范,将内存空间划分为堆、JVM方法栈、方法区、本地方法栈、PC寄存器。

  • 堆: 堆用于存储对象实例及数组值,可以认为Java中所有通过new创建的对象的内存都在此分配,Heap中对象所占用的内存由GC进行回收,在32位操作系统上最大为2GB,在64位操作系统上则没有限制,其大小可通过-Xms和-Xmx来控制,-Xms为JVM启动时申请的最小Heap内存,默认为物理内存的1/64但小于1GB;-Xmx为JVM可申请的最大Heap内存,默认为物理内存的1/4但小于1GB,默认当空余堆内存小于40%时,JVM会增大Heap到-Xmx指定的大小,可通过-XX:MinHeapFreeRatio=来指定这个比例;当空余堆内存大于70%时,JVM会减小Heap的大小到-Xms指定的大小,可通过-XX:MaxHeapFreeRatio=来指定这个比例,对于运行系统而言,为避免在运行时频繁调整Heap 的大小,通常将-Xms和-Xmx的值设成一样。
  • JVM方法栈: 为线程私有,其在内存分配上非常高效。当方法运行完毕时,其对应的栈帧所占用的内存也会自动释放。当JVM方法栈空间不足时,会抛出StackOverflowError的错误,在Sun JDK中可以通过-Xss来指定其大小。
  • 方法区: 要加载的类的信息(名称、修饰符等)、类中的静态变量、类中定义为final类型的常量、类中的Field信息、类中的方法信息。方法区域也是全局共享的,在一定条件下它也会被GC,当方法区域要使用的内存超过其允许的大小时,会抛出OutOfMemory的错误信息。在Sun JDK中这块区域对应Permanet Generation,又称为持久代,默认最小值为16MB,最大值为64MB,可通过-XX:PermSize及-XX:MaxPermSize来指定最小值和最大值。
  • 本地方法栈: 用于支持native方法的执行,存储了每个native方法调用的状态。在Sun JDK的实现中,和JVM方法栈是同一个。
  • PC寄存器: 占用的可能为CPU寄存器或操作系统内存。

2.Java堆和栈的区别

  Java把内存划分成两种:一种是栈内存,一种是堆内存。

  在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。

  堆内存用来存放由new创建的对象和数组。在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或对象后,还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,在栈中的这个特殊的变量就变成了数组或者对象的引用变量,以后就可以在程序中使用栈内存中的引用变量来访问堆中的数组或者对象,引用变量相当于为数组或者对象起的一个别名,或者代号。

  引用变量是普通变量,定义时在栈中分配内存,引用变量在程序运行到作用域外释放。而数组&对象本身在堆中分配,即使程序运行到使用new产生数组和对象的语句所在地代码块之外,数组和对象本身占用的堆内存也不会被释放,数组和对象在没有引用变量指向它的时候,才变成垃圾,不能再被使用,但是仍然占着内存,在随后的一个不确定的时间被垃圾回收器释放掉。这个也是java比较占内存的主要原因。但是在写程序的时候,可以人为的控制。

3.Java内存泄露和内存溢出

  内存泄漏:分配出去的内存回收不了

  内存溢出:指系统内存不够用了

4.Java类加载机制

  JVM将类加载过程划分为三个步骤:装载、链接和初始化。

  1. 装载(Load):装载过程负责找到二进制字节码并加载至JVM中,JVM通过类的全限定名(com.bluedavy. HelloWorld)及类加载器(ClassLoaderA实例)完成类的加载;
  2. 链接(Link):链接过程负责对二进制字节码的格式进行校验、初始化装载类中的静态变量及解析类中调用的接口、类;
  3. 初始化(Initialize):执行类中的静态初始化代码、构造器代码及静态属性的初始化。

5.内存回收

  收集器:引用计数收集器、跟踪收集器

  • 引用计数收集器:对于Java这种面向对象的会形成复杂引用关系(如ObjectB和ObjectC互相引用)的语言而言,引用计数收集器不是非常适合,Sun JDK在实现GC时也未采用这种方式。
  • 跟踪收集器实现算法:复制(Copying)、标记-清除(Mark-Sweep)和标记-压缩(Mark-Compact)

  复制:当要回收的空间中存活对象较少时,复制算法会比较高效,其带来的成本是要增加一块空的内存空间及进行对象的移动。

  标记-清除:在空间中存活对象较多的情况下较为高效,但由于标记-清除采用的为直接回收不存活对象所占用的内存,因此会造成内存碎片。

  标记-压缩:在标记-清除的基础上还须进行对象的移动,成本相对更高,好处则是不产生内存碎片。

© 著作权归作者所有

Simon丶Ma
粉丝 4
博文 134
码字总数 299850
作品 0
深圳
程序员
私信 提问
在 JNI 编程中避免内存泄漏

此文转自 IBM developerWorks JNI 编程简介 JNI,Java Native Interface,是 native code 的编程接口。JNI 使 Java 代码程序可以与 native code 交互——在 Java 程序中调用 native code;在...

IBMdW
2011/04/26
1K
1
Android 之 内存管理

概述 在android的开发中,要时刻主要内存的分配和垃圾回收,因为系统为每一个dalvik虚拟机分配的内存是有限的,在google的G1中,分配的最大堆大小只有16M,后来的机器一般都为24M,实在是少的...

等待流星
2014/03/08
68
0
【JVM】 java内存区域与内存溢出异常

前言 此系列博客是读《深入理解java虚拟机》所做的笔记整理。 No1. JVM内存管理这堵墙? 对C和C++的开发人员来说,在内存管理领域,他们既拥有每一个对象的“所有权”,也担负着每一个对象生...

binggetong
2018/05/07
0
0
堆外内存及其在 RxCache 中的使用

RxCache RxCache 是一款支持 Java 和 Android 的 Local Cache 。目前,支持堆内存、堆外内存(off-heap memory)、磁盘缓存。 github地址:https://github.com/fengzhizi715/RxCache 堆外内存(...

fengzhizi715
01/13
0
0
好程序员Java教程分享之jvm篇

好程序员java教程分享之jvm篇,在前面的文章中,介绍了JVM内存模型分为:堆区、虚拟机栈、方法区、本地方法区和程序计数器,其中堆区是JVM中最大的一块内存区域,在Java中的所有对象实例都保...

好程序员IT
06/11
59
0

没有更多内容

加载失败,请刷新页面

加载更多

一篇文章教你轻松使用fastjson

前言 只有光头才能变强。 文本已收录至我的GitHub精选文章,欢迎Star:https://github.com/ZhongFuCheng3y/3y JSON相信大家对他也不陌生了,前后端交互中常常就以JSON来进行数据交换。而有的...

Java3y
34分钟前
4
1
分组功能(tapply,by,aggregate)和* apply系列

每当我想在R中做“ map” py任务时,我通常都会尝试在apply系列中使用一个函数。 但是,我从未完全理解它们之间的区别-{ sapply , lapply等}如何将函数应用于输入/分组输入,输出将是什么样...

javail
34分钟前
4
0
PHP环境搭建之单独安装

还在使用PHP集成环境吗?教你自定义搭建配置PHP开发环境,按照需求进行安装,安装的版本可以自己选择,灵活性更大。 目录: 1. 安装Apache 2. 安装PHP 3. 安装MySQL 4. 安装Composer 观看:h...

不冷的大叔
46分钟前
4
0
为什么JavaScript变量会以美元符号开头?

我经常看到JavaScript带有以美元符号开头的变量。 您何时/为什么选择以这种方式为变量添加前缀? (我不是在问您在jQuery和其他语言中看到的$('p.foo')语法,而是普通变量,例如$name和$orde...

技术盛宴
49分钟前
4
0
TCP 三次握手

https://my.oschina.net/u/4198159/blog/3141874

奋斗的小牛
58分钟前
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部