欢迎进入Java社区论坛,与200万技术人员互动交流 >>进入 Java 运行时如何使用本机内存 Java 运行时是一个操作系统进程,它会受到我在上一节中列出的硬件和操作系统局限性的限制。运行时环境提供的功能受一些未知的用户代码驱动,这使得无法预测在每种情形中

欢迎进入Java社区论坛,与200万技术人员互动交流 >>进入

Java 运行时如何使用本机内存

Java 运行时是一个操作系统进程,它会受到我在上一节中列出的硬件和操作系统局限性的限制。运行时环境提供的功能受一些未知的用户代码驱动,这使得无法预测在每种情形中运行时环境将需要何种资源。Java 应用程序在托管 Java 环境中执行的每个操作都会潜在地影响提供该环境的运行时的需求。本节描述 Java 应用程序为什么和如何使用本机内存。

Java 堆和垃圾收集

Java 堆是分配了对象的内存区域。大多数 Java SE 实现都拥有一个逻辑堆,但是一些专家级 Java 运行时拥有多个堆,比如实现 Java 实时规范(Real Time Specification for Java,RTSJ)的运行时。一个物理堆可被划分为多个逻辑扇区,具体取决于用于管理堆内存的垃圾收集(GC)算法。这些扇区通常实现为连续的本机内存块,这些内存块受 Java 内存管理器(包含垃圾收集器)控制。

堆的大小可以在 Java 命令行使用 -Xmx 和 -Xms 选项来控制(mx 表示堆的最大大小,ms 表示初始大小)。尽管逻辑堆(经常被使用的内存区域)可以根据堆上的对象数量和在 GC 上花费的时间而增大和缩小,但使用的本机内存大小保持不变,而且由 -Xmx 值(最大堆大小)指定。大部分 GC 算法依赖于被分配为连续的内存块的堆,因此不能在堆需要扩大时分配更多本机内存。所有堆内存必须预先保留。

保留本机内存与分配本机内存不同。当本机内存被保留时,无法使用物理内存或其他存储器作为备用内存。尽管保留地址空间块不会耗尽物理资源,但会阻止内存被用于其他用途。由保留从未使用的内存导致的泄漏与泄漏分配的内存一样严重。

当使用的堆区域缩小时,一些垃圾收集器会回收堆的一部分(释放堆的后备存储空间),从而减少使用的物理内存。

对于维护 Java 堆的内存管理系统,需要更多本机内存来维护它的状态。当进行垃圾收集时,必须分配数据结构来跟踪空闲存储空间和记录进度。这些数据结构的确切大小和性质因实现的不同而不同,但许多数据结构都与堆大小成正比。

即时 (JIT) 编译器

JIT 编译器在运行时编译 Java 字节码来优化本机可执行代码。这极大地提高了 Java 运行时的速度,并且支持 Java 应用程序以与本机代码相当的速度运行。

字节码编译使用本机内存(使用方式与 gcc 等静态编译器使用内存来运行一样),但 JIT 编译器的输入(字节码)和输出(可执行代码)必须也存储在本机内存中。包含多个经过 JIT 编译的方法的 Java 应用程序会使用比小型应用程序更多的本机内存。

类和类加载器

Java 应用程序由一些类组成,这些类定义对象结构和方法逻辑。Java 应用程序也使用 Java 运行时类库(比如 java.lang.String)中的类,也可以使用第三方库。这些类需要存储在内存中以备使用。

存储类的方式取决于具体实现。Sun JDK 使用永久生成(permanent generation,PermGen)堆区域。Java 5 的 IBM 实现会为每个类加载器分配本机内存块,并将类数据存储在其中。现代 Java 运行时拥有类共享等技术,这些技术可能需要将共享内存区域映射到地址空间。要理解这些分配机制如何影响您 Java 运行时的本机内存占用,您需要查阅该实现的技术文档。然而,一些普遍的事实会影响所有实现。

