I provide an API and need to know, where methods of the API were invoked. I could of cause use reflection or the thread stacktrace, but that would include a lot of runtime cost.
I do not need the exact class name, a unique reference per invocation would be sufficient. In C I would normally use the preprocessor to automatically add __FILE__ and __LINE__ to the method invocation.
Is there a method in Java (besides code generation) to get a unique caller identification with low runtime cost?
One solution would be to have a cached Throwable which is passed in.
class StackPoint {
Throwable stack;
public Throwable getStack() {
if (stack == null)
stack = new Throwable();
return stack;
}
}
public void methodToCall(StackPoint sp) {
Throwable t = sp.getStack();
}
static final StackPoint one = new StackPoint();
methodToCall(one); // Have to remember to give each line a different StackPoint.
Note: if the method which calls this caller changes, you only record the first one ever.
There isn't a standard pattern and it is likely that if you want this to be efficient the caller will need to pass a unique id. The closest you can do is use is a lambda.
public void methodToCall(Runnable run) {
Class id = run.getClass();
}
You can call it like this
methodtoCall(()->{});
This will create a different class for each place it is called, even if it appears multiple times on the same line. It creates no garbage as it reuses the same object each time. You could make this shorter with
void methodToCall(IntFunction fun) {
}
and call
methodToCall(a->1);
As something asynchroneous is involved, split the call up, and let the API return the ID.
Ticket callTicket = api.call(params);
Logger.getLogger(getClass().getName(), Level.FINE, callTicket);
Result result = callTicket.get();
Above having a result returned (synchroneously) is probably not the case with your code. Your code will get the result delived elsewhere. But that could be a ticket system too.
Related
I have two stacks.
I want to be able to push any element onto one, but only if it was popped off the other.
Instead of My current function looks like this:
public void pushValue(int poppedValue) {
Stack.push(value)
}
I want the function to look something like this:
public void pushValue(pop() poppedValue) {
Stack.push(value)
}
How could I set the pop() function as a parameter, instead of an int?
In other words, how can I set the parameter to only accept a value that was popped from somewhere?
There is no way in Java to express that constraint. (Or in any other language, AFAIK)
(IMO) the best you can do is to pass the second Stack as an argument to the first one and make the first one responsible for popping a value; e.g.
public class Stack {
...
public int transferValue(Stack source) {
int res = source.pop(); // throws exception if source is empty
this.push(value);
return res;
}
}
This leaves you with problems regarding push:
Do you remove it entirely from the Stack API? If so, how do the elements get onto the source stack?
Do you split the Stack API into Stack and StackWithoutPush? If yes, which is the super-class / super-interface? Neither alternative is perfect. Either way, the subclass violates the contract of the superclass in some sense. (C.f. the problem of List versus UnmodifiableList APIs.)
Your syntax isn't possible, but you could make the second stack a member field and then push iff the value is present when you peek at the second stack (through the field).
private Stack otherStack = null; // <-- set this somehow (constructor?), or pass it.
public void pushValue(int newValue) {
if (otherStack != null && otherStack.peek() == newValue) {
Stack.push(newValue); // <-- please observe naming conventions (stack)
}
}
Then, pop() the value. Basically, peek, push and then pop.
I saw some example of of using supplier interface at https://dzone.com/articles/supplier-interface.
My question is, if in the above example I could do something as easy as :
driveVehicle(new Vehicle());
driveVehicle(new Car());
Why would one want to use supplier interface, if all it does is call a method, without taking in any parameters.
Suppose you have parameters stored in database that you want to keep in constant all over your app
// Assume retrieveSystemParameter query database which allows to change parameters
public static String SYSTEM_PARAMETER = StaticUtilities.retrieveSystemParameter();
That value will be initialized once and won't change untill a redeployment. That being said, if instead you use a supplier :
public static Supplier<String> SYSTEM_PARAMETER_SUPPLIER = StaticUtilities::retrieveSystemParameter;
When you need the value somewhere you will call SYSTEM_PARAMETER_SUPPLIER.get() which will retrieve parameter in the database when needed - that way if you change a parameter in database, you won't have to redeploy.
As you can see, Suppliers are lazy. They do the work when you ask them to work (by calling .get()) - that may allow you some performance gain if you deal with them wisely. Sometimes you will call a method which expect a variable X passing in method retrieveX and then end up not needing X in the method because some conditions were not met. In that case you will lose performance as you will execute the code to retrieve X while a supplier that retrieve X would only execute it when calling .get and you would only do that call if the conditions were met.
Disclaimer : the system parameter constant is just the first example that came to my mind, but considering it query the database on each .get() you'd rather cache the parameter and have the cache call .get() at a specific interval.
I guess Optional might be perfect example. Consider the following snippet:
final Product firstProduct = Optional.ofNullable(product)
.orElse(productDao.findProductById(id));
final Product secondProduct = Optional.ofNullable(product)
.orElseGet(() -> productDao.findProductById(id));
You're getting a product that may be null. In order to determine firstProduct java will have to call expression in orElse method so no matter product is null or not you always have to determine value that will be returned in case product is null.
In order to determine secondProduct database doesn't have to be queried in case product is not null because you're passing a Supplier that will be called only if product is null.
Another example is when your method that accepts a supplier is not pure (i.e., it has side effect), and the side effect happens before calling the lambda, and the behaviour of the lambda is affected by the side effect.
Consider, for instance, this example:
public class TestClass {
private String field;
public String getField() {
return field;
}
public void method(Supplier<String> supplier) {
field = "This is";
System.out.println(supplier.get() + " a test");
}
public static void main(String[] args) {
TestClass c = new TestClass();
c.method(() -> c.getField());
}
}
Here, method() is not pure, as it changes the value of field, which is used later in the lambda (through calling the getField() method). As the lambda is called in place (i.e., when get() is called), calling getField() will happen after setting the field. In other words, method() accepts a Supplier<String> instead of a String in an attempt to let the clients safely call the getField() method.
Of course, having side effects should be avoided wherever possible, and this is just a toy example, but it shows a potential place where a supplier can be used.
Supplier adds one more level of indirection.
Given that "All problems in computer science can be solved by another level of indirection", it's likely that there are some problems that can be solved by using a Supplier.
Beware, however, of the corollary "...except for the problem of too many layers of indirection."
So, if there's no problem to solve, then Supplier is overkill and you should stick to directly invoking new.
Put differently: mistrust any "pattern" or "best practice" that doesn't start by explaining a problem (your question shows, you actually do mistrust, so just keep on asking this kind of questions).
I use it to avoid the unnecessary creation of additional states:
private Supplier<Boolean> detach = () -> false;
private Supplier<Boolean> isAttached = () -> false;
private Supplier<Integer> index = () -> null;
private final Function<List<ObserverWrapper<X, Y>>, Boolean> attachFun = observers -> {
isAttached = () -> observers.contains(this);
detach = () -> observers.remove(this);
index = () -> observers.indexOf(this);
return observers.add(this);
};
public boolean attach(List<ObserverWrapper<X, Y>> observers) {
return attachFun.apply(observers);
}
public boolean isAttached() {
return isAttached.get();
}
public Integer observerIndex() {
return index.get();
}
Which some would say is unnecessary in itself, but then it becomes a philosophical problem.
A problem which would not exist if computers didn't exist, and then it becomes a real world problem of indirection.
I may admit that suppliers for me may have become an addiction, but in my mind they feel like the natural extrapolation and extension of all the programming axioms and principles.
You could use a Supplier in a map based factory class
public class StackService {
final static String INTEGERS = "Integers";
final static String DOUBLES = "Doubles";
final static String STRINGS = "Strings";
final static Map<String, Supplier<Stack>> stackType;
static {
stackType = new HashMap<>();
stackType.put(INTEGERS, Stack<Integer>::new);
stackType.put(DOUBLES, Stack<Double>::new);
stackType.put(STRINGS, Stack<String>::new);
}
public Stack<?> createStackOfType(String stackType) {
return stackType.get(stackType).get();
}
}
Here if you were to just use new Stack() you would be returning a reference to the same object rather than a new one.
I want AspectJ to inject the measuring code around all invocations of any method, on fields annotated with #Measured and capture the method's name.
This is what I have:
#Pointcut("get(#my.annotation.Measured * *) && #annotation(measured)")
public void fieldAnnotatedWithMeasured(Measured measured) {}
#Around(value = "fieldAnnotatedWithMeasured(measured)", argNames = "joinPoint,measured")
public Object measureField(ProceedingJoinPoint joinPoint, Measured measured) throws Throwable {...}
Use case:
public class A {
#Measured private Service service;
...
void call(){
service.call(); // here I want to measure the call() time and capture its name
}
This seems to surround only the access to the field, not the method invocation. I want to capture the invoked method name instide the advise.
This is not something you can do directly with a pointcut because get(), as you have noticed, is entirely different from call() or execution() pointcuts. The get() joinpoint has completely passed before the moment the call() is done. Furthermore, the call() has no idea about whether or not the target object it is called upon happens to be assigned to one or more (annotated) class members.
I think that what you want to achieve is conceptually problematic. You should rather annotate the classes or methods you want to measure, not class members. But for what it is worth, I am going to present you with a solution. Caveat: The solution involves manual bookkeeping and also reflection. Thus, it is kinda slow but maybe still fast enough for your purpose. You can decide if you give it a try. Please note that this solution is something I feel uneasy with because it does not feel like a good application of AOP.
Okay, so here is our test setup:
Field annotation:
package de.scrum_master.app;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface Measured {}
Sample class to play around with later:
package de.scrum_master.app;
public class MyClass {
private String name;
public MyClass(String name) {
super();
this.name = name;
}
#Override
public String toString() {
return "MyClass[" + name + "]";
}
void waitForAWhile() throws InterruptedException {
Thread.sleep(200);
}
}
Driver application using the sample class:
Please note how only two of the four members - one primitive and one object type - are annotated by #Measured and two others are not. I did this in order to have positive as well as negative examples so as to see whether the aspect works correctly.
Another important thing is that an object formerly assigned to an annotated class member should no longer be reported by the aspect as soon as it is no longer assigned to that member. I.e. oldMyClass.waitForAWhile(); should not be measured.
package de.scrum_master.app;
public class Application {
String foo = "unmeasured";
#Measured String bar = "measured";
MyClass myClass1 = new MyClass("unmeasured");
#Measured MyClass myClass2 = new MyClass("measured");
void doSomething() throws InterruptedException {
foo.length();
bar.length();
myClass1.waitForAWhile();
myClass2.waitForAWhile();
MyClass oldMyClass = myClass2;
myClass2 = new MyClass("another measured");
// This call should not be reported by the aspect because the object
// is no longer assigned to a member annotated by #Measured
oldMyClass.waitForAWhile();
// This call should be reported for the new member value
myClass2.waitForAWhile();
}
public static void main(String[] args) throws InterruptedException {
new Application().doSomething();
}
}
Aspect:
The aspect takes care of two things: bookkeeping and measuring. In detail:
Whenever a value gets assigned to a #Measured field, it is recorded in a set of measuredObjects because this is the only way to later know that when a method is called on that object, it really should be measured.
While it is easy to get hold of the new value in a before() : set() advice, unfortunately there is no straightforward way to get hold of the old value. This is why we need the ugly little helper method getField(Signature signature) using reflection in order to find out.
Why do we need the old value anyway? Because in order to have clean bookkeeping we have to remove unassigned objects from the measuredObjects set.
Please also note that measuredObjects is not thread-safe the way I implemented it, but you can just use a synchronized collection if you need that.
The call() advice first checks if it can find the target object in measuredObjects and stops executing if it cannot. Otherwise it measures the method call's runtime. This is straightforward.
Oh, and by the way, I am using the cleaner and more expressive native AspectJ syntax here, not the ugly annotation style. If you have any problems with that, please let me know.
package de.scrum_master.app;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Set;
import org.aspectj.lang.Signature;
import org.aspectj.lang.SoftException;
import de.scrum_master.app.Measured;
public aspect MyAspect {
private Set<Object> measuredObjects = new HashSet<>();
before(Measured measured, Object newValue, Object object) :
set(* *) &&
#annotation(measured) &&
args(newValue) &&
target(object)
{
try {
Field field = getField(thisJoinPoint.getSignature());
Object oldValue = field.get(object);
System.out.println(thisJoinPoint);
System.out.println(" old value = " + oldValue);
System.out.println(" new value = " + newValue);
measuredObjects.remove(oldValue);
measuredObjects.add(newValue);
}
catch (Exception e) {
throw new SoftException(e);
}
}
Object around(Object object) :
call(* *(..)) &&
target(object) &&
!within(MyAspect)
{
if (!measuredObjects.contains(object))
return proceed(object);
long startTime = System.nanoTime();
Object result = proceed(object);
System.out.println(thisJoinPoint);
System.out.println(" object = " + object);
System.out.println(" duration = " + (System.nanoTime() - startTime) / 1e6 + " ms");
return result;
}
private Field getField(Signature signature) throws NoSuchFieldException {
Field field = signature.getDeclaringType().getDeclaredField(signature.getName());
field.setAccessible(true);
return field;
}
}
Console log:
set(String de.scrum_master.app.Application.bar)
old value = null
new value = measured
set(MyClass de.scrum_master.app.Application.myClass2)
old value = null
new value = MyClass[measured]
call(int java.lang.String.length())
object = measured
duration = 0.080457 ms
call(void de.scrum_master.app.MyClass.waitForAWhile())
object = MyClass[measured]
duration = 200.472326 ms
set(MyClass de.scrum_master.app.Application.myClass2)
old value = MyClass[measured]
new value = MyClass[another measured]
call(void de.scrum_master.app.MyClass.waitForAWhile())
object = MyClass[another measured]
duration = 200.461208 ms
As you can see, the aspect behaves correctly. It only reports the method call on object MyClass[measured] once, while it is assigned to a #Measured field, but not when a method is called upon it after it has already been unassigned and replaced by MyClass[another measured]. The latter is correctly reported subsequently. You also see how the aspect works beautifully even for primitives like the String "measured".
Enjoy!
Update 2021-04-22: I found this old answer again and wanted to mention a few other problems with the sample code, in addition to thread-unsafety:
The Set<Object> measuredObjects does not account for the fact that the same object can be assigned to multiple fields. If we want to consider that, we need to map a unique combination of instance and field to the corresponding value, i.e. we would need some kind of Map<Field,<Map<Object, Object>> where in the nested map the key is the instance (or the class name for static fields) and the value is the current field value. Managing this kind of data structure would be more complicated than the simple set we have now, especially if we also want to remove entries after a value is being unassigned.
Currently we use a simple HashSet. Actually, that is incorrect, because normal sets check for object value equality, not object identity. I.e. we could have conflicting instances a and b, where a.equals(b), but a != b. In order to fix that, we need an IdentitySet or, with the improvement I suggested in the first bullet point, an IdentityMap.
Considering the preceding two bullet points, probably a better alternative would be a dedicated class MeasuredEntity with fields Field field, Object instance, Object value and correctly defined equals and hashCode methods. then we could use a simple hash set again in order to do the bookkeeping.
Caveat: One problem cannot be solved by any kind of AspectJ-based bookeeping: If an object is currently assigned to any #Measured field, say A.x, then of course the measuring advice will get triggered if you call A.x.doSomething(). But there is no way of knowing if the same object is assigned to a non-measured field B.y or a local variable myLocal at the same time. So if B.y.doSomething() or myLocal.doSomething() are called, the measuring advice will also fire, which might be OK or unintended, depending on your individual situation. I think that it is no problem, you just need to be aware of it.
References to instances are not being removed from the set or map if an instance goes out of scope and would otherwise be eligible for garbage collection. In order to achieve that, we would need to use weak references.
A smaller issue is that getField(..) uses field.setAccessible(true). We might want to reset the field's accessible state after use in some kind of try {} finally {}, first storing the original value in a boolean variable, then resetting it in the finally block. But if that does not bother you, it really is just a small issue and also makes code execution a bit slower when called often.
Conclusion: Manual bookkeeping is not just complicated but in practice also poses several challenges which are difficult to fully meet. Not walking this path in the first place and changing the application design instead, so as to be able to apply aspects without recording internal object state, effectively breaking class encapsulation, is the better alternative IMO.
public abstract class A {
private int result=-1;
public void final doExecuteMySpecialAlgorithm() {
result=0;
//do something here and get a new result
//it won't be -1.
}
public int getResult() {
if(result==-1)
throw new RuntimeException("Invoke my special algorithm first!");
return result;
}
}
Isn't getResult method a bad design - It is forcing user to invoke another method before it is invoked? How would you workaround this? Would your rather return -1 or say null (in case of an object type) and let the caller figure out what to do will a null return? or if you are sure that it won't be null, but for the return to be not null, you would have to invoke another method before invoking getResult method, would you just throw a RuntimeException? (or a checked exception?)
There's two ways here. Either make it synchronous (i.e. doExecuteMySpecialAlgorithm actually returns the result) or asynchronous.
The first is obvious, the second can be accomplished by returning a Future object for example. Either way, the caller doesn't need to think which is the proper order to call methods.
In some cases it may be alright to enforce the calling order of methods (such as the doFinal method in crypto classes), but you should still avoid making the code in a way that the user has to think carefully about how he's going to call your methods. Obviously he needs to know what to call, but if he needs to call 5 methods in a specific order, it probably means there should be only 1 method.
I mean after all, if you want to force the caller to call method1(), method2(), method3() in order, you should really make him call method(), which inside calls private methods method1(), method2() and method3(). That way you have the code well structured, but the caller can't fudge things up by calling the methods in the wrong order.
In your example I'd do the following:
public abstract class A {
private int result=-1;
public void final doExecuteMySpecialAlgorithm() {
result=0;
//do something here and get a new result
//it won't be -1.
}
public int getResult() {
if(result==-1)
doExecuteMySpecialAlgorithm();
return result;
}
}
This way a user can do the 'special' algorithm first, or if they 'forget' to, you (as the API writer) catch it for them and do this (instead of throwing an error).
Doing this makes your object do the work for you (object oriented design), of course this is YOUR API design, and I would assume that there would be extensive documentation dictating that if I call getResult that I must first call doExecuteMySpecialAlgorithm ... whatever you choose to implement YOU must document that the user is ordered to call function X before function Y or undefined behavior might result (or throw an error).
I come across this kind of a situation a lot.
class A{
public static boolean flag = true;
public void method(){
// calls method in class B
B b = new B();
while(someCondition){
b.method();
}
}
}
.
class B{
public void method(){
if(A.flag){
// Read all data from a flat file and store it in HashMAp/ArrayList etc
//only for the first time
A.flag = false;
}
// Manipulate the data
}
}
I seem to be running into this type of situation quite often in completely different situations.
Is this how it is normally dealt with? I feel a bit silly and unnatural using static variables and if statements to resolve the issue.
In this case, I don't want to cause an overhead by reading data every time the method is executed.
It looks like you need the Singleton Pattern. Figure out what data B needs to load upon its first use, and package that into a separate class that gets used as a singleton instance. See this link for more information on how to implement the singleton pattern in Java.
Following this pattern, you can avoid the need for checking a flag every time your method is called, and you can simultaneously avoid any threading issues (if there are any).
As John B pointed out, a simple check for null should be enough rather than using a flag. If thread safety becomes an issue, you might also look into Guava's CacheBuilder and Suppliers.memoize() for these types of situations.
Rather than reading an external flag to determine if the data has already been stored, why not check the data store to see if it is populated? Or if the data store is expensive (DB) use a local static variable rather than one in a different class.
You could simply check if the list/map that stores your data has been initialised by a previous call
class A {
public void method() {
B b = new B();
while (someCondition) {
b.method();
}
}
}
class B {
private List myList;
public void method() {
if (myList == null) {
// Read all data from a flat file and store it in myList
}
// manipulate the data
}
}