I'm trying to measure the time for certains method of some specific classes. I'm using ByteBuddy and I created the following interceptor class:
public class TimingInterceptor {
#RuntimeType
public static Object intercept(#Origin Method method,
#SuperCall Callable<?> callable) {
long start = System.currentTimeMillis();
try {
return callable.call();
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println(method + " took " + (System.currentTimeMillis() - start));
}
return null;
}
}
And this is the Java Agent Class I'm using:
public class TimerAgent {
public static void premain(String arguments,
Instrumentation instrumentation) {
new AgentBuilder.Default()
.type(ElementMatchers.nameStartsWith("BP")) // This is because I used the prefix BP to name methods I need to measure
.transform((builder, type, classLoader, module) ->
builder.method(ElementMatchers.any())
.intercept(MethodDelegation.to(TimingInterceptor.class))
).installOn(instrumentation);
}
}
I ran a test application including methods named with "BP" as prefix, and the message in the class TimingInterceptor indicating the method duration is not shown.
Some ideas guys?
Example full code:
Agent: https://github.com/rauldevilla/byte-buddy-agent
Test application: https://github.com/rauldevilla/byte-buddy-lab
To debug issues, it is always a good idea to register an AgentBuilder.Listener with your agent. The instrumentation API in the JVM suppresses all exceptions that are thrown during an instrumentation and the listener allows you to catch those exceptions and to print them for example.
For such "around" instrumentation, I generally recommend using Advice as it does not make assumptions on class loader hierarchies which you need to address explicitly when using delegation.
Related
I am looking into implementing a standard error handling on my application. I want errors that cant be dealt with(custom unchecked errors) but that also aren't catastrophic to be logged by a fault barrier without having to clutter my code with pesky try catches and logger calls.
Let me illustrate.
I have an intake that receives a json string and set it into my object model, one of the fields in said model call a timeHelper function, this function can throw an exception if the arguments are invalid(null or empty). The yield of this function is not critical to the program, in fact this program should never crash( to the best of my abilities) as it should stay up 24/7.
Model
public class MyModel{
private string myField
public void setMyField(String myfield){
this.myField = Helper.DoStuff(myField)
}
}
Intake
public class Intake{
public MyModel receiveJson(){
return JacksonMagic(arguments,MyModel.class)
}
}
Helper
Public class Helper{
public String DoStuff(String myField){
//Check that can throw exception
//regular operation with return
}
}
Now, when life is beautiful DoStuff returns a string, in fact the exception should never be thrown because it implies that the source of the json, which is external to my application, sent wrong/missing information. If it does happen I want it to be logged so I can investigate what happened. I also want to set a framework in place, probably with Spring AOP, to handle that logging. But as you can see through the example, I also want execution to continue as this is not some app breaking thing.
The execution flow I am looking for is something like
Intake > Model > Helper(THROW EXCEPTION) > Logger > Whoever Called Intake
And again, I want to do that without the try catch logger call cluter
Is this something possible with AOP?
Post answer Edit
Just want to leave some sources here.
To set up your IDE for AspectJ compilation, this article is really helpful.
https://www.baeldung.com/aspectj
This is not a good use case for exceptions.
An exception represents something that you're not able to handle, an "exceptional" occurrence that you're not able to deal with. The fact that you're saying this is a possible scenario changes this from an exception to a use-case, in which case logging a warning in your service tier is probably the best solution.
Exceptions have their place, however overusing them makes code harder to follow, since it breaks the "flow" of an application. Exceptions should not be used to control flow.
AOP, in my option, offers little when it comes to exception handling. At best it can log the exception (which can also be achieved in a much clearer way using an ExceptionHandler pattern), however it certainly can't trigger your code to continue as though it didn't happen.
If you haven't already, look into logging strategies, they can be really useful in this kind of scenario.
The bottom line is: if you want control flow to continue, don't throw an exception (checked or unchecked).
Okay, here we go with a complete MCVE, assuming you know how to use the AspectJ compiler in order to compile your project. Sorry for repeating your classes with package names, imports etc., but I like you to see all details:
First we need our helper which randomly throws unchecked exceptions so we can see the aspect in action later:
package de.scrum_master.app;
import java.util.Random;
public class Helper {
private static final Random RANDOM = new Random();
public static String doStuff(String myField) {
if (RANDOM.nextBoolean())
throw new RuntimeException("uh-oh!");
return "processed " + myField;
}
}
package de.scrum_master.app;
public class MyModel {
private String myField;
public void setMyField(String myField) {
this.myField = Helper.doStuff(myField);
}
#Override
public String toString() {
return "MyModel(myField=" + myField + ")";
}
}
package de.scrum_master.app;
public class Intake {
public MyModel receiveJson(String... arguments) {
return jacksonMagic(arguments, MyModel.class);
}
public MyModel jacksonMagic(String[] arguments, Class<?> clazz) {
MyModel myModel = new MyModel();
myModel.setMyField(arguments[0]);
return myModel;
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++)
System.out.println(new Intake().receiveJson("foo"));
}
}
Now when you run the little driver application via Intake.main you will see unhandled exceptions on the console. Here is how to handle this using an aspect. I am limiting the aspect to matching all method executions with a String return type, stupidly returning a dummy value whenever an exception occurs. You just add your more sophisticated logic in there as you see fit and also adjust the aspect's pointcut to match the methods you want to handle.
package de.scrum_master.aspect;
public aspect ErrorHandler {
String around() : execution(String *(..)) {
try {
return proceed();
} catch (Exception e) {
System.out.println("Exception handled: " + e);
return "dummy";
}
}
}
I love the expressive native AspectJ syntax, but I know that some people for whatever reason feel more comfortable with annotation-based syntax. Just look at the throws declaration, the pointcuts in string constants, the explicit joinpoint declaration, the cast - yuck! Anyway, here we go:
package de.scrum_master.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
#Aspect
public class ErrorHandler {
#Around("execution(String *(..))")
public String handleErrors(ProceedingJoinPoint thisJoinPoint) throws Throwable {
try {
return (String) thisJoinPoint.proceed();
} catch (Exception e) {
System.out.println("Exception handled: " + e);
return "dummy";
}
}
}
The console log looks like this with the aspect in place:
MyModel(myField=processed foo)
MyModel(myField=processed foo)
Exception handled: java.lang.RuntimeException: uh-oh!
MyModel(myField=dummy)
MyModel(myField=processed foo)
Exception handled: java.lang.RuntimeException: uh-oh!
MyModel(myField=dummy)
Exception handled: java.lang.RuntimeException: uh-oh!
MyModel(myField=dummy)
Exception handled: java.lang.RuntimeException: uh-oh!
MyModel(myField=dummy)
MyModel(myField=processed foo)
Exception handled: java.lang.RuntimeException: uh-oh!
MyModel(myField=dummy)
MyModel(myField=processed foo)
Is there a (pref portable) way to check if
The JVM has been stated with a particular -javaagent?
In particular I'm interested to know if the aspectj load time weaver has loaded or not. (I'm trying to provide a helpful error msg in the case of incorrect startup).
The following code shows
a way to determine any -javaagent:... JVM arguments,
a way to check if the AspectJ weaving agent entry point class (the one mentioned in the manifest entry Premain-Class: of aspectjweaver.jar) is loaded.
The former just proves that the argument was given on the command line, not that the agent was actually found and started.
The latter just proves that the weaver is available on the classpath, not that it was actually started as an agent. The combination of both should give you pretty much confidence that the agent is actually active.
package de.scrum_master.app;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.List;
public class Application {
public static void main(String[] args) {
RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
List<String> arguments = runtimeMxBean.getInputArguments();
for (String argument : arguments) {
if (argument.startsWith("-javaagent:"))
System.out.println(argument);
}
try {
Class.forName("org.aspectj.weaver.loadtime.Agent");
} catch (ClassNotFoundException e) {
System.err.println("WARNING: AspectJ weaving agent not loaded");
}
}
}
You also might find the question Starting a Java agent after program start and some of its answers helpful.
Update:
Okay, here is a combination of my own solution and yours, but one which actually works even if the weaver is unavailable, which is important because this is what you want to check in the first place:
public static boolean isAspectJAgentLoaded() {
try {
Class<?> agentClass = Class.forName("org.aspectj.weaver.loadtime.Agent");
Method method = agentClass.getMethod("getInstrumentation");
method.invoke(null);
} catch (Exception e) {
//System.out.println(e);
return false;
}
return true;
}
Update 2:
After some discussion with the OP bacar I have decided to offer a solution which does not use reflection but catches NoClassDefError instead:
public static boolean isAspectJAgentLoaded() {
try {
org.aspectj.weaver.loadtime.Agent.getInstrumentation();
} catch (NoClassDefFoundError | UnsupportedOperationException e) {
System.out.println(e);
return false;
}
return true;
}
Now both main error types
weaving agent is available on the classpath, but instrumentation has not been initiated because aspectjweaver.jar was not started as a Java agent,
agent aspectjweaver.jar is not on the classpath at all and class org.aspectj.weaver.loadtime.Agent is thus unavailable
are handled gracefully by returning false after warning messages (in this simple examples just the exceptions which say clearly what is wrong) have been printed on the console.
Possible console outputs for the two cases are:
java.lang.UnsupportedOperationException: Java 5 was not started with preMain -javaagent for AspectJ
java.lang.NoClassDefFoundError: org/aspectj/weaver/loadtime/Agent
I've found the following works (tested against 1.8.4), although it relies on undocumented aspectjweaver features so may not work across versions.
public static boolean isAspectJAgentLoaded() {
try {
org.aspectj.weaver.loadtime.Agent.getInstrumentation();
return true;
} catch (UnsupportedOperationException e) {
return false;
}
}
Explanation: when aspectj is loaded as an agent, the org.aspectj.weaver.loadtime.Agent.premain(...) static method is invoked by the JVM. This has a side effect we can test for. Calling getInstrumentation either throws UnsupportedOperationException (if it was not initialised as an agent) or returns successfully if it was.
I am implementing some tests for an existing Java Swing application, so that I can safely refactor and extend the code without breaking anything. I started with some unit tests in JUnit, since that seems the simplest way to get started, but now my priority is to create some end-to-end tests to exercise the application as a whole.
I am starting the application afresh in each test by putting each test method in a separate test case, and using the fork="yes" option in Ant's junit task. However, some of the use cases I would like to implement as tests involve the user exiting the application, which results in one of the methods calling System.exit(0). This is regarded by JUnit as an error: junit.framework.AssertionFailedError: Forked Java VM exited abnormally.
Is there a way to tell JUnit that exiting with a return code of zero is actually OK?
The library System Rules has a JUnit rule called ExpectedSystemExit. With this rule you are able to test code, that calls System.exit(...):
public class MyTest {
#Rule
public final ExpectedSystemExit exit = ExpectedSystemExit.none();
#Test
public void systemExitWithArbitraryStatusCode() {
exit.expectSystemExit();
/* the code under test, which calls System.exit(...)
* with an arbitrary status
*/
}
#Test
public void systemExitWithSelectedStatusCode0() {
exit.expectSystemExitWithStatus(0);
//the code under test, which calls System.exit(0)
}
}
System Rules needs at least JUnit 4.9.
Full disclosure: I'm the author of System Rules.
How I deal with that is to install a security manager that throws an exception when System.exit is called. Then there is code that catches the exception and doesn't fail the test.
public class NoExitSecurityManager
extends java.rmi.RMISecurityManager
{
private final SecurityManager parent;
public NoExitSecurityManager(final SecurityManager manager)
{
parent = manager;
}
public void checkExit(int status)
{
throw new AttemptToExitException(status);
}
public void checkPermission(Permission perm)
{
}
}
And then in the code, something like:
catch(final Throwable ex)
{
final Throwable cause;
if(ex.getCause() == null)
{
cause = ex;
}
else
{
cause = ex.getCause();
}
if(cause instanceof AttemptToExitException)
{
status = ((AttemptToExitException)cause).getStatus();
}
else
{
throw cause;
}
}
assertEquals("System.exit must be called with the value of " + expectedStatus, expectedStatus, status);
Could you abstract out the "system exiting" into a new dependency, so that in your tests you could just have a fake which records the fact that exit has been called (and the value), but use an implementation which calls System.exit in the real application?
If anybody needs this functionality for JUnit 5, I've written an extension to do this. This is a simple annotation you can use to tell your test case to expect and exit status code or a specific exit status code.
For example, any exit code will do:
public class MyTestCases {
#Test
#ExpectSystemExit
public void thatSystemExitIsCalled() {
System.exit(1);
}
}
If we want to look for a specific code:
public class MyTestCases {
#Test
#ExpectSystemExitWithStatus(1)
public void thatSystemExitIsCalled() {
System.exit(1);
}
}
I have a lot of methods for logging, like logSomeAction, logAnotherAction etc.
Now I want all these methods make a small pause after printing messages (Thread.sleep).
If I do it manually, I would do something like this:
//before:
public static void logSomeAction () {
System.out.println (msg(SOME_ACTION));
}
//after:
public static void logSomeAction () {
System.out.println (msg(SOME_ACTION));
try {
Thread.sleep (2000);
} catch (InterruptedException ignored) { }
}
I remember that Java has proxy classes and some other magic-making tools. Is there any way avoid copy-n-pasting N sleep-blocks to N logging methods?
You could use Aspects to add extra "orthogonal" functionality to your methods.
If that sounds too esoteric, a simpler, down-to-earth solution would be to add the sleep in a separate method, then call that method in each of your logging methods. The first time you do this, you need to touch each method, but the next time if you want to modify the extra behaviour or add something else, you can do it in one single place.
It looks like you want to use Aspect Oriented Programming. You could use Spring for AOP, or AspectJ.
The OP mentions in a comment that the preferred solution is to use plain java proxies. The current code is implemented as static methods - for java proxies to be of any use, the logger class will need to be reworked as an interface. Something like this:
public interface SomeActionLogger
{
void logSomeAction();
void logSomeOtherAction();
// etc..
}
You then create your concrete implementation
public class SystemOutActionLogger implements SomeActionLogger
{
public void logSomeAction () {
System.out.println (msg(SOME_ACTION));
}
}
You can then have Java proxies wrap the SomeActionLogger interface
class DelayAfterInvocationHandler implements InvocationHandler
{
private Object delegate;
private int duration;
DelayAfterInvocationHandler(Object delegate, int duration)
{
this.delegate = delegate;
this.duration = duration;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
Object returnValue = method.invoke(delegate, args);
Thread.sleep(duration);
// you may want to catch InterruptedEception
return returnValue;
}
}
To hide some of the not-so-pretty proxy code, you can then have a method that wraps your logger to create the delay, e.g.
public ActionLogger addDelay(SomeActionLogger logger, int delay)
{
return (ActionLogger)Proxy.newProxyInstance(
impl.getClass().getClassLoader(),
new Class[] { SomeActionLogger.class },
new DelayAfterInvocationHandler(logger, delay));
}
So you then write
SomeActionLogger log = addDelay(new SystemOutActionLogger(), 2000);
Note that the DelayInvocationHandler is orthogonal to the logging interface - it can be used to add delay to any interface. You might then create a generic wrapping method like this:
public <T> T addDelay(T delegate, int delay, Class<T> interfaceType)
{
return (T)Proxy.newProxyInstance(
delegate.getClass().getClassLoader(),
new Class[] { type },
new DelayAfterInvocationHandler(delegate, delay));
}
Make a utility class that has a static SleepFor method which includes your try ... catch block and call that from every method you want a sleep in?
Replace all the System.out.println(msg(SOME_ACTION)); with printAndWait(SOME_ACTION);
You should be able to do that with find and replace.
Then create a method
public static void printAndWait(Object someAction) {
System.out.println (msg(someAction));
try {
Thread.sleep (2000);
} catch (InterruptedException ignored) {
Thread.currentThread.interrupt();
}
}
That way the code appears once and you can change it easily in one place.
Replace all of your logSomeAction() methods with a single logAction(Action a) method. This way, when you add more actions in the future, you will not be repeating your code for handling the action log and the thread sleep.
Is there a way to annotate a method so all exceptions thrown are converted to runtime exception automagically?
#MagicAnnotation
// no throws clause!
void foo()
{
throw new Exception("bar")'
}
Project Lombok's #SneakyThrows is probably what you are looking for. Is not really wrapping your exception (because it can be a problem in a lot of cases), it just doesn't throw an error during compilation.
#SneakyThrows
void foo() {
throw new Exception("bar")'
}
You can do this with AspectJ. You declare a joinpoint (in this case invocation of the method foo) and 'soften' the exception.
Edit To elaborate a bit on this:
Say you have the following class Bar:
public class Bar {
public void foo() throws Exception {
}
}
...and you have a test like this:
import junit.framework.TestCase;
public class BarTest extends TestCase {
public void testTestFoo() {
new Bar().foo();
}
}
Then obviously the test is not going to compile. It will give an error:
Unhandled exception type Exception BarTest.java(line 6)
Now to overcome this with AspectJ, you write a very simple aspect:
public aspect SoftenExceptionsInTestCode {
pointcut inTestCode() : execution(void *Test.test*());
declare soft : Exception : inTestCode();
}
The aspect basically says that any code from within a Test (i.e.: a method that starts with "test" in a class that ends in "Test" and returns 'void') that throws an exception should be accepted by the AspectJ compiler. If an exception occurs, it will be wrapped and thrown as a RuntimeException by the AspectJ compiler.
Indeed, if you run this test as part of an AspectJ project from within Eclipse (with AJDT installed) then the test will succeed, whereas without the aspect it won't even compile.
No way to do that, at least for now I use workaround like this (simplified):
#SuppressWarnings({"rawtypes", "unchecked"})
public class Unchecked {
public static interface UncheckedDefinitions{
InputStream openStream();
String readLine();
...
}
private static Class proxyClass = Proxy.getProxyClass(Unchecked.class.getClassLoader(), UncheckedDefinitions.class);
public static UncheckedDefinitions unchecked(final Object target){
try{
return (UncheckedDefinitions) proxyClass.getConstructor(InvocationHandler.class).newInstance(new InvocationHandler(){
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (target instanceof Class){
return MethodUtils.invokeExactStaticMethod((Class) target, method.getName(), args);
}
return MethodUtils.invokeExactMethod(target, method.getName(), args);
}
});
}
catch(Exception e){
throw new RuntimeException(e);
}
}
}
And the usage looks like:
import static ....Unchecked.*;
...
Writer w = ...;
unchecked(w).write(str, off, len);
The trick is that interface is "never finished" and everytime I need unchecked method somewhere, I'll wrap that object into unchecked and let IDE generate method signature in interface.
Implementation is then generic (reflective and "slow" but usually fast enough)
There are some code post-processors and bytecode-weavers but this was not possible (not even aop or other jvm based language) for my current project, so this was "invented".
I think it is possible with bytecode re-engineering, customized compiler or perhaps aspect oriented programming1. In the contrary to Java, C# has only unchecked exceptions2.
May I ask why you want to suppress the checked exceptions?
1 according to Maarten Winkels this is possible.
2 and they are thinking about introducing checked ones, according to some Channel 9 videos.
Edit: For the question: It is possible in the sense that you can annotate your methods to flag them to be a candidate for checked exception suppression. Then you use some compile time or runtime trick to apply the actual suppression / wrapping.
However, as I don't see the environment around your case, wrapping an exception in these ways might confuse the clients of that method - they might not be prepared to deal with a RuntimeException. For example: the method throws an IOException and your clients catches it as FileNotFoundException to display an error dialog. However if you wrap your exception into a RuntimeException, the error dialog gets never shown and probably it kills the caller thread too. (IMHO).
The Checked exceptions are responsability of the method implementation.
Take very very carefully this fact. if you can do not use workaround artifacts like that.
You can do this in any case via use of the fact that Class.newInstance does not wrap an Exception thrown by the no-arg constructor in an InvocationTargetException; rather it throws it silently:
class ExUtil {
public static void throwSilent(Exception e) { //NOTICE NO THROWS CLAUSE
tl.set(e);
SilentThrower.class.newInstance(); //throws silently
}
private static ThreadLocal<Exception> tl = new ThreadLocal<Exception>();
private static class SilentThrower {
SilentThrower() throws Exception {
Exception e = tl.get();
tl.remove();
throw e;
}
}
}
Then you can use this utility anywhere:
ExUtil.throwSilent(new Exception());
//or
try {
ioMethod();
} catch (IOException e) { ExUtil.throwSilent(e); }
By the way, this is a really bad idea :-)
I use the completion / template system of Eclipse to wrap any block of code easily.
Here is my template :
try { // Wrapp exceptions
${line_selection}${cursor}
} catch (RuntimeException e) { // Forward runtime exception
throw e;
} catch (Exception e) { // Wrap into runtime exception
throw new RuntimeException(
"Exception wrapped in #${enclosing_method}",
e);
}