In which circumstances a Class.forName() can fail?

I

Ivo

Hello to all,

In which circumstances a Class.forName() can fail, when the String
comes from the STE class ???

(I have been getting ClassNotFoundException, which should never happen
by my knowledge :( )

here is the code snippet:

final String className = stackTraceElement.getClassName();
Class clazz;
try {
clazz = Class.forName(className);
} catch (final ClassNotFoundException cnfe) {
// should be totally impossible since any Class having
methods locked in a stack
// frame cannot be removed from VM.
// throw new IllegalStateException(cnfe);
return null;
}

thank you very much,

Ivo
 
I

info

How "fresh" is the StackTraceElement you extracted the class name
from ? If the STE is old, there's no guarantee that the class it
referred to is still loaded.If STEs used Class references, then that
would prevent the class from being GCed.. but since the reference is
in the form of a String, the Class can disappear.. and that would
probably give you a CNFE.
 
E

Eric Sosman

Ivo said:
Hello to all,

In which circumstances a Class.forName() can fail, when the String
comes from the STE class ???

(I have been getting ClassNotFoundException, which should never happen
by my knowledge :( )

here is the code snippet:

final String className = stackTraceElement.getClassName();
Class clazz;
try {
clazz = Class.forName(className);
} catch (final ClassNotFoundException cnfe) {
// should be totally impossible since any Class having
methods locked in a stack
// frame cannot be removed from VM.
// throw new IllegalStateException(cnfe);
return null;
}

Class.forName(String) is documented as being equivalent
to Class.forName(String, true, currentLoader), where the final
argument is the current ClassLoader. If the class you are
looking for was loaded by a different ClassLoader, I imagine
that looking for it with the wrong ClassLoader might fail.
 
I

Ivo

     Class.forName(String) is documented as being equivalent
to Class.forName(String, true, currentLoader), where the final
argument is the current ClassLoader.  If the class you are
looking for was loaded by a different ClassLoader, I imagine
that looking for it with the wrong ClassLoader might fail.

The STE is straight from a trace obtained from the current Thread, all
of which is still in scope, so not GCed.
 
E

Eric Sosman

Ivo said:
The STE is straight from a trace obtained from the current Thread, all
of which is still in scope, so not GCed.

I don't see what difference that makes. Threads are not
ClassLoaders, and ClassLoaders are not Threads, and neither
Threads nor ClassLoaders are garbage collectors.

I don't know whether your problem is or is not caused
by a ClassLoader mismatch -- how could I? -- but just
suggesting that it's something to consider.
 
A

Andreas Leitgeb

Eric Sosman said:
I don't see what difference that makes. ...

I'd think that Ivo's followup was probably rather intended
for <[email protected]>'s post, which it seems to match
better.

Ivo: it's possible, that some method of a class loaded
through a special classloader called back to your method
(loaded from normal classloader) all within the same thread.

Let your exception handler print out (or log) that error-
triggering class name. Once you see it, perhaps you
recognize it as belonging to your project, anyway.
If not, you can try googling for it, or asking here again
with the fully qualified class name.

PS: finally, perhaps it returned null from a different place,
and never really got into that one exception handler ;-)
 
I

Ivo

Thank you all for your time and help,

the root of problem was like Andreas suggested.

"that some method of a class loaded through a special classloader
called back to your method (loaded from normal classloader) all within
the same thread."

I had to obtain the instance of ClassLoader that loaded the class in
the stacktrace so I could use it latter in the Class.forName
(..., ...,...);
This solved the problem.

Cheers,
Ivo





Ivo wrote:

...
The STE is straight from a trace obtained from the current Thread, all
of which is still in scope, so not GCed.

Local variables in the method invocation that threw the exception, and
any others that completed abruptly because of the exception, are now out
of scope. Objects referenced only through those variables, and in
expressions in those methods, may have been collected.

However, "A class or interface may be unloaded if and only if its
defining class loader may be reclaimed by the garbage collector as
discussed in §12.6. Classes and interfaces loaded by the bootstrap
loader may not be unloaded."http://java.sun.com/docs/books/jls/third_edition/html/execution.html#...

That indicates that an unloaded class would also have to involve a
non-bootstrap ClassLoader. Moreover, if the class were loadable by the
bootstrap ClassLoader the forName call would have succeeded, by
initializing the class if necessary.



StackTraceElement does not validate the class name. If the exception had
been modified since being generated, the name might not even really be a
class name. Throwable has a public setStackTrace, so one could put in an
arbitrary StackTraceElement[], not necessarily one generated by
fillInStackTrace.

Have you tried displaying the class name for which the forName call
fails? It would be easy to do from the exception handler, and might
distinguish e.g. an arbitrary String from the name of a class loaded
with a non-bootstrap ClassLoader. Or maybe trigger some entirely new
hypothesis.

Patricia
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,825
Latest member
VernonQuy6

Latest Threads

Top