java虚拟内存

合集下载

java 虚拟机规范

java 虚拟机规范

java 虚拟机规范Java虚拟机规范(Java Virtual Machine Specification)是由Java语言设计者为了保证Java程序在任何平台上都能够运行,而定义的虚拟机的行为规范。

本文将详细介绍Java虚拟机规范,内容约1000字。

Java虚拟机规范定义了Java虚拟机(JVM)的结构、指令集、运行时数据区域、内存管理、异常处理、线程和同步等方面的规范。

通过遵循这些规范,开发者可以编写出具有良好可移植性和跨平台性的Java程序。

首先,Java虚拟机规范定义了JVM的结构。

JVM由类加载器、运行时数据区域、执行引擎和本地方法接口等组成。

类加载器负责加载类文件,并进行验证、解析和初始化。

运行时数据区域则包括了方法区、堆、虚拟机栈、本地方法栈和程序计数器等。

执行引擎根据操作码执行相应的指令,并对操作数栈和局部变量表进行操作。

本地方法接口则是Java虚拟机与本地操作系统的接口。

其次,Java虚拟机规范定义了JVM的指令集。

指令集包括了加载、存储、算术运算、类型转换、比较和控制流等各种指令。

每个指令都对应了Java虚拟机的一种行为,可以通过指定操作数来执行相应的操作。

Java虚拟机规范还定义了JVM的运行时数据区域。

运行时数据区域包括了方法区、堆、虚拟机栈、本地方法栈和程序计数器。

方法区用于存储类的结构信息、常量池、静态变量和方法等。

堆用于存储对象实例和数组。

虚拟机栈用于存储方法调用的局部变量表、操作数栈、动态链接和方法返回值等。

本地方法栈用于支持本地方法的调用。

程序计数器则用于记录当前线程执行的字节码指令地址。

此外,Java虚拟机规范还定义了JVM的内存管理、异常处理、线程和同步等方面的规范。

内存管理包括了垃圾收集和内存分配等。

异常处理定义了异常的分类、异常的处理流程和异常的处理方式。

线程规范包括了线程的创建、启动、执行和销毁等。

同步规范则定义了同步的机制和语义。

总结起来,Java虚拟机规范定义了Java虚拟机的行为规范,包括了JVM的结构、指令集、运行时数据区域、内存管理、异常处理、线程和同步等方面的规范。

JVM内存设置方法

JVM内存设置方法

JVM内存设置方法JVM(Java虚拟机)是Java程序的运行环境,它负责执行Java字节码,并管理程序的内存。

在运行Java程序时,合理地设置JVM的内存大小是非常重要的,它会影响程序的性能和稳定性。

下面是一些关于JVM内存设置的方法和注意事项:1. 初始堆大小(-Xms)和最大堆大小(-Xmx):初始堆大小指定了JVM初始时分配的堆内存大小,最大堆大小则指定了堆内存的上限。

可以通过在启动命令中加上-Xms和-Xmx参数来设置堆内存大小,例如:```java -Xms256m -Xmx512m MyApp```这样就设置了初始堆大小为256MB,最大堆大小为512MB。

2.堆内存的大小选择:堆内存的大小应根据应用程序的需求和服务器硬件条件来选择。

如果堆内存过小,可能会导致OutOfMemoryError;如果堆内存过大,可能会导致频繁的垃圾回收,影响程序的性能。

可以通过监控JVM的堆使用情况来判断是否需要调整堆内存的大小。

可以使用JVM自带的JVisualVM工具或第三方的工具如G1GC日志分析工具进行监控。

3.堆内存的分代设置:堆内存分为新生代(Young Generation)、老年代(Old Generation)和永久代(Permanent Generation,JDK8及之前的版本)/元空间(Metaspace,JDK8及之后的版本)。

新生代用于存储新创建的对象,老年代用于存储长时间存活的对象,永久代/元空间用于存储类和方法等信息。

可以通过设置堆内存的分代比例来调整堆内存的大小,例如:```-XX:NewRatio=2```这样就将堆内存的新生代和老年代的大小比例设置为1:2、可以根据应用程序的特点和需求进行调整。

4.非堆内存的设置:非堆内存包括方法区、直接内存等。

可以通过设置参数来调整非堆内存的大小,例如:```-XX:MaxMetaspaceSize=256m```这样就设置了元空间的最大大小为256MB。

java内存使用情况的命令

java内存使用情况的命令

java内存使用情况的命令Java是一种面向对象的编程语言,它在开发应用程序时需要使用内存来存储数据和执行代码。

因此,了解Java的内存使用情况对于开发人员来说是非常重要的。

Java虚拟机(JVM)负责管理Java应用程序的内存,它使用垃圾回收机制来自动管理内存的分配和释放。

JVM的内存可以分为以下几个部分:1. 堆(Heap):堆是Java程序运行时动态分配的内存区域,用于存储对象实例。

堆的大小可以通过命令行参数-Xmx和-Xms来设置。

-Xms表示JVM启动时初始分配的堆内存大小,-Xmx表示堆能够达到的最大内存大小。

2. 方法区(Method Area):方法区用于存储已加载的类信息、常量、静态变量等数据。

方法区的大小可以通过命令行参数-XX:PermSize和-XX:MaxPermSize来设置。

-XX:PermSize表示JVM启动时初始分配的方法区大小,-XX:MaxPermSize表示方法区能够达到的最大大小。

3. 栈(Stack):栈用于存储Java方法中的局部变量以及方法调用时的状态信息。

每个Java线程都有一个独立的栈,栈的大小是固定的,并且在线程创建时被分配。

栈的大小可以通过命令行参数-Xss来设置。

除了上述部分,JVM还会使用一些额外的内存空间,如直接内存(DirectMemory)和本地方法栈(Native Method Stack),用于存储一些特殊的数据和执行本地方法。

了解Java的内存使用情况对于定位内存泄漏和优化程序性能非常有帮助。

下面是几个常用的命令,可以用于监控和调整Java程序的内存使用情况:1. jps:该命令用于列出当前运行的Java进程,以及对应的进程ID。

2. jstat:该命令用于监控Java虚拟机的各种运行状态,包括堆的使用情况、类加载数量、垃圾回收情况等。

常用的参数包括-jstat -gcutil <pid>和-jstat-gccapacity <pid>。

《Java性能调优指南》

《Java性能调优指南》

《Java性能调优指南》随着互联网的飞速发展,Java作为一种重要的编程语言,被越来越广泛地应用于各个领域。

但是,Java程序的性能问题也随之出现。

如何调优Java 程序的性能,成为了每个开发人员需要解决的难题。

本文将为大家介绍Java性能调优的指南。

一、JVM参数设置JVM(Java虚拟机)参数设置是Java性能调优的关键。

JVM有众多的参数,不同的参数设置会对Java程序的性能产生不同的影响。

常用的JVM参数设置包括以下几个方面:1. 内存设置内存是Java程序的一大瓶颈。

如果内存设置不合理,会导致Java程序频繁地进行垃圾回收,造成程序的延迟和不稳定。

在设置内存参数时需要注意以下几点:- -Xmx: 最大堆内存,设置合理的最大堆内存大小可以减少JVM的垃圾回收次数,提高程序性能。

- -Xms: 初始堆内存,设置合理的初始堆内存大小可以加快程序启动时间,提高程序性能。

- -XX:NewRatio: 新生代与老年代的比例,如果设置得当,可以减少垃圾回收的次数。

通常新生代的大小为总堆容量的1\/3或1\/4,老年代的大小为总堆容量的2\/3或3\/4。

2. 垃圾回收设置垃圾回收是Java程序中必不可少的一部分。

合理的垃圾回收参数设置可以提高程序性能。

常用的垃圾回收参数设置包括以下几点:- -XX:+UseParallelGC: 使用并行GC,适用于多核CPU。

- -XX:+UseConcMarkSweepGC: 使用CMS GC,适用于大型Web应用程序。

- -XX:+UseG1GC: 使用G1 GC,适用于大内存应用程序。

3. JIT设置JIT(即时编译器)是Java程序中非常重要的一部分。

合理的JIT参数设置可以提高程序的性能。

常用的JIT参数设置包括以下几点:- -XX:+TieredCompilation: 启用分层编译,可以提高程序启动时间和性能。

- -XX:CompileThreshold: JIT编译阈值,设置JIT编译的最小方法调用次数,可以提高程序性能。

java jvm参数

java jvm参数

java jvm参数
Java 虚拟机(JVM)参数是用来配置 Java 虚拟机运行时环境的一组参数。

它们可以用来控制 JVM 的内存使用情况,调整垃圾回收器的行为,debugging,启用额外的错误检查等等。

1、-Xms:设置JVM初始内存大小,默认是物理内存的1/64。

2、-Xmx:设置JVM最大可用内存大小,一般设置为物理内存的1/4或1/8。

3、-Xss:设置JVM单个线程栈内存大小,通常为
512K到1024K之间。

4、-XX:+UseSerialGC:开启串行垃圾收集器,使用单线程工作,可以提高性能,但是应用程序也会受到影响。

5、-XX:+PrintGCDetails:打印出垃圾回收的详细信息,方便进行性能调优。

6、-XX:MaxPermSize:设置持久代的最大内存大小,默认情况下,持久代的内存大小取决于MaxHeapSize的值。

7、-XX:NewRatio:设置新生代和老年代的比例,默认情况下是2,即新生代是老年代的一半。

8、-XX:SurvivorRatio:设置Eden区和Survivor区的比例,默认情况下是8,即Eden区是Survivor区的八分之一。

深入理解java虚拟机

深入理解java虚拟机

