AspectJ: track new object initialization - java

I'm trying to understand AspectJ. I want to try to count all object initializations (which are initialized from the classes I've specified, not some Java-internal ones) in a project and I'm really not sure how to do this.
Let's say I have classes called A and B, where A has subclasses Aa and Ab, B has the subclasses Ba and Bb, and Bb has the subclass Bba. I'd like my aspect to track every single initialization of the objects created with those classes as a base, but I don't really understand how to properly do this (even though this should be somewhat simple). So far, I have something similar to this:
public aspect AspectCounter {
private int objects = 0;
pointcut countObjects() : initialization(A.new(..)) || initialization(B.new(..));
pointcut printObjects() : call(* Test.printCounter(..));
after() : countObjects() {
objects++;
}
after() : printObjects() {
System.out.println(objects);
}
}
Which does, at least, print the right amount of A's and B's I've created (I didn't go with B*.new(..) since it would, the way I understand it, track any initialization of Bba three times which I don't want in this case).
The way it works right now is that I have a Test class which, well, does test stuff, and after I'm done with the testing, I'm just calling an empty printCounter method that doesn't really do anything. It seems to work and does actually give me the right number of objects, but I'm sure there's a better way to do this. I really don't like having an empty method.

You cannot do this with initialization, preinitialization or execution pointcuts on *.new(..) because of the order in which they are executed. They are not nested as you might think but executed rather sequentially due to the way the JVM works. I have explained this in detail here including sample code and log output. So you are only left with the option to use a call pointcut. Here is an example:
package de.scrum_master.app;
public class A {}
package de.scrum_master.app;
public class Aa extends A {}
package de.scrum_master.app;
public class Ab extends A {}
package de.scrum_master.app;
public class B {}
package de.scrum_master.app;
public class Ba extends B {}
package de.scrum_master.app;
public class Bb extends B {}
package de.scrum_master.app;
public class Bba extends Bb {}
Driver application:
package de.scrum_master.app;
public class Application {
public static void main(String[] args) {
new A();
new Aa();
new Ab();
new B();
new Ba();
new Bb();
new Bba();
}
}
Aspect:
package de.scrum_master.aspect;
import de.scrum_master.app.A;
import de.scrum_master.app.B;
public aspect InstanceCreationCounter {
private static int count;
after() : call(A+.new(..)) || call(B+.new(..)) {
System.out.printf("%4d %s%n", ++count, thisJoinPoint);
}
}
Console log:
1 call(de.scrum_master.app.A())
2 call(de.scrum_master.app.Aa())
3 call(de.scrum_master.app.Ab())
4 call(de.scrum_master.app.B())
5 call(de.scrum_master.app.Ba())
6 call(de.scrum_master.app.Bb())
7 call(de.scrum_master.app.Bba())
I guess this is what you want.
Caveat: You need to have control over all the calling code and weave the aspect into it in order for this to work.

Related

what happens when calling a class member via an object in the context of inheritance in java

edit : it is not a duplicata : I already know by heart private is accessible within the class only, protected within class and subclasses, and other class within the same packages and public is accessible everywhere, no modifiers = package only. that is not what I am talking about. I am talking about accessing from an object : object.var.
Just go read the exemple and try yourself to understand the compiler errors, you can't with just this simple rule.
Before closing the question, make sure you got it, it's not an easy question and if you think so you may have not get the question.
Here is my code and i don't get how object.privateVar and object.protectedVar behaves when calling it from different classes
In a daughter A class i can call daughterBObject.protected while in java doc it says we can call object.protectedVar only if the class we are calling in is involved in creating the object.
heritage.closefamilly.Mother:
package heritage.closefamilly;
import heritage.faraway.Auntie;
public class Mother {
private int priv;
protected int prot;
public int pub;
public Mother(){
priv = 1;
prot = 5;
pub = 10;
}
public void testInheritance(Mother m, Daughter d, Auntie a){
System.out.println(""+m.priv+m.prot+m.pub);
System.out.println(""+d.priv+d.prot+d.pub); // d.priv compiler error
System.out.println(""+a.priv+a.prot+a.pub);// a.priv compiler error
}
}
heritage.closefamilly.Daughter :
package heritage.closefamilly;
import heritage.faraway.Auntie;
public class Daughter extends Mother{
public void testInheritance(Mother m, Daughter d, Auntie a){
System.out.println(""+m.priv+m.prot+m.pub); // m.priv compiler error
System.out.println(""+d.priv+d.prot+d.pub); // d.priv compiler error why ? we are in daughter class !
System.out.println(""+a.priv+a.prot+a.pub); // a.priv compiler error, why does a.prot compile while we are in daughter class, it doesn't extends auntie neither it is auntie's subclass .. Javadoc says Object.prot shouldn't work when class it is called in is not involed in creating Object
}
}
heritage.faraway.Auntie :
package heritage.faraway;
import heritage.closefamilly.Daughter;
import heritage.closefamilly.Mother;
public class Auntie extends Mother{
public void testInheritance(Mother m, Daughter d, Auntie a){
System.out.println(""+m.priv+m.prot+m.pub);// m.priv & m.prot compiler error
System.out.println(""+d.priv+d.prot+d.pub); // d.priv & d.prot compiler error javadoc says " it is not involved in the implementation of mother and daughter"
System.out.println(""+a.priv+a.prot+a.pub); // a.priv compiler error whY? we are in auntie class
}
}
Can anyone explain these behaves to me?
First of all, a subclass does not inherit the private members of its parent class, meaning that the Daughter class doesn't actually contain priv. In order for this to work, you need to specify a public/protected method conventionally called (in this use case) getPriv() in the Mother class. In that method you return priv so that the subclasses can use the variable accordingly.
Secondly, there is no point of implementing the method testInheritance in the child classes, because it is basically the same as in the Mother class. If you were to change this method in the child classes, so that they provide a different implementation based on their functionality, then it would make sense. In such a case, you would need to use the annotation #Override.
I think this would be a good read for you to understand the whole concept of Inheritance theoretically : https://beginnersbook.com/2013/03/oops-in-java-encapsulation-inheritance-polymorphism-abstraction/

