Letters to the Editor

What's the difference between Jxta and Jini? Find out in this month's letters.

'J2SE 1.4 premieres Java's assertion capabilities, Part 1'

Wm. Paul Rogers

Reason for -source 1.4 is obvious

Paul,

Your soapbox comments regarding the need for -source 1.4 were completely unnecessary. It's obvious that the reason it exists is so existing make files and other Java compilers don't break because people created their own assertive methods. I'm surprised that you would overlook this.

Jerry Fontaine

Jerry, I didn't necessarily overlook your point. I state that I "appreciate the pressure to preserve backward compatibility," but believe assertions are "too important to be relegated to a special, nondefault case." If you want to compile 1.3 code, you can use either a 1.3 or a 1.4 compiler. You needn't change any of your build scripts to compile 1.3 code with a 1.3 compiler. If you choose the 1.4 compiler, I'm simply stating that you should be in the position of supplying a -source 1.3 switch. Note Sun's warning: "support for 1.3 source compatibility is likely to be phased out over time." I'm not sure how they will handle the command-line switches at that time, but I'm guessing the -source 1.4 will no longer prove necessary. I don't know what that means for your build scripts. And maybe, like a distant Y2K issue to a 1991 COBOL programmer, you believe that to be too far in the future to draw any attention. Nevertheless, I don't believe your reason will be quite so "obvious" in a few years. And I certainly do believe that assertions are more important than preserving the forward compatibility of build scripts. Wm. Paul Rogers

Do you need to know during compile time if a class is assert-enabled?

Paul,

Regarding the "abusive" idiom:

boolean assertionsEnabled = false;
assert assertionsEnabled = true;

I fail to see how it works, since at compile time you have only the -source 1.4 switch to play with, and only in runtime would you have the class-specific assert switches. In contrast, for this idiom to work as expected, you'd need to know during compile time if the class is assert-enabled or not. That means you'd get more code than needed if you switch on the -source 1.4, but later activate one class for assertion in the VM. The extra code would be for the asserts of all other classes as well.

Personally, I find the class-specific asserts odd. For me, coming from the C++ world, either you are in DEBUG or RELEASE mode. Being in DEBUG mode just for one class seems strange.

Roy Tal

Roy, You could not compile code using the idiom without the -source 1.4 switch since it includes an assert statement. But you do not need to know the status of any class assertion flags at compile time for the code to compile. In fact, you can't know. Assertion status is maintained in the Class object, and there are no objects at compile time. At runtime, the statement boolean assertionsEnabled = false; always executes. The statement assert assertionsEnabled = true; executes only if assertions are enabled. So the variable assertionsEnabled does indeed reflect the assertion status for the class from which the object in question was instantiated. As for assertions and a dichotomy between DEBUG and RELEASE, that is an unfortunate aspect of Java's adoption of assertions, not a reflection on the general utility of the concept. Assertions are the bedrock of Design By Contract (DBC), and DBC is far from a simple DEBUG/RELEASE mode indicator. I wish the Java assertion facility looked more like DBC and less like the weakened C++ macro version of assertions. Wm. Paul Rogers

Should you enable assertions in a production system?

Paul,

While I agree on the backwards nature of the J2SE (Java 2 Platform, Standard Edition) 1.4 compiler, in that the switch should be -source 1.3, I don't agree on the default enabling of assertions at runtime. Assertions would not ordinarily be turned on for a production system. If you enabled assertions by default, you would specifically have to disable them when you deploy your production code.

Andrig T. Miller

Andrig, As for not turning on assertions in a production system: why not? Assertions define the boundaries of program execution. Do you want to unknowingly stray from those boundaries in your production system? You probably will want to know when you stray, as a system operating outside the defined boundaries probably won't do so for long. Expose the problem at the source, not later when it could prove difficult to find that source. Assertions demand discipline and responsibility, two characteristics I'd like to have plenty of in my development team. Wm. Paul Rogers

'Reveal the magic behind subtype polymorphism'

Wm. Paul Rogers

Where's Derived's +m2(s:String):String method?

Paul,

I have one nit to pick. You show the Derived class implementing the interface IType, but Derived doesn't have a +m2(s:String):String method. Wouldn't this result in a compile-time error? A class that implements an interface must have an implementation for all the methods. However, that doesn't really take away from your explanation of polymorphism.

Richard Stack

Richard, Actually, Derived does have an m2(String):String method, which it gets from Base by extending that class. It gets the type operation m2(String) from both Base and IType. This is perfectly legal since there are no implementation concerns to muddy the waters. Remember, the type of reference variable attached to an object merely guarantees the object has certain runtime capabilities. It does not in any way restrict or determine from where in the implementation hierarchy that object actually gets those runtime capabilities. Wm. Paul Rogers