深入理解java虚拟机(一)虚拟机内存划分Java虚拟机在执行Java程序时,会把它管理的内存划分为若干个不同的数据区。

这些区域有不同的特性,起不同的作用。

它们有各自的创建时间,销毁时间。

有的区域随着进程的启动而创建,随着进程结束而销毁,有的则始终贯穿虚拟机整个生命周期。

Java虚拟机运行时内存区域主要分为七部分,分别是:程序计数器,Java虚拟机栈,本地方法栈,方法区,Java堆,运行时常量池,直接内存。

如上图所示(图片来源于网络):蓝色区域包裹的部分为运行时几个数据区域:白色的部分为线程私有的,既随着线程的启动而创建。

每个线程都拥有各自的一份内存区域。

它们是:JAVA栈(JAVA STACK),本地方法栈(NATIVE METHOD STACK),和程序计数器(PROGRAM COUNTER REGISTER)。

黄色部分是线程共享的,所有的线程共享该区域的内容。

他们是:方法区(METHOD AREA),堆(HEAP)。

我们分别来介绍这些区域。

(1)程序计数器(program counter register)学过计算机组成原理的都知道计算机处理器中的程序计数器。

当处理器执行一条指令时,首先需要根据PC中存放的指令地址,将指令由内存取到指令寄存器中,此过程称为“取指令”。

与此同时,PC中的地址或自动加1或由转移指针给出下一条指令的地址。

此后经过分析指令,执行指令。

完成第一条指令的执行,而后根据PC取出第二条指令的地址,如此循环,执行每一条指令。

处理器的程序计数器是指寄存器,而java程序计数器是指一小块内存空间。

java代码编译字节码之后,虚拟机会一行一行的解释字节码,并翻印成本地代码。

这个程序计数器盛放的就是当前线程所执行字节码的行号的指示器。

在虚拟机概念模型中,字节码解释器工作室就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支,循环,跳转,异常处理等都依赖于它。

Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式实现的,因此为了线程切换后还能恢复执行位置,每条线程都需要一个独立的程序计数器。

java jvm 参数 -Xms -Xmx -Xmn -Xss 调优总结

java jvm 参数 -Xms -Xmx -Xmn -Xss 调优总结

