AspectJ modify property field content or add and/or change methodbody in a runtime instance

J

Jimmy

It is possible to access data member of a Java class with pointcut,
but I need to do a field assignment or even hijack/override the method
with a custom implement with AspectJ. Can someone refer me to some
sample code URL and/or tutorial for doing so?

Thanks,
Jimmy
 
R

Roedy Green

It is possible to access data member of a Java class with pointcut,
but I need to do a field assignment or even hijack/override the method
with a custom implement with AspectJ. Can someone refer me to some
sample code URL and/or tutorial for doing so?

I don't know about AspectJ, but in plain Java you can't modify the
code of the method bodies at run time the way you can in some other
languages.

What you could do is construct a new class, with different source code
for the methods, compile it on the fly, and load the modified class
with a new ClassLoader.

You can also load a number of classes on the fly, knowing only their
names you read from file or resource. Usually they would all
implement a common interface. You then have a set of delegate
objects, each of which implements the interface differently with code
decided long after your mother code was compiled.

You could also construct a class file of byte codes on the fly and
load it.

If you are a glutton for punishment, you can load classes, and probe
them to find out what sorts of methods and parms they have, and
dynamically create parameter lists to invoke them.

Some of these are quite advanced techniques.

see http://mindprod.com/jgloss/onthefly.html
http://mindprod.com/jgloss/javacompiler.html
http://mindprod.com/jgloss/jasm.html
http://mindprod.com/jgloss/classloader.html
http://mindprod.com/jgloss/delegate.html
http://mindprod.com/jgloss/reflection.html
--
Roedy Green Canadian Mind Products
http://mindprod.com

"We must be very careful when we give advice to younger people: sometimes
they follow it!"
~ Edsger Wybe Dijkstra, born: 1930-05-11 died: 2002-08-06 at age: 72
 
A

Arne Vajhøj

Jimmy said:
It is possible to access data member of a Java class with pointcut,
but I need to do a field assignment or even hijack/override the method
with a custom implement with AspectJ. Can someone refer me to some
sample code URL and/or tutorial for doing so?

Yes.

Demo:

public class Foobar
{
private int v;
public int getV() {
return v;
}
public void setV(int v) {
this.v = v;
}
public void test() {
System.out.println("test: v=" + v);
v++;
System.out.println("test: v=" + v);
}
public static void main(String[] args) {
Foobar o = new Foobar();
o.setV(7);
System.out.println("main: v=" + o.getV());
o.test();
System.out.println("main: v=" + o.getV());
}
}

import java.lang.reflect.*;

import org.aspectj.lang.*;
import org.aspectj.lang.annotation.*;

@Aspect
public class Fun {
@Pointcut("call(public void Foobar.test())")
public void foobarTest() { };
@Before("foobarTest()")
public void before(JoinPoint tjp) {
// increment v
Foobar o = (Foobar)tjp.getTarget();
o.setV(o.getV() + 1);
}
@Around(value = "foobarTest()")
public Object around(ProceedingJoinPoint pjp) {
// call twice instead of once
pjp.proceed();
pjp.proceed();
return null;
}
@AfterReturning("foobarTest()")
public void after(JoinPoint tjp) {
// increment v
Foobar o = (Foobar)tjp.getTarget();
o.setV(o.getV() + 1);
}
}

C:\>javac Foobar.java

C:\>java Foobar
main: v=7
test: v=7
test: v=8
main: v=8

C:\>ajc -source 1.5 Foobar.java Fun.aj

C:\>java Foobar
main: v=7
test: v=8
test: v=9
test: v=9
test: v=10
main: v=11

Arne
 
A

Arne Vajhøj

Roedy said:
I don't know about AspectJ, but in plain Java you can't modify the
code of the method bodies at run time the way you can in some other
languages.

What you could do is construct a new class, with different source code
for the methods, compile it on the fly, and load the modified class
with a new ClassLoader.

You can also load a number of classes on the fly, knowing only their
names you read from file or resource. Usually they would all
implement a common interface. You then have a set of delegate
objects, each of which implements the interface differently with code
decided long after your mother code was compiled.

You could also construct a class file of byte codes on the fly and
load it.

If you are a glutton for punishment, you can load classes, and probe
them to find out what sorts of methods and parms they have, and
dynamically create parameter lists to invoke them.

Some of these are quite advanced techniques.

see http://mindprod.com/jgloss/onthefly.html
http://mindprod.com/jgloss/javacompiler.html
http://mindprod.com/jgloss/jasm.html
http://mindprod.com/jgloss/classloader.html
http://mindprod.com/jgloss/delegate.html
http://mindprod.com/jgloss/reflection.html