'The Jxta solution to P2P'

Navaneeth Krishnan

What's the difference between Jxta and Jini?

Navaneeth,

Is there any overlap between Jxta and Jini? It seems to me that the issues addressed by Jxta, such as peer discovery and resolver, resemble the Jini service issues.

CJ

CJ, The two technologies feature many similarities, but they were designed with different assumptions. The main difference is that Jini assumes the presence of Java. Jxta does not. In fact Jxta is currently developed in C, Objective-C, Perl, and Ruby too. You can find many discussions on this issue in the discuss@jxta.org archive: http://www.jxta.org/servlets/ReadMsg?msgId=17314&listName=discuss. The Jxta FAQ also addresses this issue: http://www.jxta.org/project/www/docs/DomainFAQ.html#jini Navaneeth Krishnan

In a client/server architecture, is the data shared at the server and processed on the client?

Navaneeth,

Jxta would overcome many network traffic issues and have many more advantages. But in the client/server architecture, we try to share the data at the server, but do the processing on the client side. However, in Jxta the data cannot be mirrored at every client and updated every time. Instead, if the data is not on each of the individual devices then the turn-around time for a service would be greater, as it would search the destination host with the data it needs. I might have the wrong perception of Jxta or might be misunderstanding the technology. I would appreciate if you could answer my question or point me to where I can read more on this.

Sanjay

Sanjay, Though the client/server architecture can be used the way you describe, in many cases it cannot. Take the example of the World Wide Web. How much processing does your browser do when you connect to a Website? Practically none. What you mention makes more sense in the case of a three-tier architecture:

  1. The first tier: the database server storing the data
  2. The second tier: the application/Web server processing the data and generating the content
  3. The third tier: the browser presenting the content to the user

In this case, yes, the app server/Web server is a client of the database server, and it indeed does the processing. But the user's (browser or Web service client) resources still remain under-utilized. These links should answer most of your questions:

http://www.jxta.org/project/www/white_papers.html

http://www.peertal.com/papers/

http://freenet.sourceforge.net/

http://gnutella.wego.com/

Navaneeth Krishnan

Java Q&A

'Access modifiers: What gives?'

Tony Sintes

Do access modifiers prevent inheritance?

Tony,

You write:

You are absolutely correct. Access modifiers do not prevent inheritance. Instead, access modifiers affect what you can and cannot see in the subclass.

I've tried to compile the following code:

public class TestSuper
{
    private TestSuper()
    {
        System.out.println( "In the super" );
    }
}
public class TestSub extends TestSuper
{
    public TestSub()
    {
        System.out.println( "In the sub" );
    }
}

But I get the following error:

