Java History 101: Once Upon an Oak

Java History 101: Once Upon an Oak

few weeks ago I was talking to someone about the origins of Java when I realized that I had big gaps in my knowledge of Java’s history. Trying to fill these gaps, I started digging around on Sun’s Web site, and I eventually stumbled across the Oak Language Specification. Oak was the original name of what is now commonly known as Java, and this specification is the oldest manual available for Oak (i.e. Java). (For more on the origins of Java, have a look at The Green Project and Java(TM) Technology: An Early History.)

I printed the manual and kept it next to my bed in case of insomnia (so I thought). However, to my pleasant surprise, when I started reading it not only did it keep me awake, but I also discovered answers to age-old Java questions:

  • Why can you have only one public class per .java file?
  • Why are protected members also accessible from the same package?
  • Why do short fields use as much memory as int fields (at least pre-JDK 1.4)?
  • In this article, I highlight the differences between Java 0.2 (i.e., Oak 0.2) and the Java we have now. For reference, I include the section numbers in the Oak 0.2 specification.

    Why Is Each Public Class in a Separate File? (Section 1)
    I have been asked this question frequently while teaching my Java courses. Until now I have not had a good answer. Section 1 states: “Although each Oak compilation unit can contain multiple classes or interfaces, at most one class or interface per compilation unit can be public.”

    The margin explains why: “This restriction is not yet enforced by the compiler, although it’s necessary for efficient package importation.”

    The compiler would have to make an additional pass through all the compilation units (.java files) to figure out which classes were where, which would make the compilation even slower.

    One-line Javadoc Comments (Section 2.1)
    Oak had the ability to write a one-line JavaDoc comment, like so:

      public class OneLineJavaDoc {    //* The number of lines allowed in a document.    public int numberOfLines;  }

    Fortunately, Java does not support this confusing construct.

    Additional Keywords (Section 2.3)
    Oak had some additional keywords that are not available in Java:

  • clone, const and goto were keywords, and ushort, string, Cstring and unsynchronized were obsolete by version 0.2. Isn’t it amazing how quickly things become obsolete in this industry?
  • protect and unprotect were nasty keywords for writing terrible exception code (more about that later).
  • enum was a keyword, but the sidebar stated that enum isn’t implemented yet. So, the answer to the question why does Java not have enum is not a heavy philosophical one about object-oriented polymorphism and strategy patterns. It is simply that James Gosling didn’t implement it in time, and his management forced him to push the language out the door before he could finish the feature. đŸ˜‰
  • Unsigned Integer Values (Section 3.1)
    The specification says “the four integer types of widths of 8, 16, 32, and 64 bitsare signed unless prefixed by the unsigned modifier.

    The margin explains further: “unsigned isn’t implemented yet; it might never be.” How right the author was.

    Storage of Integer Values (Section 3.1)
    In my newsletter on Determining Memory Usage in Java, I noted that when you have a data member of byte or short, it still uses at least 4 bytes of memory. This changed in JDK 1.4. The Oak spec provides the historical reason why this was done:

    “A variable’s type does not directly affect its storage allocation. Type only determines the variable’s properties and legal range of values. If a value is assigned to a variable that is outside the legal range of the variable, the value is reduced modulo the range.”

    I wish I had known that when I wrote my first Java program. I spent a lot of time deliberating which data types I wanted to use in order to save memory, but I was actually wasting my time. Since this changed as of JDK 1.4, now using bytes and shorts does help to reduce the memory footprint.

    Arrays (Section 3.5)
    In Oak, you were able to declare arrays as follows:

      int a[10];  a[5] = 1;

    However, you were also able to declare an array in the current Java fashion with new. Because having two ways of doing the same thing causes confusion, I am very pleased that the old way was removed.

    Const vs. Final (Sections 4.6 and 4.9)
    Apparently, programmers initially were meant to use final only for classes and methods and const for making fields constant.

    Private Did Not Exist (Sections 4.10)
    This was to me the most surprising part of Oak 0.2. It had only three access levels (public, protected, and private) as opposed to the current four. Private did not require a keyword and equated to the current “package private” or “friendly” or “package access” type of access level. All classes in a particular package could use all variables and methods declared in the classes in that package, regardless of public, protected, and private declarations. I am very glad that they introduced a more private version of private, one that was accessible only within the class.

    The lack of private as you know it today explains why when a member is protected, it is also accessible from within the same package. When Oak was written, protected was obviously accessible within the package because its private (Java’s “package access”) was the most restrictive access level. I seem to remember that in JDK 1.0 you had a fifth access level called “private protected”, which meant that only subclasses could access the member.

    This piece of surprising history also explains why fields are not private by default?they actually were “private” originally, when private meant something different. Needless to say, I am quite pleased to have the more restrictive “private” modifier. Without it, the industry would be in even more trouble. Abstract Methods (Section 5)
    As in C++, abstract methods were defined like so:

      public interface Storing {    void freezeDry(Stream s) = 0;  }

    Assertions and Pre/Postconditions (Sections 7, 7.1, and 7.2)
    Unfortunately, the assertions in Oak 0.2 were not implemented in time, so they were thrown out to satisfy the release deadline. If you think that assertions are back in JDK 1.4, have a look at the power that the Oak 0.2 assertions would have given you:

      class Calender {     static int lastDay[12]=       {31,29,31,30,31,30,31,31,30,31,30,31};     int month assert(month>=1 && month<=12);     int date assert(date>=1 && date<=lastDay[month]);   } 

    Although objects are not required to obey the legality constraints within methods, the constraints are enforced at the entry and exit of every public and protected method. I wish James Gosling had worked a few more weekends (if that were possible) to finish the implementation of assert as it appeared in the original Oak spec. In addition, the spec also loosely defined preconditions and postconditions, but they also were given the boot due to time pressure. What a pity.

    Post-incrementing Strings (Section 8.1.4)
    In Oak, you were able to post-increment a String. You could literally say s1++;, which was equivalent to s1 = s1 + 1;. The post-increment statement is often (if not always) implemented as +=1, so it seems that this also was true for Strings. Fortunately, Java does not allow this anymore.

    Goto … (Section 9.3)
    Of course, being based on C, Oak included the infamous goto statement. Fortunately, Java does not. Exceptions (Section 9.4)
    Where does the name RuntimeException come from? Aren’t all exceptions thrown at runtime? Of course they are, but these exceptions are called runtime because they are thrown by the runtime system.

    In Oak 0.2, all exceptions were unchecked, meaning that no throws clause existed. My guess is that checked exceptions were added only after the whole exception hierarchy was already set in wet concrete. I would have preferred a separate branch for checked exceptions, something like:

      public class Throwable { }    /** Serious errors in the virtual machine */  public class Error extends Throwable { }  public class CheckedException extends Throwable { }  public class IOException extends CheckedException { }  public class UncheckedException extends Throwable { }  public class NullPointerException extends UncheckedException { }

    This way you would avoid catching unchecked exceptions when you catch CheckedException. However, the exception class hierarchy appears to have been developed before the idea of checked vs. unchecked exceptions, so we are stuck with an exception mechanism that will cause headaches for generations to come.

    Asynchronous Exceptions (Section 9.4.2)
    If your program gets an asynchronous exception, you are dead. A few weeks ago I was looking at a program that was throwing OutOfMemoryError. This hiccup can happen at any time really, which is why it is called an asynchronous exception. Another scenario in which this can happen is with Thread.stop(). As you can imagine, this is inherently dangerous (which is why it is deprecated).

    In Oak, life was even more precarious. You could cause an asynchronous exception in another thread using Thread’s postException() method. Now that was dangerous! Imagine if other threads could cause asynchronous exceptions at any place in your code!

    In order to safeguard your code, you could “protect” it. If you wanted to indicate that you had some critical code, which could not handle asynchronous exceptions, you did the following:

      protect {    /* critical section goes here */  }

    And code that was quite happy with asynchronous exceptions did the following:

      unprotect {    /* code that can afford asynchronous exceptions */  }

    A note in the margin said that the default would probably be changed to not allow asynchronous exceptions except in explicitly unprotected sections of code. I’m very glad that this feature was tossed. I cannot imagine how complex the Java programs would have become with it in place.

    The End
    That’s it. The rest of the manual was filled with a Glossary and an Index, which pushed the final page count to 38 pages?probably to satisfy some manager who wanted a manual that wouldn’t blow away in the wind when he showed it to the marketing guys on the golf course.

    Even though this manual was written way back in 1994, it provided for fascinating reading, even late at night.

    Editor’s Note: This article first appeared in Dr. Kabutz’s The Java(tm) Specialists’ Newsletter under the title Once upon an Oak …. To subscribe, send an email to [email protected].


    About Our Editorial Process

    At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

    See our full editorial policy.

    About Our Journalist