I'm having a problem with a custom ClassLoader class that was written to
dynamically load classes from zip or jar files. The way this is supposed
to work is as follows: the ClassLoader iterates through each entry in the
zip or jar, and if the file name ends with ".class" it extracts the bytes
and tries to define the image as a class. Simple enough. However, we ran
into problems with class dependencies; for example, if Car is a class and
class Beetle extends Car, the definition of Beetle will fail if Beetle
comes before Car in the jar file. To attempt to fix this, I added logic
to catch LinkageErrors during the class defining call (later changed to
catch all Throwables) and "defer" loading of classes that had problems,
saving them in a collection under the assumption that something we'll load
later will work out the knots. Deferred classes are revisited in a series
of passes after the whole jar file has been gone through. It was clumsy,
but I thought it would work. Then I had problems where sometimes a class
would be automatically defined when it was needed for an inter-class
dependency (in the example above, Car might be automatically defined when
Beetle comes up, even before Car was reached in the jar file); this would
happen for some dependencies but not others, and I never detected a
pattern. This led to a problem with redefining a class that the
ClassLoader already had defined -- this also throws a LinkageError, if I
recall. Therefore, I added logic to check to see whether a class was
already defined to the ClassLoader before attempting to define it -- if it
was already defined, I skip it.
This leads me to the two main bugs I think I've found. The first problem
is that sometimes my call to ClassLoader.findLoadedClass() returned
non-null even when the class was not loaded. This caused the logic I just
described to skip classes that shouldn't have been skipped. To stop this,
I leave "culling" of already defined classes to the end of the process,
right before I start complaining about errors. (This is all in
TBAppClassLoader.defineClientJarClasses(), for which the code is
attached.) The other problem is that ClassLoader.defineClass() sometimes
throws J. Random Error when defining a class, but if you keep trying long
enough with exactly the same parameters, eventually it will work! (See
the attached console listing in classloadertestoutput.txt .)
I'm attaching the code for our TBAppClassLoader class, the jar file it's
trying to load, and the console listing as it's trying to do it. Could
you suggest a workaround (at least a better workaround than I've come up
with)?
The problem reproduces with the following system configurations:
Win NT 4.0 with service pack 3
Java Plug-in/JRE 1.2.2
Pentium based systems
(we have seen this problem all over our client base on
NT, Win 95, and Win 98)
Please see the README file included with the testcase for the steps to reproduce this problem.
dynamically load classes from zip or jar files. The way this is supposed
to work is as follows: the ClassLoader iterates through each entry in the
zip or jar, and if the file name ends with ".class" it extracts the bytes
and tries to define the image as a class. Simple enough. However, we ran
into problems with class dependencies; for example, if Car is a class and
class Beetle extends Car, the definition of Beetle will fail if Beetle
comes before Car in the jar file. To attempt to fix this, I added logic
to catch LinkageErrors during the class defining call (later changed to
catch all Throwables) and "defer" loading of classes that had problems,
saving them in a collection under the assumption that something we'll load
later will work out the knots. Deferred classes are revisited in a series
of passes after the whole jar file has been gone through. It was clumsy,
but I thought it would work. Then I had problems where sometimes a class
would be automatically defined when it was needed for an inter-class
dependency (in the example above, Car might be automatically defined when
Beetle comes up, even before Car was reached in the jar file); this would
happen for some dependencies but not others, and I never detected a
pattern. This led to a problem with redefining a class that the
ClassLoader already had defined -- this also throws a LinkageError, if I
recall. Therefore, I added logic to check to see whether a class was
already defined to the ClassLoader before attempting to define it -- if it
was already defined, I skip it.
This leads me to the two main bugs I think I've found. The first problem
is that sometimes my call to ClassLoader.findLoadedClass() returned
non-null even when the class was not loaded. This caused the logic I just
described to skip classes that shouldn't have been skipped. To stop this,
I leave "culling" of already defined classes to the end of the process,
right before I start complaining about errors. (This is all in
TBAppClassLoader.defineClientJarClasses(), for which the code is
attached.) The other problem is that ClassLoader.defineClass() sometimes
throws J. Random Error when defining a class, but if you keep trying long
enough with exactly the same parameters, eventually it will work! (See
the attached console listing in classloadertestoutput.txt .)
I'm attaching the code for our TBAppClassLoader class, the jar file it's
trying to load, and the console listing as it's trying to do it. Could
you suggest a workaround (at least a better workaround than I've come up
with)?
The problem reproduces with the following system configurations:
Win NT 4.0 with service pack 3
Java Plug-in/JRE 1.2.2
Pentium based systems
(we have seen this problem all over our client base on
NT, Win 95, and Win 98)
Please see the README file included with the testcase for the steps to reproduce this problem.