Or he could just use AOP as he suggested himself, which is
intended to do this kind of stuff.

Arne
 
J

Jimmy

Thank you for everyone's help. Allow me to clarify few things ...

- I like to modify the data member and/or method body of a class with
AspectJ in compile time.
- The source codes came from a non-obfuscated jar which allow me to
extend and/or override _some_ of the codes. However, there're few
private/package-private class/method I need to override.

How can I do this AspectJ? It'd be nice with some sample codes.

Thanks again,
Jimmy
 
R

Roedy Green

Thank you for everyone's help. Allow me to clarify few things ...

- I like to modify the data member and/or method body of a class with
AspectJ in compile time.
- The source codes came from a non-obfuscated jar which allow me to
extend and/or override _some_ of the codes. However, there're few
private/package-private class/method I need to override.

How can I do this AspectJ? It'd be nice with some sample codes.

Unfortunately, you are the first person I have seen mention it is
years. I don't think there is a newsgroup on it. Perhaps someone has
a blog or forum who might be able to help.

This kind of think in raw Java is quite a production. I come from a
FORTH environment where it is fairly easy to roll your own such
features. At first it looked like the JVM was designed to make them
easy.

--
Roedy Green Canadian Mind Products
http://mindprod.com

"We must be very careful when we give advice to younger people: sometimes
they follow it!"
~ Edsger Wybe Dijkstra, born: 1930-05-11 died: 2002-08-06 at age: 72
 
A

Arne Vajhøj

Jimmy said:
Thank you for everyone's help. Allow me to clarify few things ...

- I like to modify the data member and/or method body of a class with
AspectJ in compile time.

That is what AspectJ does - see previously posted demo.
- The source codes came from a non-obfuscated jar which allow me to
extend and/or override _some_ of the codes. However, there're few
private/package-private class/method I need to override.

You have some class X using another class Y. Do you have the
source code for both X and Y or ?
How can I do this AspectJ? It'd be nice with some sample codes.

I already posted some demo code.

If that does not apply to your problem, then you need to
explain what the difference is.

Arne
 
J

Jimmy

Thanks again for all comments.

I have all source codes, however, there's no setter method for the
private data members. In the extreme case, if I need to change both
private data member and private method in a private sub class of a
package private class, can this be done still with AspectJ?

Thanks,
Jimmy
 
A

Arne Vajhøj

Jimmy said:
I have all source codes, however, there's no setter method for the
private data members. In the extreme case, if I need to change both
private data member and private method in a private sub class of a
package private class, can this be done still with AspectJ?

The method intercept should be doable using the around
technique in the previous example.

Accessing the private field requires reflection but it
can be facilitated by AspectJ.

Demo:

public class Dummy {
public int v;
public Dummy() {
v = 123;
}
public String toString() {
return "#" + v + "#";
}
}

public interface Hack {
public void setV(int v);
}

import java.lang.reflect.*;

public aspect HackImpl {
declare parents: Dummy implements Hack;
public void Hack.setV(int v) {
try {
Field field = getClass().getDeclaredField("v");
field.setAccessible(true);
field.setInt(this, v);
} catch (NoSuchFieldException nsfe) {
nsfe.printStackTrace();
} catch (IllegalAccessException iae) {
iae.printStackTrace();
}
}
}

public class Main {
public static void main(String[] args) {
Dummy o = new Dummy();
System.out.println(o);
((Hack)o).setV(456);
System.out.println(o);
}
}

C:\>ajc Main.java Dummy.java Hack.java HackImpl.aj

C:\>java Main
#123#
#456#

Arne
 
J

Jimmy

Thanks again. However, if Dummy's constructor is either protected or
private, we can't instantiate as "Dummy o = new Dummy()" in static
Main. Can or how AspectJ still override/hijack in this case?

Thanks,
Jimmy
 
A

Arne Vajhøj

Jimmy said:
Thanks again. However, if Dummy's constructor is either protected or
private, we can't instantiate as "Dummy o = new Dummy()" in static
Main. Can or how AspectJ still override/hijack in this case?

Whether Dummy is created directly via constructor or via a factory
method does not matter.

Arne
 
A

Arne Vajhøj

Arne said:
Whether Dummy is created directly via constructor or via a factory
method does not matter.

I will like to add that AOP is invented to make is easy to implement
crosscutting concerns - it is not invented to make it possible
to violate encapsulation.

If the stuff you are trying to access is declared private, then maybe
there is a reason for that.

Arne
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,740
Latest member
JudsonFrie

Latest Threads

Top