                      VisualAge(R) for Java(TM)
                             Version 3.0

                     Java Compiler and Related Topics

                            RELEASE NOTES


Table of Contents
-----------------

1.0 Compiler - Limitations and known problems
   1.1 Incremental compilation
   1.2 Problem handling
   1.3 Exporting types
   1.4 Debug attributes
   1.5 Inner types
       1.5.1 Default abstract methods
       1.5.2 Imports in default package
       1.5.3 Explicit qualification
       1.5.4 this.super()
       1.5.5 Access to synthetic names
       1.5.6 Method overloading
       1.5.7 Anonymous type modifiers
       1.5.8 Visibility of sibling classes
       1.5.9 Use of member interfaces
   1.6 Other clarifications and limitations
       1.6.1 Circular constructor invocation
       1.6.2 Incompatible interfaces
       1.6.3 Class and method collisions
       1.6.4 Method ordering on export
       1.6.5 Type visibility in a default package
       1.6.6 Empty statements
       1.6.7 Simple name imports
       1.6.8 Protected constructor visibility
       1.6.9 Numeric underflow
       1.6.10 Definite assignment in dead code
       1.6.11 Assignment conversion
       1.6.12 Incremental compiler may produce conflicting serialVersionUID
       1.6.13 Static final variable dependency analysis
       1.6.14 Side Effects of copying and renaming
       1.6.15 Source positions for do-while loop
       1.6.16 Inconsistencies during incremental compilation 
2.0 Searching
3.0 Referenced types
4.0 Project limitations
5.0 .class files in the IDE

1.0 Compiler - Limitations and known problems
---------------------------------------------

VisualAge for Java implements the Java Language Specification. In
areas where the specification is unclear, VisualAge uses JDK
1.1.7 as a reference implementation.

1.1 Incremental compilation

VisualAge supports incremental compilation. Incremental
compilation allows the developer to see the effects of his/her
changes as they are made, rather than explicitly invoking the
compiler periodically to find the problems that have been introduced
during the last edit cycle. In addition to compiling the method that
the developer has just changed, any methods that are impacted by this
change are also automatically recompiled. Changing (or adding or
deleting) a class definition also triggers this automatic
recompilation.  As a result, binary compatibility is automatically
ensured by the compiler for any program implemented within the
environment.

These incremental changes take effect immediately.  A thread that is
repeatedly invoking a method immediately starts executing the new
method. Code may be changed in the debugger as well; any change in
the debugger takes effect upon completion and saving of the edit.

1.2 Problem handling

All problems that are detected are classified as either warnings or
errors. Warnings are reported on problems that can be ignored by the
compiler without changing the semantics of the developer's program.
The existence of a warning does not effect the execution of the
program; the code executes as if it were written correctly (for 
example, detecting unreachable code does not prevent running it). 
Errors are more severe problems that cannot be ignored since the
semantics of the program is corrupted, and therefore its execution
cannot complete. If there is an error in a method, the debugger shows
the problem description and a stack trace containing the problem method
(or if it is an initialization problem, the constructor or the code
that triggered the static initialization). A method with an error
cannot be run until the error is fixed.
 
The VisualAge compiler detects problems in several phases (parsing,
type checking, code generation, and so on). Proceeding to the
next phase is allowed only if no error has been detected.
Thus errors detected in some phases cause the compilation process to
be aborted. Therefore, fixing a compilation problem may reveal other
previously unreported problems.

Some problems are more serious than others. For example, f a class 
subclasses a nonexistent class VisualAge cannot create instances of
this class. It is also difficult to accurately compile methods when
much of the context is unavailable. Under these conditions, the
compiler ignores the methods. Later, when the missing classes and
interfaces are available, the methods are fully compiled
automatically.

The conditions above may cause reported problems to appear to have
dissapeared.Possible reasons for this are:

   a. The problems have been superseded by more significant errors
and just discarded.  If the more serious errors are resolved, these
problems will return.

   b. A field initialization problem was detected and reported
against the constructor.  When such a constructor is saved, the
problem report is "credited" to the class and no longer kept with the
constructor.

