Tôi làm việc trên ứng dụng Tomcat sử dụng bộ thu CMS cùng với thanh bộ nhớ để kích hoạt GC. Khi tôi tải lại các ứng dụng web, đôi khi tôi kết thúc trong một tình huống mà gen cũ đủ đầy đủ để kích hoạt GC nhưng các Trình nạp lớp chết không được thu thập.Khi nào thì gen perm được thu thập?
Tôi đọc rằng các lớp học được phân bổ vào thể loại perm và đoán rằng chúng được bỏ qua bởi bộ sưu tập gen cũ. Tôi đã viết bài kiểm tra sau đây để kiểm tra lý thuyết này.
package test;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.io.IOUtils;
/*
JVM Options:
-server -XX:+UseMembar -XX:+UseConcMarkSweepGC
-XX:+UseParNewGC -XX:CMSInitiatingOccupancyFraction=80
-XX:+UseCMSInitiatingOccupancyOnly -Xms100m -Xmx100m
-XX:PermSize=100m -XX:NewSize=10m -XX:MaxNewSize=10m
-verbose:gc -Xloggc:gc.log -XX:+PrintGCTimeStamps
-XX:+PrintGCDetails
*/
public class ClassLoaderTest extends ClassLoader
{
@Override
protected synchronized Class<?> loadClass(String xiName, boolean xiResolve)
throws ClassNotFoundException
{
if (xiName.equals("test"))
{
// When asked to load "test", load Example.class
Class<?> c = Example.class;
String className = c.getName();
String classAsPath = className.replace('.', '/') + ".class";
InputStream stream = c.getClassLoader().getResourceAsStream(classAsPath);
byte[] classData = null;
try
{
classData = IOUtils.toByteArray(stream);
}
catch (IOException e)
{
e.printStackTrace();
}
return defineClass(className, classData, 0, classData.length);
}
return super.loadClass(xiName, xiResolve);
}
public static class Example {}
public static ClassLoaderTest classLoaderTest;
public static void main(String[] args) throws Exception
{
// Allocate CL in new gen
classLoaderTest = new ClassLoaderTest();
// Load a class - allocated in perm gen
classLoaderTest.loadClass("test");
// Discard CL
classLoaderTest = null;
// Pause at end
Thread.sleep(99 * 60 * 1000);
}
public final byte[] mMem = new byte[85 * 1024 * 1024];
}
Tôi chạy lớp này và theo dõi kết quả sử dụng VisualVM và thấy rằng có thực sự nhiều Old and Young gen bộ sưu tập xảy ra mà không có sự Classloader chết được thu thập và do đó mảng byte lớn vẫn trong bộ nhớ.
Điều gì sẽ kích hoạt Perm Gen được thu thập?
Bạn biết chữ "Perm" là viết tắt của [... right?] (Http://en.wiktionary.org/wiki/permanent#Adjective) –
Bộ nhớ được cấp phát trong Java Perm Gen vẫn có thể được thu thập. JVM sử dụng Perm Gen để giữ dữ liệu mà nó dự kiến sẽ được giải phóng rất hiếm khi. – mchr