java jvm 参数 -Xms -Xmx -Xmn -Xss 调优总结常见配置举例堆大小设置JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制;系统的可用虚拟内存限制;系统的可用物理内存限制.32位系统下,一般限制在1.5G~2G;64为操作系统对内存无限制.我在Windows Server 2003 系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m.典型设置:java -Xmx3550m -Xms3550m -Xmn2g -Xss128k-Xmx3550m:设置JVM最大可用内存为3550M.-Xms3550m:设置JVM促使内存为3550m.此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存.-Xmn2g:设置年轻代大小为2G.整个堆大小=年轻代大小 + 年老代大小 + 持久代大小.持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小.此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8.-Xss128k: 设置每个线程的堆栈大小.JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K.更具应用的线程所需内存大小进行调整.在相同物理内存下,减小这个值能生成更多的线程.但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右.java -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0-XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代).设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5-XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的大小比值.设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6-XX:MaxPermSize=16m:设置持久代大小为16m.-XX:MaxTenuringThreshold=0: 设置垃圾最大年龄.如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代. 对于年老代比较多的应用,可以提高效率.如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论. 回收器选择JVM给了三种选择:串行收集器,并行收集器,并发收集器,但是串行收集器只适用于小数据量的情况,所以这里的选择主要针对并行收集器和并发收集器.默认情况下,JDK5.0以前都是使用串行收集器,如果想使用其他收集器需要在启动时加入相应参数.JDK5.0以后,JVM会根据当前系统配置进行判断.吞吐量优先的并行收集器如上文所述,并行收集器主要以到达一定的吞吐量为目标,适用于科学技术和后台处理等.典型配置:java -Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:+UseParallelGC-XX:ParallelGCThreads=20-XX:+UseParallelGC:选择垃圾收集器为并行收集器.此配置仅对年轻代有效.即上述配置下,年轻代使用并发收集,而年老代仍旧使用串行收集.-XX:ParallelGCThreads=20:配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收.此值最好配置与处理器数目相等.java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC-XX:ParallelGCThreads=20 -XX:+UseParallelOldGC-XX:+UseParallelOldGC:配置年老代垃圾收集方式为并行收集.JDK6.0支持对年老代并行收集.java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC-XX:MaxGCPauseMillis=100-XX:MaxGCPauseMillis=100:设置每次年轻代垃圾回收的最长时间,如果无法满足此时间,JVM会自动调整年轻代大小,以满足此值.java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC-XX:MaxGCPauseMillis=100 -XX:+UseAdaptiveSizePolicy-XX:+UseAdaptiveSizePolicy:设置此选项后,并行收集器会自动选择年轻代区大小和相应的Survivor区比例,以达到目标系统规定的最低相应时间或者收集频率等,此值建议使用并行收集器时,一直打开.响应时间优先的并发收集器如上文所述,并发收集器主要是保证系统的响应时间,减少垃圾收集时的停顿时间.适用于应用服务器,电信领域等.典型配置:java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:ParallelGCThreads=20-XX:+UseConcMarkSweepGC -XX:+UseParNewGC-XX:+UseConcMarkSweepGC:设置年老代为并发收集.测试中配置这个以后,-XX:NewRatio=4的配置失效了,原因不明.所以,此时年轻代大小最好用-Xmn 设置.-XX:+UseParNewGC:设置年轻代为并行收集.可与CMS收集同时使用.JDK5.0以上,JVM会根据系统配置自行设置,所以无需再设置此值.java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseConcMarkSweepGC-XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction:由于并发收集器不对内存空间进行压缩,整理,所以运行一段时间以后会产生"碎片",使得运行效率降低.此值设置运行多少次GC以后对内存空间进行压缩,整理.-XX:+UseCMSCompactAtFullCollection:打开对年老代的压缩.可能会影响性能,但是可以消除碎片辅助信息JVM提供了大量命令行参数,打印信息,供调试使用.主要有以下一些:-XX:+PrintGC输出形式:[GC 118250K->113543K(130112K), 0.0094143 secs][Full GC 121376K->10414K(130112K), 0.0650971 secs]-XX:+PrintGCDetails输出形式:[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs]118250K->113543K(130112K), 0.0124633 secs][GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured:112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs]-XX:+PrintGCTimeStamps -XX:+PrintGC:PrintGCTimeStamps可与上面两个混合使用输出形式:11.851: [GC 98328K->93620K(130112K), 0.0082960 secs]-XX:+PrintGCApplicationConcurrentTime:打印每次垃圾回收前,程序未中断的执行时间.可与上面混合使用输出形式:Application time: 0.5291524 seconds-XX:+PrintGCApplicationStoppedTime:打印垃圾回收期间程序暂停的时间.可与上面混合使用输出形式:Total time for which application threads were stopped: 0.0468229 seconds-XX:PrintHeapAtGC:打印GC前后的详细堆栈信息输出形式:34.702: [GC {Heap before gc invocations=7:def new generation total 55296K, used 52568K [0x1ebd0000, 0x227d0000, 0x227d0000)eden space 49152K, 99% used [0x1ebd0000, 0x21bce430, 0x21bd0000)from space 6144K, 55% used [0x221d0000, 0x22527e10, 0x227d0000)to space 6144K, 0% used [0x21bd0000, 0x21bd0000, 0x221d0000)tenured generation total 69632K, used 2696K [0x227d0000, 0x26bd0000,0x26bd0000)the space 69632K, 3% used [0x227d0000, 0x22a720f8, 0x22a72200, 0x26bd0000) compacting perm gen total 8192K, used 2898K [0x26bd0000, 0x273d0000,0x2abd0000)the space 8192K, 35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00, 0x273d0000) ro space 8192K, 66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00, 0x2b3d0000) rw space 12288K, 46% used [0x2b3d0000, 0x2b972060, 0x2b972200, 0x2bfd0000) 34.735: [DefNew: 52568K->3433K(55296K), 0.0072126 secs]55264K->6615K(124928K)Heap after gc invocations=8:def new generation total 55296K, used 3433K [0x1ebd0000, 0x227d0000,0x227d0000)eden space 49152K, 0% used [0x1ebd0000, 0x1ebd0000, 0x21bd0000)from space 6144K, 55% used [0x21bd0000, 0x21f2a5e8, 0x221d0000)to space 6144K, 0% used [0x221d0000, 0x221d0000, 0x227d0000)tenured generation total 69632K, used 3182K [0x227d0000, 0x26bd0000,0x26bd0000)the space 69632K, 4% used [0x227d0000, 0x22aeb958, 0x22aeba00, 0x26bd0000) compacting perm gen total 8192K, used 2898K [0x26bd0000, 0x273d0000,0x2abd0000)the space 8192K, 35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00, 0x273d0000) ro space 8192K, 66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00, 0x2b3d0000) rw space 12288K, 46% used [0x2b3d0000, 0x2b972060, 0x2b972200, 0x2bfd0000) }, 0.0757599 secs]-Xloggc:filename:与上面几个配合使用,把相关日志信息记录到文件以便分析. 常见配置汇总堆设置-Xms:初始堆大小-Xmx:最大堆大小-XX:NewSize=n:设置年轻代大小-XX:NewRatio=n:设置年轻代和年老代的比值.如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4-XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值.注意Survivor区有两个.如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5-XX:MaxPermSize=n:设置持久代大小收集器设置-XX:+UseSerialGC:设置串行收集器-XX:+UseParallelGC:设置并行收集器-XX:+UseParalledlOldGC:设置并行年老代收集器-XX:+UseConcMarkSweepGC:设置并发收集器垃圾回收统计信息-XX:+PrintGC-XX:+PrintGCDetails-XX:+PrintGCTimeStamps-Xloggc:filename并行收集器设置-XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数.并行收集线程数.-XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间-XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比.公式为1/(1+n)并发收集器设置-XX:+CMSIncrementalMode:设置为增量模式.适用于单CPU情况.-XX:ParallelGCThreads=n:设置并发收集器年轻代收集方式为并行收集时,使用的CPU数.并行收集线程数.调优总结年轻代大小选择响应时间优先的应用:尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选择).在此种情况下,年轻代收集发生的频率也是最小的.同时,减少到达年老代的对象.吞吐量优先的应用:尽可能的设置大,可能到达Gbit的程度.因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用.年老代大小选择响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数.如果堆设置小了,可以会造成内存碎片,高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间.最优化的方案,一般需要参考以下数据获得:并发垃圾收集信息持久代并发收集次数传统GC信息花在年轻代和年老代回收上的时间比例减少年轻代和年老代花费的时间,一般会提高应用的效率吞吐量优先的应用:一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代.原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象.较小堆引起的碎片问题因为年老代的并发收集器使用标记,清除算法,所以不会对堆进行压缩.当收集器回收时,他会把相邻的空间进行合并,这样可以分配给较大的对象.但是,当堆空间较小时,运行一段时间以后,就会出现"碎片",如果并发收集器找不到足够的空间,那么并发收集器将会停止,然后使用传统的标记,清除方式进行回收.如果出现"碎片",可能需要进行如下配置:-XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩.-XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩在同一个工程下,有两个类,这两个类中只有很少的变动,而最关健的FOR却没有一点变动,可是当我分别运行这两个程序的时候却出现一个很严重的问题,一个程序循环的快,一个循环的慢.这到底是怎么回事呢~???苦苦寻找了半天也没有想到是为什么,因为程序改变的部分根不影响我循环的速度,可是结果却是有很大的差别,一个大约是在一分钟这内就可以循环完,可是另一个却需要六七分钟,这根本就不是一个数据理级的麻.两个完全一样的循环,从代码上根本上是看不出有什么问题.不得以求助同事吧,可是同事看了也感觉很诡异,两个人在那订着代码又看了一个多小时,最后同事让我来个干净点的,关机重启.我到也听话,就顺着同事的意思去了,可就在关机的这个时候他突然说是不是内存的问题,我也空然想到了,还真的有可能是内存的问题,因为快的那个在我之前运行程序之前可给过 1G的内存啊,而后来的这个我好像是没有设过内存啊,机器起来了,有了这个想法进去看看吧,结果正中要害,果真是慢的那个没有开内存,程序运行时只不过是 JVM默认开的内存.我初步分析是因为内存太小,而我的程序所用内存又正好卡在JVM所开内存边上,不至于溢出.当程序运行时就得花费大部分时间去调用 GC去,这样就导致了为什么相同的循环出现两种不同的效率~!顺便把内存使用情况的方法也贴出来:public static String getMemUsage() {long free = ng.Runtime.getRuntime().freeMemory();long total = ng.Runtime.getRuntime().totalMemory(); StringBuffer buf = new StringBuffer();buf.append("[Mem: used ").append((total-free)>>20).append("M free ").append(free>>20).append("M total ").append(total>>20).append("M]");return buf.toString();}google一下,大概就说JVM是这样来操作内存:堆(Heap)和非堆(Non-heap)内存按照官方的说法:"Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配.堆是在 Java 虚拟机启动时创建的.""在JVM中堆之外的内存称为非堆内存(Non-heap memory)".可以看出JVM主要管理两种类型的内存:堆和非堆.简单来说堆就是Java代码可及的内存,是留给开发人员使用的;非堆就是JVM留给自己用的,所以方法区,JVM内部处理或优化所需的内存(如JIT编译后的代码缓存),每个类结构(如运行时常数池,字段和方法数据)以及方法和构造方法的代码都在非堆内存中.堆内存分配JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4.默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时, JVM会减少堆直到-Xms的最小限制.因此服务器一般设置-Xms,-Xmx相等以避免在每次GC 后调整堆的大小.非堆内存分配JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4.JVM内存限制(最大值)首先JVM内存首先受限于实际的最大物理内存,假设物理内存无限大的话,JVM 内存的最大值跟操作系统有很大的关系.简单的说就32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制,这个限制一般是 2GB-3GB(一般来说Windows系统下为1.5G-2G,Linux系统下为2G-3G),而64bit以上的处理器就不会有限制了JVM内存的调优1. Heap设定与垃圾回收Java Heap分为3个区,Young,Old和Permanent.Young 保存刚实例化的对象.当该区被填满时,GC会将对象移到Old 区.Permanent区则负责保存反射对象,本文不讨论该区.JVM的Heap分配可以使用-X参数设定, -Xms初始Heap大小-Xmxjava heap最大值-Xmnyoung generation的heap大小JVM有2个GC线程.第一个线程负责回收Heap的Young区.第二个线程在Heap 不足时,遍历Heap,将Young 区升级为Older区.Older区的大小等于-Xmx减去-Xmn,不能将-Xms的值设的过大,因为第二个线程被迫运行会降低JVM的性能. 为什么一些程序频繁发生GC?有如下原因:l 程序内调用了System.gc()或Runtime.gc().l 一些中间件软件调用自己的GC方法,此时需要设置参数禁止这些GC.l Java的Heap太小,一般默认的Heap值都很小.l 频繁实例化对象,Release对象.此时尽量保存并重用对象,例如使用StringBuffer()和String().如果你发现每次GC后,Heap的剩余空间会是总空间的50%,这表示你的Heap处于健康状态.许多Server端的Java程序每次GC后最好能有65%的剩余空间.经验之谈:1.Server端JVM最好将-Xms和-Xmx设为相同值.为了优化GC,最好让-Xmn值约等于-Xmx的1/3[2].2.一个GUI程序最好是每10到20秒间运行一次GC,每次在半秒之内完成[2]. 注意:1.增加Heap的大小虽然会降低GC的频率,但也增加了每次GC的时间.并且GC 运行时,所有的用户线程将暂停,也就是GC期间,Java应用程序不做任何工作. 2.Heap大小并不决定进程的内存使用量.进程的内存使用量要大于-Xmx定义的值,因为Java为其他任务分配内存,例如每个线程的Stack等.2.Stack的设定每个线程都有他自己的Stack.-Xss每个线程的Stack大小Stack的大小限制着线程的数量.如果Stack过大就好导致内存溢漏.-Xss参数决定Stack大小,例如-Xss1024K.如果Stack太小,也会导致Stack溢漏.3.硬件环境硬件环境也影响GC的效率,例如机器的种类,内存,swap空间,和CPU的数量. 如果你的程序需要频繁创建很多transient对象,会导致JVM频繁GC.这种情况你可以增加机器的内存,来减少Swap空间的使用[2].4.4种GC第一种为单线程GC,也是默认的GC.,该GC适用于单CPU机器.第二种为Throughput GC,是多线程的GC,适用于多CPU,使用大量线程的程序.第二种GC与第一种GC相似,不同在于GC在收集Young区是多线程的,但在Old区和第一种一样,仍然采用单线程.-XX:+UseParallelGC参数启动该GC.第三种为Concurrent Low Pause GC,类似于第一种,适用于多CPU,并要求缩短因GC造成程序停滞的时间.这种GC可以在Old区的回收同时,运行应用程序.-XX:+UseConcMarkSweepGC参数启动该GC.第四种为Incremental Low Pause GC,适用于要求缩短因GC造成程序停滞的时间.这种GC可以在Young区回收的同时,回收一部分Old区对象.-Xincgc参数启动该GC.。

虚拟内存的设置

虚拟内存的设置

虚拟内存的设置引言:在计算机系统中,虚拟内存是一种用于管理计算机内存的技术。

它将硬盘上的一部分空间用作内存的扩展,允许计算机运行更大的程序或处理更多的数据。

而虚拟内存的设置在计算机性能和系统稳定性方面起着至关重要的作用。

本文将探讨虚拟内存的设置原理、影响以及优化方法。

一、虚拟内存的设置原理虚拟内存是基于分页机制实现的。

操作系统将物理内存划分为固定大小的单元,称为页面。

当系统执行一个程序时,它将程序的一部分加载到物理内存中的页面上。

当程序需要更多的内存空间时,如果物理内存不足,系统会将不常用的页面置换到硬盘上的虚拟内存中,从而释放物理内存供其他程序使用。

这样,系统就可以运行比实际物理内存大小更大的程序了。

二、虚拟内存的设置影响正确设置虚拟内存的大小可以显著提升计算机性能和系统的稳定性。

以下是虚拟内存设置的几个关键因素:1. 初始大小:系统在启动时分配给虚拟内存的初始存储空间大小。

如果初始大小设置过小,系统可能不足以支持运行大型程序或处理大规模数据时的内存需求。

因此,合理设置初始大小非常重要。

2. 最大大小:虚拟内存的最大存储空间大小。

如果设置过小,在系统运行过程中可能会导致内存不足的情况,从而影响系统的正常运行。

而如果设置过大,会占用过多的硬盘空间。

因此,需要根据计算机具体配置和应用需求合理设置最大大小。

3. 页面大小:操作系统将物理内存划分为页面的大小。

页面大小的选择可能会影响程序的性能。

大页面大小有助于提高程序的访问速度,但也会消耗更多的物理内存。

小页面大小则可以提高页面的利用率。

选择页面大小需要权衡计算机硬件能力和应用场景。

三、优化虚拟内存的设置对于大多数用户来说,操作系统在安装时会自动设置虚拟内存的默认值,但用户仍然可以根据自己的需求进行优化。

