Is there a way to remove a previously added code block in Javassist?
I'm working on a project which modifies .class files via Javassist. Among other things it adds some code into constructors. I want this process to be runnable on the same .class file again and again without any side effects. However at the moment, after each run the same code is added to constructor one more time.
Is there a way to prevent this?
If you know the code to remove you can do it with Javassist easily:
In the next example this will remove all lines that contains the method "printStackTrace" of any "Exception" class, all the magic occurs with the instrument and replace methods
...
ClassPool cp = ClassPool.getDefault();
try{
CtClass ct = cp.getCtClass("com.cm.main.ConcretClass");
CtMethod m = ct.getDeclaredMethod("testException");
m.instrument(new ExprEditor() {
public void edit(MethodCall m) throws CannotCompileException {
String regexPattern = ".*Exception";
if (m.getClassName().matches(regexPattern) && m.getMethodName().matches("printStackTrace")) {
m.replace(";");
}
}
;
});
} catch (CannotCompileException e) {
e.printStackTrace();
} catch (NotFoundException e) {
e.printStackTrace();
} catch (BadBytecode badBytecode) {
badBytecode.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
...
The ConcretClass:
public class ConcretClass{
public String getName() {
return this.name + "-Extra";
}
public void testException(){
try {
FileOutputStream file = new FileOutputStream("C:\\Temp\\downloads");
file.close();
} catch (FileNotFoundException e2) {
e2.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Related
I’m using Javassist (3.25.0-GA) and Java 8 with a custom Agent to transform bytecode and add print statements to existing catch{} clauses. This works for simple cases, but has a problem with the compiled bytecode of the try-with-resources syntax.
Here is a basic example of what I'm trying to do and the results when it works correctly on standard try/catch blocks:
// before byte code manipulation
public void methodWithCatchClause() {
try {
throwsAnException();
} catch (Exception ex) {
handleException(ex);
}
}
// after byte code manipulation
public void methodWithCatchClause() {
try {
throwsAnException();
} catch (Exception ex) {
System.out.println("CATCH CLAUSE!"); // added by Javassist
handleException(ex);
}
}
The logic I'm using to transform the bytecode is inspired by another SO post [0]:
// from https://stackoverflow.com/questions/51738034/javassist-insert-a-method-at-the-beginning-of-catch-block
ControlFlow cf = new ControlFlow(ctMethod); // ctMethod == methodWithCatchClause()
for (ControlFlow.Block block : cf.basicBlocks()) {
ControlFlow.Catcher catchers[] = block.catchers();
for (int i = 0; i < catchers.length; i++) {
ControlFlow.Catcher catcher = catchers[i];
ControlFlow.Block catcherBlock = catcher.block();
int position = catcherBlock.position();
int lineNumber = ctMethod.getMethodInfo().getLineNumber(position);
ctMethod.insertAt(lineNumber + 1, "System.out.println(\"CATCH CLAUSE!\");");
}
}
But this code breaks in conjunction with the try-with-resources syntax. As a concrete example this code:
public void tryWithResources() {
try (TestAutoClosable test = new TestAutoClosable()) {
test.doStuff();
} catch (Exception ex) {
handleException(ex);
}
}
Turns into this after code generation:
public void tryWithResources() {
try {
TestAutoClosable test = new TestAutoClosable();
Throwable var2 = null;
try {
System.out.println("CATCH CLAUSE!");
test.doStuff();
} catch (Throwable var12) {
var2 = var12;
throw var12;
} finally {
if (test != null) {
if (var2 != null) {
try {
test.close();
} catch (Throwable var11) {
var2.addSuppressed(var11);
}
} else {
test.close();
}
}
}
} catch (Exception var14) {
System.out.println("CATCH CLAUSE!");
System.out.println("CATCH CLAUSE!");
System.out.println("CATCH CLAUSE!");
// this goes on for 15 more entries...
this.handleException(var14);
}
}
This of course is causing "CATCH CLAUSE!" to be printed multiple times in odd places. It might be helpful to mention that empty catch clauses, regardless of try/catch syntax, break in a similar fashion (maybe the underlying cause is related?).
I would expect something closer to this as the end result:
public void tryWithResources() {
try {
TestAutoClosable test = new TestAutoClosable();
Throwable var2 = null;
try {
test.noop();
} catch (Throwable var12) {
System.out.println("CATCH CLAUSE!");
var2 = var12;
throw var12;
} finally {
if (test != null) {
if (var2 != null) {
try {
test.close();
} catch (Throwable var11) {
var2.addSuppressed(var11);
}
} else {
test.close();
}
}
}
} catch (Exception var14) {
this.handleException(var14);
}
}
I'm trying to figure out if I have a simple error in my code or if my approach is entirely wrong. I would appreciate any help with the matter. Thanks in advance.
[0] Javassist: insert a method at the beginning of catch block
Is it any possible way there to write catch block inside a method and call it from finally when an exception occured in try block
Ex:
try
{
int a=0,b=0;
a=b/0;
}
finally
{
callExceptions();
}
}
public static void callExceptions()
{
catch(Exception e)
{
System.out.println(e);
}
}
catch block must follow a try block. It can't stand alone.
And finally block are made to be after the catch.
You wrote an alone catch inside a finally. That doesn't make sense.
The easiest solution is to pass the exception to the method as a parameter:
public static myMethod() {
try
{
int a=0,b=0;
a=b/0;
}
catch (Exception e)
{
callExceptions(e);
}
finally
{
// do what ever you want or remove this block
}
}
public static void callExceptions(Exception e)
{
System.out.println(e);
}
Ways to uses try/catch/finally
1.- when you want to try to use some method, if everything goes well, will continue else one exception will be thrown on catch block.
try {
// some method or logic that might throw some exception.
} catch (ExceptionType name) {
// catch the exception that was thrown.
}
2.- It's the same the first but adding finally block means that the finally block will always be executed independently if some unexpected exception occurs.
try {
// some method or logic that might throw some exception.
} catch (ExceptionType name) {
// catch the exception that was thrown.
} finally {
// some logic after try or catch blocks.
}
3.- try and finally blocks are used to ensure that a resource is closed regardless of whether the try statement completes normally or abruptly. For example:
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
Referencias Official documentation JAVA for try/catch/finally blocks
On your case:
public static myMethod() {
try {
int a=0,b=0;
a=b/0;
} catch (Exception e) {
callException(e);
}
}
public static void callException(Exception e) {
System.out.println(e);
}
This was too long for a comment so sorry it's not a direct answer to your question (as others have pointed out, that's not possible). Assuming what you're trying to do is define a common way to handle your exception logic in one place, Callable might be a way to go. Something like the following might suffice... Although I'm not going to comment on whether any of it is a good idea...
static E callAndHandle(final Callable<E> callable) {
try {
return callable.call();
} catch (final Exception ex) {
System.out.println(ex);
return null;
}
}
static void tryIt() {
final String result = callAndHandle(() -> {
// Thing which might throw an Exception
return "ok";
});
// result == null => there was an error here...
}
Unfortunately Runnable doesn't declare any Exception in the signature, so if you know it always needs to be void and you don't like the return null; or similar hacks, you'd have to define your own interface to pass in.
I need to handle Exceptions which are raised by Catch block code in Java
Example, to "handle" an Exception:
try
{
// try do something
}
catch (Exception e)
{
System.out.println("Caught Exception: " + e.getMessage());
//Do some more
}
More info see: See: https://docs.oracle.com/javase/tutorial/essential/exceptions/catch.html
However if you want another catch in your try catch, you can do the following:
try
{
//Do something
}
catch (IOException e)
{
System.out.println("Caught IOException: " + e.getMessage());
try
{
// Try something else
}
catch ( Exception e1 )
{
System.out.println("Caught Another exception: " + e1.getMessage());
}
}
Be careful with nested try/catch, when your try catch is getting to complex/large, consider splitting it up into its own method. For example:
try {
// do something here
}
catch(IOException e)
{
System.out.println("Caught IOException: " + e.getMessage());
foo();
}
private void foo()
{
try {
// do something here (when we have the IO exception)
}
catch(Exception e)
{
System.out.println("Caught another exception: " + e.getMessage());
}
}
Instead of cascading try/catch (like in most of the other answers), I advise you to call another method, executing the required operations. Your code will be easier to maintain by this way.
In this method, put a try/catch block to protect the code.
Example :
public int classicMethodInCaseOfException(int exampleParam) {
try {
// TODO
}
catch(Exception e)
{
methodInCaseOfException();
}
}
public int methodInCaseOfException()
{
try {
// TODO
}
catch(Exception e)
{
//TODO
}
}
Do as you would do in an usual try/catch situation :
try{
throw new Exception();
}catch(Exception e1){
try{
throw new Exception();
}catch(Exception e2){
//do something
}
}
You can add new try catch block in your main catch block.
try
{
int b=10/0;
}catch(ArithmeticException e)
{
System.out.println("ArithmeticException occurred");
try
{
int c=20/0;
}catch(ArithmeticException e1)
{
System.out.println("Another ArithmeticException occurred");
}
}
I think the most clean way is to create method which is catching the exceptions occurs in its body. However it can be very dependent to the situation and type of code you are dealing with.
One example of what you are asking about is closing a Stream which is opened in a try-catch-finally block. For example:
package a;
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Main {
public static void main(String[] args) {
OutputStream out = null;
try {
out = new BufferedOutputStream(new FileOutputStream("temp.txt"));
} catch (FileNotFoundException e) {
e.printStackTrace();
//TODO: Log the exception and handle it,
// for example show a message to the user
} finally {
//out.close(); //Second level exception is
// occurring in closing the
// Stream. Move it to a new method:
closeOutPutStreamResource(out);
}
}
private static void closeOutPutStreamResource(OutputStream out){
try {
out.close();
} catch (IOException e) {
// TODO: log the exception and ignore
// if it's not important
// OR
// Throw an instance of RuntimeException
// or one of it's subclasses
// which doesn't make you to catch it
// using a try-catch block (unchecked)
throw new CloseOutPutStreamException(e);
}
}
}
class CloseOutPutStreamException extends RuntimeException{
public CloseOutPutStreamException() {
super();
}
public CloseOutPutStreamException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
public CloseOutPutStreamException(String message, Throwable cause) {
super(message, cause);
}
public CloseOutPutStreamException(String message) {
super(message);
}
public CloseOutPutStreamException(Throwable cause) {
super(cause);
}
}
Here I illustrated a situation which the second level exception is occurring in the finally block, but the same can apply for the exceptions occur in the catch block.
In my point of view writing methods such as closeOutPutStreamResource can be useful because they are packaging a boiler plate code for handling very common exceptions and they are making your codes more elegant.
Also it would be your choice to catch and log the exception in closeOutPutStreamResource or to throw it to other layers of your program. But it would be more elegant to wrap this unimportant checked exceptions into RuntimeException without a need for catching.
Hope this would be helpful.
You can use try catch block any where in methods or in block, so you can write try catch in catch block as well.
try {
// master try
}catch(Exception e){
// master catch
try {
// child try in master catch
}catch(Exception e1){
// child catch in master catch
}
}//master catch
It's not necessary to have a nested try-catch block when catch block throws Exception as all answers here suggest. You can enclose the caller method with try-catch to handle that Exception.
I have a class that allows to download a file from the internet:
public String download(String URL) {
try {
if(somethingbad) {
// set an error?
return false;
}
}
//...
catch (SocketException e) {
e.printStackTrace();
}
catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
catch (ClientProtocolException e) {
e.printStackTrace();
}
catch(InterruptedIOException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
Now, I am calling this function in another class and i want to show a message that will help me figure out why this will not work.
what can i do to display something like this?
HTTPReq r = new HTTPReq("http://www.stack.com/api.json");
if(r.err) {
showMessage(getMessage());
}
and the getMessage() will return the SocketException or IOException or even "empty url" if the URL is empty.
First of all I do not think you need all these:
SocketException, UnsupportedEncodingException, ClientProtocolException since they extend IOException
but if you want you can do this:
public String download(String URL) throws IOException, Exception {
try {
if(somethingbad) {
throws new Exception("My Message);
}
}
catch (IOException e) {
throw e;
}
}
And then in your other file:
try {
// some stuff
}
catch (Exception e) {
// do something with e.getMessage();
}
catch (IOException e) {
// do something with e.getMessage();
}
Instead of just doing e.printStackTrace() inside the catch blocks, throw the exception back like so:
throw e;
Then you can surround the calling code like so:
try {
HTTPReq r = new HTTPReq("http://www.stack.com/api.json");
} catch (Exception e) {
// Show error message
}
Due to my company's policy of using Eclipse and using Eclipse's code-autofix, the following code pattern appears excessively in the codebase:
InputStream is = null;
try {
is = url.openConnection().getInputStream();
// .....
} catch (IOException e) {
// handle error
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
// handle error
}
}
}
IMO it's extremely fugly and hard to read, especially the portion within the finally block (is there really a need to catch 2 instances of IOException?). Is there anyway to streamline the code such that it looks cleaner?
Why do anything? It's working code. It's correct.
Leave it be.
First, about using IOUtils - may worth a shot telling your supervisors that the very application-server / Java runtime environment they might use, uses IOUtils and similar libraries itself. so in essence you're not introducing new components to your architecture.
Second, no, not really. There isn't really any way around it other than writing your own utility that will immitate IOUtils' closeQuietly method.
public class Util {
public static void closeStream(inputStream is) {
if (is != null) {
try {
is.close();
} catch (IOException e) {
// log something
}
}
}
Now your code is
InputStream is = null;
try {
is = url.openConnection().getInputStream();
// .....
} catch (IOException e) {
// handle error
} finally {
Util.closeStream(is);
}
Not a lot else to do as the IOException in the catch might have some specific processing.
See this question, use the closeQuietly() solution.
InputStream is = null;
try {
is = url.openConnection().getInputStream();
// .....
} catch (IOException e) {
// handle error
} finally {
IoUtils.closeQuietly(is);
}
// stolen from the cited question above
public class IoUtils {
public static closeQuietly (Closeable closeable) {
try {
closeable.close();
} catch (IOException logAndContinue) {
...
}
}
}
Or wait for JDK7's ARM blocks.
You could define something like this somewhere:
private static interface InputStreamCallback {
public void doIt(InputStream is) throws IOException;
}
private void with(InputStreamCallback cb) {
InputStream is = null;
// Creational code. Possibly adding an argument
try {
cb.doIt(is);
} catch (IOException e) {
// handle error or rethrow.
// If rethrow add throws to method spec.
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
// handle error or rethrow.
}
}
}
}
And invoke your code like this:
with(new InputStreamCallback() {
#Override
public void doIt(InputStream is) throws IOException {
is = url.openConnection().getInputStream();
// .....
}
});
If you declare with method static in a helper class, then you could even do an import static of it.
There's a drawback. You need to declare url final.
EDIT: creational code is not the point. You can arrange it in several ways. The callback is the point. You could isolate what you need to do there.