Welcome to my website. I am always posting links to photo albums, art, technology and other creations. Everything that you will see on my numerous personal sites is powered by the formVistaTM Website Management Engine.

icon.linkedin.jpgicon.twitter.jpg

  • Subscribe to this RSS Feed
  • Using a ProcessBuilder to Execute an OS Level Command and Properly Read the Exit Code from a Java Process
    10/06/2011 10:42AM

    There are many a situation where a developer will want to execute an OS level command in another process and read not only the standard out (stdout), and standard error (sterr), but also the exit code returned from the process.

    To do so, utilize the ProcessBuilder class along with a helper class (ProcessWrapper) that will provide the ability to set a timeout for the process and read the exit code in a separate thread.

    Following is an example and the ProcessWrapper class with an explaination:

    import java.io.IOException;

    public class ProcessBuilderTest {

        /**
         * Time in milliseconds that we will wait for the process to complete before
         * timing out and killing it.
         */
        private static final long fTimeout = 10000;

        public static void main(String[] args) {

            String[] commandArray = { "some", "command" };

            ProcessBuilder processBuilder = new ProcessBuilder(commandArray);

            Process process = null;
            try {
                process = processBuilder.start();
            } catch (IOException e) {
                // TODO: Error handling, logging
            }

            // --------------------------------------------------------------------
            // Read the exit code from the fProcess
            ProcessWrapper processWrapper = new ProcessWrapper(process);
            processWrapper.start();

            int exitCode = 0;
            try {
                processWrapper.join(fTimeout);

                // Check for an exit code from the process
                if (processWrapper.getfExitCode() != null) {
                    exitCode = processWrapper.getfExitCode();
                } else {
                    // Set our exit code to 1
                    exitCode = 1;
                    process.destroy();
                }
            } catch (InterruptedException e) {
                processWrapper.interrupt();
                Thread.currentThread().interrupt();
                process.destroy();
            }

            System.out.print("exitCode = " + exitCode);
        }

        public static class ProcessWrapper extends Thread {

            private final Process fProcess;

            private Integer fExitCode;

            public Integer getfExitCode() {
                return fExitCode;
            }

            public ProcessWrapper(Process fProcess) {
                this.fProcess = fProcess;
            }

            public void run() {
                try {
                    fExitCode = fProcess.waitFor();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    In the ProcessBuilderTest main() method the command to be executed is build in the commandArray String[].

    A ProcessBuilder instance is created and passed the command to execute. Then a Process instance providing a reference to the process running on the OS is instantiated via the ProcessBuilder.start() command.

    Here is where the wrapper class that helps us to read the exit code comes in. A ProcessWrapper is instantiated and passed a reference to the process on construction, and then the thread started with the .start() invocation.

    Then processWrapper.join(fTimeout) is invoked telling the current thread to wait for the completion of the processWrapper thread, or interrupt it (timeout) after the value of fTimeout (in this case 10 seconds).

    If the processWrapper thread completes before the timeout the main thread invokes processWrapper.getfExitCode(), to acquire the exit code from the process. If not, the process is killed and we pass an exitCode of 1 to indicate abnormal completion.

    Attached is a .zip of the java classes for reference and testing.

    Attachment: processbuildertest.zip 1308 bytes
  • Dynamically Instantiating Classes in Java
    09/16/2011 11:42AM

    There are a number of cases when you may not know exactly what class you will be instantiating and want to be able to dynamically instatiate specific classes based on a configuration file or a condition during runtime.

    To do so, you will need to define an Interface for your classes and can then use the following code as a guide:

    String className = args[0];
    String qualifiedClassName = null;
    Class instanceClass = null;

    try {
            qualifiedClassName = fClassPackage.getName() + "." + className;
            instanceClass = Class.forName(qualifiedClassName);
    } catch(ClassNotFoundException e) {
            e.printStackTrace();
    }

    Interface dynamicInstance = null;

    try {
            dynamicInstance = (Interface) instanceClass.newInstance();
    } catch(InstantiationException e) {
            e.printStackTrace();
    } catch (IllegalAccessException e) {
            e.printStackTrace();
    }

    // Set fields in new instance
    dynamicInstance.setSomething("foo");


    Keep in mind that dynamically instantiated classes must include a no argument constructor.  As a result, you will need to have mutator methods for each field that requires configuration in your class.


  • Regular Expression Library
    09/16/2011 11:35AM
  • Preserving File Permissions When Copying Files with Ant
    09/16/2011 9:16AM

    If you want to retain the file permissions of a file that you copy with ant you must use the <exec> command instead of? <copy>.

    So, instead of:

    <copy file="${source.file}" tofile="${dest.path}/${dest.file}" overwrite="true"/>

    Use:

    <exec executable="cp">
    ??? <arg value="-pf"/>
    ??? <arg value="${source.file}"/>
    ??? <arg value="${dest.path}/${dest.file}"/>
    </exec>

  • java.lang.OutOfMemoryError: unable to create new native thread Exception When Using SmbFileInputStream
    09/15/2011 4:04PM
    I am writing an application that copies files from a Samba share using the JCIFC Java CIFS Client Library (which, btw, is a very helpful, widely used, and well developed project).

    As usual I am under the gun to get something up and running so I do not have the luxury to explore all of the details as much as I would like.? My application gets a directory listing of a Samba share and then spawns a new thread for each new file (with a limit, of course) which copies the file to the local file system via a SmbFileInputStream and FileOutputStream as follows (without the obligatory try/catch blocks for readability):

    (An SmbFile instance is provided by the calling code)

    byte[] readBuffer = new byte[1024];
    int bytesRead = 0;

    File fileDestination = new File("/tmp/", "destinationFile");
    FileOutputStream fileDestinationFOS = new FileOuputStream(fileDestination);

    SmbFileInputStream smbFIS = new SmbFileInputStream(smbFile);

    while ((bytesRead = smbFIS.read(readBuffer)) != -1 ) {
    fileDestination.write(readBuffer, 0, bytesRead);
    }

    smbFIS.close();
    fileDestinationFOS.close();


    When I run it I get the following Exception:

    Exception in thread "Thread-3" java.lang.OutOfMemoryError: unable to create new native thread
    at java.lang.Thread.start0(Native Method)
    at java.lang.Thread.start(Thread.java:614)
    at jcifs.UniAddress.lookupServerOrWorkgroup(UniAddress.java:173)
    at jcifs.UniAddress.getAllByName(UniAddress.java:290)
    at jcifs.UniAddress.getByName(UniAddress.java:245)
    at jcifs.smb.Dfs.getTrustedDomains(Dfs.java:62)
    at jcifs.smb.Dfs.resolve(Dfs.java:167)
    at jcifs.smb.SmbFile.resolveDfs(SmbFile.java:671)
    at jcifs.smb.SmbFile.send(SmbFile.java:773)
    at jcifs.smb.SmbFileInputStream.readDirect(SmbFileInputStream.java:181)
    at jcifs.smb.SmbFileInputStream.read(SmbFileInputStream.java:142)
    at jcifs.smb.SmbFileInputStream.read(SmbFileInputStream.java:132)
    at com.ngc.amap.mapDaemon.FileScanDaemon$RemoteFileCopier.run(FileScanDaemon.java:461)
    at java.lang.Thread.run(Thread.java:636)


    After considerable searching and testing I determined that the call to jcifs.smb.SmbFile.resolveDfs(SmbFile.java:671) was spawning numerous Threads that were consuming all of the RAM availble to naitive thread in my JVM.? Increasing the amount of RAM to the JVM didn't help.

    The solution that I found was to set the following properties in my application prior to the instantiation of any of the jcifs.* classes.? In this case, these properties were set in the main method of my entry point class.

    System.setProperty("jcifs.resolveOrder", "DNS");
    System.setProperty("jcifs.smb.client.dfs.disabled", "true");


    Once set, I was able to run as expected without the OutOfMemoryErrors
Advanced Search

Categories

Archives