1. 调整虚拟内存大小:根据计算机的实际应用需求,可以适当调整虚拟内存的初始大小和最大大小。

建议将初始大小设置为物理内存的1.5倍,并将最大大小设置为物理内存的3倍。

java jvm参数配置方法

java jvm参数配置方法

一、概述在Java编程中,JVM(Java虚拟机)参数配置是非常重要的一环,它能够对Java应用程序的性能和行为产生重大影响。

通过合理配置JVM 参数,可以提高Java应用程序的运行效率和稳定性,从而更好地满足需求。

本文将介绍Java JVM参数配置的方法,包括常用的参数选项和配置方式。

二、参数类型JVM参数可以分为两类:标准参数和非标准参数。

标准参数是被所有的JVM实现所支持的参数,用于控制JVM的运行方式,例如内存大小、垃圾回收器的选择等。

非标准参数则是被某个特定的JVM实现所支持的参数,通常用于调试和诊断。

三、常用的标准参数1. -Xms和-Xmx:分别用于指定JVM的初始内存和最大内存。

-Xms512m表示JVM启动时分配的初始内存为512MB,-Xmx1024m表示JVM分配的最大内存为1GB。

2. -XX:NewSize和-XX:MaxNewSize:用于指定新生代内存的初始大小和最大大小。

3. -XX:PermSize和-XX:MaxPermSize:用于指定永久代内存的初始大小和最大大小(仅适用于JDK1.7以前的版本,JDK1.8之后永久代已被元空间(Metaspace)取代)。

4. -XX:+UseParallelGC:启用并行垃圾回收器。

5. -XX:+UseConcMarkSweepGC:启用CMS垃圾回收器。

四、配置方式1. 命令行参数配置:可以通过在启动Java应用程序时添加参数来配置JVM参数。

例如:java -Xms512m -Xmx1024m -jar myapp.jar2. 环境变量配置:可以通过设置环境变量来配置JVM参数。

在Windows系统中,可以在系统属性中设置JAVA_OPTS环境变量,然后在该环境变量中添加JVM参数。

3. 配置文件配置:可以在JVM的配置文件中(如jvm.options、java.conf等)添加相应的参数配置。

这种方式适用于需要频繁修改参数的情况。

java out of memory解决方法

java out of memory解决方法

java out of memory解决方法摘要:1.Java 内存溢出的原因2.Java 内存溢出的后果3.Java 内存溢出的解决方法4.总结正文:一、Java 内存溢出的原因Java 内存溢出是指Java 程序在运行过程中,申请的内存超过了Java 虚拟机(JVM)能够分配的最大内存,导致程序无法正常运行的现象。

Java 内存溢出的原因有很多,以下是一些常见的原因:1.程序中存在大量的对象实例,导致内存占用过高。

2.程序循环过程中,频繁地创建和销毁对象,导致内存分配和回收的开销过大。

3.程序中存在内存泄漏,导致部分内存无法被及时回收。

4.JVM 启动参数配置不合理,导致JVM 分配的内存过小。

二、Java 内存溢出的后果Java 内存溢出会导致程序运行异常,甚至直接崩溃。

严重的内存溢出可能导致JVM 崩溃,进而影响整个系统的稳定性。

此外,内存溢出还会影响程序的性能,导致程序运行速度变慢。

三、Java 内存溢出的解决方法要解决Java 内存溢出的问题,需要从以下几个方面入手:1.优化程序代码- 减少不必要的对象实例,尽量使用局部变量和静态变量。

- 减少循环中对象的创建和销毁,尽量使用对象池技术。

- 定期检查程序内存使用情况,查找内存泄漏问题,并及时修复。

2.合理配置JVM 参数- 调整JVM 启动参数,增加堆内存的大小(-Xmx 参数)。

- 调整垃圾回收器(Garbage Collector, GC)的配置,优化内存回收策略。

3.使用内存分析工具- 使用Java 内存分析工具(如VisualVM、JProfiler 等)分析程序的内存使用情况,找出内存泄漏和瓶颈。

- 根据分析结果,优化程序代码和内存管理策略。

4.调整服务器硬件配置- 提高服务器的内存容量,以满足程序运行所需的内存需求。

- 优化服务器的硬件配置,提高服务器性能,降低内存使用压力。

四、总结Java 内存溢出问题需要综合考虑程序代码、JVM 参数、内存分析工具和服务器硬件配置等多方面因素。

java jvm堆内存扩容机制以及缩容机制

java jvm堆内存扩容机制以及缩容机制

一、介绍Java虚拟机(JVM)是一种能够在计算机上运行Java程序的虚拟机。

在Java应用程序运行的过程中,JVM会使用堆内存来存储对象实例。

堆内存的大小会直接影响程序的性能和稳定性。

了解JVM堆内存的扩容机制以及缩容机制对于Java开发人员来说是非常重要的。

二、堆内存的扩容机制1. 初始内存和最大内存在启动Java程序时,可以通过设置参数-Xms和-Xmx来指定JVM堆内存的初始大小和最大大小。

初始内存指定JVM堆内存的初始大小,最大内存指定JVM堆内存的最大大小。

当JVM启动时,会先分配初始内存,并且在应用程序运行中达到初始内存的上限时,堆内存会自动扩容。

当堆内存扩容达到最大内存时,程序会抛出内存溢出错误。

2. 自动扩容JVM堆内存的自动扩容是由垃圾回收器(GC)来完成的。

当堆内存中的对象实例占用的空间超过了当前内存的剩余空间时,GC会触发一次垃圾回收操作,释放部分无用对象实例的内存空间,从而使堆内存得以扩容。

这种自动扩容机制可以有效地避免了由于堆内存空间不足而导致的程序性能下降或者程序崩溃的情况。

三、堆内存的缩容机制1. 内存回收JVM堆内存的缩容机制是由GC和虚拟机内部的内存管理器来完成的。

当堆内存中的对象实例占用的空间下降到一定程度时,内存管理器会自动触发一次内存回收操作,将不再使用的内存空间释放出来,从而使堆内存得以缩容。

这种自动缩容机制可以帮助程序及时释放不再使用的内存空间,提高堆内存的利用率,从而提升程序的性能和稳定性。

2. 手动内存回收除了自动内存回收之外,开发人员也可以通过调用System.gc()方法手动触发一次垃圾回收操作,来释放不再使用的内存空间。

这种手动的内存回收操作也可以帮助程序及时释放内存空间,提高程序的性能和稳定性。

四、总结JVM堆内存的扩容机制和缩容机制是保障Java程序高性能和稳定运行的重要环节。

通过合理设置初始内存和最大内存参数,以及合理使用垃圾回收器和内存管理器,可以有效地管理JVM堆内存的扩容和缩容,从而提高程序的性能和稳定性。

jvm 向os申请内存的机制

jvm 向os申请内存的机制

JVM(Java虚拟机)是Java程序的运行评台,它负责将Java字节码转换为机器码并在操作系统上运行。

在JVM的运行过程中,内存管理是一个非常重要的环节,其中向操作系统申请内存是一个核心机制。

本文将从JVM向操作系统申请内存的机制展开探讨,希望为读者提供深入了解JVM内存管理的知识。

一、JVM内存结构在探讨JVM向操作系统申请内存的机制之前,首先需要了解JVM的内存结构。

JVM的内存可以分为三部分:堆(Heap)、栈(Stack)和方法区(Method Area)。

其中堆用于存储对象实例和数组,栈用于存储局部变量和方法调用,方法区用于存储类信息、常量、静态变量等。

二、内存申请过程1. 程序启动当一个Java程序启动时,JVM会为该程序分配一定的内存。

这部分内存一般是由操作系统分配给JVM的,称为虚拟机初始化内存(Initial Heap)和虚拟机最大内存(Maximum Heap)。

虚拟机初始化内存用于存放JVM运行所需的数据结构,虚拟机最大内存表示JVM最大可用的堆内存。

2. 堆内存分配JVM对堆内存的管理是一种延迟分配的策略。

也就是说,JVM并不是在程序启动时一次性向操作系统申请所需的堆内存,而是根据程序运行的需要在必要时向操作系统动态申请内存。

在堆内存分配时,有两种情况需要考虑:- 新对象分配内存:当程序中创建新的对象实例或数组时,JVM会根据对象的大小向操作系统申请内存。

如果堆内存中有足够的空间,JVM会直接在堆中为对象分配内存,并记录对象的位置区域。

如果堆内存中没有足够的连续空间,JVM会触发一次垃圾回收操作,释放一些无用的对象,从而腾出足够的内存空间。

- 大对象分配内存:当程序中需要创建一个较大的对象时,堆内存中可能没有足够的连续空间来满足对象的分配需求。

这时,JVM会将对象存放到“老年代”(Old Generation),并触发一次“Full GC”(full garbage collection)操作来释放老年代中无用的对象,从而为大对象的分配腾出空间。

java jvm 参数 Xms Xmx Xmn Xss 调优总结【VIP专享】

java jvm 参数 Xms Xmx Xmn Xss 调优总结【VIP专享】

