GJD V2 design
In Java, there can be only one JVM per process, so a single JVM is started by the driver code. Alternatively, the UPoC code must set the class path for both of them. Even then, you cannot destroy a JVM and create another without ending the process. Thus, the JVM becomes a global static in the engine.
When a JVM is started, the thread that started it becomes the main Java main thread. That thread cannot be terminated or the JVM errors. The starting of the JVM cannot be finished in an engine thread. It is only finished in its own sub-thread. That sub-thread exists until the engine process is shut down.
In the initial design, the JVM parameters were contained in an .ini file named for the protocol thread.
An issue results when more than one UPoC and GJD protocol thread are in use.
When the UPoC starts, the thread might not contain a GJD protocol driver. The JVM parameters in V2 are common to the process. A new control file is introduced that is named for the process instead of a thread. All GJD protocol threads still have their thread_name.ini file. The JVM section of those files might contain only an "include" directive that points to the process_name.pni file.
The driver section of thread_name.ini remains unchanged as it sets up the GJD instance in the JVM. When the UPoC code starts, first the process_name.pni file is directly accessed because there may not be any thread_name.ini for that engine thread. (Remember that Java UPoCs can be used in translations, so the thread name can be the xlate thread and not a protocol thread.)
During JVM activation, its parameters are obtained first from process_name.pni, if it exists. If it does not exist, then thread_name.ini is used, if it exists. If neither of these files exist, then it is assumed that the parameters are the defaults for UPoC use.
The process_name.pni file contains any user settings, such as configuring the JVM for Java debugging operations.
In earlier versions, the java_uccs directories were searched for any jar files and they were added to the default class path. Now, this searching feature has been added for any user-specified directory in the class path.
When there are more than one GJD in the process, the directive USE_LOADER=true
must be added to the JVM section of
process_name.pni. This entry causes a URLClassLoader
instance to be used for loading the user’s
classes.
If it is not there, then the default JVM loader is used. Same-named classes that are used in different drivers are not unique. Protocol thread restarts can reuse previously loaded classes whose memory may not be garbage collected.
With multiple GJD threads in the process, indicated by USE_LOADER=true
, the user class loading is modified so that
each GJD uses its own instance of URLClassLoader
.
Because it becomes the root loader for all GJD’s classes and the loader is part of a
class, if the same class is used in more than one GJD they are not the same class.
When a GJD thread is shut down, the instance of the loader is destroyed. All classes that it loaded are cleaned up by the JVM garbage collector. If the GJD protocol thread is restarted, then a new instance of the loader is created. No class instances are reused from the previous running of the thread.
A Java driver shared mode restriction is that using its own classloader of the java app must be issued in shared mode of the Java driver.
There are problems in using the shared JVM in that the URLClassLoader
must be used for all class loading. The shared JVM could
also be the root loader for such in the GJD. Not all available code has this feature.
For example, Tomcat, during start up, ignores this loader and uses the system loader. In
this case, two instances of Tomcat cannot exist in a single process. The protocol thread
cannot be restarted if it is shut down. In general, you cannot know this problem exists
without using the code and trying a protocol thread restart and looking for errors. For
user-written code that uses things that also cannot be run as applications, there should
be no problems.