Hello,
I'm trying to find a way to introduce a member in another type via ITD but making sure it is safe published. According to the Java Memory Model, all final fields are guaranteed to be safe published after the constructor execution ends and everything not final is not guaranteed to ever be seen by another threads, so if I don't want to make use of synchronization I better make sure my things are final.. For the use case I have in hand, I'm trying to make a Runnable keep some information from the thread in which it was created and make it available to the thread in which it will be later run, a stub of what I did is this:
Aspect:
privileged public aspect ContextAware {
private final TraceContext MyRunnable.context = TraceContext.current();
}
Runnable (scala code, also tried java and the effects are the same):
class MyRunnable extends Runnable {
def run() {}
}
so far so good, but de-compiling the weaved MyRunnable class showed me something pretty different to what I was expecting:
public class MyRunnable
implements Runnable
{
public void run()
{
}
public MyRunnable()
{
ContextAware.ajc$interFieldInit$kamon_instrumentation_ContextAware$kamon_instrumentation_MyRunnable$context(this);
}
public static TraceContext ajc$get$context(MyRunnable myrunnable)
{
return myrunnable.context;
}
public static void ajc$set$context(MyRunnable myrunnable, TraceContext tracecontext)
{
myrunnable.context = tracecontext;
}
private TraceContext context;}
The "context" member in the weaved class is not final and the delegation on ajc$... for initializing the field seems unnecessary.. If it is a ITD member and the weaver is already putting some code inside the constructor to initialize a field that is supposed to be final, why the weaver is not just leaving the field as final and putting "context = TraceContext.current()" instead of "ContextAware.ajc$...." in the constructor?.. Maybe I'm doing something wrong, or I have wrong assumptions on how aspectj works.