垃圾回收是Java程序员了解最少的一部分。他们认为Java虚拟机接管了垃圾回收,因此没必要去担心内存的申请,分配等问题。但是随着应用越来越复杂,垃圾回收也越来越复杂,一旦垃圾回收变的复杂,应用的性能将会大打折扣。所以,Java程序员了解垃圾回收的机制并且知道怎样解决“内存溢出”问题会有很大的益处。在Java中,有两个非常普遍的内存溢出问题。一个是堆内存溢出,另一个是持久代内存溢出。

持久代和类加载器

Java对象是java 类的实例。每当创建一个Java对象时,Java虚拟机都会创建该对象的内部引用并且保存在堆中。如果一个类是第一次访问,那么它必须通过Java虚拟机加载进来。类加载是定位,寻找,加载class文件和解析class文件结构的过程。类加载器负责确保加载正确的class文件。Java程序里面每一个class文件需要被同一个类加载加载。类加载器是 java.lang.ClassLoader 类的实例。目前为止,类加载器是在持久代空间里面加载类的。

Java虚拟机也创建了Java类的内部引用保存在持久代。在垃圾回收期间,Java对象和类都当做对象处理并且以同样的方式回收。最初Java对象和类都是保存在堆中。

一个性能优化措施:一旦持久代创建后,就会把classes放入里面。Classes是Java虚拟机的部分实现,我们不应该用我们的数据结构填满Java堆。持久代包含以下类信息:

  • 类方法
  • 类名称
  • 常量池信息
  • 对象数组和与类相关的类型数组
  • 被Java虚拟机使用的内部对象
  • 编译器用于优化的信息

现在我们知道了持久代是什么,接下来看看在这块会是什么原因引起内存问题。

持久代空间

当Java虚拟机需要加载定义的一个新class,但是在持久代中没有足够的空间就会抛出‘Java.Lang.OutOfMemoryError: PermGen Space’异常。默认分配给持久代的大小在server模式下是64MB ,在client模式下是32MB 。这就有两个原因可能会引起持久代内存溢出问题的发生。

第一个原因可能是你应用或者服务器已经有非常多的class在你的持久代中,已经不能容纳所有的class了。

-XX:MaxPermSize=XXXM

如果是因为大量的class导致持久代的空间的不足引起的问题,那么你可以增加持久代的大小通过–XX:MaxPermSize=XXm  参数。这将增加持久代的可用空间来保存class。看起来像这样: -XX:MaxPermSize=256m

-XX:+CMSClassUnloadingEnabled

这个参数表示在使用CMS垃圾回收机制的时候是否启用类卸载功能。默认这个是设置为不启用的,所以你想启用这个功能你需要在Java参数中明确的设置下面的参数:

-XX:+CMSClassUnloadingEnabled

如果你启用了CMSClassUnloadingEnabled ,垃圾回收会清理持久代,移除不再使用的classes。这个参数只有在 UseConcMarkSweepGC  也启用的情况下才有用。参数如下:

-XX:+UseConcMarkSweepGC

-XX:+CMSPermGenSweepingEnabled

这个参数表示是否会清理持久代。默认是不清理的,因此我们需要明确设置这个参数来调试持久代内存溢出问题。这个参数在Java6中被移除了,因此你需要使用 -XX:+CMSClassUnloadingEnabled 如果你是使用Java6或者后面更高的版本。那么解决持久代内存大小问题的参数看起来会是下面这样子:

-XX:MaxPermSize=128m -XX:+UseConcMarkSweepGC XX:+CMSClassUnloadingEnabled

内存泄露

第二个原因可能是内存泄露。那么加载的类怎样变成不用的呢?

在Java中通常class是永久存在的。一旦class被加载,他们就呆在内存中,即使服务器上的应用停掉了。像cglib这样可以动态产生class的类库会使用很多持久代空间,因为它动态的创建很多class。频繁的使用在运行时创建的代理类。当一个类定义可以为多个实例重用时很容易创建新的代理类。

Sping和Hibernate经常会代理某些class。这些代理的class是通过类加载器加载的。产生的类定义如果一直不回收就会导致持久代空间很快就满了。

你需要确定是不是内存泄露引起的持久代空间的问题,同时解决它。增加持久代空间大小将不会有用,这只会延迟它的发生,因为在某个时间点持久代还是会被填满。

如果你正在使用tomcat遇到了内存泄露问题,最新版本的tomcat有能力处理一些内存泄露问题。详细请看:

总结

一旦你遇到了持久代内容溢出问题,你需要找出这个问题是因为加载了大量的class文件还是内存泄露引起的。如果是因为class的数量过多,你可以增加持久代分配的空间大小来解决这个问题。如果是因为内存泄露,你需要引起内存泄露的根源所在并且定位它。一些框架像cglib,Spring,Hibernate会创建大量的动态类,因此对于使用这些框架的应用最好是分配多一点的持久代空间。

原文链接: http://www.javacodegeeks.com/2013/12/decoding-java-lang-outofmemoryerror-permgen-space.html