java jvm 参数 -Xms -Xmx -Xmn -Xss 调优总结常见配置举例堆大小设置JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制;系统的可用虚拟内存限制;系统的可用物理内存限制.32位系统下,一般限制在1.5G~2G;64为操作系统对内存无限制.我在Windows Server 2003 系统, 3.5G物理内存,JDK5.0下测试,最大可设置为1478m.典型设置:java -Xmx3550m -Xms3550m -Xmn2g -Xss128k-Xmx3550m:设置JVM最大可用内存为3550M.-Xms3550m:设置JVM促使内存为3550m.此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存.-Xmn2g:设置年轻代大小为2G.整个堆大小=年轻代大小 + 年老代大小 + 持久代大小.持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小.此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8.-Xss128k: 设置每个线程的堆栈大小.JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K.更具应用的线程所需内存大小进行调整.在相同物理内存下,减小这个值能生成更多的线程.但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右.java -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0-XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代).设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5-XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的大小比值.设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6-XX:MaxPermSize=16m:设置持久代大小为16m.-XX:MaxTenuringThreshold=0: 设置垃圾最大年龄.如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代. 对于年老代比较多的应用,可以提高效率.如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论.回收器选择JVM给了三种选择:串行收集器,并行收集器,并发收集器,但是串行收集器只适用于小数据量的情况,所以这里的选择主要针对并行收集器和并发收集器.默认情况下,JDK5.0以前都是使用串行收集器,如果想使用其他收集器需要在启动时加入相应参数.JDK5.0以后,JVM会根据当前系统配置进行判断.吞吐量优先的并行收集器如上文所述,并行收集器主要以到达一定的吞吐量为目标,适用于科学技术和后台处理等.典型配置:java -Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20-XX:+UseParallelGC:选择垃圾收集器为并行收集器.此配置仅对年轻代有效.即上述配置下,年轻代使用并发收集,而年老代仍旧使用串行收集.-XX:ParallelGCThreads=20:配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收.此值最好配置与处理器数目相等.java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParallelOldGC-XX:+UseParallelOldGC:配置年老代垃圾收集方式为并行收集.JDK6.0支持对年老代并行收集.java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:MaxGCPauseMillis=100-XX:MaxGCPauseMillis=100:设置每次年轻代垃圾回收的最长时间,如果无法满足此时间,JVM会自动调整年轻代大小,以满足此值.java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:MaxGCPauseMillis=100 -XX:+UseAdaptiveSizePolicy-XX:+UseAdaptiveSizePolicy:设置此选项后,并行收集器会自动选择年轻代区大小和相应的Survivor区比例,以达到目标系统规定的最低相应时间或者收集频率等,此值建议使用并行收集器时,一直打开.响应时间优先的并发收集器如上文所述,并发收集器主要是保证系统的响应时间,减少垃圾收集时的停顿时间.适用于应用服务器,电信领域等.典型配置:java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:ParallelGCThreads=20 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC-XX:+UseConcMarkSweepGC:设置年老代为并发收集.测试中配置这个以后,-XX:NewRatio=4的配置失效了,原因不明.所以,此时年轻代大小最好用-Xmn设置. -XX:+UseParNewGC:设置年轻代为并行收集.可与CMS收集同时使用.JDK5.0以上,JVM会根据系统配置自行设置,所以无需再设置此值.java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseConcMarkSweepGC -XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection-XX:CMSFullGCsBeforeCompaction:由于并发收集器不对内存空间进行压缩,整理,所以运行一段时间以后会产生"碎片",使得运行效率降低.此值设置运行多少次GC以后对内存空间进行压缩,整理.-XX:+UseCMSCompactAtFullCollection:打开对年老代的压缩.可能会影响性能,但是可以消除碎片辅助信息JVM提供了大量命令行参数,打印信息,供调试使用.主要有以下一些:-XX:+PrintGC输出形式:[GC 118250K->113543K(130112K), 0.0094143 secs][Full GC 121376K->10414K(130112K), 0.0650971 secs]-XX:+PrintGCDetails输出形式:[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs][GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured: 112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs]-XX:+PrintGCTimeStamps -XX:+PrintGC:PrintGCTimeStamps可与上面两个混合使用输出形式:11.851: [GC 98328K->93620K(130112K), 0.0082960 secs]-XX:+PrintGCApplicationConcurrentTime:打印每次垃圾回收前,程序未中断的执行时间.可与上面混合使用输出形式:Application time: 0.5291524 seconds-XX:+PrintGCApplicationStoppedTime:打印垃圾回收期间程序暂停的时间.可与上面混合使用输出形式:Total time for which application threads were stopped:0.0468229 seconds-XX:PrintHeapAtGC:打印GC前后的详细堆栈信息输出形式:34.702: [GC {Heap before gc invocations=7:def new generation total 55296K, used 52568K [0x1ebd0000, 0x227d0000, 0x227d0000)eden space 49152K, 99% used [0x1ebd0000, 0x21bce430, 0x21bd0000)from space 6144K, 55% used [0x221d0000, 0x22527e10, 0x227d0000)to space 6144K, 0% used [0x21bd0000, 0x21bd0000, 0x221d0000)tenured generation total 69632K, used 2696K [0x227d0000, 0x26bd0000, 0x26bd0000)the space 69632K, 3% used [0x227d0000, 0x22a720f8, 0x22a72200,0x26bd0000)compacting perm gen total 8192K, used 2898K [0x26bd0000, 0x273d0000, 0x2abd0000)the space 8192K, 35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00,0x273d0000)ro space 8192K, 66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00,0x2b3d0000)rw space 12288K, 46% used [0x2b3d0000, 0x2b972060, 0x2b972200,0x2bfd0000)34.735: [DefNew: 52568K->3433K(55296K), 0.0072126 secs] 55264K->6615K(124928K)Heap after gc invocations=8:def new generation total 55296K, used 3433K [0x1ebd0000, 0x227d0000, 0x227d0000)eden space 49152K, 0% used [0x1ebd0000, 0x1ebd0000, 0x21bd0000)from space 6144K, 55% used [0x21bd0000, 0x21f2a5e8, 0x221d0000)to space 6144K, 0% used [0x221d0000, 0x221d0000, 0x227d0000)tenured generation total 69632K, used 3182K [0x227d0000, 0x26bd0000, 0x26bd0000)the space 69632K, 4% used [0x227d0000, 0x22aeb958, 0x22aeba00,0x26bd0000)compacting perm gen total 8192K, used 2898K [0x26bd0000, 0x273d0000, 0x2abd0000)the space 8192K, 35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00,0x273d0000)ro space 8192K, 66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00,0x2b3d0000)rw space 12288K, 46% used [0x2b3d0000, 0x2b972060, 0x2b972200,0x2bfd0000)}, 0.0757599 secs]-Xloggc:filename:与上面几个配合使用,把相关日志信息记录到文件以便分析.常见配置汇总堆设置-Xms:初始堆大小-Xmx:最大堆大小-XX:NewSize=n:设置年轻代大小-XX:NewRatio=n:设置年轻代和年老代的比值.如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4-XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值.注意Survivor区有两个.如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5-XX:MaxPermSize=n:设置持久代大小收集器设置-XX:+UseSerialGC:设置串行收集器-XX:+UseParallelGC:设置并行收集器-XX:+UseParalledlOldGC:设置并行年老代收集器-XX:+UseConcMarkSweepGC:设置并发收集器垃圾回收统计信息-XX:+PrintGC-XX:+PrintGCDetails-XX:+PrintGCTimeStamps-Xloggc:filename并行收集器设置-XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数.并行收集线程数.-XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间-XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比.公式为1/(1+n)并发收集器设置-XX:+CMSIncrementalMode:设置为增量模式.适用于单CPU情况.-XX:ParallelGCThreads=n:设置并发收集器年轻代收集方式为并行收集时,使用的CPU数.并行收集线程数.调优总结年轻代大小选择响应时间优先的应用:尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选择).在此种情况下,年轻代收集发生的频率也是最小的.同时,减少到达年老代的对象.吞吐量优先的应用:尽可能的设置大,可能到达Gbit的程度.因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用.年老代大小选择响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数.如果堆设置小了,可以会造成内存碎片,高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间.最优化的方案,一般需要参考以下数据获得:并发垃圾收集信息持久代并发收集次数传统GC信息花在年轻代和年老代回收上的时间比例减少年轻代和年老代花费的时间,一般会提高应用的效率吞吐量优先的应用:一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代.原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象.较小堆引起的碎片问题因为年老代的并发收集器使用标记,清除算法,所以不会对堆进行压缩.当收集器回收时,他会把相邻的空间进行合并,这样可以分配给较大的对象.但是,当堆空间较小时,运行一段时间以后,就会出现"碎片",如果并发收集器找不到足够的空间,那么并发收集器将会停止,然后使用传统的标记,清除方式进行回收.如果出现"碎片",可能需要进行如下配置:-XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩.-XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩在同一个工程下,有两个类,这两个类中只有很少的变动,而最关健的FOR却没有一点变动,可是当我分别运行这两个程序的时候却出现一个很严重的问题,一个程序循环的快,一个循环的慢.这到底是怎么回事呢~苦苦寻找了半天也没有想到是为什么,因为程序改变的部分根不影响我循环的速度,可是结果却是有很大的差别,一个大约是在一分钟这内就可以循环完,可是另一个却需要六七分钟,这根本就不是一个数据理级的麻.两个完全一样的循环,从代码上根本上是看不出有什么问题.不得以求助同事吧,可是同事看了也感觉很诡异,两个人在那订着代码又看了一个多小时,最后同事让我来个干净点的,关机重启.我到也听话,就顺着同事的意思去了,可就在关机的这个时候他突然说是不是内存的问题,我也空然想到了,还真的有可能是内存的问题,因为快的那个在我之前运行程序之前可给过 1G的内存啊,而后来的这个我好像是没有设过内存啊,机器起来了,有了这个想法进去看看吧,结果正中要害,果真是慢的那个没有开内存,程序运行时只不过是 JVM默认开的内存.我初步分析是因为内存太小,而我的程序所用内存又正好卡在JVM所开内存边上,不至于溢出.当程序运行时就得花费大部分时间去调用 GC去,这样就导致了为什么相同的循环出现两种不同的效率~!顺便把内存使用情况的方法也贴出来:public static String getMemUsage() {long free = ng.Runtime.getRuntime().freeMemory();long total = ng.Runtime.getRuntime().totalMemory();StringBuffer buf = new StringBuffer();buf.append("[Mem: used ").append((total-free)>>20).append("M free ").append(free>>20).append("M total ").append(total>>20).append("M]");return buf.toString();}google一下,大概就说JVM是这样来操作内存:堆(Heap)和非堆(Non-heap)内存按照官方的说法:"Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配.堆是在 Java 虚拟机启动时创建的.""在JVM中堆之外的内存称为非堆内存(Non-heap memory)".可以看出JVM主要管理两种类型的内存:堆和非堆.简单来说堆就是Java代码可及的内存,是留给开发人员使用的;非堆就是JVM留给自己用的,所以方法区,JVM内部处理或优化所需的内存(如JIT编译后的代码缓存),每个类结构(如运行时常数池,字段和方法数据)以及方法和构造方法的代码都在非堆内存中.堆内存分配JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4.默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时, JVM会减少堆直到-Xms的最小限制.因此服务器一般设置-Xms,-Xmx相等以避免在每次GC 后调整堆的大小.非堆内存分配JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4.JVM内存限制(最大值)首先JVM内存首先受限于实际的最大物理内存,假设物理内存无限大的话,JVM内存的最大值跟操作系统有很大的关系.简单的说就32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制,这个限制一般是 2GB-3GB(一般来说Windows系统下为1.5G-2G,Linux系统下为2G-3G),而64bit以上的处理器就不会有限制了JVM内存的调优1. Heap设定与垃圾回收Java Heap分为3个区,Young,Old和Permanent.Young保存刚实例化的对象.当该区被填满时,GC会将对象移到Old 区.Permanent区则负责保存反射对象,本文不讨论该区.JVM的Heap分配可以使用-X参数设定,-Xms初始Heap大小-Xmxjava heap最大值-Xmnyoung generation的heap大小JVM有2个GC线程.第一个线程负责回收Heap的Young区.第二个线程在Heap 不足时,遍历Heap,将Young 区升级为Older区.Older区的大小等于-Xmx减去-Xmn,不能将-Xms的值设的过大,因为第二个线程被迫运行会降低JVM的性能.为什么一些程序频繁发生GC?有如下原因:l 程序内调用了System.gc()或Runtime.gc().l 一些中间件软件调用自己的GC方法,此时需要设置参数禁止这些GC.l Java的Heap太小,一般默认的Heap值都很小.l 频繁实例化对象,Release对象.此时尽量保存并重用对象,例如使用StringBuffer()和String().如果你发现每次GC后,Heap的剩余空间会是总空间的50%,这表示你的Heap处于健康状态.许多Server端的Java程序每次GC后最好能有65%的剩余空间.经验之谈:1.Server端JVM最好将-Xms和-Xmx设为相同值.为了优化GC,最好让-Xmn值约等于-Xmx的1/3[2].2.一个GUI程序最好是每10到20秒间运行一次GC,每次在半秒之内完成[2].注意:1.增加Heap的大小虽然会降低GC的频率,但也增加了每次GC的时间.并且GC 运行时,所有的用户线程将暂停,也就是GC期间,Java应用程序不做任何工作. 2.Heap大小并不决定进程的内存使用量.进程的内存使用量要大于-Xmx定义的值,因为Java为其他任务分配内存,例如每个线程的Stack等.2.Stack的设定每个线程都有他自己的Stack.-Xss每个线程的Stack大小Stack的大小限制着线程的数量.如果Stack过大就好导致内存溢漏.-Xss参数决定Stack大小,例如-Xss1024K.如果Stack太小,也会导致Stack溢漏.3.硬件环境硬件环境也影响GC的效率,例如机器的种类,内存,swap空间,和CPU的数量.如果你的程序需要频繁创建很多transient对象,会导致JVM频繁GC.这种情况你可以增加机器的内存,来减少Swap空间的使用[2].4.4种GC第一种为单线程GC,也是默认的GC.,该GC适用于单CPU机器.第二种为Throughput GC,是多线程的GC,适用于多CPU,使用大量线程的程序.第二种GC与第一种GC相似,不同在于GC在收集Young区是多线程的,但在Old 区和第一种一样,仍然采用单线程.-XX:+UseParallelGC参数启动该GC.第三种为Concurrent Low Pause GC,类似于第一种,适用于多CPU,并要求缩短因GC造成程序停滞的时间.这种GC可以在Old区的回收同时,运行应用程序.-XX:+UseConcMarkSweepGC参数启动该GC.第四种为Incremental Low Pause GC,适用于要求缩短因GC造成程序停滞的时间.这种GC可以在Young区回收的同时,回收一部分Old区对象.-Xincgc参数启动该GC.。

