10

I need to test some JMX monitoring scripts I have developed, In particular I would like to verify that my monitoring of the PermGen region is working. So in order to test this I would like to be able to run a bit of code that loads a significant number of classes in order to consume PermGen.

My current plan is to write a script to generate prefix(1..n).java compile them and then on cue run:

for( int i=1 ; i < n ; i ++){
    Class.forName("com.mypackage.prefix"+i);
}

Is there a more elegant solution to achieve this?

Gareth Davis
  • 27,701
  • 12
  • 73
  • 106
  • I think that if you instantiate a new ClassLoader and load the same class over and over, it will reach your goal without the need to create tons of different classes. Alternatively, I think that String.intern() can also fill your PermGen space – Guillaume Polet Mar 21 '12 at 10:27
  • @Guillaume: that's an answer, not a comment! – Tom Anderson Mar 21 '12 at 10:28
  • @Tom, yes and no because I am not sure of this, so this is more a suggestion. I don't want to look affirmative on this. ;-) – Guillaume Polet Mar 21 '12 at 10:36
  • 1
    @Guillaume : Woot! Memory leak successfully created String.intern()..works a tread... one completely broken glassfish instance! (not that it worked to start with). Do you want to add that as an answer – Gareth Davis Mar 21 '12 at 10:43
  • `prefix(1..n).java` should be `prefix(1..n).class` in the question, shouldn't it? – user unknown Mar 21 '12 at 12:25
  • I didn't really expand on my idea, but I was going to generate the .java files then compile them into .class...I'll update the question to be clear – Gareth Davis Mar 21 '12 at 12:28

1 Answers1

10

OK, so looks like String.intern() will do the trick. Here is one implementation I found. Credits goes to Gareth as well:

public static void main(String[] args) throws ClassNotFoundException {
    int i = 0;
    StringBuilder sb = new StringBuilder("a");
    for (i = 0; i < 20; i++) {
        sb.append(sb.toString());
    }
    System.err.println(sb.length());
    i = 0;
    Set<String> strings = new HashSet<String>();
    while (true) {
        strings.add(sb.append(i++).toString().intern());
        System.err.println(i);
    }
}
Guillaume Polet
  • 47,259
  • 4
  • 83
  • 117
  • Nice solution. The bit that caught me out the first time around is that unless you retain a reference to the interned string the GC will simply empty the strings from PermGen on the FullGC that you will eventually force. – Gareth Davis Mar 21 '12 at 11:03