Java Programming, Lecture Notes # 54, Revised 10/06/99.
Preface
Introduction
Using the System Class
The Standard I/O Streams
System Properties
Forcing (Requesting) Finalization and Garbage Collection
Miscellaneous System Methods
General Security Considerations
The Runtime Object, Using System-Dependent Properties
Review
Students in Prof. Baldwin's Introductory Java Programming classes at ACC are responsible for knowing and understanding all of the material in this lesson (except that they are not responsible for detailed information that is specific to C++).
The detailed material on C++ is provided as supplementary material for the benefit of persons already familiar with C++ who are making the transition into Java.
Sometimes your program will need to access various "system" resources such as stream I/O, the system clock, etc.
Java provides the System class which provides a platform-independent interface between your program and these resources. Otherwise, every time you needed to run your program on a different platform, you would have to modify it to take the peculiarities of the new platform into account.
The System class is a member of the java.lang package. The following table shows the declarations of the various fields and methods contained in the System class.
public final class java.lang.System extends java.lang.Object { // Fields public static PrintStream err; public static InputStream in; public static PrintStream out; // Methods public static void arraycopy( Object src, int src_position, Object dst, int dst_position, int length); public static long currentTimeMillis(); public static void exit(int status); public static void gc(); public static Properties getProperties(); public static String getProperty(String key); public static String getProperty( String key, String def); public static SecurityManager getSecurityManager(); public static void load(String filename); public static void loadLibrary(String libname); public static void runFinalization(); public static void setProperties(Properties props); public static void setSecurityManager( SecurityManager s); } |
You will recognize that we have used some of the members of this class, such as out, in, exit(), currentTime(), and getProperties(), in earlier lessons. In some cases we were using those members without really understanding what we were doing.
We will attempt to rectify that lack of understanding in this lesson.
You don't instantiate an object of the System class to use it, because all of its variables and methods are class variables and methods.
In fact, you cannot instantiate an object of the System class. It is a final class, and all of its constructors are private. That is why you don't see the normal collection of constructors in the above table.
You will recall that in order to access a class variable or method, you simply join it with the name of the class using a period such as in the very familiar
System.out.println("my string"); |
Class methods are accessed using the same syntax. In a previous lesson, we used the following code to return the default system properties which were passed to a constructor in order to store them in a Properties object:
System.getProperties() |
You may want to go back and review that sample program.
The print(), println(), and write() Methods
Arguments to print() and println()
Printing Objects of Different Data Types
A major future lesson deals with Input/Output Streams. This section of this lesson touches on the subject only in relation to the use of the System class.
The streams used for reading and writing to the standard input and output devices are probably the most often used aspect of the System class.
As you are already aware, System provides one stream for reading from the standard input device, one stream for writing to the standard output device, and one stream for writing to the standard error device.
There are three standard input and output streams managed by the System class:
These streams are automatically opened and linked to the devices when a program begins execution.
The class variables out and err are of type PrintStream, meaning that they have access to the methods of the PrintStream class. PrintStream provides the following three methods to print text to the stream:
You are already familiar with the first two of these methods. Having these methods available in the PrintStream class means that you can write statements such as
System.out.print(...); System.out.println(...); System.out.write(...); |
The methods print() and println() are the same except that println() automatically places a newline in the stream at the end of the material in the argument list.
The write() method is used to write bytes to the stream. You can use write() to write data which is not intended to be interpreted as text (such as bit-mapped graphics data).
The print() and println() methods both take a single argument of any of the following types:
In each case, the system converts the data to an appropriate set of characters and transfers those characters to the standard output device.
If you invoke println() with no arguments, it simply places a newline in the stream.
As you are already aware, the println() method can be used to translate variables of all the primitive types into their representative character values and display them on the standard output device.
In addition, overloaded versions (of toString) are available to produce appropriate output for objects of various standard classes. For example, the following statements
Thread objectData = new Thread(); System.out.println(objectData); |
might produce the following output.
Thread[Thread-4,5,main] |
The toString() method, possibly overloaded, is used to convert objects to their String representation.
When you use print() or println() to print an object, the output depends on the type of the object. For example, printing a String object yields the contents of the String.
Printing a Thread object produces an output string in the following format:
ThreadClass[name,priority,group] |
We will be discussing thread objects in detail in a subsequent lesson.
Security Considerations with System Properties
Reading System Properties
Writing System Properties
In an earlier lesson, we learned that properties are key/value pairs that your Java programs can use to establish and maintain various attributes or parameters between invocations.
The Java environment also maintains a set of system properties that contain information about the current environment. As we demonstrated in an earlier lesson, you can access the system properties through the System class. This set of properties defines traits or attributes of the current working environment.
The system properties are initialized to contain information about the runtime environment, including information such as the current user, current version of the Java runtime, etc., when the runtime system first starts up.
Here is a reproduction of the system parameters which were accessed and displayed on my computer in a previous lesson:
-- listing properties -- user.language=en java.home=C:\JAVA_JDK\JAVA\BIN\.. awt.toolkit=sun.awt.windows.WToolkit file.encoding.pkg=sun.io java.version=1.1.3 file.separator=\ line.separator= user.region=US file.encoding=8859_1 java.vendor=Sun Microsystems Inc. user.timezone=CST user.name=Baldwin os.arch=x86 os.name=Windows 95 java.vendor.url=http://www.sun.com/ user.dir=C:\BALDWIN\JavaProg\Combined\Java java.class.path=.;c:\Baldwin\JavaProg;C:\JAVA_JDK\JAV... java.class.version=45.3 os.version=4.0 path.separator=; user.home=C:\JAVA_JDK\JAVA\BIN\.. |
Several different methods are available in the System class to read or write system properties. You can access properties one at a time using the key name, or you can read the entire set of properties in one operation as was done above.
As of the date of this writing (1/26/97) applets can access some, but not all system properties. Also, applets cannot write system properties. You might expect major changes in this area in upcoming months. We will discuss this in more detail later.
Two methods are provided by the System class to read system properties:
If you go back and examine the class declarations at the beginning of this lesson, you will note that there are two overloaded versions of getProperty().
Both versions are used to retrieve the property named as the first argument. One of the two versions only has one argument.
Also both versions return an object of type String. The names of all the standard keys are listed in the table above which shows the values associated with each of the keys on my computer at one point in history.
In the event that the first of the two methods is unable to find the key, it will return a null reference.
The second overloaded version of the getProperty() method requires two strings as arguments. The first argument is the key to look up and the second argument is a default value to return if the key cannot be found or if it has no value.
A third method provided by the System class to access properties is the getProperties() method.
This method returns a Properties object that contains the complete set of system property key/value pairs. This is the method that was used in an earlier lesson to produce the complete list of system properties shown above.
Having created such an object, you can use the various methods of the Properties class to query the object for specific values.
You can also use one of the available methods of the Properties class to list the entire set of properties. This was discussed in an earlier lesson.
You can modify the existing set of system properties using the setProperties() method of the System class.
This method takes a Properties object that has been initialized to contain the key/value pairs for the properties that you want to set. This method replaces the entire set of system properties with the new set represented by the object.
In general, you should probably be careful not to overwrite system properties.
The setProperties() method changes the set of system properties for the current running application only.
The runtime system re-initializes the system properties each time its starts up. Therefore, changes made using setProperties() are not persistent.
Changing the system properties within an application will not effect future invocations of the Java interpreter for this or any other application.
If you want your changes to the system properties to be persistent, then your application must save the values in a file before exiting and load them again upon startup. The Properties class provides methods for saving and loading property objects.
All objects in Java are instantiated dynamically at run time on the heap. Whenever there are no longer any variables that reference an object, it becomes eligible for garbage collection.
The garbage collector runs asynchronously in the background, collecting objects that are no longer referenced and making the memory occupied by those objects available for re-use.
The finalize() method for an object is always executed before the memory occupied by that object is reclaimed.
You can override the finalize() method with respect to classes that you define to cause code of your choice to be executed before the memory is reclaimed.
According to The Java Tutorial by Campione and Walrath,
"...you can force the garbage collector to run using System's gc() method. Also, you can force the runtime system to perform object finalization using System's runFinalization() method." |
Also according to Campione and Walrath,
"This method (runFinalization() )calls the finalize() methods on all objects that are waiting to be garbage collected." |
In another paragraph, Campione and Walrath state
"You can ask the garbage collector to run at any time by calling System's gc() method" |
The distinction here is between "forcing" the garbage collector to run and "asking" the garbage collector to run.
The following method was added to the System class in JDK 1.1.
runFinalizersOnExit(boolean) With this method, you can guarantee that finalization will occur before the program exits. This enables you to guarantee that any necessary cleanup will be accomplished before program termination by overriding the finalize() method for your class to perform that cleanup. To guarantee finalization on exit, call this method passing true as an argument somewhere early in your program. |
Of the three methods involving finalization and garbage collection, the only one that I have found to be reliable is runFinalizersOnExit().
System.runFinalization() and System.gc() don't seem to behave as I would hope they would. However, the JavaSoft documentation points out that these two methods simply "suggest" that the JVM "expend its best effort" to do what you have requested (finalization or garbage collection).
C++ programmers should note that finalization and garbage collection do not replicate the action of a destructor in C++. For an excellent discussion of this topic, see the soon-to-be-published book by Bruce Eckel, Thinking in Java. A URL was provided in an earlier lesson where you can review a draft copy of this book on line or download it and review it off line. |
Copying Arrays
Exiting the Runtime Environment
An examination of the declaration list for the System class at the beginning of this lesson indicates that there are a variety of miscellaneous methods available within the class.
You can use the System method named arraycopy() to efficiently copy data from one array into another. As you can see in the declaration, the arraycopy() method requires five arguments.
public static void arraycopy(Object src, int src_position, Object dst, int dst_position, int length); |
Two Object arguments indicate the array to copy from and the array to copy to.
Three int arguments indicate the starting location in each the source and the destination array, and the number of elements to copy.
The destination array must be allocated before you call arraycopy() and it must be large enough to contain the data being copied.
You can exit the Java interpreter by calling System.exit() and passing an integer exit code as a parameter. Note that not all operating systems pay attention to the exit code.
According to The Java Tutorial,
"Invocation of the exit() method is subject to security restrictions. So depending on the browser that an applet is running in, a call to exit() from within an applet will likely result in a SecurityException." |
According to Campione and Walrath,
"The security manager is an object that enforces a certain security policy for a Java application. You can set the current security manager for your applications using System's setSecurityManager() method and you can retrieve the current security manager using System's getSecurityManager() method." |
A subsequent lesson will discuss creating and installing your own security manager using these methods in detail.
Also according to Campione and Walrath,
"The security manager for an application can be set only once. Typically, a browser sets its security manager during its startup procedure. Thus, most of the time, applets cannot set the security manager because it's already been set. A SecurityException will result if your applet attempts to do so." |
You should be able to meet most of your system programming needs by using the platform-independent interface provided by the System class.
It is possible to bypass the platform-independent interface of the System class and use system resources directly from the runtime environment.
The Java environment provides a Runtime object which represents the current runtime environment. You can use this object to access system resources directly.
In doing so, you will probably lose the ability to execute your application on different platforms.
Runtime objects provide two platform-dependent services:
Q - Java provides the System class which provides a platform-dependent interface between your program and various system resources: True or False? If false, explain why.
A - False. Java provides the System class which provides a platform-independent interface between your program and those resources.
Q - You must instantiate an object of the System class in order to use it: True or False? If false, explain why.
A - False. You don't need to instantiate an object of the System class to use it, because all of its variables and methods are class variables and methods.
Q - The following code fragment can be used to instantiate an object of the System class: True or False? If false, explain why.
System mySystemObject = new System(); |
A - False. You cannot instantiate an object of the System class. It is a final class, and all of its constructors are private.
Q - What is the purpose of the write() method of the PrintStream class?
A - The write() method is used to write bytes to the stream. You can use write() to write data which is not intended to be interpreted as text (such as bit-mapped graphics data).
-end-