 |
J2SE Archives
Blarg#27: Don't use finalize() as your only teardown method.
Posted by jfalkner on July 31, 2007 at 04:17 PM | Permalink
| Comments (8)
In short, don't rely on the finalize() method as your only cleanup method, especially if it is deleting files. Instead make up a cleanup method (cleanup() works nicely) that lazy deletes things. Here is an example.
public class Example {
boolean isCleanedUp = false;
public synchronized void cleanup() {
if (isCleanedUp) return;
// flag as cleaned up
isCleanedUp = true;
// put your clean up code here.
// delete files, close DB connections, etc.
}
public void finalize() {
cleanup();
super.finalize();
}
}
Wait...why do the above if the garbage collector will always call finalize before freeing up memory associated with an object? The reason is because the garbage collector doesn't always get a chance to clean up objects before the JVM terminates. This can be problematic, particularly in cases where you've made a temporary file or a socket connection that needs to be properly cleaned up.
By using an explicit cleanup() method as shown above you have an explicit method for cleaning up resources associated with an object the moment you are done using the object. Additionally, the boolean flag protects your code from accidentally trying to clean up the resource twice. The term "lazy delete" is used loosely because this approach is like lazy loading. The delete will occur only once and only when the code actually needs to do it.
Do note that the cleanup() method also nicely works in a try-finally block.
Example example = null;
try {
example = new Example();
// do whatever logic you need to
}
finally {
example.cleanup();
}
And one last trick copied from Bruce Eckel. If you are worried that portions of your code aren't cleaning up resources properly, simply tweak the finalize() method to check the isCleanedUp boolean and report finalize() calls that occur before any explicit call to cleanup().
PWC Java Course 06/12/06
Posted by jfalkner on June 12, 2006 at 06:18 AM | Permalink
| Comments (0)
This is reference page for the Java course I taught for PWC. We'll put links and notes here for things that we talk about in the course. You can also leave comments for anything that I miss.
Links for the tools that we use.
- Java Development Kit (JDK) 5.0: This is the code that will compile and execute Java. Remeber to set your classpath to include the "/bin" directory and you may have to include the "-cp ." flag when running code.
- Netbeans IDE: This is the tool that we used to develop code. You can also download the profiles from here.
- JavaDocs: Your best buddy when programming. This code comes with "the Java platform" and it can make life easy when coding. Knowing what classes exist in the JavaDocs and how to use them is what makes for a great Java programmer.
Links for the tools that we use.
- Java Development Kit (JDK) 5.0: This is the code that will compile and execute Java. Remeber to set your classpath to include the "/bin" directory and you may have to include the "-cp ." flag when running code.
- Netbeans IDE: This is the tool that we used to develop code. You can also download the profiles from here.
- JavaDocs: Your best buddy when programming. This code comes with "the Java platform" and it can make life easy when coding. Knowing what classes exist in the JavaDocs and how to use them is what makes for a great Java programmer.
Links for the course games.
- Rock, Paper, Scissors Challenge
- RockPaperScissorsChallenge.zip
- Rock, Paper, Scissors Snapshots of Opponent's Code
- Tuesday's Challengers: This JAR file includes the compiled code for the players on Tuesday. We won't look at the source-code until Friday. Here are the player names so that you can add them to your local tournment.
"rockpaperscissorschallenge.JoeTuesday",
"rockpaperscissorschallenge.JoeZinziTuesday",
"rockpaperscissorschallenge.JaysonWalkerTuesday",
"rockpaperscissorschallenge.MaheshTuesday",
"rockpaperscissorschallenge.MartinTuesday",
"rockpaperscissorschallenge.RoyLawsonTuesday",
"rockpaperscissorschallenge.ScottDeBoerTuesday",
"rockpaperscissorschallenge.SteveTuesday",
"com.jirawat.JirawatUttayayaTuesday"
- Wednesday's Challengers: This JAR file includes the compiled code for the players on Wednesday. We won't look at the source-code until Friday. Here are the player names so that you can add them to your local tournment.
"rockpaperscissorschallenge.wednesday.Joe",
"com.joezinzi.wednesday.JoeZinzi",
"rockpaperscissorschallenge.wednesday.JaysonWalkerForTheWin",
"rockpaperscissorschallenge.wednesday.MaheshForTheWin",
"rockpaperscissorschallenge.wednesday.Martin",
"com.roy.rpc.wednesday.RoyLawsonRPS",
"rockpaperscissorschallenge.wednesday.ScottDeBoer",
"PackageTest.wednesday.SteveRockPaperScissors4",
"com.jirawat.wednesday.JirawatUttayayaRps"
- Thursday's Challengers:
"rockpaperscissorschallenge.thursday.Joe",
"com.joezinzi.thursday.JoeZinzi",
"com.jaysonwalker.rpc.thursday.JaysonWalkerForTheWin",
"rockpaperscissorschallenge.thursday.MaheshForTheWin",
"com.martinrokicki.thursday.MartinRockPaperScissors",
"com.roy.rpc.thursday.RoyLawsonRPS",
"rockpaperscissorschallenge.thursday.ScottDeBoer",
"PackageTest.thursday.SteveRockPaperScissors4",
"com.jirawat.thursday.JirawatUttayayaRps"
Friday's Challengers + Jayson's Learning Player: This is the final JAR file for Friday's code. Congrats to Joe Zinzi for coming out with the best code. You'll have to also include Thursday's JAR and the players from the original challenge code in order to include all the players in the list.
I've included one more player: LearningRockPaperScissors. This player learns how to play based on how everyone else is playing -- behold the power of static variables! You'll note that this code wins 60% of the time after 1,000 tournaments, 75% of the time after 10,000 tournaments, and 80%+ of the time with 100,000 tournaments. It seems to handily beat any hard-coded strategy. Take a peek at the code. I've e-mailed it to everyone in the class with the final source-code ZIP.
// default players
"rockpaperscissorschallenge.RockForTheWin",
"rockpaperscissorschallenge.ScissorsForTheWin",
"rockpaperscissorschallenge.PaperForTheWin",
"rockpaperscissorschallenge.BeatRepeaters",
"rockpaperscissorschallenge.RandomForTheWin",
// class players
"rockpaperscissorschallenge.JoeTuesday",
"com.joezinzi.JoeZinzi",
"com.jaysonwalker.rpc.wednesday.JaysonWalkerForTheWin",
"rockpaperscissorschallenge.thursday.MaheshForTheWin",
"com.martinrokicki.thursday.MartinRockPaperScissors",
"com.roy.rpc.thursday.RoyLawsonRPS",
"rockpaperscissorschallenge.thursday.ScottDeBoer",
"PackageTest.SteveRockPaperScissors5",
"com.jirawat.thursday.JirawatUttayayaRps",
"rockpaperscissorschallenge.LearningRockPaperScissors"
And here is a printout of the class's final results:
*** Statistics after playing 10000 tournaments ***
JoeZinzi: 2445 wins or 24.45%
MartinRockPaperScissors: 2133 wins or 21.33%
SteveRockPaperScissors5: 1811 wins or 18.11%
JaysonWalkerForTheWin: 807 wins or 8.07%
RandomForTheWin: 752 wins or 7.52%
RoyLawsonRPS: 752 wins or 7.52%
MaheshForTheWin: 681 wins or 6.81%
JirawatUttayayaRps: 479 wins or 4.79%
ScottDeBoer: 142 wins or 1.42%
BeatRepeaters: 8 wins or 0.08%
*** Tables of Wins/Loses/Ties versus a particular opponent ***
SteveRockPaperScissors5 JaysonWalkerForTheWin JirawatUttayayaRps JoeZinzi MartinRockPaperScissors RoyLawsonRPS BeatRepeaters JoeTuesday PaperForTheWin RandomForTheWin RockForTheWin ScissorsForTheWin MaheshForTheWin ScottDeBoer
SteveRockPaperScissors5 0/0/0 2641/0/0 1444/232/478 682/2302/462 1524/1239/355 1293/661/497 941/212/194 0/0/0 1021/0/0 879/842/307 962/0/0 980/0/0 764/766/778 1265/283/218
JaysonWalkerForTheWin 0/2641/0 0/0/0 628/611/619 307/1543/889 662/1709/260 1967/18/72 1217/57/5 0/0/0 956/0/0 759/749/284 998/0/0 1015/0/0 2104/0/0 645/678/222
JirawatUttayayaRps 232/1444/478 611/628/619 0/0/0 805/1372/141 695/1207/279 440/845/564 1196/0/0 0/0/0 967/0/0 664/664/230 992/0/0 1010/0/0 0/1727/0 471/0/995
JoeZinzi 2302/682/462 1543/307/889 1372/805/141 0/0/0 1137/1619/782 1614/768/255 1377/0/0 0/0/0 1038/0/0 930/928/309 1096/0/0 1082/0/0 1342/965/191 1990/0/0
MartinRockPaperScissors 1239/1524/355 1709/662/260 1207/695/279 1619/1137/782 0/0/0 1758/513/265 1314/37/64 0/0/0 995/0/0 949/938/298 1018/0/0 1008/0/0 1645/606/239 1132/304/349
RoyLawsonRPS 661/1293/497 18/1967/72 845/440/564 768/1614/255 513/1758/265 0/0/0 973/72/179 0/0/0 995/0/0 744/707/248 925/0/0 931/0/0 1907/0/0 1035/173/386
BeatRepeaters 212/941/194 57/1217/5 0/1196/0 0/1377/0 37/1314/64 72/973/179 0/0/0 0/0/0 837/0/0 472/457/171 829/0/0 899/0/0 50/1098/72 0/1095/0
JoeTuesday 0/0/0 0/0/0 0/0/0 0/0/0 0/0/0 0/0/0 0/0/0 0/0/0 0/0/0 0/0/0 0/0/0 0/0/0 0/0/0 0/0/0
PaperForTheWin 0/1021/0 0/956/0 0/967/0 0/1038/0 0/995/0 0/995/0 0/837/0 0/0/0 0/0/0 406/370/128 804/0/0 0/810/0 0/970/0 0/978/0
RandomForTheWin 842/879/307 749/759/284 664/664/230 928/930/309 938/949/298 707/744/248 457/472/171 0/0/0 370/406/128 0/0/0 384/423/141 392/368/128 734/740/266 561/564/186
RockForTheWin 0/962/0 0/998/0 0/992/0 0/1096/0 0/1018/0 0/925/0 0/829/0 0/0/0 0/804/0 423/384/141 0/0/0 794/0/0 0/1029/0 0/887/0
ScissorsForTheWin 0/980/0 0/1015/0 0/1010/0 0/1082/0 0/1008/0 0/931/0 0/899/0 0/0/0 810/0/0 368/392/128 0/794/0 0/0/0 0/922/0 0/901/0
MaheshForTheWin 766/764/778 0/2104/0 1727/0/0 965/1342/191 606/1645/239 0/1907/0 1098/50/72 0/0/0 970/0/0 740/734/266 1029/0/0 922/0/0 0/0/0 1544/0/0
ScottDeBoer 283/1265/218 678/645/222 0/471/995 0/1990/0 304/1132/349 173/1035/386 1095/0/0 0/0/0 978/0/0 564/561/186 887/0/0 901/0/0 0/1544/0 0/0/0
BUILD SUCCESSFUL (total time: 14 seconds)
And here is a printout when the LearningRockPaperScissors class enters the mix.
*** Statistics after playing 10000 tournaments ***
LearningRockPaperScissors: 7687 wins or 76.87%
RandomForTheWin: 724 wins or 7.24%
MartinRockPaperScissors: 528 wins or 5.28%
JoeZinzi: 313 wins or 3.13%
SteveRockPaperScissors5: 263 wins or 2.63%
RoyLawsonRPS: 150 wins or 1.5%
JaysonWalkerForTheWin: 112 wins or 1.12%
MaheshForTheWin: 106 wins or 1.06%
JirawatUttayayaRps: 69 wins or 0.69%
ScottDeBoer: 38 wins or 0.38%
BeatRepeaters: 21 wins or 0.21%
*** Tables of Wins/Loses/Ties versus a particular opponent ***
SteveRockPaperScissors5 JaysonWalkerForTheWin JirawatUttayayaRps JoeZinzi MartinRockPaperScissors RoyLawsonRPS BeatRepeaters JoeTuesday LearningRockPaperScissors PaperForTheWin RandomForTheWin RockForTheWin ScissorsForTheWin MaheshForTheWin ScottDeBoer
SteveRockPaperScissors5 0/0/0 1794/0/0 1044/165/338 383/1300/300 959/810/246 898/469/370 773/197/171 0/0/0 0/4117/4 866/0/0 705/684/240 856/0/0 946/0/0 548/583/525 986/251/144
JaysonWalkerForTheWin 0/1794/0 0/0/0 475/461/477 216/965/567 416/1167/197 1443/10/39 1089/50/3 0/0/0 0/3392/1 888/0/0 608/669/199 883/0/0 876/0/0 1554/0/0 555/563/211
JirawatUttayayaRps 165/1044/338 461/475/477 0/0/0 566/899/85 521/876/231 318/647/414 1077/0/0 0/0/0 8/2705/5 853/0/0 608/597/176 829/0/0 891/0/0 0/1417/0 409/0/818
JoeZinzi 1300/383/300 965/216/567 899/566/85 0/0/0 684/1019/454 1122/469/176 1185/0/0 0/0/0 11/4612/14 867/0/0 739/758/250 922/0/0 887/0/0 939/647/137 1506/0/0
MartinRockPaperScissors 810/959/246 1167/416/197 876/521/231 1019/684/454 0/0/0 1185/354/177 1090/26/59 0/0/0 345/3984/165 873/0/0 773/750/248 924/0/0 872/0/0 1137/442/162 933/218/300
RoyLawsonRPS 469/898/370 10/1443/39 647/318/414 469/1122/176 354/1185/177 0/0/0 807/72/155 0/0/0 94/3078/85 884/0/0 601/629/213 904/0/0 852/0/0 1431/0/0 763/155/293
BeatRepeaters 197/773/171 50/1089/3 0/1077/0 0/1185/0 26/1090/59 72/807/155 0/0/0 0/0/0 142/1185/131 805/0/0 420/427/158 804/0/0 768/0/0 42/1018/52 0/949/0
JoeTuesday 0/0/0 0/0/0 0/0/0 0/0/0 0/0/0 0/0/0 0/0/0 0/0/0 0/0/0 0/0/0 0/0/0 0/0/0 0/0/0 0/0/0 0/0/0
LearningRockPaperScissors 4117/0/4 3392/0/1 2705/8/5 4612/11/14 3984/345/165 3078/94/85 1185/142/131 0/0/0 0/0/0 976/0/1 1230/1226/417 992/1/0 954/0/1 3107/5/0 2029/51/33
PaperForTheWin 0/866/0 0/888/0 0/853/0 0/867/0 0/873/0 0/884/0 0/805/0 0/0/0 0/976/1 0/0/0 391/367/115 788/0/0 0/788/0 0/939/0 0/829/0
RandomForTheWin 684/705/240 669/608/199 597/608/176 758/739/250 750/773/248 629/601/213 427/420/158 0/0/0 1226/1230/417 367/391/115 0/0/0 352/342/106 380/348/139 607/654/214 501/532/183
RockForTheWin 0/856/0 0/883/0 0/829/0 0/922/0 0/924/0 0/904/0 0/804/0 0/0/0 1/992/0 0/788/0 342/352/106 0/0/0 764/0/0 0/853/0 0/840/0
ScissorsForTheWin 0/946/0 0/876/0 0/891/0 0/887/0 0/872/0 0/852/0 0/768/0 0/0/0 0/954/1 788/0/0 348/380/139 0/764/0 0/0/0 0/901/0 0/834/0
MaheshForTheWin 583/548/525 0/1554/0 1417/0/0 647/939/137 442/1137/162 0/1431/0 1018/42/52 0/0/0 5/3107/0 939/0/0 654/607/214 853/0/0 901/0/0 0/0/0 1282/0/0
ScottDeBoer 251/986/144 563/555/211 0/409/818 0/1506/0 218/933/300 155/763/293 949/0/0 0/0/0 51/2029/33 829/0/0 532/501/183 840/0/0 834/0/0 0/1282/0 0/0/0
BUILD SUCCESSFUL (total time: 15 seconds)
- Sudoku Challenge
- SudokuChallenge.zip
Other helpful links we talked about.
Blarg #19: Simple things make me happy. An os.name list.
Posted by jfalkner on February 27, 2006 at 12:44 PM | Permalink
| Comments (0)
I like that Java can tell you what platform it is running on, but often I forget what strings to expect from the os.name and os.arch System properties. Google revealed a nice list.
Why would you ever want to use this? It is handy in any case where you need to know if you are running on Mac OSX, Linux, Windows, or any other specific platform. For instance, if you want to save a config file in an appropriate directory, e.g. "C:\Program Files\MyApp" versus "/opt/MyApp"
Since I referenced the list, may as well reference how you would get the property.
String os = System.getProperty("os.name");
Hooray for the simple things. Thanks to the Lopica project for keeping this list.
Blarg 17: Ant command line parameters broken?
Posted by jfalkner on November 02, 2005 at 02:24 PM | Permalink
| Comments (0)
I like using Ant. I think it rocks. I can't say I'm as much a fan of Windows, and here is a work around I'd like to highlight in a google-cacheable location.
Recently I bumped a development environment running on a Windows XP box up to JDK 1.5 along with installing Ant 1.6.5. Suddenly any command line parameters passed to ant were being ignored. The fix? Make sure you don't have any trailing backward slashes ("\") in your path variables, e.g use C:\foo instead of C:\foo\.
Why? Windows and Java have a fun way of escaping them. Here is a link to a good talk on the feature along with a more proper writeup.
Blarg #7: How long does it takes to compress a response using a GZIP filter?
Posted by jfalkner on January 27, 2004 at 09:13 PM | Permalink
| Comments (1)
Hi, just found out about your book the other day from java.net and was
really grateful for the example of the Compression code. I've had to
implement that in the past on the web server level and it was a real
pain then, but this was relatively effortless. I'm adding this book to
my to-buy list.
I do have a question. Perhaps if others are interested some sort of
improvement could be integrated. Where would we add output messages
that would help us with the timing of the compression?
i.e.If I put something like this in GZipFilter:
System.out.println("GZIP supported, compressing.");
long ini = System.currentTimeMillis();
GZIPResponseWrapper wrappedResponse = new
GZIPResponseWrapper(response);
chain.doFilter(req, wrappedResponse);
wrappedResponse.finishResponse();
System.out.println("Compressed in " +
(System.currentTimeMillis()-ini) + " ms");
I get the total time for the entire request, not just the time it
takes to do the compression. >From testing I realize the compression
time is pretty short, say in the order of tens of microseconds, but
I'm still pretty interested. I was thinking that moving the time
initializer from before the response constructor to before the
finishResponse method call would work, but I wasn't sure if that would
get the total compression time, or just the time for the last output
to be flushed from the response buffer.
Thanks,
Ronald
Hi Ronald,
Awesome. I'm glad you found my book, and I hope you enjoy it.
The trick here is to split the request and compression in to two
separate things. Buffer the response, then compress the buffer and time
only the compression. You can more or less do this easily by editing the
code in the com.jspbook.GZIPResponseStream class, e.g. here is the
existing code in the close() method of GZIPResponseStream.
ByteArrayOutputStream baos = (ByteArrayOutputStream)bufferedOutput;
// prepare a gzip stream
ByteArrayOutputStream compressedContent = new ByteArrayOutputStream();
GZIPOutputStream gzipstream = new GZIPOutputStream(compressedContent);
byte[] bytes = baos.toByteArray();
gzipstream.write(bytes);
gzipstream.finish();
// get the compressed content
byte[] compressedBytes = compressedContent.toByteArray();
You can see the response gets put in to a byte array, then the byte
array is compressed and the results are saved to another byte array. You
could put a time check in as follows (very similar to what you were
doing).
ByteArrayOutputStream baos = (ByteArrayOutputStream)bufferedOutput;
// prepare a gzip stream
ByteArrayOutputStream compressedContent = new ByteArrayOutputStream();
long ini = System.currentTimeMillis(); // <------- starting timing here
GZIPOutputStream gzipstream = new GZIPOutputStream(compressedContent);
byte[] bytes = baos.toByteArray();
gzipstream.write(bytes);
gzipstream.finish();
// get the compressed content
byte[] compressedBytes = compressedContent.toByteArray();
System.out.println("Compressed in " + (System.currentTimeMillis()-ini) +
" ms"); // <-------------- stop timing here
And the result is you are only counting how long the compression took.
Although fair warning needs to be given. The current GZIPResponseStream
class tries to buffer content, as shown above (it allows you to set the
content-length header properly), but when compressing really big files
the filter streams content back to the client as not to use up all of
your web application's memory. The above timing example won't work if
you are testing it on files larger than the buffer -- the default buffer
is 50k, you may need to increase it for your benchmark.
In general, the resources it takes to compress content aren't an issue.
However, if you find that compression takes up too much processing
power, remember you can combine compression with caching to try and
reduce the overhead.
Cheers,
Jayson Falkner
jayson@jspinsider.com
A few links
Blarg #6: How do I become an expert Java developer?
Posted by jfalkner on January 27, 2004 at 08:11 AM | Permalink
| Comments (4)
Hi,
I'm a young java programmer(for now) and on the brink of writing my SCJP1.4 exam I want to be a Java Developer(J2EE) more than anything else. I've picked up REALLY REALLY bad coding conventions and norms along my path to Java-enlightenment and I would like to know from YOU, what could I do to turn this around and become a precision Java Developer, Are there Rules and Guidelines (in ENGLISH) that I can follow that will set me apart as a "developer of note"?
Please Advise
Lloyd
Hi Lloyd, depending on who you ask there are many different answers to this question. However, a great way to get started is by reading the Java coding conventions Sun encourages -- most all Java code you see will roughly follow these. These conventions fall along the lines of standard Java documentation, which is the next place you should look when seeking advice about Java. As a rule of thumb, check Java documentation first and goggle second.
If you really want to practice coding or look at a bunch of "good" code, try hacking away at your favorite open-source project (I'd suggest Tomcat, http://jakarta.apache.org/tomcat, or JBoss, http://jboss.org). You'll find lots of code that will show how general Java code usually looks, and you will also be able to see lots of examples of clever coding tricks. Plus, if you can really understand what is going on in a decent sized open-source project, odds are your Java skills are up to snuff.
Some Links
Jayson Falkner
jayson@jspinsider.com
http://www.jspbook.com
|