2016-12-16 14 views
0

Я следующий код, который генерирует (намеренно) в PermGen java.lang.OutOfMemoryError:Флаги для PermGen не работает, как ожидалось: -XX: + CMSClassUnloadingEnabled и -XX: + CMSPermGenSweepingEnabled


public class Main { 

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, InterruptedException { 
     String name = "MyClass"; 
     DynamicClassLoader cl = new DynamicClassLoader(); 

     int i = 0; 
     while (true) { 
      //code for generating the binary for a class to be loaded. 
      ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); 
      cw.visit(Opcodes.V1_7, Opcodes.ACC_PUBLIC, name + ++i, null, "java/lang/Object", null); 
      MethodVisitor con = cw.visitMethod(Opcodes.ACC_PUBLIC, "", "()V", null, null); 
      con.visitCode(); 
      con.visitVarInsn(Opcodes.ALOAD, 0); 
      con.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "", "()V", false); 
      con.visitInsn(Opcodes.RETURN); 
      con.visitMaxs(1, 1); 
      cw.visitEnd(); 
      //binary code for class successfully generated 

      Class clazz = cl.defineClass(name + i, cw.toByteArray()); 
      Object o = clazz.newInstance(); 
      System.out.println(o.getClass().getName()); 
     } 
    } 

    private static class DynamicClassLoader extends ClassLoader { 
     public Class defineClass(String name, byte[] b) { 
      return defineClass(name, b, 0, b.length); 
     } 
    } 
} 

Я бегу этот код в Java 7 Как и ожидалось, он получает ошибку java.lang.OutOfMemoryError: PermGen space. Когда я пытаюсь запустить эту программу с указанными флагами следующим образом:

java -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled -jar target/permgen.jar 

, я все еще получаю ту же ошибку, в точно таким же точке, когда я запускаю его без флагов. Я ожидал, что если я поместил эти флаги, если бы не было общего обновления PermGen, по крайней мере частичное улучшение было бы видно. Но это не так.

Вопрос: Я не понимаю смысл этих флагов? Можете ли вы подробно, если это так, пожалуйста? В противном случае, какие-либо предложения?

N.B. Выход java -version является:

ява версия "1.7.0_95"

OpenJDK Runtime Environment (IcedTea 2.6.4) (7u95-2.6.4-3)

OpenJDK 64-разрядного сервера VM (сборка 24.95-b01, смешанный режим)

+2

Можете ли вы изменить свой тестовый пример, чтобы ваш экземпляр 'DynamicClassLoader' не поддерживался на протяжении всей продолжительности теста? AFAIK, все загрузчики классов сохраняют ссылку на все классы, которые они загружают. Если ваш загрузчик классов GC'ed, ваши классы не могут быть GC'ed. – omajid

+0

@omajid Спасибо. Вы попали в гвоздь. :). Пожалуйста, отправьте его как ответ, чтобы принять его. – artaxerxe

ответ

1

Все загрузчики классов содержат надежные ссылки на все классы, которые они загружают. В вашем примере вы продолжаете использовать один экземпляр DynamicClassLoader. Этот загрузчик классов в свою очередь сохраняет сильные ссылки на все классы, которые вы загружаете. Таким образом, сборщик мусора никогда не видит объекты без ссылок, которые он может собрать.

Если вы модифицируете тестовый кейс для использования отдельных загрузчиков классов, сборщик мусора должен иметь возможность идентифицировать, что ваши классы не используются и должны восстановить память.

 Смежные вопросы

  • Нет связанных вопросов^_^