从最基本的层面来看,使用更多的类将需要使用更多内存。(这可能意味着您的本机内存使用量会增加,或者您必须明确地重新设置 PermGen 或共享类缓存等区域的大小,以装入所有类)。记住,不仅您的应用程序需要加载到内存中,框架、应用服务器、第三方库以及包含类的 Java 运行时也会按需加载并占用空间。

Java 运行时可以卸载类来回收空间,但是只有在非常严酷的条件下才会这样做。不能卸载单个类,而是卸载类加载器,随其加载的所有类都会被卸载。只有在以下情况下才能卸载类加载器:

Java 堆不包含对表示该类加载器的 java.lang.ClassLoader 对象的引用。

Java 堆不包含对表示类加载器加载的类的任何 java.lang.Class 对象的引用。

在 Java 堆上,该类加载器加载的任何类的所有对象都不再存活(被引用)。

需要注意的是,Java 运行时为所有 Java 应用程序创建的 3 个默认类加载器( bootstrap、extension 和 application )都不可能满足这些条件,因此,任何系统类(比如 java.lang.String)或通过应用程序类加载器加载的任何应用程序类都不能在运行时释放。

即使类加载器适合进行收集,运行时也只会将收集类加载器作为 GC 周期的一部分。一些实现只会在某些 GC 周期中卸载类加载器。

也可能在运行时生成类,而不用释放它。许多 JEE 应用程序使用 JavaServer Pages (JSP) 技术来生成 Web 页面。使用 JSP 会为执行的每个 .jsp 页面生成一个类,并且这些类会在加载它们的类加载器的整个生存期中一直存在 ―― 这个生存期通常是 Web 应用程序的生存期。

另一种生成类的常见方法是使用 Java 反射。反射的工作方式因 Java 实现的不同而不同,但 Sun 和 IBM 实现都使用了这种方法,我马上就会讲到。

当使用 java.lang.reflect API 时,Java 运行时必须将一个反射对象(比如 java.lang.reflect.Field)的方法连接到被反射到的对象或类。这可以通过使用 Java 本机接口(Java Native Interface,JNI)访问器来完成,这种方法需要的设置很少,但是速度缓慢。也可以在运行时为您想要反射到的每种对象类型动态构建一个类。后一种方法在设置上更慢,但运行速度更快,非常适合于经常反射到一个特定类的应用程序。

Java 运行时在最初几次反射到一个类时使用 JNI 方法,但当使用了若干次 JNI 方法之后,访问器会膨胀为字节码访问器,这涉及到构建类并通过新的类加载器进行加载。执行多次反射可能导致创建了许多访问器类和类加载器。保持对反射对象的引用会导致这些类一直存活,并继续占用空间。因为创建字节码访问器非常缓慢,所以 Java 运行时可以缓存这些访问器以备以后使用。一些应用程序和框架还会缓存反射对象,这进一步增加了它们的本机内存占用。

[1] [2] [3] [4] [5] [6] [7] [8] [9]

