Java虚拟机内存管理原理基础入门

Jdk:Java程序设计语言、Java虚拟机、Java API类库。

Jdk是用于支持Java程序开发的最小环境。

Jre:Java API类库中的Java SE API子集、Java虚拟机。

Jre是支持Java程序运行的标准环境。

Program Counter Register:较小的内存空间,可以看作当前线程所执行的字节码的行号指示器。是唯一一个Java虚拟机规范中没有规定OutOfMemoryError的区域。

VM Stack:生命周期和线程相同,它描述了Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。

两种异常:StackOverflowError、OutOfMemoryError

Native Method Stack:类似VM Stack,且Sun HotSpot直接合二为一!

Heap:最大的一块内存,虚拟机启动时创建,唯一目的就是存放对象实例的。

Method Area:存储已被虚拟机加载的类信息、常量、静态变量、即使编译器编译后的代码等数据。Java虚拟机规范称其为堆的逻辑部分,别名却叫Non-Heap(非堆),或永久代

Runtime Constant Pool:方法区的一部分

Direcrt Memory:不是虚拟机运行时数据区的一部分,也不是虚拟机规范定义的内存区域。

对象的创建—关键字new

内存划分方法:指针碰撞(堆内存规整,通过移动指针分配内存)、空闲列表(堆内存不规整,通过更新内存列表分配内存)。

TLAB(Thread Local Allocation Buffer):本地线程分配缓冲,对于所创建的线程都会分配一块独立的空间,避免内存分配冲突,提升内存分配效率。

对象的内存布局:对象头(Header)、实例数据(Instance Data)和对其填充(Padding)。

对象的访问定位:Java程序通过栈上的reference(引用)数据来操作堆上的具体对象。

  方式:句柄和直接指针(Sun HotSpot)。

OutOfMemoryError异常实战

工具:Eclipse Memory Analyzer

内存泄漏Memory Leak、内存溢出Memory Overflow

判断对象是否死亡—堆内存

1、引用计数算法:给对象添加一个引用计数器,每当有一个地方引用它是,计数器加1;当引用失效时,计数器减1;任何时刻计数器为0的对象就是不可能再被使用的。

2、可达性分析算法:通过“GC Roots”对象作为起始点向下搜索,当一个对象到GC Roots没有任何引用链相连,证明此对象是不可用的。

To be or not to be!

1、 使用上述算法判断对象是否使用;

2、 如果不再被使用,则标记并筛选;

    刷选是否有必要执行finalize()方法,如下情况不需要执行:

    l 对象没覆盖finalize()方法;

    l finalize()方法已经被虚拟机调用过;

3、 如果有必要执行,则把该对象放置在F-Queue队列中;

4、 由一个虚拟机自动建立、低优先级的Finalizer线程去执行它,即由虚拟机来触发执行;

5、 GC对队列中的对象会进行第二次标记,即给对象重新建立引用,就能移除回收集合;

注意:任何一个对象的finalize()方法都只会被系统调用一次!

方法区回收

主要两部分:废弃常量和无用的类

控制参数

-Xnoclassgc:关闭虚拟机对class的垃圾回收功能;

-verbose:class:监视有多少类被加载;

-XX:TraceClassLoading、-XX:TraceClassUnLoading:打印类被加载和卸载的过程信息;

注意:在大量使用反射、动态代理、CGLib等ByteCode框架、动态生成JSP以及OSGI这类频繁自定义ClassLoader的场景都需要虚拟机具备类卸载的功能,以保证永久代不会溢出!

垃圾收集算法

1、标记—清除算法:容易产生内存碎片

2、复制算法:堆被划分成两个不同的区域:新生代(Young) 主要是用来存放新生的对象、老年代(Old) 主要存放应用程序中生命周期长的内存对象。新生代 (Young)又被划分为三个区域:Eden、From Survivor、To Survivor。

默认的,新生代(Young)与老年代(Old)的比例的值为1:2

默认的,Edem : from : to = 8 : 1 : 1

3、标记—整理算法

4、分代收集算法

HotSpot算法实现GC

枚举根节点:逐个检查;(Stop The World,GC执行时必须停顿所有Java执行线程)

在OopMap协助下,HotSpot可以快速并准确地完成枚举。

安全点:只有在安全点才能停顿开始GC

安全区域:安全点的扩展,在安全区域可以停顿开始GC

垃圾收集器:内存回收的具体实现。

GC日志

GC常用参数

内存分配策略

1、对象优先在Eden分配:新生代GC(Minor GC)、老年代GC(Major GC/Full GC)

2、大对象直接进入老年代:

3、长期存活的对象将进入老年代:给每个对象定义一个年龄(Age)计数器。对象在Eden出生并经过第一次Minor GC后仍然存活,并且能被Survicor容纳的话,将被移动到Survivor空间,并对象年龄设为1。对象在Survivor中每“熬过”一次Minor GC,年龄就增加1,当年龄增加到一定程度(默认15),晋升到老年代中。

