一.Java 程序的运行机制与普通程序,如C或C++ 程序的运行机制有很大的区别。
  普通程序运行之前必须首先编译成可执行的二进制码或机器码。机器码是与底层的硬件结构相关的,即使书写源代码的时候没有利用平台特定的扩展语言,如特定的文件访问或图形用户界面,生成的机器码仍然被绑定到一个特定的硬件平台,从而只能运行在那个体系结构上,也就是说,为Sun工作站编译的机器码不能运行在PC机上,为PC机编译的机器码不能运行在苹果机上,以此类推。
  与此相反,Java源代码不是为某种特定平台编译的,而是编译成与平台无关的字节码(Byte Code),这种字节码叫做Java Class(Java 类文件)。在任何一种操作系统平台上的字节码都是一样的,因此都可以在任何支持Java 虚拟机(JVM)的计算机上运行。JVM 直接受操作系统控制(而不是Java程序直接受操作系统控制),它负责将字节码转换成在特定平台上能够运行的机器码。正是由于这个原因,Java做到了“write once, run anywhere”(书写一次,到处运行)
  运行Java程序时,首先需要由JVM把Java class加载到JVM里面。通常情况下,我们不会去关注JVM的内部工作细节而只是直接拿来使用。然而,作为一个Java开发人员,你经常会遇到与内存相关的性能问题。这个问题最可怕的就是OutOfMemoryError:PermGen space错误。
  这个错误通常会在以下三种情况下发生(服务器以Tomcat为例):
  (1)应用程序加载了大量的类。
  (2)在单一的Tomcat实例下运行多个Web应用程序。
  (3)在运行的Tomcat实例中反复“热部署”Web应用程序。
  下面我们对该错误进行探究,分析该错误的常见原因,并给出避免这一错误的解决办法。
  1.JVM 的内存结构
  为了理解这一错误,我们必须了解JVM的内存是如何构造的。
  JVM有两个内存区域,一个是堆(heap),另一个是栈(stack)。局部的变量和方法驻留在栈里面,其余的一切都驻留在堆中。
  Java的堆又进一步按照区域进行组织,这些区域被称为generation。一个对象在JVM存在的时间越长,它被升迁到老的generation中的几率就越高。年轻的generation要比老的generation更多、更容易地被垃圾回收。同时还存在一些单独的堆空间,被称为永久保存区域(permanent generation),它们不属于Java堆的一部分,用来存放类和类的描述。
  类加载器的工作是不断地部署和取消部署Java类。例如,将一个Web应用程序部署到Web服务器或取消部署。在Web服务器上,所有应用程序都有自己的类加载器,部署或取消部署应用程序时,它的类定义和类加载器分别投入到永久保存区域中或者从永久保存区域中删除。
  2.OutOfMemoryError: PermGen space
  当永久保存区域的空间耗尽时OutOfMemoryError: PermGen space就会发生,这个错误一般是由于内存泄漏导致的。所谓内存泄漏,是指java类和类加载器在被取消部署后不能被垃圾回收。怎么会发生这种情况呢?举个例子:假如我们有一个Student类,这个类是Web应用程序jar包的一部分,同时在Web服务器的lib文件夹中包含了某种日志框架,其中有一个Log类提供register方法调用,从而使得别的类通过注册就可以使用日志功能。如果Student类被注册了,那么Log类就开始拥有了一个对Student对象的引用(reference)。当Student类取消部署时,它仍然是注册Log类的,Log类仍然拥有对Student对象的引用,因此,Student对象永远不会被垃圾回收。此外,由于Student对象拥有一个对它的ClassLoader的引用,所以ClassLoader本身永远也不会被垃圾回收,从而导致由它加载的所有类都不会被回收。
  一个更为典型的例子是使用代理对象。Spring和Hibernate常常为某些类生成代理类,这些代理类也是通过类加载器加载的,并且存储在永久保存区域的堆空间,它们永远不会被丢弃,从而会导致永久保存区域的堆空间被填满。
  3.如何避免永久保存区域内存不足
  3.1 增加PermGen堆的最大尺寸
  当遇到java.lang.OutOfMemoryError:PermGen space错误时,我们可以做的第一件事情是增加永久保存区域的最大尺寸,该尺寸的缺省设置是64 M,我们可以将它设置成128 M以上。这个工作不能通过常规的JVM参数 -Xms(设置初始堆大小)和-Xmx(设置最大堆大小)来完成,因为前面已经提到,永久保存区域完全独立于普通的Java堆,这些参数是用来设置普通的Java堆的。不过也有类似参数用于设置永久保存区域的规模:
  java -XX:MaxPermSize=128 M
  该设置将永久保存区域设置为128 M,这个大小是默认设置的两倍。
  对于Tomcat服务器,则需要修改TOMCAT_HOME/bin/catalina.sh
  SET JAVA_OPTS=-XX:PermSize=64 M -XX:MaxPermSize=128 M
  3.2 避免使用静态字段
  确保在编写Java类时,不要使用静态变量作为对其他对象的引用。
  3.3使用JDK动态代理,而不是CGLIB代理
  一些第三方的框架,如CGLIB会吞食大量的PermGen。因此,当遇到PermGen错误时,应尽快升级cglib到最新版;改用JDK动态代理,也是一个不错的选择。
  3.4更新到最新版本Hibernate3.2
  此外,新版本的Hibernate不再使用CGLIB作为字节码提供者了,所以及时升级Hibernate,会大大降低出错的机会。
  3.5共用的jar文件放到共享目录下
  如果在服务器上同时发布了多个应用,那么应该把共用的jar文件放到所有应用都可以访问的目录下。针对Tomcat而言,如果Tomcat下面有多个应用,应尽可能地把lib目录下共用的jar文件放到Tomcat的common\lib或shared\lib下,以避免重复发布,发布速度和运行速度上也会有所提升。
  4.结束语
  内存不足问题是潜伏较深的问题,且不容易解决。一般情况下,当发生该错误的时候,需要确定为什么某些类不被垃圾回收,只有这样做才能够消除这个错误。
  