--------------------Configuration: JDK version 1.4 
< Default >--------------------
C:\Program Files\Xinox Software\JCreator LE\MyProjects\TestSub.java:4: 
TestSuper() has private access in TestSuper
    {
    ^
1 error

If what you write is true, then my code should compile fine. The only limitation would be that the subclass could not directly call super();. However, doesn't my compiler error show that private access to a constructor does in fact limit inheritance? Since the subclass's constructor cannot see the super's constructor to even compile, I therefore cannot inherit.

Jason Adam

Jason, I think there is a little confusion over what I meant exactly when I said that "Access modifiers do not prevent inheritance." Sure, if you declare your constructors as private you've cut inheritance off at the knees -- it can't be done. But I chose not to put that in my answer since it doesn't resolve the question asked. The point of the article was to show that methods and attributes defined in a parent still exist within a child even if the private access modifier hides them. It is safe to assume that based on the question, inheritance has happened; the reader just wants to know what happens to the attributes declared private. My answer points out that the attributes and methods are still there -- you just can't see them. So the answer comes from the point of view that inheritance has happened, and I concluded that private does not prevent a child from inheriting code. Looking back, I can see your point. Here's the original statement that the question was based on:

When you create a subclass, it cannot inherit any of the superclass's methods and variables that are restricted by access modifiers.

Maybe a better answer would have reworded the statement that originally confused the reader: When you create a subclass, it cannot directly access any of the superclass's methods and variables that are restricted by access modifiers. Those methods and variables are still there when you inherit; the child just can't see them Tony Sintes

'Can ThreadLocal solve the double-checked locking problem?'

Brian Goetz

To solve DCL, why not declare two synchronized blocks?

Brian,

I have a comment on DCL (double-checked locking) that I haven't seen anyone else suggest yet. I read the articles on why DCL doesn't work, and DCL seems to revolve around how the scope of variable initialization is contained within the same synchronized block. So I was thinking: why not declare two synchronized blocks? So, the following code:

  public Resource getResource() {
    if (resource == null) {
      synchronized {
        if (resource == null)
          resource = new Resource();
      }
    }
    return resource;
  }

becomes

  public Resource getResource() {
    if (resource == null) {
      synchronized {
        if (resource == null){
          synchronized {
            resource = new Resource();
          }
        }
      }
    }
    return resource;
  }

If you need to describe two different classes to lock on, you can make the first synchronized call synchronized(FirstClass.class), and second synchronized block synchronized(SecondClass.class). But I'm not sure about the semantics of two synchronized blocks within the same thread (what they lock on).

Chris Knoll

Chris, The inner synchronized block is a no-op because the compiler knows that the thread must already hold the lock. The basic problem is that you're reading resource outside a synchronized block, when it might have been written by another thread, which has all sorts of problems. Though using two consecutive synchronized blocks works for now, it's not recommended because the proposed new memory semantics would make that trick fail. Brian Goetz

ThreadLocal is worth the performance price

Brian,

The ThreadLocal approach you present might be twice as slow as the synchronized approach, but in a multi-CPU environment, that is a marginal price to pay. The real scalability problem with synchronization is manifested in multi-CPU environments, where the likelihood of thread contention is much higher but, unfortunately, so is the cost -- the waiting thread looses its allocated processing quota and a pricey context-switch occurs.

The ThreadLocal approach might appear to take more CPU time, but it can be well worth it. Especially if that overhead is going to be eliminated in JDK 1.4.

Dror Harari

Dror, Yes, definitely. Some of these issues are raised in my article "Threading Lightly: Sometimes It's Best Not To Share" (IBM developerWorks, October 2001), which focuses more on the scalability benefits of ThreadLocal. Now that ThreadLocal is not going to be such a performance disaster, there will be many applications for it that have been previously ignored, and it's about time. Brian Goetz

'Understanding JavaServer Pages Model 2 architecture'

Govind Seshadri

Is MVC a design pattern?

Govind,

You describe Model-View-Controller (MVC) as a design pattern. I believe MVC is an architecture that includes some design patterns. Kindly, correct me if I'm wrong.

Ahmed Aboul-Enein

Ahmed, In the past some literature has called MVC a pattern; others call it an architecture. But you are right: the current consensus seems to be to call it an architecture. The J2EE (Java 2 Platform, Enterprise Edition) Patterns Catalog and the Gang of Four also seem to support that theory. Now I agree as well. Govind Seshadri

Java 101

'Class and object initialization'

Jeff Friesen

Object initializers are useful

Jeff,

You state:

Contrary to my feelings about the class block initializer, I do doubt the usefulness of an object block initializer. It seems that everything you can do in an object block initializer, you could also do with a constructor. That does not mean object block initializers are not useful -- only that I would like to see a good use for them.

I can present a use for object initializers from my own experience: A class has multiple constructors. Each constructor has a common segment of code. I declare a private method private void commonCode() and invoke this method in every constructor. It could be replaced with an object initializer.

Ramesh

Ramesh, To avoid explicit duplication in source code, the object block initializer is the perfect place for such code. I put together the following source code:

 
// Test.java
 
class Test
{
   {
      commonSetup ();
   }
 
   Test ()
   {
      this (0);
   }
 
   Test (double d)
   {
      System.out.println ("Test() d = " + d);
   }
 
   Test (int x)
   {
      System.out.println ("Test(int) x = " + x);
   }
 
   void commonSetup ()
   {
      System.out.println ("Common setup");
      System.out.println ("More common setup");
   }
 
   public static void main (String [] args)
   {
      Test t1 = new Test ();
      Test t2 = new Test (5);
      Test t3 = new Test (1.0);
   }
}

When run,

Test

produces the following output:

 
Common setup
More common setup
Test(int) x = 0
Common setup
More common setup
Test(int) x = 5
Common setup
More common setup
Test() d = 1.0

Apart from

Test()

, each constructor explicitly calls

commonSetup()

-- because the compiler places object block initializer instructions into equivalent

<init>

methods. The

Test()

constructor indirectly calls

commonSetup()

-- at the

<init>

method level -- through the

Test(int x)

constructor. There is one caution that comes to mind with this approach: Suppose I introduce another

Test

constructor that should not call any other

Test

constructor or

commonSetup()

-- at the

<init>

method level (example:

Test (boolean b) { }

). Due to the

Test

program's current architecture, there does not appear to be a way to prevent such a constructor from calling

commonSetup()

. Regardless of the above caution, your suggestion has much merit. Jeff Friesen