4、动态对象年龄判定:虚拟机并不是永远要求对象年龄到一定程度才能晋升老年代,如果在Survivor空间中相同年龄所有对象大小总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代。

5、空间分配担保:老年代的连续空间大于新生代对象总大小或者历次晋升的平均大小就会进行Minor GC,否则将进行Full GC。

工具

JDK1.5中,getAllStackTraces()用于获取虚拟机中所有线程的StackTraceElement对象。

HSDIS:JIT生成代码反汇编。

JConsole:Java监视与管理控制平台,基于JMX。

VisualVM:多合一故障处理工具

时间: 2024-10-06 12:13:49

Java虚拟机内存管理原理基础入门的相关文章

Java虚拟机内存管理机制

自动内存管理机制 Java虚拟机(JVM)在执行Java程序过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有的区域则是依赖用户线程的启动和结束而建立和销毁.根据<Java虚拟机规范 第2版>规定,运行时数据区包括: 1.程序计数器 一块较小的内存空间,不在Ram上,而是直接划分在CPU上的,程序员无法直接操作它.当前线程所执行的字节码的行号指示器,通过改变这个计数器的值来选取下一条需要执行的字节码指令.每条

关于java虚拟机内存管理的一些讲解

java数据类型: 1)原始类型:Primitive Types(原始值) 数值类型(Numeric Types) 整型类型(Integral Types),浮点类型(Floating-Point Types) 布尔类型(Boolean Types) returnAddress类型:表示一条字节码指令的操作码(Opcode).在所有的虚拟机支持的原始类型之中,只有 returnAddress 类型是不能直接 Java 语言的数据类型对应起来的. 2)引用类型:Reference Types(引用

(三)java虚拟机内存管理和线程独占区和线程共享区

一.内存管理 二.线程独占区之程序计数器(Program Counter Register) 程序计数器是一块较小的内存空间,它可以看做是当前线程所执行的字节码的行号指示器.在虚拟机的概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支.循环.跳转.异常处理.线程恢复等基础功能都需要依赖这个计数器来完成. 如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址:如果正在执行的是Native方法,这个计数器值则为空(Und

探秘Java虚拟机——内存管理与垃圾回收

详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt106 1.Java虚拟机运行时的数据区 2.常用的内存区域调节参数 -Xms:初始堆大小,默认为物理内存的1/64(<1GB):默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制 -Xmx:最大堆大小,默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小

探秘Java虚拟机——内存管理与垃圾回收(转)

本文主要是基于Sun JDK 1.6 Garbage Collector(作者:毕玄)的整理与总结,原文请读者在网上搜索. 1.Java虚拟机运行时的数据区 2.常用的内存区域调节参数 -Xms:初始堆大小,默认为物理内存的1/64(<1GB):默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制 -Xmx:最大堆大小,默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制

深入理解Java虚拟机—内存管理机制

前面说过了类的加载机制,里面讲到了类的初始化中时用到了一部分内存管理的知识,这里让我们来看下Java虚拟机是如何管理内存的. 先让我们来看张图 有些文章中对线程隔离区还称之为线程独占区,其实是一个意思了.下面让我们来详细介绍下这五部分: 运行时数据区 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域,这些区域都拥有自己的用途,并随着JVM进程的启动或者用户线程的启动和结束建立和销毁. 先让我们了解下进程和线程的区别: 进程是资源分配的最小单位,线程是程序执行的

java虚拟机内存管理

虚拟机运行时数据区 线程共享 java Heap java heamp是java虚拟机可配置管理的最大内存区:唯一的目的用于存储实例对象,所有线程共享: GC堆,回收技术主要采用分代收集算法:java Heap细分为:新生代.老生代:划分本身与存放内容无关:无论怎么划分,都是为了更好的分配和回收内存: 逻辑上连续,物理上未必连续: 利用-Xms.-Xmx进行配置,无法分配及扩展时,将会抛出OutOfMerroyError错误: method area 存储对象:虚拟机加载的类信息.常量.静态变量

深入理解java虚拟机---java虚拟机内存管理(六)

java虚拟机栈的理解 虚拟机栈就是我们所熟知的栈内存,栈内存属于线程独有的.而在栈内存中的局部变量表中存储的引用类型只是存储对象的内存地址.对象的创建在堆内存中,即对象在线程共享区中. 局部变量表: 局部变量表的内存空间在编译时期完成分配,用于存放编译期间可知的各种基本数据类型,引用类型以及returnAdress类型.就是我们所熟知的栈内存. 模拟栈内存溢出 当在一个线程中不停的死循环调用一个方法时,因为方法的执行会在帧分配固定内存的大小,所以不停调用方法(前一个方法未执行完成弹出栈),会在

java虚拟机——内存管理与垃圾回收机制

一  java内存区域与内存溢出异常(OOM) 1.运行时数据区域划分