Classes must be syntactically correct in order for the compiler to
accept them; however methods only need a syntactically valid method
header. Such a method is recorded in the workspace as a problem
method, and behaves as described above.

Some problems reported on classes do not provide source highlighting.
For these problems, you should attempt to deduce the effected type
and find it in the class definition source.

1.3 Exporting types

A type can be exported in two formats: .java or .class. A type in
the environment that is from a .class file can only be exported in
.class format since there is no source available. Any source class
can be exported as either .java or .class format. The IDE does not
allow a developer to export in .class format if there are any errors
in the class - these errors must be corrected first. However, it is
possible to export in .java format even if there are errors. In this
case, the resulting file is not valid input for another java compiler.

1.4 Debug attributes

The VisualAge compiler produces debug attributes (if requested).  

A Java compiler must prevent any user code from explicitly reading 
an uninitialized local variable, however, a program may get interrupted 
in a state where some variables are not yet set, but already declared
(user interrupt, ...) and a debugger may try to show all visible 
variables at this point using the debug attributes recorded in .class 
files for this purpose. These debug attributes contain the visibility 
range for each local variable, and VisualAge considers each 
variable to be visible from its declaration to the end of its 
definition scope, where other compilers may consider it to be visible 
only once it is initialized.

Therefore, some external debuggers may fail on VisualAge output when
attempting to display variables which are not yet bound to a value
(for example, trying to display the content of an array which has not yet 
been defined). The VisualAge debugger handles this case correctly.  
Due to the VisualAge algorithm for assigning visibility ranges, a 
debugger may order local variables differently when using VisualAge 
output than when using another compiler's output.

1.5 Inner classes

The Inner Classes Specification does not cover the full
implementation details and is still being enhanced. 

1.5.1 Default abstract methods

A compiler should produce default abstract methods for any abstract
class that does not implement or inherit implementations methods
defined in the abstract class' superinterfaces.  VisualAge
correctly produces these default abstract methods for top level and
type member classes; however, these methods are not produced for
local types.  If this condition should occur, a compilation error is
reported. To work around this limitation, simply explicitly define
the necessary abstract methods in the abstract local class.

1.5.2 Imports in default package

If type members are imported in a type from a default package, a
warning is incorrectly reported notifying the developer that the
package does not exist.  This warning should be ignored.

1.5.3 Explicit qualification

VisualAge does not request explicit qualification for implicit use of
inherited methods, when it is hiding an enclosing one. VisualAge
considers inherited methods prior to enclosing ones without issuing
an error (note that qualifying explicitly the code would be accepted
as well).

Here is a example of such a case, the implicit access to foo() should
yield a complaint:

public class MethodQualification {
   void foo() {
      System.out.println("Inherited foo() for anonymous type");
      class Local {
         void foo(){
            System.out.println("Enclosing foo() for anonymous type");
            // should request explicit qualification
            new MethodQualification () { {foo();} }; 
         }
      };
   }
}

another example involving fields :

public class FieldQualification {
   String field = "Inherited field for anonymous type";
   void foo() {
      class Local {
         String field = "Enclosing field for anonymous type";
         void foo() {
            new FieldQualification() {
               {
                  // should request explicit qualification
                  System.out.println(field); 
               }
            };
         }
      };
   }
}


1.5.4 this.super()

Some compilers allow constructors to contain super invocation of the
form "this.super()". VisualAge rejects this because it is not legal
to use this in a constructor invocation.

1.5.5 Access to synthetic names

VisualAge does allows the use of $ names to refer to nested types.
In addition, VisualAge allows the use of $ names to access synthetic
fields. Developers should not use these names.

1.5.6 Method overloading

The inner class specification notes that class scoping does not
influence overloading. VisualAge searches through enclosing types
until an applicable method is found. If a method with the intended
name, but that does not have the correct number of arguments is
found, it is ignored, and the search is continued. Some compilers
stop when reaching this type of method.

1.5.7 Anonymous type modifiers

Some compilers treat anonymous inner types as final types with
respect to casting conversion. VisualAge does not do this; therefore
some casting conversion problems may only be detected at runtime, as
shown in the following example:

class CheckInstanceOf {
   void v() {
      new Object() {
         // should complain on the instanceof check at compile-time
         boolean b = this instanceof Runnable;  
      };
   }
}


