Letters to the Editor

New Media Programming columnist Bill Day does his honorable best to answer all his mail -- praise, suggestions and grumbles alike. Plus: Bill Venners fields a slew of tough Design Techniques-related questions, Mark Johnson sets the record straight on serializing class objects, and more

1 2 3 Page 2
Page 2 of 3
  • Ask Digital Bitcasting's MPEG Advisor.
  • Check out Digigami's MegaPEG, an all-software (though not all Java) MPEG-1 and MPEG-2 encoder. (It takes AVI and QuickTime as input. You can download a demo version.)
  • Visit Ligos Technology, which also has a software-only MPEG-1/2 encoder. The company just released a new version for Windows NT/95 that takes advantage of Intel MMX capabilities, if your system has it. You can download a demo version here, too.
  • Search through mpeg.org and especially its Search MPEG Software and Products page.

I haven't used any of the encoders mentioned above, so I can't make any statement about the quality of their output. (I use an SGI utility, dmconvert, on my IRIX system to encode MPEG-1 from QuickTime or various other formats.) In theory, if you can find an all-software MPEG encoder that exposes an API for your use, you should at least be able to wrap the encoder to provide Java bindings to it. It's not an all-Java solution, but it could give you access to an encoder from within Java. I hope this information helps. I would be interested to know what you find out about this, so please do keep jmf-interest informed if you find an all-Java MPEG encoder. Bill Day

Design Techniques: "Object finalization and cleanup" by Bill Venners

Read

Down to the nitty gritty

Bill,

Great article! After reading it, I did some experiments to see for myself how finalizers behave on my platform. I got one result I just don't understand, and I can't find anything specific in the JLS to explain it.

In the first experiment, main calls a method that creates three objects that circularly reference each other. No references are kept. main then asks for garbage collection (lucky for me I actually get it), and all three objects are destroyed before main exits. Great! JVM isn't fooled by circular references.

In the second experiment, main creates the three objects in a nested block. The objects are not garbage collected until main exits, which surprised me. My thinking was that the variables would fall out of scope when the inner block ended, and would be eligible for immediate garbage collection. Instead, it appears that the JVM is keeping a reference around until main exits. Is that what's happening? Am I getting a peek at the nitty gritty of how the JVM handles local variables?

I have my doubts that the code will survive whatever formatting this Web form is going to do to it. I appreciate any time you can spare to help me understand what's happening here.

Wayne Conrad

Wayne, Yes, you probably are witnessing a nitty-gritty implementation detail. You are right that local variables go out of scope after the closing curly brace of the block in which they are declared. You are also right that this means the VM could garbage collect those things. But JVMs get to decide when to initiate garbage collection. As you seem to be aware, System.gc() doesn't force JVMs to garbage collect. What I imagine is going on inside the JVM you are using is that all the words of the current stack frame are counted as valid root nodes for the garbage collector. Even though one or two of the words contain references that have already gone out of scope, the VM doesn't bother to keep track of that or to take the time to null out those local variables when they go out of scope. The VM could reuse those slots in the local variables section of the Java stack frame after the variables go out of scope, but in this case it probably didn't. Once main() exits, the stack frame containing all those local variable references is popped, and they are no longer root nodes for garbage collection. Thus, the objects will be garbage collected only after the method returns. Bill Venners

Multiple-transaction vs. single-transaction log files

Bill,

A couple of comments on your article.

First, I think the writeToFile() method in LogFileManager and LogFileTransaction should check that logFileOpen is true.

Second, I failed to see the difference between LogFileManager and LogFileTransaction (other than the fact that LogFileManager has a default constructor). Could you elaborate on the difference?

Roque Oliveira

Roque, On your first comment, that LogFileManager.writeToFile() should check that logFileOpen is true, you may have a good point. Basically what I want this method to do if the log file is not open is throw an exception, to indicate that the class isn't being used correctly. Currently it throws IOException if the log file isn't open. A better approach may be to define a LogFileNotOpenException class, check logFileOpen first in writeToFile(), and if logFileOpen is false, throw LogFileNotOpenException. This more explicit exception could communicate better that the error was an improper use of the class, rather than some generic IOError. In my current column, which covers exceptions, I recommend making a separate exception class for each kind of exception you want to report, so it seems I haven't followed my own advice. As for your second question, the big difference between LogFileManager and LogFileTransaction is not the default constructor, but the fact that LogFileTransaction doesn't have an openLogFile() method and LogFileManager does. Because of this, LogFileTransaction can be used for one log file transaction and then must be thrown away. To do another transaction, you have to create a new LogFileTransaction object. With a single LogFileManager instance, however, you can do multiple transactions with the same (or different) log files. As I mentioned at the end of the article, most of the classes in the java.io package use the model demonstrated by LogFileTransaction. Bill Venners

Beating the splitName() method blues

Bill,

Thanks a lot for your inspiring and interesting articles. I'm very interested in good styles of coding, structure, and design and it's always good to see the principles explicated so nicely.

One thing has bothered me with Java, though, and I thought that you might have some thoughts on the subject. The thing is that Java is the only language I know of that will not allow parameters passed by reference.