Java应用Top命令RES内存占用高分析(转)

Java应用Top命令RES内存占用高分析(转)

Java应⽤Top命令RES内存占⽤⾼分析(转)分析给⼤拇指,转存ps aux命令执⾏结果的⼏个列的信息的含义USER 进程所属⽤户PID 进程ID%CPU 进程占⽤CPU百分⽐%MEM 进程占⽤内存百分⽐VSZ 虚拟内存占⽤⼤⼩单位:kb(killobytes)RSS 实际内存占⽤⼤⼩单位:kb(killobytes)TTY 终端类型STAT 进程状态START 进程启动时刻TIME 进程运⾏时长,进程已经消耗的CPU时间COMMAND 启动进程的命令的名称和参数top 命令 VSZ,RSS,TTY,STAT, VIRT,RES,SHR,DATA的含义VIRT:virtual memory usage 虚拟内存1、进程“需要的”虚拟内存⼤⼩,包括进程使⽤的库、代码、数据等2、假如进程申请100m的内存,但实际只使⽤了10m,那么它会增长100m,⽽不是实际的使⽤量RES:resident memory usage 常驻内存1、进程当前使⽤的内存⼤⼩,但不包括swap out2、包含其他进程的共享3、如果申请100m的内存,实际使⽤10m,它只增长10m,与VIRT相反4、关于库占⽤内存的情况,它只统计加载的库⽂件所占内存⼤⼩SHR:shared memory 共享内存1、除了⾃⾝进程的共享内存,也包括其他进程的共享内存2、虽然进程只使⽤了⼏个共享库的函数,但它包含了整个共享库的⼤⼩3、计算某个进程所占的物理内存⼤⼩公式:RES – SHR4、swap out后,它将会降下来DATA1、数据占⽤的内存。

如果top没有显⽰,按f键可以显⽰出来。

2、真正的该程序要求的数据空间,是真正在运⾏中要使⽤的。

top 运⾏中可以通过 top 的内部命令对进程的显⽰⽅式进⾏控制。

内部命令如下:s – 改变画⾯更新频率l – 关闭或开启第⼀部分第⼀⾏ top 信息的表⽰t – 关闭或开启第⼀部分第⼆⾏ Tasks 和第三⾏ Cpus 信息的表⽰m – 关闭或开启第⼀部分第四⾏ Mem 和第五⾏ Swap 信息的表⽰N – 以 PID 的⼤⼩的顺序排列表⽰进程列表P – 以 CPU 占⽤率⼤⼩的顺序排列进程列表M – 以内存占⽤率⼤⼩的顺序排列进程列表h – 显⽰帮助n – 设置在进程列表所显⽰进程的数量q – 退出 tops – 改变画⾯更新周期序号列名含义a PID 进程idb PPID ⽗进程idc RUSER Real user named UID 进程所有者的⽤户ide USER 进程所有者的⽤户名f GROUP 进程所有者的组名g TTY 启动进程的终端名。

JAVA内存分配算法分析

JAVA内存分配算法分析

内存空洞及内存分配算法研究前言 (2)几个简单的场景(Linux 64位下测试): (2)Linux默认的内存分配机制 (3)1.glibc的内存分配机制: (4)2.glibc的内存释放机制: (5)为什么会有内存空洞 (5)Fastbin介绍 (6)3.Linux多线程环境下内存空洞所占内存可能会翻数倍 (6)4.Stlport内存管理相关说明 (8)Glibc常见内存管理参数介绍 (9)如何消除内存空洞的影响 (10)1.内存空洞的外在现象 (11)2.一个判断是否有内存空洞的脚本 (11)3.自己实现并使用一个内存分配器 (13)其它的内存分配器介绍及使用 (18)4.实现的一个内存泄露检查工具 (18)总结 (19)前言内存泄露一直是C或C++程序员的一个很头疼的问题,但更严重的是有些时候我们发现即使我们调用free或delete释放了内存,进程占用内存也不下降,这也给很多程序员以藉口,如果发现内存使用量增长,要求排查时,我们往往会说,“内存我都释放了,Purify也跑过了,这是内存空洞造成的,是glibc 的行为我也无能为力。

事实上也是,简单的分配不释放的内存泄露问题一般在开发者测试阶段甚至之前就可以排查掉,但这并不代表没有内存问题,特别是对于电信领域,很多程序运行数月甚至数年都不会停,很多很小的问题在乘以时间后会无限放大。

本文首先介绍了Linux的内存分配机制,以及在真实场景下引发的问题,并提出了一些解决方法,并介绍了如何实现并使用一个简单的内存分配器,以及项目组实现的判断是否有内存空洞的一个脚本,和一个内存泄露检查工具。