1.5.8 Visibility of sibling classes

The rules determining the visibility of sibling classes will
report an error anytime a local type is defined with the same name as
a sibling member type.  In the following example, M2 defined as a
local type is actually in conflict with the sibling member class,
which is also visible and bound as M1's superclass.  VisualAge
reports this error.

class ExportedNames {
  void foo() {
    class Local {
      class M1 extends M2 {
        void bar() {
          class M2 {} // M2 already defined
        }
      }
      class M2 {}
    }
  }
}

1.5.9 Use of member interfaces

Some compilers may accept the following code, however specifications
are unclear whether this is legal or not, and issues are still being
debated at this point.

class A implements A.C {
  interface C {}
}

VisualAge for Java will reject such code claiming A.C is not defined.

Note that using a static member class is rejected by all compilers, 
even though the same rule as for interface should apply since there
is no need for an enclosing instance.

class A extends A.C {
  static class C {}
}

1.6 Other clarifications and limitations

1.6.1 Circular constructor invocation

It is a compile-time error for a constructor to directly or
indirectly invoke itself through a series of one or more explicit
constructor invocations involving 'this'. Only the direct
invocation case is detected in the current implementation. 

1.6.2 Incompatible interfaces

It is a compile-time error to cast an interface T to an interface S
if S and T contain methods with the same signature but different
return types This error is not detected at compile time, but at 
runtime, and a class cast exception is thrown.

1.6.3 Class and method collisions

During source file import, class and method collisions are silently
ignored. The last definition in the file is used.  This also occurs
if the class definition contains two definitions of a single method.

1.6.4 Method ordering on export

When exporting code, the ordering of methods may not be the same as
during the initial import, nor the previous export, thus no
assumption should be made on the method ordering in exported source
files or class files. Field ordering is preserved.

1.6.5 Type visibility in a default package

Classes defined in a default package are only visible within the
default package. It is not possible to access these classes from
outside the default package.

1.6.6 Empty statements

Empty statements are ignored. Therefore, the compiler does not report
unreachable code errors on unreachable empty statements.  The
following methods exhibits this behavior:

void f () {
   return;
   label: ;
}

void g () {
   return;
   ;;;;;
}

In addition, semicolons are silently ignored when included in a
class definition.  Therefore the compiler accepts the following
class definition.

class C {
   ;;;;
}

1.6.7 Simple name imports

An import of a simple name is ignored.  No errors are detected or
reported, and the import is ignored during name resolution. 

1.6.8 Protected constructor visibility

It is an error for a protected constructor to be invoked from another
package, even if the type is a subclass of the type defining the
constructor. VisualAge detects and reports this error.

1.6.9 Numeric underflow

VisualAge does not report compile time numeric underflow.  Therefore
the following incorrect code is accepted:

    double ds =1.0E-326;

This expression has a value of 0.0.

1.6.10 Definite Assignment in dead code

Definite assignment in conditionals is handled differently depending
on compiler implementations. VisualAge will detect dead code
and not propagate initializations outside the dead code. Note that
definite assignment rules for an IF statement enforce that even
though the code inside the dead branch is unreachable, it is not
reported as such and is silently eliminated during code generation.

class DeadCode1 {
   final static boolean Debug = false;
   int foo() {
      final int i;
      if (Debug) i = 1;
      i = 2;  // some compilers complain about a duplicate assignment.
      return i;
   }
}

In the following example, VisualAge reports that the
assignment 'k = i' is using an uninitialized variable, and since this
assignment is in dead code, it actually never occurs and therefore
the next assignment statement sets the local 'k' for the first time.

class DeadCode2 {
  final static boolean Debug = false;
  int foo() {
    int i;
    final int k;
    if (Debug) { k = i; } // local i may not be initialized.
    k = 1;
    return k;
  }
}

In the following example, VisualAge only reports the use of an
uninitialized variable.

class DeadCode3 {
   final static boolean Debug = false;
      int foo() {
         int i;
         final int k;
         if (false) { k = i; } 
         if (false) { k = 1; }
         k = 1;     
         return k;
      }
}


