Based on duncanIdaho's ClassPath class, I modded this code. Aim is to "find all classes that are instances of a given interface or class" at runtime. I'd been using it OK for a while, and adding small fixes as problems came up (e.g. additional Throwable's).
But now...I'm getting a massive memory leak, and no idea how to solve it. Mem usage goes from 64MB to over 160MB before process is killed - just from this one method.
Note that I ran this on the same PC 12 hours earlier wihtout problems, and it produce approx 4 classes as a result of the method (which is correct - there are only 4 test instances for the code I'm currently working with).
So...AFAICS there is no reason why this shouldn't at the very least GC if it spirals out of control; I've checked that it (theoretically) isn't hanging onto references.
EDIT: see the rest of thread for details, but basically the OOME is from too much method calling, hence sidesteps GC. Silly me can no longer recognise an infinite recusive loop in java runtimes (probably simply because it looks different in logging frameworks compared to in DOS prompt where I learnt it

)
I could try to limit by package name using the regex, but I'd like to be fully automatic and not rely on unreliable voluntary naming conventions! Meanwhile, any ideas on why this code OutOfMemoryError's on 1.4.2_05 instead of GC'ing?
NB: ignore the poor package name; that was from before i got the JGF domain - it will be fixed before I post the JAR!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| package com.grexengine.jgf;
import java.util.ArrayList; import java.util.Iterator;
public class ClassLocater { public static Class[] getSubclassesOf( Class targetType ) { return getSubclassesOf( targetType, ".*" ); } public static Class[] getSubclassesOf( Class targetType, String regex ) { ArrayList matches = new ArrayList(); ClassPath cp = new ClassPath(); Iterator i = cp.classNameIterator(); while ( i.hasNext() ) { String className = (String)i.next(); if ( className.matches( regex ) && !className.equals( targetType.getName() ) ) { Class clazz = null; try { clazz = Class.forName( className ); } catch (ClassNotFoundException cnfx ) { continue; } catch (NoClassDefFoundError cnfx ) { continue; } catch( UnsatisfiedLinkError cnfx ) { continue; } finally { if ( clazz != null && targetType.isAssignableFrom( clazz ) ) { matches.add( clazz ); } } } } return (Class[])matches.toArray( new Class[0] ); } } |