解密Java内存溢出之持久代的更多相关文章

  1. Java内存溢出异常(下)

    此篇是上一篇文章Java内存溢出异常(上)的续篇,没有看过的同学,可以先看一下上篇.本篇文章将介绍剩余的两个溢出异常:方法区和运行时常量池溢出. 方法区和运行时常量池溢出 这部分为什么会放在一起呢?在 ...

  2. java内存溢出的解决思路

    原文地址:https://www.cnblogs.com/200911/p/3965108.html 内存溢出是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于虚拟机能 ...

  3. Java基础学习总结(30)——Java 内存溢出问题总结

    Java中OutOfMemoryError(内存溢出)的三种情况及解决办法 相信有一定java开发经验的人或多或少都会遇到OutOfMemoryError的问题,这个问题曾困扰了我很长时间,随着解决各 ...

  4. Java 内存溢出分析

    原文地址:Java 内存溢出分析 博客地址:http://www.moonxy.com 一.前言 Java 的 JVM 的内存一般可分为 3 个区:堆(heap).栈(stack)和方法区(metho ...

  5. 模拟Java内存溢出

    本文通过修改虚拟机启动参数,来剖析常见的java内存溢出异常(基于jdk1.8). 修改虚拟机启动参数Java堆溢出虚拟机栈溢出方法区溢出本机直接内存溢出 修改虚拟机启动参数   这里我们使用的是ID ...

  6. Java 内存溢出(java.lang.OutOfMemoryError)的常见情况和处理方式总结

    最近老是遇见服务器内存溢出的问题,故在网上搜了搜,总结了一些java内存溢出的解决方式 java.lang.OutOfMemoryError这个错误我相信大部分开发人员都有遇到过,产生该错误的原因大都 ...

  7. java内存溢出分析(二)

    我们继续java内存溢出分析(一)的分析,点击Details>按钮,显示如下图,我们发现有一个对象数量达到280370216个,再点击其中的List objects 点击后,显示下图 至此,我们 ...

  8. Java内存溢出详解

    转自:http://elf8848.iteye.com/blog/378805 一.常见的Java内存溢出有以下三种: 1. java.lang.OutOfMemoryError: Java heap ...

  9. Java内存溢出的详细解决方案

    本文介绍了Java内存溢出的详细解决方案.本文总结内存溢出主要有两种情况,而JVM经常调用垃圾回收器解决内存堆不足的问题,但是有时仍会有内存不足的错误.作者分析了JVM内存区域组成及JVM设置虚拟内存 ...

随机推荐

  1. 如何将现有的项目添加到远程的git库里面!

    我们经常都会遇到这样的场景,就是将本地的一个项目同步到网上远程的git库里面.最近也遇到这样的问题,发现网上很少人讲到这个问题,但是这个问题是很多程序员遇到的版本库管理的最早的拦路虎. 我的远程是ht ...

  2. Mybatis基本用法

    搭建mybatis环境 1, 导入需要的jar包 mybatis-*.*.*.jar ojdbc6.jar 2, 配置mybatis的总配置文件: mybatis-config.xml 配置根标签 & ...

  3. Velocity 语法详解

    Velocity是基于Java的模板引擎,它允许页面设计者引用Java中定义的方法.页面设计者和Java开发者能够同时使用MVC的模式开发网站,这样网页设计者能够把精力放在页面的设计上,程序员也可以把 ...

  4. Python 3基础教程13-写入文件

    前面介绍了函数,这篇我们就利用Python 内构函数open来写入字符串到txt文件里. 直接看demo.py 这里有一个小问题,如果我要输入时中文到txt文件会报unicode错误,暂时没法解决.

  5. Spider_Man_6 の Scrapy_Downloader Middleware(针对一下🐷🐷🐷)

    下载器中间件(Downloader Middleware) 下载器中间件是介于Scrapy的request/response处理的钩子框架.是用于全局修改Scrapy request和response ...

  6. ThreadLocal 学习

    JDK 1.2版本就已经提供了java.lang.ThreadLocal.其为多线程程序的并发问题提供了一种新的思路.使用该工具类可以简洁地编写出优美的多线程程序. 当使用ThreadLocal维护变 ...

  7. CodeForces C. Maximal Intersection

    http://codeforces.com/contest/1029/problem/C You are given nn segments on a number line; each endpoi ...

  8. Nginx主要模块常用指令说明

    核心模块(Core Modules): 主模块(Main Module):配置和服务器全局有关的一些参数,比如错误日志.进程.权限等 user worker_processes error_logsy ...

  9. JZOJ 5305 C先生

    题意: 有一个n个点,m条边的图,没有重边.自环,且每一条边最多属于一个环路. 给出q组询问,每次询问u,v两点间的路径有多少种可能. 思路: 先看下方样例说明: 由样例说明可以得知,路径上每经过一个 ...

  10. 【POJ 2752 Seek the Name, Seek the Fame】

    Time Limit: 2000MSMemory Limit: 65536K Description The little cat is so famous, that many couples tr ...