📄 tij0051.html
字号:
<font color="#0000ff">if</font>(created == 47)
System.out.println("Created 47");
}
<font color="#0000ff">protected</font> <font color="#0000ff">void</font> finalize() {
<font color="#0000ff">if</font>(!gcrun) {
gcrun = <font color="#0000ff">true</font>;
System.out.println(
"Beginning to finalize after " +
created + " Chairs have been created");
}
<font color="#0000ff">if</font>(i == 47) {
System.out.println(
"Finalizing Chair #47, " +
"Setting flag to stop Chair creation");
f = <font color="#0000ff">true</font>;
}
finalized++;
<font color="#0000ff">if</font>(finalized >= created)
System.out.println(
"All " + finalized + " finalized");
}
}
<font color="#0000ff">public</font> <font color="#0000ff">class</font> Garbage {
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
<font color="#0000ff">if</font>(args.length == 0) {
System.err.println("Usage: \n" +
"java Garbage before\n or:\n" +
"java Garbage after");
<font color="#0000ff">return</font>;
}
<font color="#0000ff">while</font>(!Chair.f) {
<font color="#0000ff">new</font> Chair();
<font color="#0000ff">new</font> String("To take up space");
}
System.out.println(
"After all Chairs have been created:\n" +
"total created = " + Chair.created +
", total finalized = " + Chair.finalized);
<font color="#0000ff">if</font>(args[0].equals("before")) {
System.out.println("gc():");
System.gc();
System.out.println("runFinalization():");
System.runFinalization();
}
System.out.println("bye!");
<font color="#0000ff">if</font>(args[0].equals("after"))
System.runFinalizersOnExit(<font color="#0000ff">true</font>);
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
above program creates many
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Chair</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects, and at some point after the garbage collector begins running, the
program stops creating
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Chair</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">s.
Since the garbage collector can run at any time, you don’t know exactly
when it will start up, so there’s a flag called
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>gcrun</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to indicate whether the garbage collector has started running yet. A second flag
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>f</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is a way for
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Chair</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to tell the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>main( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
loop that it should stop making objects. Both of these flags are set within
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finalize( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which is called during garbage collection.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Two
other
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>static</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
variables,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>created</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finalized</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
keep track of the number of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>obj</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">s
created versus the number that get finalized by the garbage collector. Finally,
each
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Chair</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
has its own (non-
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>static</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">)
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>int</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>i</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
so it can keep track of what number it is. When
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Chair</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
number 47 is finalized, the flag is set to
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>true</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to bring the process of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Chair
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">creation
to a stop.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">All
this happens in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>main( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
in the loop
</FONT><P></DIV>
<font color="#990000"><PRE> <font color="#0000ff">while</font>(!Chair.f) {
<font color="#0000ff">new</font> Chair();
<font color="#0000ff">new</font> String("To take up space");
} </PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
might wonder how this loop could ever finish, since there’s nothing
inside that changes the value of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Chair.f</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
However, the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>finalize( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
process will, eventually, when it finalizes number 47.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
The creation of a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object during each iteration is simply extra garbage being created to encourage
the garbage collector to kick in, which it will do when it starts to get
nervous about the amount of memory available.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">When
you run the program, you provide a command-line argument of
“before” or “after.” The “before” argument
will call the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>System.gc( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method (to force execution of the garbage collector) along with the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>System.runFinalization( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method to run the finalizers. These methods were available in <A NAME="Index302"></A>Java
1.0, but the <A NAME="Index303"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>runFinalizersOnExit( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method that is invoked by using the “after” argument is available
only in Java 1.1<A NAME="Index304"></A></FONT><A NAME="fnB19" HREF="#fn19">[19]</A><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and beyond. (Note you can call this method any time during program execution,
and the execution of the finalizers is independent of whether the garbage
collector runs).
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
preceding program shows that, in Java 1.1, the promise that finalizers will
always be run holds true, but only if you explicitly force it to happen
yourself. If you use an argument that isn’t “before” or
“after” (such as “none”), then neither finalization
process will occur, and you’ll get an output like this:
</FONT><P></DIV>
<font color="#990000"><PRE>Created 47
Beginning to finalize after 8694 Chairs have been created
Finalizing Chair #47, Setting flag to stop Chair creation
After all Chairs have been created:
total created = 9834, total finalized = 108
bye!</PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Thus,
not all finalizers get called by the time the program completes.
</FONT><A NAME="fnB20" HREF="#fn20">[20]</A><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
To force finalization to happen, you can call
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>System.gc( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
followed by
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>System.runFinalization( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
This will destroy all the objects that are no longer in use up to that point.
The odd thing about this is that you call
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>gc( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>before</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
you call
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>runFinalization( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which seems to contradict the Sun documentation, which claims that finalizers
are run first, and then the storage is released. However, if you call
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>runFinalization( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
first, and then
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>gc( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
the finalizers will not be executed.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">One
reason that Java 1.1<A NAME="Index305"></A>
might default to skipping finalization for all objects is because it seems to
be expensive. When you use either of the approaches that force garbage
collection you might notice longer delays than you would without the extra
finalization.
</FONT><a name="_Toc375545284"></a><a name="_Toc408018486"></a><P></DIV>
<HR><DIV ALIGN=LEFT><A NAME="fn19" HREF="#fnB19">[19]</A><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
</FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black">Unfortunately,
the implementations of the garbage collector in Java 1.0 would never call
</FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black"><B>finalize( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black">
correctly. As a result,
</FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black"><B>finalize( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black">
methods that were essential (such as those to close a file) often didn’t
get called. The documentation claimed that all finalizers would be called at
the exit of a program, even if the garbage collector hadn’t been run on
those objects by the time the program terminated. This wasn’t true, so as
a result you couldn’t reliably expect
</FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black"><B>finalize( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black">
to be called for all objects. Effectively,
</FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black"><B>finalize( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black">
was useless in Java 1.0.
</FONT><P></DIV>
<DIV ALIGN=LEFT><A NAME="fn20" HREF="#fnB20">[20]</A><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black">
By the time you read this, some Java Virtual Machines may show different
behavior.
</FONT><P></DIV>
<div align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0050.html">Prev</a> | <a href="tij0052.html">Next</a>
</div>
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -