Java 为什么永久代空间在增长?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2051734/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 03:01:07  来源:igfitidea点击:

Why is PermGen space growing?

javamemory-leaksmemory-management

提问by Pablo Fernandez

I've read a few articles, and I understood the following (please correct me and/or edit the question if I'm wrong):

我已经阅读了几篇文章,并且我了解以下内容(如果我错了,请纠正我和/或编辑问题):

The java heap is segmented like this:

java堆是这样分段的:

  • Young Generation: objects that are created go here, this part is frequently and inexpensively garbage collected

  • Old Generation: objects that survive the garbage collections of the Young generation go here, this area is garbage collected less frequently and using a more CPU demanding process/algorithm (I believe it's called mark-sweep)

  • 年轻代:创建的对象在这里,这部分被频繁且廉价地垃圾收集

  • 老年代:在年轻代垃圾收集中幸存下来的对象到这里,这个区域垃圾收集的频率较低,并且使用对 CPU 要求更高的进程/算法(我相信它被称为标记扫描)

Edit: as stated by another user, PermGen is not a part of the region called heap

编辑:如另一位用户所述,永久代不属于名为 heap

  • PermGen: this area is filled of your app classes metadata and many other things that do not depend on the application usage.
  • PermGen:这个区域充满了你的应用程序类元数据和许多其他不依赖于应用程序使用的东西。

So, knowing this... why does my PermGen space grows when the app is under heavy load? For what I said before this space should not incrementally fill in spite of the app load, but as I said in the beginning probably I'm wrong about some assumptions.

那么,知道这一点......为什么我的永久代空间在应用程序负载较重时会增长?对于我之前所说的,尽管应用程序加载,这个空间不应该增量填充,但正如我在开始时所说的,我可能对某些假设是错误的。

In fact if the PermGen space is growing, is there a way of garbage collect or reset it?

事实上,如果 PermGen 空间在增长,是否有垃圾收集或重置它的方法?

采纳答案by Joshua McKinnon

Actually, in Sun's JVM Permanent Generation (PermGen) is completely separate from the heap. Are you sure you aren't looking at the Tenured Generation? It would be suspicious indeed if your Permanent Generation kept growing.

实际上,在 Sun 的 JVM 中,永久代 (PermGen) 与堆是完全分开的。你确定你不是在看老一代吗?如果您的永久一代继续增长,确实会令人怀疑。

If your perm gen IS growing constantly, it is a difficult area to dig into. Generally it should grow when new classes are loaded for the first time (and potentially certain uses of reflection could also cause this). Interned strings are also stored in perm gen.

如果你的烫发不断增长,这是一个很难挖掘的领域。通常它应该在第一次加载新类时增长(并且反射的某些潜在用途也可能导致这种情况)。实习字符串也存储在 perm gen 中。

If you happen to be on Solaris, you could use jmap -permstatto dump out perm gen statistics, but that option does not appear to be available on Windows (and potentially other platforms). Here is the documentation on jmap for Java 6

如果您碰巧在 Solaris 上,则可以使用jmap -permstat转储 perm gen 统计信息,但该选项在 Windows(以及可能的其他平台)上似乎不可用。这是有关 Java 6 的 jmap 的文档

From Sun's guide on JConsole(which will let you view the size of these pools):

来自 Sun 的JConsole 指南(可让您查看这些池的大小):

For the HotSpot Java VM, the memory pools for serial garbage collection are the following.

  • Eden Space (heap): The pool from which memory is initially allocated for most objects.
  • Survivor Space (heap): The pool containing objects that have survived the garbage collection of the Eden space.
  • Tenured Generation (heap): The pool containing objects that have existed for some time in the survivor space.
  • Permanent Generation (non-heap): The pool containing all the reflective data of the virtual machine itself, such as class and method objects. With Java VMs that use class data sharing, this generation is divided into read-only and read-write areas.
  • Code Cache (non-heap): The HotSpot Java VM also includes a code cache, containing memory that is used for compilation and storage of native code.

对于 HotSpot Java VM,串行垃圾回收的内存池如下。

  • Eden Space(堆):最初为大多数对象分配内存的池。
  • Survivor Space(堆):包含在 Eden 空间的垃圾收集中幸存下来的对象的池。
  • Tenured Generation(堆):包含在幸存者空间中存在一段时间的对象的池。
  • 永久代(非堆):包含虚拟机本身所有反射数据的池,例如类和方法对象。对于使用类数据共享的Java VM,这一代分为只读和读写区域。
  • 代码缓存(非堆):HotSpot Java VM 还包括一个代码缓存,其中包含用于编译和存储本机代码的内存。

回答by Jonathan Feinberg

Are you doing something funky with the classloader chain? Are you calling intern()on a bunch of strings?

你在用类加载器链做一些时髦的事情吗?你在调用intern()一堆字符串吗?

回答by Jim Mitchener

This is a very common problem when you are manipulating the classloader. This is seen a lot in Java EE apps when you are redeploying hibernate/cglib. For more info check out

当您操作类加载器时,这是一个非常常见的问题。当您重新部署 hibernate/cglib 时,这在 Java EE 应用程序中很常见。欲了解更多信息,请查看

http://opensource.atlassian.com/confluence/spring/display/DISC/Memory+leak+-+classloader+won%27t+let+go

http://opensource.atlassian.com/confluence/spring/display/DISC/Memory+leak+-+classloader+won%27t+let+go

回答by John Stauffer

The most common causes I've seen are:

我见过的最常见的原因是:

  • Custom classloaders that don't carefully free up older classes after loading new ones.
  • Classes remaining in PermGen after redeploying an application multiple times (more common in Dev than Prod)
  • Heavy use of Proxy classes, which are created synthetically during runtime. It's easy to create new Proxy classes when an a single class definition could be reused for multiple instances.
  • 自定义类加载器在加载新类后不小心释放旧类。
  • 多次重新部署应用程序后仍保留在 PermGen 中的类(在开发中比生产中更常见)
  • 大量使用代理类,这些类是在运行时综合创建的。当单个类定义可用于多个实例时,很容易创建新的 Proxy 类。

回答by Jason Stelzer

This is one of the more annoying problems to debug. There are a lot of reasons you could be seeing growing permgen use. Here are 2 links I found very useful in both understanding how leaks happen as well as tracking down what is causing them.

这是调试中比较烦人的问题之一。您可能会看到 permgen 的使用越来越多,原因有很多。这里有 2 个链接,我发现它们在理解泄漏如何发生以及追踪导致泄漏的原因方面非常有用。

http://frankkieviet.blogspot.com/2006/10/how-to-fix-dreaded-permgen-space.html

http://frankkieviet.blogspot.com/2006/10/how-to-fix-dreaded-permgen-space.html

http://frankkieviet.blogspot.com/2006/10/classloader-leaks-dreaded-permgen-space.html

http://frankkieviet.blogspot.com/2006/10/classloader-leaks-dreaded-permgen-space.html

回答by Sajid

If you are working with Java EE application it's probably a classloader leak.

如果您正在使用 Java EE 应用程序,则可能是类加载器泄漏。

you might find the following additional links to be useful:

您可能会发现以下附加链接很有用:

http://www.zeroturnaround.com/blog/rjc201/

http://www.zeroturnaround.com/blog/rjc201/

http://www.ibm.com/developerworks/java/library/j-dclp3/index.html

http://www.ibm.com/developerworks/java/library/j-dclp3/index.html

回答by stones333

The most common causes I've seen are:

我见过的最常见的原因是:

  1. Java classes are loaded
  2. JAXBContext.newInstance
  3. String.intern()
  1. Java 类已加载
  2. JAXBContext.newInstance
  3. String.intern()