5

I need to inject few methods to every initialized object using AspectJ.

I thought using this :

pointcut vistaInjection(Object o)
    : initialization(java.lang.Object.new() ) 
    && target(o)
    && !within(objectAspect);

before(Object o): methodInjection(o){System.err.println("INIT");}

to pointcut initialization of object, so I can inject these methods directly into the object that is part of every other object.

However, it does't work. Do you have any idea why? Or what may be an other way how to make 100% sure that every single initialized object will be pointcut? *.new does not work for stuff such String, Lists and others.

Thank you!

Marosh
  • 63
  • 1
  • 1
  • 3
  • Is there an error ? Could you be more specific about mal function ? – JEY Jun 27 '13 at 09:16
  • no there is no error. just Object creation does not trigger advice.. Sorry, I don't understand, what is "mal" function? I have just realized, that creating other objects does not initialize Object constructor therefor it would be useless anyway. I will need to find other way how to pointcut all object creations. – Marosh Jun 27 '13 at 09:43

2 Answers2

19

User selig is right: You probably do not want to intercept all object creations, especially not those in JDK/JRE classes. But for what it is worth, here is an explanation of what works and how and what not:

A little driver application:

public class Application {
    public static void main(String[] args) {
        new Application();
        new String();
    }
}

An aspect with different types of constructor-related pointcuts/advice:

public aspect ObjectCreationAspect {
    before() : preinitialization(*.new(..)) && !within(ObjectCreationAspect) {
        System.out.println(thisJoinPointStaticPart);
    }

    before() : initialization(*.new(..)) && !within(ObjectCreationAspect) {
        System.out.println(thisJoinPointStaticPart);
    }

    before() : call(*.new(..)) && !within(ObjectCreationAspect) {
        System.out.println(thisJoinPointStaticPart);
    }

    before() : execution(*.new(..)) && !within(ObjectCreationAspect) {
        System.out.println(thisJoinPointStaticPart);
    }
}

The woven driver application's output:

call(Application())
preinitialization(Application())
initialization(Application())
execution(Application())
call(java.lang.String())

Explanation:

There are different types of weaving in AspectJ:

  • Compile-time weaving (CTW): Only classes which are compiled by ajc (AspectJ compiler) can be woven. This excludes JDK/JRE classes and also 3rd party libraries which you do not compile from source. the sample output from above shows the effect of compile-time weaving.
  • Binary weaving (BW): The AspectJ compiler is used to compile aspect code directly into existing byte code. This works with your own precompiled application classes as well as with 3rd party libraries. Theoretically it also works with JDK/JRE classes if you put rt.jar on the AspectJ compiler's in-path. JDK/JRE weaving is a bit tricky, but I have done it before. You can produce a newly woven version of rt.jar or just a small JAR file with a few woven JDK classes which then you prepend to the boot-classpath of the JDK/JRE when firing up your application.
  • Load-time weaving (LTW): Basically this is BW, but done dynamically during class-loading. In this AspectJ scenario you can only weave classes which are loaded by a classloader under the influence of an aspect weaver. Thus, it works with you own code and 3rd party libraries, but usually not with JDK/JRE bootstrapping classes which are loaded before the aspect weaver is loaded. It is a hen-and-egg type of problem: The weaver needs the JRE to be running before it can be loaded, but in order to weave JRE classes the weaver would have to be there before those classes are bootstrapped.

Now what you can easily do is intercept calls to JDK/JRE constructors from your own code oder woven 3rd party code, as you can see in the log output line saying call(java.lang.String()). You cannot intercept internal calls from JRE class to JRE class though.

Having said all that I really wonder what kind of horrible thing you want to do. I mean, you explain it and it sounds like a tremendous design error. Or you want to re-invent the wheel and write some kind of profiler or debugger which already exists. What do you expect from intercepting each single object creation? It would tremendously slow down your application, drastically increase memory consumption and create even more objects, if only the strings you are logging. Please reconsider and try to think about what you really want to do. Maybe then we can suggest a smart way of achieving your goal.

kriegaex
  • 63,017
  • 15
  • 111
  • 202
  • Thank you very much for your complex answer. I am working on an experiment, absolutely not on real application... I want to implement altered version of object capabilities. It means that I can create an object and de-authorize certain methods and pass this object to a third party. If the third party attempts to execute de-authorize method, exception is thrown. This should be applied to every object, even JDK/JRE. I am achieving this by static modification by declare parents .... to all classes. Again, even Java classes. – Marosh Jul 11 '13 at 10:49
  • Then user can call e.g o.deauthorize("methodName") and on o.methodName, exception is thrown. There are then two options I considered. First is to create pointucts in runtime, what I have found as not possible, second is do deauthorization by Annotations(haven't fully explored yet) and third is simple brute force done by interception all methods calls in application and comparing them with an "de-authorized methods". The last one is stupid and make it all unfeasible thought, because it would slow down system as you said tremendously. – Marosh Jul 11 '13 at 10:50
  • @kriegaex can you take a look at a similar question https://stackoverflow.com/questions/53270967/reentrantreadwritelock-with-aspectj-pointcut-for-every-initialized-type-of-mystr – Panagiotis Drakatos Nov 12 '18 at 22:43
1

Have you tried

pointcut vistaInjection(Object o)
    : (initialization(*.new()) || (initialization(*.new(..)))
    && target(o)
    && !within(objectAspect);

i.e. calling .new() on anything and allowing no and some arguments.

Note - you probably don't want to pick up all object creations.. what are you planning on doing with them!

selig
  • 4,834
  • 1
  • 20
  • 37
  • Nope, it doesn't work neither. I am trying to implement something similar to object capabilities using AOP. So every object is injected with an code that enable revoke access to particular method. Then when this un-authorized method is executed exception is thrown. In the concept i propose every object is in the same time object capability. therefore I need to pick every all object creation – Marosh Jun 29 '13 at 19:57