几个简单的场景(Linux 64位下测试):✧连续分配1001块100K的内存,把前面分配的1000块内存释放掉,此时通过top检查进程所占内存,发现内存完全不会下降;✧每次分配一块8字节内存,和一块100K的内存,连续分配1000次,然后依次把这些内存全部释放,此时通过top检查进程所占内存,发现内存不会下降;✧多线程下同样的内存使用不当的程序,Linux上内存上涨量可能会是数倍于AIX10M左右的文本数据,如果以一定的格式存储于stlport的数据结构中,实际占用内存会膨胀100倍以上上述的几种场景看似简单,但实际上却都是真实的血淋淋的案例抽象出来的,有些案例的定位花费了大量的人力,而这些场景往往都是purify之类工具测试不出来的,下面通过介绍linux的内存分配机制来解释上述场景,并提出解决方案。

java虚拟机内存不足,“CouldnotcreatetheJavaVirtualMach。。。

java虚拟机内存不足,“CouldnotcreatetheJavaVirtualMach。。。

java虚拟机内存不⾜,“CouldnotcreatetheJavaVirtualMach。

在运⾏java程序时,遇到问题"Could not create the Java Virtual Machine."如下截图:⼤概原因,就是java堆内存不⾜以运⾏JVM,需要增加内存。

⽹上搜索此问题,⼤部分都是针对某个程序进⾏修改JVM内存的解决⽅法,⽐如eclipse,等。

试问,若是其他程序出现问题了呢?现在给出⼀个全局的java虚拟机修改内存的⽅法。

在WIN XP,WIN 7,WIN8都可以。

解决⽅案:增加⼀个系统环境变量变量名:_JAVA_OPTIONS变量值:-Xmx512M保存后,就OK!!下⾯给出关于java堆内存的⼀个介绍,这是⼀个英⽂⽹页的翻译过来的。

关于java堆内存:Java -Xmx is the configuration parameter to control the amount of memory Java uses on a system. Basically these settings are there to control the Heap memory size of Java. There are two settings related to Java heap memory:-Xmx to set the maximum heap memory size-Xms to set the minimum heap memory sizeTips to set the Java heap memory sizeManaging the Java heap memory size for a server is very crucial as the whole performance depends on this memory size, off course there are other factors which affects the performance. So let’s see how you can set these parameters to control the Java heap memory size.Do not set -Xmx to too small valueIf you set -Xmx too small for your server then your application may not work properly and you may get Out of memory exception. So never set this too small as this is the maximum amount of memory you are allocating for Java and it cannot utilize memory beyond the set value. It is always advisable to set -Xmx to a higher value if you have enough memory space available on your server. On the other hand if you set -Xmx value to a higher value your other resources will not be able to perform well as you have already reserved some of your memory for Java. So before setting the maximum heap size memory just check how much memory is free. To do so, stop your application server and check the free memory and accordingly you can set the maximum memory size. For example if you have 512M free memory then you can set heap memory to 300M safely i.e. -Xmx300m.Set -Xms to a small valueIf you set -Xms to higher value you might run out of memory. So always try to keep it to a small value like -Xms16m. In tomcat when you restart the server it starts a Java process and that process takes the same -Xms as the default value for the tomcat and if it is higher you may get out of memory.Now let’s see how to set java heap memory in different servers.How to set java heap size in TomcatTo set the java heap size in tomcat you need to edit the catalina.sh (On Linux) or catalina.bat (On Windows) file. You can find these files inside the bin directory of tomcat. Open the appropriate file and search for CATALINA_OPTS and set the value as shown below, you can change the max and min value to whatever you want.set CATALINA_OPTS=-Xms64m -Xmx512mexport CATALINA_OPTS=”-Xms64m -Xmx512m”setenv CATALINA_OPTS “-Xms64m -Xmx512m”⼤概翻译如下:Java - xmx配置参数控制Java系统上使⽤的内存量。

java虚拟机底层原理

java虚拟机底层原理

java虚拟机底层原理Java虚拟机(JVM)是一种在Java编程语言中使用的虚拟机,它能够执行Java 字节码并提供了一个运行环境,使得Java程序可以在各种不同的硬件平台上运行。

JVM的底层原理包括以下几个方面:1. 内存管理JVM中的内存管理包括堆、栈、方法区等区域的划分和分配。

其中堆用于存储对象实例,栈用于存储方法调用和局部变量,方法区用于存储类信息、常量等。

JVM通过内存分配器来实现内存的分配和回收,常用的内存分配器有基于指针的分配器和基于垃圾回收的分配器。

2. 类加载JVM中的类加载包括类的装载、验证、准备、解析和初始化等阶段。

在类加载过程中,JVM会根据类的元数据,将字节码文件加载到内存中,并生成一个表示该类的Class对象。

类加载过程中需要进行各种验证和检查,以确保类的安全性和正确性。

3. 垃圾回收JVM中的垃圾回收用于清除不再使用的对象,以释放内存空间。

JVM通过垃圾回收器来管理内存的回收和释放,常用的垃圾回收器有关联式垃圾回收器、标记-清除垃圾回收器、复制垃圾回收器等。

垃圾回收器通过检测不再使用的对象,将其标记为垃圾并进行回收,以释放内存空间。

4. JIT编译JVM中的JIT编译器将Java字节码实时编译为本地机器代码,以提高程序的执行效率。

JIT编译器根据程序的运行情况,对经常执行的热点代码进行优化和编译,使得程序可以更快地执行。

5. 异常处理JVM中的异常处理用于处理程序运行过程中出现的异常情况,以避免程序崩溃。

JVM提供了异常处理机制,当程序发生异常时,JVM会在堆栈中查找合适的异常处理程序,并将控制权转交给该程序进行处理。

6. 多线程JVM中的多线程用于支持多任务并发执行。

JVM提供了线程调度器和线程同步机制,使得程序可以创建多个线程并发执行多个任务。

在多线程编程中,需要注意线程之间的同步和互斥问题,以避免出现死锁等问题。

总之,Java虚拟机的底层原理包括内存管理、类加载、垃圾回收、JIT编译、异常处理和多线程等方面。

MemoryUsage:监测java虚拟机内存使用

MemoryUsage:监测java虚拟机内存使用

MemoryUsage:监测java虚拟机内存使⽤通过MemoryUsage可以查看Java 虚拟机的内存池的内存使⽤情况。

MemoryUsage类有四个值(均以字节为单位):===Init===java虚拟机在启动的时候向操作系统请求的初始内存容量。

java虚拟机在运⾏的过程中可能向操作系统请求更多的内存或将内存释放给操作系统,所以init的值是不确定的。

===Used===当前已经使⽤的内存量。

===Committed===表⽰保证java虚拟机能使⽤的内存量,已提交的内存量可以随时间⽽变化(增加或减少)。

Java 虚拟机可能会将内存释放给系统,committed 可以⼩于 init。

committed 将始终⼤于或等于 used。

===Max===表⽰可以⽤于内存管理的最⼤内存量(以字节为单位)。

可以不定义其值,如果定义了该值,最⼤内存量可能随时间⽽更改。

已使⽤的内存量和已提交的内存量将始终⼩于或等于 max(如果定义了 max)。

如果内存分配试图增加满⾜以下条件的已使⽤内存将会失败:used > committed,即使 used <= max 仍然为 true(例如,当系统的虚拟内存不⾜时)。

可以通过⼀下diamante,随时监测java虚拟机内存使⽤情况:package tools;import ng.management.ManagementFactory;import ng.management.MemoryUsage;import java.util.Scanner;public class memory_usage {public static void main(String[] args) {Scanner in = new Scanner(System.in);while (true) {System.out.println("input enter to continue, input other to break.");String s = in.nextLine();if (!s.equals("")){break;}MemoryUsage mu = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();long getCommitted = mu.getCommitted();long getInit = mu.getInit();long getUsed = mu.getUsed();long max = mu.getMax();System.out.println("===================================<br/>");System.out.println(">>getCommitted(byte)>>" + getCommitted + "<br/>");System.out.println(">>getInit(byte)>>" + getInit + "<br/>");System.out.println(">>getUsed(byte)>>" + getUsed + "<br/>");System.out.println(">>max(byte)>>" + max + "<br/>");System.out.println("===================================<br/>");System.out.println(">>getCommitted(KB)>>" + getCommitted / 1000 + "<br/>");System.out.println(">>getInit(KB)>>" + getInit / 1000 + "<br/>");System.out.println(">>getUsed(KB)>>" + getUsed / 1000 + "<br/>");System.out.println(">>max(KB)>>" + max / 1000 + "<br/>");System.out.println("===================================<br/>");System.out.println(">>getCommitted(MB)>>" + getCommitted / 1000 / 1000 + "<br/>"); System.out.println(">>getInit(MB)>>" + getInit / 1000 / 1000 + "<br/>");System.out.println(">>getUsed(MB)>>" + getUsed / 1000 / 1000 + "<br/>");System.out.println(">>max(MB)>>" + max / 1000 / 1000 + "<br/>");}System.out.println("====end====");}}--End--。

查看java进程占用内存[转]

查看java进程占用内存[转]

查看java进程占⽤内存[转]使⽤ps查看JAVA进程使⽤的内存和虚拟内存( 内存管理 ):$ ps -p ${pid} -o rss,vszRSS VSZ7152568 17485844VSZ是虚拟内存,RSS是实际使⽤的内存,单位KB。

你会发现,RSS会远远超过了-Xmx的设定。

为什么呢?⾸先要搞清楚JVM的内存机制: JVM内存区域总体分两类,heap区和⾮heap 区(本地内存) 。

heap区:堆区分为Young Gen,Old Gen。

⾮heap区: Code Cache(代码缓存区)、Perm Gen(永久代)、Jvm Stack(java虚拟机栈)、Local Method Statck(本地⽅法栈)。

这样,⼤概懂了吧。

-Xmx设定的仅仅只是heap区。

JDK1.8有Native Memory Tracker也可以帮助定位内存。