jvm在windows和linux,理解JVM如何使用Windows和Linux上的本机内存相关推荐

  1. 理解JVM如何使用Windows和Linux上的本机内存

    转至:http://www.chineselinuxuniversity.net/articles/23291.shtml 摘要:Java™ 堆耗尽并不是造成 java.lang.OutOfMemor ...

  2. 理解 JVM 如何使用 Windows 和 Linux 上的本机内存

    http://www.ibm.com/developerworks/cn/java/j-nativememory-linux/ Java 堆(每个 Java 对象在其中分配)是您在编写 Java 应用 ...

  3. 内存详解-理解 JVM 如何使用 Windows 和 Linux 上的本机内存

    内存详解 理解 JVM 如何使用 Windows 和 Linux 上的本机内存 Java™ 堆耗尽并不是造成 java.lang.OutOfMemoryError 的惟一原因.如果本机内存 耗尽,则会 ...

  4. JAVA 内存详解 (理解 JVM 如何使用 Windows 和 Linux 上的本机内存)

    级别: 中级 Andrew Hall , 软件工程师, IBM 2009 年 5 月 11 日 Java™ 堆耗尽并不是造成 java.lang.OutOfMemoryError 的惟一原因.如果本机 ...

  5. 内存详解mdash;mdash;理解 JVM 如何使用 AIX 上的本机内存

    理解 JVM 如何使用 AIX 上的本机内存 Java™ 堆耗尽并不是造成 java.lang.OutOfMemoryError 的惟一原因.如果本机内存 耗尽,则会发生普通调试技巧无法解决的 Out ...

  6. 深入理解JVM虚拟机6:深入理解JVM类加载机制

    深入理解JVM类加载机制 简述:虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制. 下面我们具体 ...

  7. 深入理解JVM - ZGC垃圾收集器

    如果下面的一些概念有些不清楚的可以先看深入理解JVM - 垃圾收集器和深入理解JVM - Shenandoah垃圾收集器. ZGC(Z Garbage Collector)是一款由Oracle公司研发 ...

  8. 关于JVM参数-XX:SurvivorRatio的理解

    关于JVM参数-XX:SurvivorRatio的理解 JVM参数中有一个比较重要的参数SurvivorRatio,它定义了新生代中Eden区域和Survivor区域(From幸存区或To幸存区)的比 ...

  9. 【JVM】LXF_深入理解JVM专题(1-4)

    文章目录 前言 深入理解JVM虚拟机开篇:JVM介绍与知识脉络梳理 深入理解JVM虚拟机1:JVM内存模型 与 永久代的消失 深入理解JVM虚拟机2:JVM垃圾回收基本原理和算法 1. 各种GC的触发 ...

最新文章

  1. jQuery如果选中复选框
  2. Atitit.论垃圾文件的识别与清理 文档类型垃圾文件 与api概要设计pa6.doc
  3. iOS 数据解析之使用TFHpple解析html
  4. flex4 SuperTabNavigator 添加关闭图片
  5. 单链表反转(递归和非递归)
  6. 如何用python做俄罗斯方块_你的童年有俄罗斯方块吗?教你用 Python 实现俄罗斯方块!...
  7. vfp mysql教程_VFP基础教程 5.5 编辑框控件(editbox)
  8. 《Unix编程艺术》pdf
  9. c语言程序的函数组成包括两个部分,c语言函数由哪两部分组成
  10. 极域电子教室师生端连接不上怎么解决
  11. 计算机通信网络(二)路由基本概念及静态路由配置
  12. 深刻对比一下阿里云服务器和腾讯云服务器的优劣和区别
  13. 迪文串口屏幕通信问题
  14. 时序数据预测:Holt-Winters
  15. tr闭包_蓝色的梦 的动态 - SegmentFault 思否
  16. 手机玩exe游戏的模拟器_安卓游戏模拟器App | 手机玩红警手机玩暗黑破坏神手机玩魔兽手机玩星际手机玩……...
  17. 计算机进去bios方式,电脑进入BIOS的两种实用方法
  18. Rocksdb prefix Bloomfilter
  19. mysql sql 取年份_mysql – 从时间戳sql中获取年份
  20. java 使用jacob实现word转pdf

热门文章

  1. 11-Qt6 QByteArray字节数组类
  2. Qt Creator linux下使用SVN
  3. 带参函数_更好的理解Python第五弹函数预处理与指针
  4. html5的交互式微课,浅谈交互式微课的几个特征
  5. java用不用stream_Java parallelStream不使用预期的线程数
  6. linux5.8不能上网,Ubuntu 8.04不能上网的问题的解决方法
  7. pacemaker集群管理相关命令
  8. mysql保存中文异常Incorrect string value: '\xE4\xBD\xA0\xE5\xA5\xBD' for column'
  9. python用代码表示5与2的整除_Python教程5:Python 2.x和Python 3.x的区别有哪些?
  10. python ip动态代理_Scrapy 配置动态代理IP的实现