The Source for Java Technology Collaboration
User: Password:



Jayson Falkner's Blog

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





Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds