Java process error messages

How to display a detailed error message using try< >catch() < >blocks

Suppose in your program you might get an IndexOutOfBoundsException. i am handling it in the following way:

try< //throws an IndexOutOfBoundsException during runtime >catch(IndexOutOfBoundsException ex)

This will only display java.lang.IndexOutOfBoundsException. But I would like to display a detailed error message (which won’t terminate the program), like the one that java gives us (lineNumber, fileName, etc) when we do not handle the error and thus terminates the program.

4 Answers 4

In Java you can use printStackTrace on any exception object to get the stack trace printed by Java. In your case a minimal:

try < // Throw an IndexOutOfBoundsException >catch (IndexOutOfBoundsException ex)

This prints the stack trace to System.err . You can also pass it a print stream or even System.out to print to that particular stream.

Additionally, if you use java logger, you can use:

Use ex.printStackTrace() method to print the exception:

try < int[] x = new int[1]; x[2] = 5; >catch (IndexOutOfBoundsException ex) < ex.printStackTrace(); >System.err.println("Program completed successfully"); 

If you are running in an environment where console output is not desirable, call ex.getStackTrace() , and display elements in a way that is consistent with the user interface of your program.

this was very helpful brother 🙂 but this prints out too much information. I would like the error message to be like the one java gives. java.lang.ArrayIndexOutOfBoundsException: 6 at sth.main(sth.java:15) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at edu.rice.cs.drjava.model.compiler.JavacCompiler.runCommand(JavacCompiler.java:266)

Источник

how to get error message when excuting java command?

I call a class which is located somewhere in a jar file (using java -classpath path/file.jar classname) within my java code. This work well but only if the command is well formed. If I make a mistake the getRuntime().exect(command) just doesn’t say anything. Bellow I have the working command invocation. I would like to get the error message when the command doesn’t work. If I make a mistake in a cmd (windows) I get a proper error and I can fix it. But not within my java application. I left a ‘if(input.ready())’ since if I don’t the program freezes when the command line is incorrect. This happens when executing ‘input.readLine()’.

 // Execute a command with an argument that contains a space String[] genKOSCommand = new String[] < "java", "-classpath", Config.XDSI_TEST_KIT_HOME + "/xdsitest/lib/xdsitest.jar;" + Config.XDSI_TEST_KIT_HOME + "/xdsitest/classes", "ca.etsmtl.ihe.xdsitest.docsource.SimplePublisher", "-k", "C:/Softmedical/Viewer_Test/xdsi-testkit-2.0.4/xdsihome/usr/data/image14.dcm" >; Process child = Runtime.getRuntime().exec(genKOSCommand); BufferedReader input = new BufferedReader(new InputStreamReader( child.getInputStream()), 13107200); String line = null; if (input.ready()) < while ((line = input.readLine()) != null) < System.out.println(line); >try < child.waitFor(); >catch (InterruptedException e) < // TODO Auto-generated catch block e.printStackTrace(); >> 

3 Answers 3

BufferedReader errinput = new BufferedReader(new InputStreamReader( child.getErrorStream())); 

