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!

/** * An essential part of Java - locates any Class, anywhere. * </P> * This feature would have been nice as part of the JDK for the last 7 years, but Sun hasn't * added it, so we did it instead. * <P> * Browse the different static methods to see what kinds of search you can do... */publicclassClassLocater{/** * Find all instances of the given <code>Class</code> or interface by * loading all classes on the class path. * * @param targetType the superclass of all returned classes. * @return an array of all subclasses of <code>targetType</code> */ public staticClass[] getSubclassesOf( ClasstargetType ) { return getSubclassesOf( targetType, ".*" ); }

/** * Answers an <code>Iterator</code> over fully qualified <code>Class</code> * names found on the classpath. * @return an <code>Iterator</code> over the elements in this list */publicIteratorclassNameIterator() {returnclassNames.iterator();

}

/** * Answers an <code>ArrayList</code> of all <code>Class</code> names found * on the classpath. * @return an <code>ArrayList</code> of class names. */publicArrayListgetClassNames() {returnclassNames;

IIRC Class.forName() not only loads a class but also makes any static initialization to occur (execution of static blocks and static fields). Maybe a new class has been added to the system that creates some huge static objects?

IIRC Class.forName() not only loads a class but also makes any static initialization to occur (execution of static blocks and static fields). Maybe a new class has been added to the system that creates some huge static objects?

Doh. Of course, that could explain it...however, I don't believe I have added anything with static inits of non trivial size.

I'll go do some more logging and come back with more data. I'd been hoping I was missing something obvious, but obviously not .

Oops. Seen the problem - didaho's algo only works on toy examples (no offense, but just think what happens when you get mutually referential manifests GULP).

Rewriting it now to be iterative rather than ultra-deep (potentially infinite) recursive. I think it was collapsing with OOME because of too much recursion, 99.99% of which was unnecessary .

EDIT: just to be clear, DI never presented his code as perfect, so it's fair enough that it's not optimized or anything. I adopted it in order to polish it a bit. It's just that it had worked perfectly for lots of small situations and I'd got used to it doing so, without bothering to go through the code with a fine tooth comb.

OK, I rewrote the ClassPath from scratch and now it doesn't fail even in mutually (infinitely) recursive situations, and it's noticeably faster in most cases. .

If someone wants the code urgently, email me (ceo @ grexengine.com) and I'll give you a fixed-up binary JAR. Otherwise, it can wait until JGFv3 is up, and will appear as one of the first 5 items in the "source code" section.

Ironically I was using these classes to auto-discover JGF-specific modules during the JGF server's boot process when I discovered this problem .

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org