1.0 Introduction
2.0 The Class Libraries
2.1 General notes
2.2 Package java.lang
2.2.1 Exceptions
2.2.2 Class Loader
2.2.3 Special case for Runtime.getRuntime().exec (...);
2.2.4 Reference Objects
2.3 Package java.awt
2.3.1 Graphics
2.3.2 Drag and drop
2.4 Package sun.tools.jar
2.5 Changing Java class libraries
3.0 Program Execution
3.1 Java threads
3.1.1 Threads and JNI
3.1.2 Terminating threads in the Debugger
3.2 Simulating multiple virtual machines
3.3 Running Java programs and changing a type
3.4 Object finalization
3.5 Memory limit
3.6 JNI
3.6.1 Unsupported JNI API
This release note provides information on the class libraries provided with VisualAge for Java, Version 3.5. In addition, it describes how programs are executed within the VisualAge for Java environment.
VisualAge for Java, Version 3.5 is based on the Sun J2SDK v1.2.2 class libraries. The Sun JDK and VisualAge for Java implementations are highly compatible, however, there are some differences.
These are two of the major differences:
2.2 package java.lang
2.2.1 Exceptions
The stack trace information which is provided by the Throwable.printStackTrace(...) method will not match exactly the
stack trace output from a Sun VM. This reflects different underlying implementations, and is
not a defect.
When an uncaught exception causes the debugger to open, only the stack between the last place where the exception was caught (for example, by a "synchronize (...) { ... }" statement) and the root of the stack trace will be visible. There are two possible strategies for debugging under this scenario:
The ThreadDeath exception does not provide any details stack trace information.
2.2.2 Class Loader
The IDE treats projects loaded into the workspace as elements of the classpath or as extensions.
A class will
be found by a Java program if the project it is in is added to the classpath. If
the project is set as an extension, it will be found automatically.
When a program attempts to locate a class or resource the search proceeds as follows:
The Class Loaders included with VisualAge for Java are constructed in such a way that they respect the user-specified classpath, extensions, system classpath, and the rules of the development environment concerning how classes are brought into the workspace and code repository. This leads to the following restrictions:
Each project in the IDE must have a resource directory in the file system. If the project has no resources, an empty directory must exist or the classes that are inside the IDE will not be found. Any project may be set as an extension project. The project's directory must have the project name and must be inside:
The resources are not moved around when setting a project to be an extension,
this must be done manually.
2.2.3 Special case for Runtime.getRuntime().exec (...);
You can launch an external program by the use of Runtime.getRuntime().exec (...). If
the program is executable, the IDE will recognize it and will run the Java program in the IDE itself. For
instance, load project "IBM Java Examples" and try the following in the Scrapbook
Runtime.getRuntime().exec ("java com.ibm.ivj.examples.awttests.AwtRollingOTI");
If you open the Debugger you will see that the new Java program is running in the IDE itself.
You will see the extra text "<unnamed>" as part of the name listed in the
Debugger.
If you need to launch a Java program outside the IDE, make sure you give it a different name or
simply use an absolute file path to it.
2.2.4 Reference Objects
Currently only java.lang.ref.WeakReference is fully implemented. Other reference objects are treated as strong references by the garbage
collector.
2.3 package java.awt
2.3.1 Graphics
The following are the known limitations and omissions in the AWT graphics support as provided by the VisualAge for Java, Version 3.5
class libraries. Some of these cases describe platform behavior which application programmers should be aware of.
2.3.2 - Drag and drop
The following are the known limitations and omissions in the AWT drag & drop support as provided by
VisualAge for Java. Some of these
cases describe platform behavior which application programmers should be aware of.
2.4 Package sun.tools.jar
Running the JAR utility from the IDE does not convert wildcard arguments as in the following:
jar cvf test.jar *.class
This is correct behavior -- in the Sun implementation it is the JAR.EXE file which provides wildcarding, not the Java code.
2.5 Changing Java class libraries
In VisualAge for Java, Version 3.5, certain packages and classes in Java class libraries
can be replaced or deleted. As well, you can add your own packages and classes into
a project.
While some of the packages and classes can be changed or removed, under no
circumstances should these packages and classes be moved into another project in the workspace. If this is done, behavior of the packages and classes will be
undefined.
Warning: The aspects of the execution environment described in this section may change in future releases. Therefore, you should avoid implementing code that relies on the behavior described here.
Java threads are not implemented as OS threads. Basically, the whole environment runs as a single OS thread, and Java threads are
implemented in software by the environment itself. Threads are scheduled based on time slices of approximately 10 milliseconds. You
cannot change this value.
Although priorities of Java threads can be changed by the API available in java.lang.Thread, internally they are scheduled as
though they all have the same priority. The IDE itself also runs as a thread (which is not visible to application code), but at a higher
priority. This may cause the other threads to "freeze" when IDE operations are being performed.
This approach allows the IDE user interface to be more responsive to user actions.
However, it also means that if the IDE user interface blocks for some
reason, the environment will appear as though it has hung.
Waiting on OS blocking calls or blocking on monitors (such as synchronized methods) can cause this behavior. Java code that is run from within the IDE UI thread can potentially lock the environment. Typically, this does not happen, but it can occur when evaluating synchronized methods from the debugger and during certain operations performed by the visual composition editor.
3.1.1 Threads and JNI
Even though threads in the IDE are not implemented with real OS threads, a JNI call that may end up making an OS blocking call will
not lock the whole VM. A proprietary mechanism is used so that the other Java threads still run, simulating the concurrency of real OS
threads.
3.1.2 Terminating threads in the Debugger
Caution should be used when terminating threads in the debugger because it may cause deadlocks or prevent an application from
processing events. For instance, the standard AWT event dispatch thread for a Java program (that has AWT windows) shows up in the list
of available threads, and if it is terminated, that particular program will no longer respond to UI events
like mouse move, enter, or click. You will have to terminate that Java program using the
Debugger to get the window(s) to close.
If you use the Visual Composition Editor (VCE) and you have enabled "Show system programs" from the Debugging page of the Options dialog,
you will be able to see the AWT EventQueue thread for the program you are building visually. The same restrictions apply here - make sure
you do not terminate any of the threads or the program itself. Make sure you use just the VCE itself for that particular program. Internal errors may happen if you fail to do so.
The Scrapbook can have multiple pages, each of which behaves like a completely separate Java program running in its own virtual machine.
Code that is run in one page has no side-effects on code running in other pages. Therefore, if you have client/server programs, for
example, and you want to test them in the same machine, there is no need to start two separate environments. All you need to do is open a
page in the Scrapbook and type in code to launch your server, then go to another page and type the code to launch your client code. They
behave as if they were launched from two separate virtual machines.
Here is a simple example. If you have class X with static slot y, and it is initialized with null as shown below:
public static String y = null;
and you go to one new page of the Scrapbook and run:
X.y = "abc"; com.ibm.uvm.tools.DebugSupport.inspect (X.y);
you get an Inspector showing:
"abc"
Now go to another new page of the Scrapbook and run:
com.ibm.uvm.tools.DebugSupport.inspect (X.y);
In this Inspector the value of y is still null.
Note, however, that if you add, modify or delete methods or classes, the changes are global to the environment. That is, any changes in
the code either in methods, or the shape of the classes, are immediately visible in all Scrapbook pages where these classes are
used (and in all associated inspectors, debuggers, and so on). In some cases, depending on the change, the Scrapbook page may be reset
- see the section: 'Running Java programs and changing a type'.
As you would expect, code which is run from Run > In Applet Viewer and
Run > Run Main menu items also behaves like a
completely separate Java program running in its own virtual machine.
You can change methods as a Java program runs. The changes will have an immediate impact on the behavior of the application, so you can experiment with changes. However, if you change a type significantly (adding/removing fields, etc.) all programs where that type has been initialized will be terminated. In the case of Scrapbook pages, the pages will be reset.
Changes in static fields do not cause program termination or Scrapbook pages to be reset.
A special case of this behavior is the finalize() method. An object will only be finalized if a finalize() method (other than the one in
Object) was defined at the time the object was instantiated. Adding a finalizer to running code will allow any new objects to be finalized
when they become garbage, but any pre-existing objects will not be finalized. If a finalizer is deleted, when the objects are collected
the nearest superclass, finalize() implementation is used (potentially the one in Object).
Objects that are no longer referenced may be finalized if they implement the finalize() method. However, it is important to note
that nothing prevents users from writing finalizers that can, potentially, loop forever. For instance, a finalizer
like the following can be implemented:
while (true) {};
This would make the finalizer thread loop forever, being unable to finalize any other objects.
Another obvious case is deadlock, where a finalizer attempts to call a synchronized method, and there is already a different thread in the
monitor associated with the object. In this case the finalizer will have to wait until the monitor is released. If the monitor is never
released due to program bugs, the finalizer will also block forever.
Programs can also generate garbage at a high rate, in which case the finalizers have to be run more often. Running finalizers is very
important in an integrated environment like the IDE, since it can host multiple programs running (for instance, multiple applets, or
multiple pages in the Scrapbook), simulating multiple virtual machines as described in section 3.2.
Not running finalizers could mean leaking OS resources, which is why the IDE is careful about finalizing as much as possible.
In order to cope with the constraints above, the IDE reserves a finalizer thread with an internal priority higher than the priority
at which the Java programs usually run (see the section on Java threads for more
information). This thread sleeps for a while, then it wakes up and
finalizes some objects, then it sleeps again. If the garbage creation rate is high, it will run longer (finalizing) between sleeps. It
also has a timeout to run finalization. If objects cannot be finalized in that particular interval the finalizer thread is terminated and a new one is created, and the whole finalization
mechanism is restarted. Currently the finalization timeout is five seconds, and the finalizer
sleeps and wakes up every second. These
values cannot be changed.
VisualAge for Java has an aggressive memory allocation scheme that attempts to compact the heap several times before asking the OS
for more memory. In addition, there is a relatively high limit on how much memory can be allocated from the OS. If the machine has
over committed on memory allocation, the compaction algorithm will cause swapping. If the user wishes to manually cut down the amount
of memory available to the product (and cause OutOfMemoryError exception to be thrown earlier), add the following two lines
of text to the end of the ide.ini file in the program directory:
[VM Options]
maximumMemoryLimit=ZZZ
Where ZZZ is the maximum number of BYTES the product should be allowed to allocate. (e.g.: maximumMemoryLimit=128000000 for approx.
128MB memory limit).
Note also that the VM behaves differently than the Sun J2SDK(TM) when dealing with OutOfMemoryError. Attempting to allocate many more
objects after the exception has been thrown can lead to the abrupt termination of the whole IDE.
If you experience OutOfMemoryError messages, you should shut down the IDE and
raise the maximumMemoryLimit.
3.6.1 Unsupported JNI API
The JNI Invocation API methods are not implemented.
This is a known limitation in VisualAge for Java, Version 3.5.
The following are implemented (JNI 1.2 APIs):
FromReflectedMethod
FromReflectedField
ToReflectedMethod
ToReflectedField
The following are implemented:
AttachCurrentThread
DetatchCurrentThread
The following are implemented as NOP (they succeed but do nothing):
EnsureLocalCapacity
PushLocalFrame
PopLocalFrame
The following are implemented to fail:
JNI_CreateJavaVM
DestroyJavaVM
JNI_GetDefaultJavaVMInitArgs
The following are implemented but incomplete:
JNI_GetCreatedJavaVMs - returns either nothing or the active VM