本文摘自中国论文网,原文地址:http://www.xzbu.com/8/view-3801715.htm

Java内存不足之PermGen space错误探究的更多相关文章

  1. 出现 java.lang.OutOfMemoryError: PermGen space 错误的原因及解决方法

    一.原因及解决方法[1] 1.原因:堆内存的永久保存去区内存分配不足(缺省默认为64M),导致内存溢出错误. 2.解决方法:重新分配内存大小,-Xms1024M -Xmx2048M -XX:PermS ...

  2. windows系统bat方式启动tomcat出现java.lang.OutOfmemoryError:PermGen Space 错误

    1.问题情景: 在部署项目时,将两个应用部署到同一个tomcat下,通过startup.bat启动服务时,控制台出现出现java.lang.OutOfmemoryError:PermGen Space ...

  3. Tomcat死机报OutOfMemoryError: PermGen space错误

    最近,用户没怎么使用系统,页面就卡死,访问不了.仔细一看是Tomcat假死,好几次都这样.重启也慢的很,很着急.最后,看了下 conf/logs 里的配置文件,发现是 OutOfMemoryError ...

  4. PermGen space错误解决方法

    在看下文之前,首先要确认意见事情,就是你是怎样启动tomcat的,我们在平时的开发环境其中,都是通过startup.bat方式启动tomcat的,那么你依照以下的方式,去改动/bin/catalina ...

  5. tomcat内存溢出之PermGen space

    线上一台web服务器不能正常访问了,检查了一下,tomcat进程还在,就是web不能正常访问,重启一下tomcat恢复正常,查询日志,发现提示内存溢出,如下图: java.lang.OutOfMemo ...

  6. tomcat启动出现PermGen space错误

    今天部署项目时,出现了jvm内存溢出的问题,显示PermGen  space错误. 经过不断的努力,终于解决出来了. 步骤如下: 在eclipse中菜单栏run-->RunConfigurati ...

  7. IDEA控制台问题:java lang OutOfMemoryError:PermGen space

    PermGen space的全称是Permanent Generation space,是指内存的永久保存区域. OutOfMemoryError: PermGen space从表面上看就是内存溢出, ...

  8. JMeter-java.lang.OutOfMemoryError: PermGen space错误

    PermGen space的全称是Permanent Generation space,是指内存的永久保存区域,这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被 ...

  9. 在Eclipse中运行Jboss时出现java.lang.OutOfMemoryError:PermGen space及其解决方法

    在Eclipse中运行Jboss时出现java.lang.OutOfMemoryError:PermGen space及其解决方法 在Eclipse中运行Jboss时,时间太长可能有时候会出现java ...

随机推荐

  1. C#中的DllImport使用方法

    DllImport是System.Runtime.InteropServices命名空间下的一个属性类,其功能是提供从非托管DLL导出的函数的必要调用信息 DllImport属性应用于方法,要求最少要 ...

  2. 【TCP/IP详解 卷一:协议】第十二章 广播与多播 ping实验

    我手机连接到wifi上所分配到的IP地址:192.168.1.116 子网掩码:255.255.255.0 路由器:192.168.1.1 ping 192.168.1.116 (ping 一台主机的 ...

  3. 又见链表 --- 另一种Creat方式与反转

    链表 作为一种数据结构,链表以其方便的增删查改功能,实现了无数经典有用的程序. 在之前的帖子里,我构建链表的方式是建立一个不储存数据的head节点,然后通过一边输入数据一边建立结点的方式构建整个链表. ...

  4. HDU 3586 Information Disturbing(二分+树形dp)

    http://acm.split.hdu.edu.cn/showproblem.php?pid=3586 题意: 给定一个带权无向树,要切断所有叶子节点和1号节点(总根)的联系,每次切断边的费用不能超 ...

  5. UVa 10970 大块巧克力

    https://vjudge.net/problem/UVA-10970 题意: 把一个m行n列的矩形巧克力切成mn个1×1的方块,需要切几刀. 思路: 可以考虑用动态规划的方法去做,当然,最简单的是 ...

  6. navicat Window . MAC版常用快捷键

    navicat 结合快捷键 1.ctrl+q 打开查询窗口 2.ctrl+/ 注释sql语句 3.ctrl+shift +/ 解除注释 4.ctrl+r 运行查询窗口的sql语句 5.ctrl+shi ...

  7. phpMyAdmin-Error:The mbstring extension is missing. Please check your PHP configuration.

    1.打开php.ini 2.找到 ; extension_dir = "./",把前面的分号去掉.引号里改成extension_dir = "D:php/ext" ...

  8. robot_pose的类型

    http://docs.ros.org/api/geometry_msgs/html/msg/Pose.html

  9. python 集合的运算

    x = frozenset([, , , , ]) y = frozenset([, , , , ]) #如果x与y没有公共元素,返回true print(x.isdisjoint(y)) #返回x与 ...

  10. C++创建虚拟机调用JAVA类

    ZC: 简要摘抄: “ 1.      Object类出创建JVM. 使用Java类之前必须要创建JVM环境.JDK由java.exe来完成.本文有Object类的静态方法BeginJVM来创建,用E ...