From ###@###.### Thu Feb 1 05:59:36 1996
From: ###@###.### (Jonathan Payne)
To: ###@###.###, ###@###.###
Cc: ###@###.###, arthur.vanhoff@Eng, frank.yellin@Eng, lindholm@Eng,
pavani@Eng, Sami.Shaio@Eng
Subject: HOLY SHIT I FIGURED IT OUT!
[For those of you just joining, I have had a horrible bug in Java,
causing it to segv, because a String literal is arriving in a method
as an Object handle that's showing major signs of having been garbage
collected]
Paul, you will be happy to know this is not your fault!
It's MY fault, although a major bug in Java.
I am accidentally looking for a class called:
ticker..sched
This should be an error, but it's not. Internally class names are
stored as
ticker/sched
so "/" is the separator. So the Class.forName(foo) method takes a
name with "." in it, and replaces them with "/".
ticker//sched
It then looks for a class by that name, but doesn't find it because
it's not there. So it looks for a file in the classpath by that name,
and of course UNIX doesn't mind "//" in a pathname - it silently
removes the extra slash. So it finds the class, loads it from the
file system, reads teh actual classname from the .class file, and
makes an entry in the classes list under the name:
ticker/sched
After all, that's the correct name, as stored by the compiler.
So then later, I ask again for
ticker..sched
which is turned into
ticker//sched
which is not found when a simple search for it in the classes list is
made, because it's called
ticker/sched
in that list. So it reloads the fucking class, and stores it in the
classes list, silently REPLACING the previous entry for that name!!
You see, by the time it gets stuck in the classes list, it has the
canonical name, and it searches the same class list as it does
initially to see if it needs to load the class, except this time it
searches it with the canonical name and finds the match.
If this doesn't make sense, I will explain again tomorrow (I mean in a
few hours). The upshot of it is, there's more than one version of
this class, and the latest version of the class is always the one
stored in the class list. It's that class list which is used by the
garbage collector to mark class variables and constant pools. BUT, I
have my own class list, stored in a hash table, and it's with that
Class class instance that I create a new instance of the particular
class, using its constant pool, etc. That constant pool is NOT being
marked by the GC!
You might think (as I just did in a panic!) that, hell, if I have a
reference to a class in a Hashtable, then that must mean that that
class is garbage collected, and so is its constant pool, so where's
the bug? But the answer is, Instances of class Class, when
encountered, are "fake" objects, with a few instance variables, such
as the class name, I believe, and the garbage collector does not go
mark static variables and the constant pool when it encounters them,
probably because it's already marked all of them in the initial "find
all the roots" pass of the garbage collector.
HOLY FUCKING SHIT, I AM RIGHT!
This kills me.
From: ###@###.### (Jonathan Payne)
To: ###@###.###, ###@###.###
Cc: ###@###.###, arthur.vanhoff@Eng, frank.yellin@Eng, lindholm@Eng,
pavani@Eng, Sami.Shaio@Eng
Subject: HOLY SHIT I FIGURED IT OUT!
[For those of you just joining, I have had a horrible bug in Java,
causing it to segv, because a String literal is arriving in a method
as an Object handle that's showing major signs of having been garbage
collected]
Paul, you will be happy to know this is not your fault!
It's MY fault, although a major bug in Java.
I am accidentally looking for a class called:
ticker..sched
This should be an error, but it's not. Internally class names are
stored as
ticker/sched
so "/" is the separator. So the Class.forName(foo) method takes a
name with "." in it, and replaces them with "/".
ticker//sched
It then looks for a class by that name, but doesn't find it because
it's not there. So it looks for a file in the classpath by that name,
and of course UNIX doesn't mind "//" in a pathname - it silently
removes the extra slash. So it finds the class, loads it from the
file system, reads teh actual classname from the .class file, and
makes an entry in the classes list under the name:
ticker/sched
After all, that's the correct name, as stored by the compiler.
So then later, I ask again for
ticker..sched
which is turned into
ticker//sched
which is not found when a simple search for it in the classes list is
made, because it's called
ticker/sched
in that list. So it reloads the fucking class, and stores it in the
classes list, silently REPLACING the previous entry for that name!!
You see, by the time it gets stuck in the classes list, it has the
canonical name, and it searches the same class list as it does
initially to see if it needs to load the class, except this time it
searches it with the canonical name and finds the match.
If this doesn't make sense, I will explain again tomorrow (I mean in a
few hours). The upshot of it is, there's more than one version of
this class, and the latest version of the class is always the one
stored in the class list. It's that class list which is used by the
garbage collector to mark class variables and constant pools. BUT, I
have my own class list, stored in a hash table, and it's with that
Class class instance that I create a new instance of the particular
class, using its constant pool, etc. That constant pool is NOT being
marked by the GC!
You might think (as I just did in a panic!) that, hell, if I have a
reference to a class in a Hashtable, then that must mean that that
class is garbage collected, and so is its constant pool, so where's
the bug? But the answer is, Instances of class Class, when
encountered, are "fake" objects, with a few instance variables, such
as the class name, I believe, and the garbage collector does not go
mark static variables and the constant pool when it encounters them,
probably because it's already marked all of them in the initial "find
all the roots" pass of the garbage collector.
HOLY FUCKING SHIT, I AM RIGHT!
This kills me.