Create a Class whose object can not be created

I am studying for my BS, and my professor has given me a task, he said: Create a class without using any access modifier or interface keyword whose object can't be created.
I went through Google but can't find the solution. How can this be done in Java?
Enums are classes (JLS§8.9) that cannot be instantiated and cannot be subclassed; just create one without any values:
enum Foo {}
Other possibilities depending on interpretation:
JonK and T.J. Crowder considered throwing an exception from the constructor:
final class Example {
Example() {
throw new Exception();
}
}
But nick zoum pointed out that an instance is still created and exists, briefly, prior to the exception, even though it cannot (in the example above) be retained.
nick zoum considered abstract:
abstract class Example {
}
...but T.J. Crowder pointed out that abstract classes can be subclassed (they cannot be final), and a subclass instance "is a" superclass instance.
I'm not a Java person, but other answers gave me this idea:
import java.util.*;
import java.lang.*;
import java.io.*;
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
Object o = new Problematic();
// unreachable
}
}
class Problematic
{
static
{
int i = 1 / 0 ;
}
}
Try it on ideone
I'm pretty sure there's no way of making a Problematic and surviving...
(Note that when I tried throw new Exception(); in the static initializer it wouldn't compile)
Have you tried the keyword abstract?
For example:
abstract class Test{}
Of course this can be overwritten, so please check this answer for a more foolproof design.
Without hearing exactly how your professor phrased it, "without using any access-modifier" might mean they are attempting to teach you how the "default" access modifier works?
In which case:
package mypackage.nocreate;
class MyClass {
}
And then:
package mypackage;
import mypackage.nocreate.MyClass;
public class Test {
public static void main(String[] args) {
new MyClass(); // not allowed - in a different package
}
}
You could argue that - in the source code at least - that doesn't use any access modifier :)
Anonymous inner class should be the answer.
Example:
public abstract class HelloWorld{
abstract void x();
public static void main(String []args){
System.out.println("Hello World");
HelloWorld h = new HelloWorld(){
void x(){
System.out.println(" ");
}
};
h.x();
}
}
A class is created, but it's name is decided by the compiler which extends the HelloWorld class and provides the implementation of the x() method.

How to check if class has methods added by aspect?

Suppose I have a simple class:
public class TestClass {
/*...*/
}
I created an aspect which injects new method to this class:
public aspect TestAspect {
public void TestClass.aspectMethod() {
/*...*/
}
}
Now, how can I check if TestClass has method added by TestAspect in runtime?
The simplest way would be to simply reflect on the class:
TestClass.class.getDeclaredMethod("aspectMethod")
which will throw NoSuchMethodException if it isn't there. Or if you have the bytes you could use a byte code visitor to check what methods exist in the byte code - but the reflective route would be less messing around.
Andy's answer is the correct one, I just want to answer your follow-up question from the comment:
Duck typing is not a Java feature, but if you use ITD in order to make the class implement an interface and then have an instance of your aspect-extended class you can use instanceof MyInterface in order to determine what you need to know. Other ways (also using reflection) are also available:
Interface with the method you want to add later via ITD:
package de.scrum_master.app;
public interface MyInterface {
void myMethod();
}
Sample driver application:
package de.scrum_master.app;
import java.lang.reflect.Type;
public class Application {
public static void main(String[] args) {
Application application = new Application();
// Use an instance
System.out.println(application instanceof MyInterface);
System.out.println(MyInterface.class.isInstance(application));
// Use the class
for (Type type : Application.class.getGenericInterfaces())
System.out.println(type);
for (Class<?> clazz : Application.class.getInterfaces())
System.out.println(clazz);
}
}
Aspect:
package de.scrum_master.aspect;
import de.scrum_master.app.Application;
import de.scrum_master.app.MyInterface;
public aspect MyAspect {
declare parents : Application implements MyInterface;
public void Application.myMethod() {}
}
Application output:
true
true
interface de.scrum_master.app.MyInterface
interface de.scrum_master.app.MyInterface

I need to have a java method that can be accessed from anywhere within my API but cannot be accessed from the application using the API

I am developing a java API. During my development, I keep facing the following issue:
I have two classes in two different packages. Class A in package x, and class B in package y. I need the class A to access a method M defined in class B. Hence, the modifier that should be used for the method M is public. However, I do not want to allow the developer who will use my API in his/her java application to access the method M. The problem is that the method M has a public modifier as I mentioned, and hence anyone can access it within the API or from outside the API. At the same time, if I decrease the modifier level of the method M to protected or private, the class A will not be able to access the method M because it belongs to a different package. How can I solve this problem? Is my only solution to have A and B in the same package?
Create an interface and expose only that to the public, hiding your implementation. For example:
My implementation (in say, for example, application.jar):
public class Test implements TestInterface {
public void somePrivateStuff() { }
public void somePublicStuff() { }
}
Dear world, here is my API (in say, for example, publicAPI.jar):
public interface TestInterface {
public void somePublicStuff();
}
Other developers would compile against your publicAPI.jar. The runtime implementation would come from your application.jar.
The only way to restrict access to specific classes is to make the method protected or package-private. Both only allow access within the package. I would suggest reformatting your package structure.
Inside the method, you can insert:
Throwable th = new Throwable().fillInStackTrace();
StackTraceElement element = th.getStackTrace()[TEST BETWEEN 3 AND 5];
if (element.getClassName().startsWith("your.package")) {
// CONTINUE YOUR METHOD.
}
else {
// USER ACCESSING FROM AN APPLICATION.
// THROW EXCEPTIONS, SHUTDOWN THE SYSTEM... DO WHAT YOU WANT.
}
On the second line, test between 3, 4 and 5, and see which one returns the correct element.getClassName().
You can split you project into 2: the public API and it implementation.
Define 2 interfaces for the class B:
The public interface for your library users (in API project).
Your inner interface that extends the public one and adds method M.
User will be dependent on you API in compilation and will get the implementation in the run-time.
You could use reflection. Here's an example.
package b;
public class B {
private void m() {
System.out.println("Called m()");
}
}
and
package a;
import b.B;
import java.lang.reflect.Method;
public class A {
public static void main(String[] args) throws Exception {
B b = new B();
Method m = B.class.getDeclaredMethod("m");
m.setAccessible(true);
m.invoke(b);
}
}
Which outputs
Called m()

PowerMock whenNew without #PrepareForTest?

This is my situation, I have 2 very simple classes:
public class B {
public void doSomething(){
System.out.println("doSomething B reached");
}
}
And:
public class A {
public void doSomething(){
B b = new B();
b.doSomething();
System.out.println("doSomething A reached");
}
}
I want to test method doSomething of class A with Mockito. Therefor, I want to mock an instance of class B and give this to A when it is instantiating class B. I don't want b.doSomething() to be reached at all, for isolation reasons.
I know I can reach this behaviour by creating the following unittest:
#RunWith(PowerMockRunner.class)
public class TestA {
#Test
#PrepareForTest(A.class)
public void testDoSomethingOfA() throws Exception{
A a = PowerMockito.spy(new A());
B b = PowerMockito.mock(B.class);
PowerMockito.whenNew(B.class).withNoArguments().thenReturn(b);
a.doSomething();
}
}
which results in output:
doSomething A reached
So this work! However, my problem now is that we use the Jococo plugin for test coverage. Jococo doesn't cover code tested with the #PrepareForTest(A.class) statement. And my company values accurate code testing coverage.
My question: Is there another way around to give A an instantiation of B without having to use the #PrepareForTest statement?
Many thanks in advance!
To answer my own question, yes, use an agent: https://github.com/jayway/powermock/wiki/PowerMockAgent
#Rens Groenveld: After integrating PowerMockAgent, did you make any changes in your test class or source code ? I tried integrating PowerMockAgent and removed my main source class from #PrepareForTest but the behavior is same (creating new instance instead of mock).
I have tried jacoco offline instruments and many other solution, It did not work.
I can not post to your comment (needs 50 points) hence added as answer.

Categories