1.6.11 Assignment conversion

VisualAge does not provide an implicit narrowing conversion for 
constant expressions from char to byte. 

The following type of statements are not accepted by VisualAge:

byte b = 'a';  // JLS 5.2
byte[] ar = {'a'};   // JLS 5.2, 10.6

1.6.12 Incremental compiler may produce conflicting serialVersionUID

To facilitate incremental compilation, synthetic fields and methods
are not created. Although this usually does not impact program
execution, it may impact the serialVersionUID (since the synthetic
methods are considered when computing the serialVersionUID
for the class). When this condition arises, objects serialized in 
the IDE will not be readable by another runtime. There are two 
ways to produce consistent serialVersionUID's everywhere. First, 
define a static long field serialVersionUID that records the 
serialization hash.  Second, if editing the source is not 
a viable solution, export the necessary classes as .class files 
and then re-import them.

1.6.13 Static final variable dependency analysis

If a static final variable depends on the value of a static final
variable defined in another class, then changing the second
variable's value does not cause the initial variable's value to
change. To work around this problem, delete and add the offending
project, package, or type. Any dependency error can be resolved
using this workaround.

1.6.14 Side effects of copying and renaming

When a package or class is copied or renamed, qualified references to
the changed package or class are not edited. Problems are
reported to show you where the code must be changed.

1.6.15 Source positions of do-while Loop

The computation of source positions of Do-While loops is wrong, and
may affect debug attributes produced by the compiler. This in turn
may affect highlighting within the debugger. Another consequence is
that the code assist may not provide assistance inside a Do-While
loop.

1.6.16 Inconsistencies during incremental compilation 

When incrementally adding a missing type, there are circumstances
where the incremental compilation process will fail to automatically
update some existing problems. This problem only occurs when the only
reference to the added type corresponds to one of the following cases:

  - missing type was the return type of a method being invoked,
  - missing type was the type of a field being accessed,
  - missing type was an exception type of a method being invoked,
  - missing type was type of a field defined in a local class,
 
When adding the required implementations for abstract methods defined
on implemented interfaces, the incremental compilation process may
fail to update the subclasses of the class where the required method
implementations are defined.

In all such cases, forcing the code to recompile will be the only way 
to get rid of those undesirable problems (for example, unload then 
reload the problem code).

2.0 Searching
-------------
The search engine examines the .class file information associated
with the class. There are times when the results of such a search
can provide non-intuitive results. In particular, a constructor
reports that it references a type if the field initializer for that
type in the class definition references a type. This occurs because
the instance field initializers become part of the constructor at
compile time.

If the search engine finds an inner type, it answers the enclosing
type or enclosing method as the result. The inner type can then be
found in the enclosing type or enclosing method.

3.0  Referenced types
---------------------

VisualAge computes the referenced types and referenced
projects given a starting class. The mechanism for doing this is
similar to the search engine described above.  There are a few
limitations with the current solution.  First, references to a class
by name are not considered a reference to the class.  For example,
the expression Class.forName("MyPackage.MyClass") does not report a
reference to MyPackage.MyClass.  Second, the referenced types
algorithm does not include types that are only found in method
signatures.  This is not a limitation for programs since a program
always provides an argument of the appropriate type.  However, if you
are exporting a framework, it is possible that some types may be
omitted.  Finally, if there are errors in the classes that are being
searched for referenced types, the operation fails.  To work around
this problem, add the missing types.


4.0 Project limitations
-----------------------

For each project in the workspace, a corresponding resources
directory is created.  This directory is named with the project name.
If the project name is not a valid directory name, most likely
because the name was too long, the directory will not be created and
a message will be written to the log.

In the enterprise version of VisualAge, the Administrator can change
the owner of the system projects to another user.  It is strongly
recommended that the Administrator does not change this unnecessarily.
   

5.0 .class Files in the IDE
---------------------------

VisualAge manages both source and binary (.class file)
classes.  Binary classes are not verified on import.  It is assumed
that only valid class files are imported.  A system error may be
reported if an invalid class file is imported.  The compiler validates 
the superclass and superinterfaces of the binary class, and also the 
fields when the class is added to the workspace.  The methods are not 
validated.