I am currently working on a project where the "other guys" have decided on a design scheme that works, but it makes me feel uneasy, because I know it's wrong. It's not the way it's supposed to be -- a feeling, I believe you know!

An example header would look like this:

 
                                       public void getAccount(Transaction t,
                                       String accountName,
                                       StringBuffer created,
                                       StringBuffer modified) throws TransactionException
                                      

The two StringBuffers are used to return values. The trick is that you have to pass to this method two empty but non-null StringBuffers. The dates will be encoded into these in some well-defined way, and you can then decode the dates back again. Because you can only append to a StringBuffer, and not delete from it, it's crucial that the StringBuffers are empty on entry. (Well, it isn't really; you just have to know when you handle the result.) The method can't do something like

 
                                       created = new StringBuffer( /* the return value goes here */ );
                                      

because the caller's "create" StringBuffer would still point to the old StringBuffer. The return value will be lost, and at some point garbage collected.

Another common technique in this scenario is to pass empty but non-null collections, of some sort, that the method can fill in. In some places they've even constructed a method that returns two lists that are parallel, so that the first element of list A is one attribute of something, and the first element of list B is another attribute of the same thing.

This is clearly very ugly, and not the way things were intended to be in Java. I see two solutions, and neither is good:

  1. I could encapsulate all the return values we want for some specific method into a simple wrapper class, complete with constructor(s), get methods, and set methods, just like in JavaBeans. This would be conceptually nice, but in our case there would be loads of them. Just about 50 different classes. That's a lot of classes to write. Which brings me to my second, and preferred, solution:

  2. I could split up the 65 methods, so that each returns one thing. This could be done in one of two ways:

    • Each method could be set to perform the operations necessary and return just one value

    • We could introduce a "master" method to perform the operation, and one additional method for each value that needed to be returned

The first solution is almost impossible due to performance issues: the data are retrieved from a database using a single SQL query that returns just the values needed and the very same values that are returned by the method. The second solution is not conceptually sound, violating your "minimize coupling" mantra.

The problem here clearly stems from the design problems of coupling object-oriented Java with relational databases. And from the fact that the API we're designing is supposed to work with programs written in other languages, most notably C, that are not object-oriented. And from the fact that the parties involved cannot agree on a common object model.

It may be that I'm the only one experiencing the problem of not being able to return, for instance, two strings. The issue can be cut down to the following:

Consider a method that takes a string name as input parameter, parses it, and wants to return it in the following parts: title, first name, middle initial, and last name. The choice is between:

  • public (String, String, String, String) splitName(String name) -- which is not possible;

  • public SplitName splitName(String name) -- where we have to define a class SplitName that contains the four String fields.

  • public String getTitle(String name)
                                           public String getFirstName(String name)
                                           ...  
                                          

    -- where there is a performance penalty; and

  • public void splitName(String name)
                                           public String getTitle()
                                           ... 
                                          
    -- which is just as ugly as the StringBuffers.

Do you have any solutions to the problem that I might have missed? Or have you come across existing articles that deal with the issue? I would be delighted to hear from you, as it's painful to me to keep looking at this code.

Lars Pind

Lars, Yours is a good question because it's something every Java programmer will encounter from time to time. There is no right answer, but I can talk a bit about what I would do in this situation and why. First, Java's garbage collector is one big reason we can be more productive programming in Java than in non-garbage-collected languages such as C++. Because of the garbage collector, we don't have to worry about chasing down subtle memory bugs. But the garbage collector does one other thing that makes our lives more pleasant in Java as compared to C++: It makes it OK for a method to allocate memory for an object and pass it back to the caller. If I were to ask you for a pen, and you were in the mood to give me one, you would likely reach into your pocket and pull out a pen, then give it to me. I would then most likely use it, forget that it was yours, and leave it somewhere. This is a real-life scenario. In C++, if I encountered an analogous arrangement in someone's code, I would frown. In other words, if I encountered a function, say

borrowPen()

, that allocated memory for a new

Pen

object and returned it, I would find this to be less-than-admirable design. Why? Because I feel that in C++, classes that allocate memory need to take some responsibility for freeing that memory. If I were designing a class that needed to return a

Pen

object from a

borrowPen()

method, I would usually try to either:

  • Have the caller to the method pass in a pointer or reference to memory of a Pen object that my method was to fill with state. (Then the caller would be responsible for freeing the memory.)
  • Allocate memory for a new Pen object in borrowPen() and have a returnPen() method in the class as well. (Once again it would be partly the caller's responsibility to free the memory by invoking returnPen() sometime later, but at least there is some hint that a second method returnPen() has to be invoked. On the other hand, returnPen() could keep a bundle of pens internally, so it may not free them necessarily as they come in, which means my class is taking some responsibility for deciding when to free the memory.)

In Java, however, such design became a lot easier and more like real life. The

borrowPen()

method can just create a new

Pen

object (pull it out of its pocket), return a reference to the object, and forget about it. The caller can use the

Pen

object, and then it too can forget about it. The garbage collector will take care of freeing the memory occupied by the

Pen

object once no one needs it anymore. So, that is how I like to return stuff in Java. Therefore, I would solve your

splitName

issue as follows:

Related:
1 2 3 Page 2
Page 2 of 3