When processing the input from the different streams, it is better to do it in a different thread (since those calls ( readLine etc.) are blocking calls.

Источник

How to get an exception message in a String variable in java?

I need to process an exception message when any exception is caught in Java. I am working on a Database Connection class. When I give wrong details like username, password, host name, sid, etc, the control goes to catch block and gives an error. I would like to get this error message on the JSP side and redirect to the same page with that error message. However, when I get the error message in Java, it always takes a null value. My code example is here.

String errorMessage = null; try< // CODE Where Exception occure >catch(SQLException se)< errorMessage = se.getMessage(); >catch(Exception e)< System. out.println("In Exception block."); errorMessage = e.getMessage(); >finally

3 Answers 3

At first, the answer of @Artem Moskalev should be right in most ways. In your case, you’d said:

It will goes to Exception block but the errorMessage is null.

So, let’s try two cases to debug the behavior:

class Test1 < public static void main (String[] args) throws java.lang.Exception < String errorMessage = null; try< throw(new Exception("Let's throw some exception message here")); >catch(Exception e)< System.out.println("In Exception block."); errorMessage = e.getMessage(); >finally < System.out.println(errorMessage); >> > 
In Exception block. Let's throw some exception message here 

Seems to work like you expected.

class Test2 < public static void main (String[] args) throws java.lang.Exception < // String errorMessage = null; // To make the difference between non-initialized value // and assigned null value clearer in this case, // we will set the errorMessage to some standard string on initialization String errorMessage = "Some standard error message"; try< throw(new Exception()); >catch(Exception e)< System.out.println("In Exception block."); errorMessage = e.getMessage(); >finally < System.out.println(errorMessage); >> > 

Why is that? Because you’re accessing e.getMessage() , but if the message is emtpy e.getMessage() will return null . So the null isn’t from the initialization, but from the return value of e.getMessage() , when e doesn’t have any error message (for example if there is a NullPointerException thrown).

Читайте также:  Контрольные по информатике html

Источник

Best way to process/handle Error stream messages

I need to process different Error/Exception messages generated compile/run time. I execute a Java program an read the stream thus generated :

final Process p2 = builder.start(); BufferedReader in = new BufferedReader(new InputStreamReader(p2.getInputStream())); 

For each success , the output is generated and shown. No problem there. But I need to show custom message for every Error message. EG:

Error: Main method not found in class dummy.helloParse10.hello, please define the main method as: public static void main(String[] args) or a JavaFX application class must extend javafx.application.Application 

May be customized as : Error: Main method not found My current approach is very ugly and limited . I am looking if «Exception» string is present in error stream and then taking out the sub- strings.Something like :

if(tError.contains("Exception")) tError=tError.substring(tError.indexOf("main\"")+5,tError.indexOf("at")) + "( At Line: "+tError.substring(tError.indexOf(".java")+6); 

But it do not customize my approach in a broad way. What is the best thing I could do? Edit : I think my question is unclear. Basically I am executing a Java program via ProcessBuilder .

 //Compile the program Process p = Runtime.getRuntime().exec("javac filename "); // Now get the error stream if available : BufferedReader in = new BufferedReader(new InputStreamReader(p.getOutputStream())); String line = null; while ((line = in.readLine()) != null) < //process error in compilation. >. . // ProcessBuilder to execute the program.java //Read the output or runtime Exception 

No the output of the process can be the result of te java program or an exception/error which is taken from the process steam an is in String form.Need to manipulate those Errors. Update : I can now solve the compile time errors via Java Compiler API as suggested by @Miserable Variable .How can I deal with Runtime Exceptions similarly ? EDIT : In actual it is not possible to modify the program to be run in a new process.They are user specific.

Читайте также:  Новое окно

I’m not sure what you are looking for. If you are trying to use custom exception Then You can creating custom exception (it should extends Exception), Place your logic in try block, In catch block always create custom Exception with custom message and throw it.

@bakki I know about user-defined exceptions.These are the exceptions generated while executing a Java program in a new process.I only have the error stream in hand .

4 Answers 4

For identifying errors in compilation, instead of running javac using ProcessBuilder a better alternative might be to use Java Compiler API.

I have never used it myself but it seems pretty straightforward.

It would be much easier IMO if your program relies on a logging framework to log its errors in a certain log format. You can benefit from this by using a log parser. It should be simple to write your own and maybe you can define a dictionary of common errors patterns that are assigned to your specific program.

If your program does not follow a well-defined log pattern and you want a scalable approach, then one possible way is to implement a Grok-based solution. Grok is used in powerful tools like Logstash. See this post for how to do this in Java.

I cannot make changes in the program which I want to run. Otherwise there are many options available.edited.

For Runtime exceptions ,you could look into ProcessBuilder and streaming the error exceptions and then checking for the same.Here are some examples that can help you:

The way I understand it is,

Problem statement:

Write a Java program which should be able to 1. Take an input as Java program file 2. Compile it and produce errors if can't compile 3. Run the class file generated in previous step 4. Produce the run time exceptions generated by the invocation if any Assumptions: 1. Class would contain a "main" method else it can't be run using "java" program

Given above problem statement I have produced a solution. Before code I think it’s a good idea to explain what it does, in the order it does it.

Solution steps:

1. Compile the Java code using the compiler API (using ToolProvider.getSystemJavaCompiler()) 2. Use DiagnosticCollector to collect for any compilation errors that might have ocurred. 3. If compilation is successful then load the generated class in byte array. 4. Use ClassLoader.defineClass() to load class file from byte array into JVM runtime. 5. Once class is loaded, use reflection to find the main method, if not present throw main not found related exceptions. 6. Run main method, and report back any runtime exceptions produced. Note: If needed Standard input and output streams can be redirected for the new program and original objects can be saved as originals for main program. I haven't done it, but it's trivial to do.

Working code:

import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.tools.Diagnostic; import javax.tools.DiagnosticCollector; import javax.tools.JavaCompiler; import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; public class JreMain < private static final String PATH_TO_JAVA_FILE = "src/main/java/MyProgram.java"; public static void main(String[] args) < JreMain main = new JreMain(); System.out.println("Running a java program"); String filePath = PATH_TO_JAVA_FILE; File javaFile = new File(filePath); /*compiling the file */ ListerrorList = main.compile(Arrays.asList(javaFile)); if(errorList.size() != 0) < System.out.println("file could not be compiled, check below for errors"); for(String error : errorList) < System.err.println("Error : " + error); >> else < main.runJavaClass(filePath, new String[] <>); > > @SuppressWarnings() private void runJavaClass(String filePath, String[] mainArguments) < System.out.println("Running " + filePath); ClassLoader classLoader = getClass().getClassLoader(); Class klass = null; String fileNameWithoutExtension = filePath.substring(0, filePath.length() - ".java".length()); String className = getClassName(fileNameWithoutExtension); /* loading defineClass method in Classloader through reflection, since it's 'protected' */ try < /* signature of defineClass method: protected final ClassdefineClass(String name, byte[] b, int off, int len)*/ Method defineClassMethod = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, Integer.TYPE, Integer.TYPE); defineClassMethod.setAccessible(true); /* attempting to load our class in JVM via byte array */ byte[] classBytes = getClassBytes(fileNameWithoutExtension + ".class"); klass = (Class)defineClassMethod.invoke(classLoader, className, classBytes, 0, classBytes.length); > catch (NoSuchMethodException e) < e.printStackTrace(); >catch (SecurityException e) < e.printStackTrace(); >catch (IllegalAccessException e) < e.printStackTrace(); >catch (IllegalArgumentException e) < e.printStackTrace(); >catch (InvocationTargetException e) < e.printStackTrace(); >/* checking if main method exists, in the loaded class, and running main if exists*/ if(klass != null) < try < Method mainMethod = klass.getMethod("main", String[].class); Class returnType = mainMethod.getReturnType(); /*Checking for main method modifiers and return type*/ if( !Modifier.isStatic(mainMethod.getModifiers()) || !Modifier.isPublic(mainMethod.getModifiers()) || !(returnType.equals(Void.TYPE) || returnType.equals(Void.class))) < throw new RuntimeException("Main method signature incorrect, expected : \"public static void main(String[] args)\","); >/* finally invoking the main method **/ mainMethod.invoke(null, new Object[]); > catch (NoSuchMethodException e) < throw new RuntimeException("Class " + klass.getCanonicalName() + " does not declare main method"); >catch (SecurityException e) < e.printStackTrace(); >catch (IllegalAccessException e) < e.printStackTrace(); >catch (IllegalArgumentException e) < e.printStackTrace(); >catch (InvocationTargetException e) < /*e.printStackTrace();*/ System.err.println("Exception in main :"); throw new RuntimeException(e.getCause()); >> > private String getClassName(String fileNameWithoutExtension) < String className = null; int lastIndex = -1; if( ( lastIndex = fileNameWithoutExtension.lastIndexOf(File.separator)) != -1) < className = fileNameWithoutExtension.substring(lastIndex + 1); >if( ( lastIndex = fileNameWithoutExtension.lastIndexOf("\\")) != -1) < className = fileNameWithoutExtension.substring(lastIndex + 1); >else if( ( lastIndex = fileNameWithoutExtension.lastIndexOf("/")) != -1) < className = fileNameWithoutExtension.substring(lastIndex + 1); >return className; > private byte[] getClassBytes(String classFilePath) < ByteArrayOutputStream baos = new ByteArrayOutputStream(); File classFile = new File(classFilePath); if(!classFile.exists()) < throw new RuntimeException("Class file does not exist : " + classFile.getAbsolutePath()); >byte[] buffer = new byte[2048]; int readLen = -1; FileInputStream fis = null; try < fis = new FileInputStream(classFile); while( (readLen = fis.read(buffer)) != -1) < baos.write(buffer, 0, readLen); >> catch (IOException e) < e.printStackTrace(); >finally < if(fis != null) < try < fis.close(); >catch (IOException e) < e.printStackTrace(); >> > return baos.toByteArray(); > @SuppressWarnings("restriction") public List compile (List javaFileList) < System.out.println("Started compilation"); ListerrorList = new ArrayList(); JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); DiagnosticCollector diagnostics = new DiagnosticCollector(); StandardJavaFileManager fileManager = compiler.getStandardFileManager( diagnostics, null, null); Iterable compilationUnits = fileManager .getJavaFileObjectsFromFiles(javaFileList); compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits) .call(); for (Diagnostic diagnostic : diagnostics .getDiagnostics()) < String diagnosticMessage = String.format("Error on line %d in %s%n", diagnostic.getLineNumber(), diagnostic.getSource().toUri() + " : \n\t" + diagnostic.getMessage(null)); /*Following gives out of box good message, but I used above to show the custom use of diagnostic * String diagnosticMessage = diagnostic.toString();*/ errorList.add(diagnosticMessage); >try < fileManager.close(); >catch (IOException e) < e.printStackTrace(); >return errorList; > > 

Thanks to @Miserable Variable, I was almost set to create a process for the javac program, but your answer saved me some ugly code.

Command line arguments

//in the JreMain.compile() List compilerOptionsList = Arrays.asList("-classpath", "jar/slf4j-api-1.7.10.jar", "-verbose"); JavaCompiler.CompilationTask compilationTask = compiler.getTask(null, fileManager, diagnostics, compilerOptionsList, null, compilationUnits); 

For Java runtime arguments:

They will have to be passed to our JareMain program itself. java -classpath "jar/slf4j-api-1.7.10.jar;" -verbose JreMain 

For main method of new program:

//second argument here is going to main method main.runJavaClass(filePath, new String[] <>); 

Источник

Оцените статью