NMT必须先通过VM启动参数中打开,不过要注意的是,打开NMT会带来5%-10%的性能损耗。

-XX:NativeMemoryTracking=[off | summary | detail]off: 默认关闭summary: 只统计各个分类的内存使⽤情况.detail: Collect memory usage by individual call sites.⼀般在启动参数上加⼊-XX:NativeMemoryTracking=detail,然后通过jcmd查看NMT报告以及查看对⽐情况。

jcmd <pid> VM.native_memory [summary | detail | baseline | summary.diff | detail.diff | shutdown] [scale= KB | MB | GB] summary: 分类内存使⽤情况.detail: 详细内存使⽤情况,除了summary信息之外还包含了虚拟内存使⽤情况。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

目录java虚拟机内存管理机制(一):JVM内存管理总结【分享】收藏 (1)java虚拟机内存管理机制(二):了解JVM的内存管理与垃圾回收收藏 (5)java虚拟机内存管理机制(三):我主管写的一些jvm内存管理知识收藏 (8)java虚拟机内存管理机制(一):JVM内存管理总结【分享】收藏近期看了看Java内存泄露的一些案例,跟原来的几个哥们讨论了一下,深入研究发现JVM 里面还是有不少以前不知道的细节,这里稍微剖析一下。

先看一看JVM的内部结构——如图所示,JVM主要包括两个子系统和两个组件。

两个子系统分别是Class loader子系统和Execution engine(执行引擎) 子系统;两个组件分别是Runtime data area (运行时数据区域)组件和Native interface(本地接口)组件。

Class loader子系统的作用:根据给定的全限定名类名(如ng.Object)来装载class文件的内容到Runtime data area中的method area(方法区域)。

Java程序员可以extends ng.ClassLoader类来写自己的Class loader。

Execution engine子系统的作用:执行classes中的指令。

任何JVM specification实现(JDK)的核心都是Execution engine,不同的JDK例如Sun 的JDK 和IBM的JDK好坏主要就取决于他们各自实现的Execution engine的好坏。

Native interface组件:与native libraries交互,是其它编程语言交互的接口。

当调用native方法的时候,就进入了一个全新的并且不再受虚拟机限制的世界,所以也很容易出现JVM无法控制的native heap OutOfMemory。

Runtime Data Area组件:这就是我们常说的JVM的内存了。

它主要分为五个部分——1、Heap (堆):一个Java虚拟实例中只存在一个堆空间2、Method Area(方法区域):被装载的class的信息存储在Method area的内存中。

当虚拟机装载某个类型时,它使用类装载器定位相应的class文件,然后读入这个class文件内容并把它传输到虚拟机中。

3、Java Stack(java的栈):虚拟机只会直接对Java stack执行两种操作:以帧为单位的压栈或出栈4、Program Counter(程序计数器):每一个线程都有它自己的PC寄存器,也是该线程启动时创建的。

PC寄存器的内容总是指向下一条将被执行指令的饿地址,这里的地址可以是一个本地指针,也可以是在方法区中相对应于该方法起始指令的偏移量。

5、Native method stack(本地方法栈):保存native方法进入区域的地址以上五部分只有Heap 和Method Area是被所有线程的共享使用的;而Java stack, Program counter 和Native method stack是以线程为粒度的,每个线程独自拥有自己的部分。

了解JVM的系统结构,再来看看JVM内存回收问题了——Sun的JVM Generational Collecting(垃圾回收)原理是这样的:把对象分为年青代(Young)、年老代(Tenured)、持久代(Perm),对不同生命周期的对象使用不同的算法。

(基于对对象生命周期分析)如上图所示,为Java堆中的各代分布。

1. Young(年轻代)年轻代分三个区。

一个Eden区,两个Survivor区。

大部分对象在Eden区中生成。

当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当这个Survivor 区满时,此区的存活对象将被复制到另外一个Survivor区,当这个Survivor去也满了的时候,从第一个Survivor区复制过来的并且此时还存活的对象,将被复制年老区(Tenured。

需要注意,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden 复制过来对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从第一个Survivor去过来的对象。

而且,Survivor区总有一个是空的。

2. Tenured(年老代)年老代存放从年轻代存活的对象。

一般来说年老代存放的都是生命期较长的对象。

3. Perm(持久代)用于存放静态文件,如今Java类、方法等。

持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些class,例如Hibernate等,在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。

持久代大小通过-XX:MaxPermSize=进行设置。

举个例子:当在程序中生成对象时,正常对象会在年轻代中分配空间,如果是过大的对象也可能会直接在年老代生成(据观测在运行某程序时候每次会生成一个十兆的空间用收发消息,这部分内存就会直接在年老代分配)。

年轻代在空间被分配完的时候就会发起内存回收,大部分内存会被回收,一部分幸存的内存会被拷贝至Survivor的from区,经过多次回收以后如果from区内存也分配完毕,就会也发生内存回收然后将剩余的对象拷贝至to区。

等到to区也满的时候,就会再次发生内存回收然后把幸存的对象拷贝至年老区。

通常我们说的JVM内存回收总是在指堆内存回收,确实只有堆中的内容是动态申请分配的,所以以上对象的年轻代和年老代都是指的JVM的Heap空间,而持久代则是之前提到的Method Area,不属于Heap。

了解完这些之后,以下的转载一热衷于钻研技术的哥们Richen Wang关于内存管理的一些建议——1、手动将生成的无用对象,中间对象置为null,加快内存回收。

2、对象池技术如果生成的对象是可重用的对象,只是其中的属性不同时,可以考虑采用对象池来较少对象的生成。

如果有空闲的对象就从对象池中取出使用,没有再生成新的对象,大大提高了对象的复用率。

3、JVM调优通过配置JVM的参数来提高垃圾回收的速度,如果在没有出现内存泄露且上面两种办法都不能保证内存的回收时,可以考虑采用JVM调优的方式来解决,不过一定要经过实体机的长期测试,因为不同的参数可能引起不同的效果。

如-Xnoclassgc参数等。

推荐的两款内存检测工具1、jconsole JDK自带的内存监测工具,路径jdk bin目录下jconsole.exe,双击可运行。

连接方式有两种,第一种是本地方式如调试时运行的进程可以直接连,第二种是远程方式,可以连接以服务形式启动的进程。

远程连接方式是:在目标进程的jvm启动参数中添加-Dcom.sun.management.jmxremote.port=1090-Dcom.sun.management.jmxremote.ssl=false-Dcom.sun.management.jmxremote.authenticate=false 1090是监听的端口号具体使用时要进行修改,然后使用IP加端口号连接即可。

通过该工具可以监测到当时内存的大小,CPU的使用量以及类的加载,还提供了手动gc的功能。

优点是效率高,速度快,在不影响进行运行的情况下监测产品的运行。

缺点是无法看到类或者对象之类的具体信息。

使用方式很简单点击几下就可以知道功能如何了,确实有不明白之处可以上网查询文档。

2、JProfiler 收费的工具,但是到处都有破解办法。

安装好以后按照配置调试的方式配置好一个本地的session即可运行。

可以监测当时的内存、CPU、线程等,能具体的列出内存的占用情况,还可以就某个类进行分析。

优点很多,缺点太影响速度,而且有的类可能无法被织入方法,例如我使用jprofiler时一直没有备份成功过,总会有一些类的错误简单的概念:堆(Heap)和非堆(Non-heap)内存按照官方的说法:“Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配。

堆是在Java 虚拟机启动时创建的。

”“在JVM中堆之外的内存称为非堆内存(Non-heap memory)”。

可以看出JVM主要管理两种类型的内存:堆和非堆。

简单来说堆就是Java代码可及的内存,是留给开发人员使用的;非堆就是JVM留给自己用的,所以方法区、JVM内部处理或优化所需的内存(如JIT编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码都在非堆内存中。

∙堆内存分配JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4。

默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。

因此服务器一般设置-Xms、-Xmx相等以避免在每次GC 后调整堆的大小。

∙非堆内存分配JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。

∙JVM内存限制(最大值)首先JVM内存限制于实际的最大物理内存(废话!呵呵),假设物理内存无限大的话,JVM 内存的最大值跟操作系统有很大的关系。

简单的说就32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制,这个限制一般是2GB-3GB(一般来说Windows系统下为1.5G-2G,Linux系统下为2G-3G),而64bit以上的处理器就不会有限制了java虚拟机内存管理机制(二):了解JVM的内存管理与垃圾回收收藏Java语言具备GC(垃圾回收)的能力,内存管理不需要应用程序去过问,这很方便。

但是,GC是怎么进行的,JVM的内存参数应该怎么调整,如何优化,往往我们不是太清楚。

看过一些资料后,对Sun JVM的内存管理以及垃圾回收的机制大概有了一个概念,这里将这些资料归纳和翻译出来。

本文内容主要基于Sun JVM 1.3.1,在后续版本中有不少优化措施,但是这些基本概念还是不变的。

这里假设大家对GC的概念和基本原理都已经了解,不详细叙述了。

当JVM进行GC的时候,是要消耗CPU资源和需要一定时间的,这会影响到程序的正常运行,因此需要尽可能减少GC消耗的时间。

Java程序运行过程中,对象的生命周期有长有短,其中相当大部分是都是比较短命的,例如局部的对象一用完就可以回收了。

在大多数情况下,只要能够及时回收这些短命对象的内存,就能够确保JVM有足够内存来分配给新的对象。

因此JVM采用一种分代回收(generational collection) 的策略,用较高的频率对年轻的对象(young generation)进行扫描和回收,这种叫做minor collection,而对老对象(old generation)的检查回收频率要低很多,称为major collection。

相关文档
最新文档