VisualAge(R) for Java(TM)

Version 3.5

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 Accessing static fields from a static member type
      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 copy/rename
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 for Java uses J2SDK(TM) v1.2.2 as a reference implementation.

1.1 Incremental compilation

VisualAge for Java 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 affect 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 are 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 for Java compiler detects problems in several phases (for example, parsing, type checking, code generation, ...). Proceeding to the next phase is allowed only if no error has been detected so far. 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. If a class subclasses a nonexistent class for example, VisualAge for Java 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 been lost:

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 for Java 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 for Java 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 for Java 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 for Java debugger handles this case correctly. 

Due to the VisualAge for Java algorithm for assigning visibility ranges, a debugger may order local variables differently when using VisualAge for Java output than when using another compiler's output.

1.5 Inner classes

The Inner Classes Specification does not cover the full implementation details.

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 for Java 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 for Java does not request explicit qualification for implicit use of inherited methods, when it is hiding an enclosing one. VisualAge for Java 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 for Java rejects this because it is not legal to use this in a constructor invocation.

1.5.5 Access to synthetic names
VisualAge for Java does allows the use of $ names to refer to nested types. In addition, VisualAge for Java allows the use of $ names to access synthetic fields. Do not use these names.

1.5.6 Method overloading
The inner class specification notes that class scoping does not influence overloading. VisualAge for Java 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 for Java 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 for Java 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 Accessing static fields from a static member type
VisualAge for Java does not resolve fields of qualified member types such as X.Y.h correctly.

package test;
    public class X {
    public static class Y {
    public static String h = "hello";
    }
}


To refer to the static variable X.Y.h, first add the single type import:

import test.X.Y;

public class Z {
String a = test.X.Y.h; // fails to resolve Y correctly
String b = Y.h; // work-around
}

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 run-time, 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 for Java detects and reports this error.

1.6.9 Numeric underflow
VisualAge for Java 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 for Java 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 for Java 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 for Java 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 for Java does not provide an implicit narrowing conversion for  constant expressions from char to byte.

The following statements are not accepted by VisualAge for Java:

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 work-around.

1.6.14 Side effects of copy/rename
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. 

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 for Java 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 edition of VisualAge for Java, 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 for Java 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.