Java SE 6
Java & Linux
Java & Linux
By: Calvin Austin
Jan. 1, 2003 12:00 AM
It's been over two years since I wrote my last article about using the Java runtime on Linux ("Java Technology on the Linux Platform" [JDJ, Vol. 5, issue 12]). The Java platform and Linux distributions have not stood still during that time, so I'm taking this opportunity to answer some of the frequent questions that have surfaced since then and provide some insight into some of the more complex issues. If you're a seasoned Java on Linux user or are planning to move to the Linux platform, I trust you'll find the answer you're looking for!
The most visible difference when deploying a Java application on Linux is that each Java thread shows up as its own process. This means that the /proc filesystem will have an entry for each thread and the output of the ps command will list 10 or so processes for a single Java Virtual Machine. This is normal, but it's also confusing and inefficient. Later releases of the ps command (in package procps 2.0.7 and later) will hide the Java threads and display only the master process in the ps output. The full list of threads can be displayed using -m option to ps. Only in newer releases of the Linux kernel will the number of entries in the /proc filesystem be reduced.
The overhead for implementing threads using this design means that you may need to allow a little more time for Java applications to start up on Linux and reduce the number of concurrent threads if the application is thread heavy.
Why Doesn't Someone Fix This?
The earlier NGPT project is based on an M:N thread mapping that has been popular with other Unix operating systems. The M:N solution maps multiple user threads, Java threads in our case, and often runs those threads on a smaller number of kernel threads. Kernel threads are traditionally seen as more expensive for an operating system than user threads.
The newer NPTL approach is to keep the 1:1 thread mapping - one user or Java thread to one kernel thread - but optimize the kernel for thread-related operations, including signal handling, synchronization, and thread creation speed.
Both thread libraries also require modifications to the Linux kernel. NPTL requires the 2.5 kernel that's the development version of the official 2.6 Linux kernel. NGPT can be bolted on to existing 2.4 kernel distributions by rebuilding the kernel with an NGPT patch.
There's also a chance that some of the necessary NPTL kernel changes may also be back ported to 2.4 kernels as a patch.
We've been evaluating both these libraries and have seen some encouraging results from the newer NPTL library due to its compatibility with the existing LinuxThreads pthread library. The current level of compatibility means that applications like the Java runtime will not need to be recompiled or ported and will work "out of the box."
Do You Really Need All Those Threads?
You can reduce the number of threads by using either a connection pool of listening threads or the new New IO Selector and ServerSocketChannel. The Selector class available in J2SE 1.4 manages a list of registered channels and returns those with an event pending. Each ServerSocketChannel can be placed in a nonblocking mode; in this mode the Selector can be used to multiplex sockets in a way that's similar to the Unix poll command. The scalability benefits of using one thread to manage socket connections can be seen in Figure 1.
The chat server used in this test was first implemented using blocking IO (Old IO), and then rewritten to use the multiplexing sockets (New IO). The Linux thread overhead becomes apparent after as little as 100 connections.
The Java Runtime and GCC 3.2
This change in compatibility is apparent if you try to use a Java plug-in with a build of the Mozilla Web browser that was compiled with GCC 3.2. Fortunately, most Linux distributions still supply a browser based on the earlier C++ interface. We're working with the Mozilla team to remove the C++ plug-in dependency; this would enable the plug-in to work with a browser built with either compiler. If the Java runtime were built with GCC 3.2 today, then the plug-in wouldn't work on an earlier browser.
We are planning to build the next major J2SE release on Linux with GCC 3.2, and it should work on both old and new browsers. Our friends at blackdown.org are also planning to release a special GCC 3.2 version for testing.
Java Plug-in Installation Tips for Mozilla
The following small script can be used if you have installed JDK 1.4.1_01 and are using the default Mozilla install directory.
To verify that you have successfully upgraded your plug-in, look at the Java console output. This can be configured using the ControlPanel command from the Java runtime.
Linux Debugging Tools
Using GDB on a Running Process
gdb /usr/java/j2sdk1.4.1_01/bin/java 11712
The 11712 number in the example is the parent Java process thread ID. Most of the Java processes in a ps listing will have a common parent process; this is the parent thread that you'll use as the process number to pass to the GDB.
With the GDB attached to the JVM, you can run any GDB commands. If you've used GDB before, these commands will look familiar. The info threads command lists the Linux threads, the t command selects a thread to be the current thread, and the where command lists the stack frames in that thread.
Starting a Java Virtual Machine Using GDB
To enable the JVM to run from inside GDB on Linux with J2SE 1.4.0 and later, use the following steps.
First, set the LD_LIBRARY_PATH environment variable to point to the Java installation directories; the example shown is for the J2SE 1.4.1_01 release. You can add your own LD_LIBRARY_PATH to point to a JNI library, for example, but add those directories to the end of the LD_LIBRARY_PATH variable.
Next start GDB. From J2SE 1.4.0 onward the Java shell script wrapper used to start the JVM has been replaced by a small executable program. The GDB session can simply be started as follows:
All that remains is to instruct GDB to ignore some of the common signals used by the Hotspot Virtual Machine, and then provide the arguments to the Java program, in this instance the Java2Demo.jar file.
If you want to stop in your own JNI library, enter the following GDB command to trap each time a dynamic library is loaded.
set stop-on-solib-events 1
Use the cont GDB command to continue execution until you can see that your library has been loaded; this should occur after a dozen attempts. You can list the shared libraries by running the sharedlibrary GDB command.
Finally, to break on a function in your JNI library, enter the GDB command break with the function name you want to stop in.
Reader Feedback: Page 1 of 1
Latest Cloud Developer Stories
Subscribe to the World's Most Powerful Newsletters
Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
SYS-CON Featured Whitepapers
Most Read This Week