How can I weave aspect code into existing class files within JARs? - java

I am new to aspectj and I have one doubt whether we can inject the code before the function that exists in the jar file using aspectj.

Before I answer your question, some advice:
Please learn how to ask clear, understandable questions.
Please use a subject which clearly expresses what you want to ask (I have just edited yours in order to achieve that).
Please use a web search engine or read at least minimal introductory material before asking FAQs.
Now the answer: Yes, you can weave aspect code into third-party class files or JARs. There are two ways to achieve that:
Binary weaving: Use the AspectJ compiler ajc in order to apply your aspects upon class files in an existing JAR. For that purpose, put the JAR on the compiler's inpath. After compilation you can re-package the newly woven class files into a new JAR which then you can deploy and use instead of the original one.
Load-time weaving (LTW): Start the JVM with the AspectJ weaving agent via command line option -javaagent:pathto/aspectjweaver.jar in order to achieve aspect weaving during classloading. This way you sacrifice some start-up time, but do not need to create a modified JAR file. Everything happens dynamically.
And now please read some AspectJ documentation.

Related

Java - make a library and import optional

I have a library that I'm using in an Java application - it's important for certain functionality, but it's optional. Meaning that if the JAR file is not there, the program continues on without issue. I'd like to open source my program, but I can not include this library, which is necessary to compile the source code as I have numerous import statements to use the API. I don't want to maintain two code sets. What is the best way to remove the physical jar file from open source release, but still maintain the code to support it where other people could still compile it?
the typical approach taken is to define the wrapper API (i.e. interfaces) and include those interfaces in the open sourced code, and then provide configuration options where one can specify class names of classes that implement certain interfaces.
You will import API interfaces instead of importing classes directly into your open sourced code. This way, you are open sourcing the API but not the implementation of the parts that you do not want to open source or you cannot open source.
There are many examples, but take a look at JDBC API (interfaces) and JDBC drivers (implementation classes) for starters.
I was pretty much typing the same thing as smallworld with one addition. If this API were necessary you can use a project build tool like Maven to handle the dependencies on you project. If someone checks it out from source control with the pom they can download the dependencies for themselves and you don't have to include them in a source repo.
There's probably a number of ways to fix this, here's a couple I can think of:
If you have only a couple of methods you need to invoke in the 3rd party library, you could use reflection to invoke those methods. It creates really verbose code, that is hard to read though.
If you don't have too much of the API in the 3rd party library you use, you could also create a separate JAR file, containing just a non-functional shell of the classes in the library (just types with the same names and methods with the same signatures). You can then use this JAR to distribute and compile against. At run-time you'd replace it with the real JAR if available.
The most common way is probably to just create a wrapper API in a separate module/project for the code that is dependent on the 3rd party library, and possibly distribute a pre-built JAR. This might go against your wish to not maintain two code sets, but may prove to be the best and less painful solution in the long run.

Is AspectJ required on the classpath when weaving at compile-time?

I asked this question a few days ago, and managed to get it working using compile-time weaving.
However, when the application runs and it invokes the toString() method which I mixed into my DTO via AOP, I get the exception below.
I didn't expect AspectJ to be required in the runtime classpath. After all, I've used compile-time weaving, so the bytecode should already be in its final state, right? Why is AspectJ expected to be present at runtime?
java.lang.ClassNotFoundException: org.aspectj.lang.NoAspectBoundException
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:506)[osgi-3.6.2.R36x_v20110210.jar:]
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:422)[osgi-3.6.2.R36x_v20110210.jar:]
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:410)[osgi-3.6.2.R36x_v20110210.jar:]
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)[osgi-3.6.2.R36x_v20110210.jar:]
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)[:1.6.0_35]
... 51 more
Is there a way to instruct AspectJ to drop all references to itself in the resulting bytecode?
N.B.: I'm running in an OSGi environment - but that's definitely irrelevant.
Whether you use compile-time, post-compile-time or load-time weaving, the woven bytecode will have a dependency on a small number of types - shipping them in a jar is seen as easier than generating them into every compiled app. These types are encapsulated in the small jar 'aspectjrt.jar'. You won't need the weaver jar or the compiler jar on the classpath, just the small runtime jar. It contains a few different things:
definitions of the runtime visible annotations that might have been used to write the aspect (#Before, #Aspect)
exception types for when things go wrong (NoAspectBoundException) or to implement language features (SoftException)
utility code to implement some language features, for example cflow threadlocal stack management.
all the support classes for thisJoinPoint. When you access something like getSignature() on thisJoinPoint you might get back a MemberSignature.
If would be possible to avoid a lot of these if you aren't using those language features, but NoAspectBoundException would likely still be an issue - even the simplest aspect will depend on that. Right now there is no way to compile that will avoid the jar dependency entirely.
It would be possible to modify AspectJ to do extra code generation to avoid the dependency entirely, but that isn't a common request and so no work has been done on it.
(There are builds of aspectjrt.jar that include the right OSGi manifest info, for use in that environment - the jar included in the standard distro doesn't get that manifest correct right now)
I believe you'll still need the AspectJ runtime libraries regardless of when the weaving took place.

Spring Source Tool Help Needed

i am applying AspectJ in spring source tool
do i need to configure load time or compile weaving in spring source tool
i will be very happy if any provide details of using AspectJ for applying Aspect on Spring Source Tool
This is a very advanced topic, way beyond the scope of a single StackOverflow question.
Basically:
The simplest case is Spring AOP,
where you don't use AspectJ at all,
but create Java proxies from AspectJ
annotations. This is also the least
powerful option. Only a few pointcuts
are supported, and the targets must
be Spring Beans.
The most powerful option is static
AspectJ compilation, which you
usually integrate in your build
system (works fine with ant or
maven). Your class files are actually
changed to include the aspects. This
is called compile-time weaving.
Load-time weaving is somewhere
inbetween. You want to advise code,
but you don't want to change the
class files, so you "advise the
classloader" (this is not an adequate
definition, but it gives you an
idea). Loadtime-weaving is also
usually your only choice if you want
to add aspects to 3rd party library
code.
You should read AspectJ in Action by Ramnivas Laddad to understand all the subtle differences.
Either way, the settings you use in STS should reflect the settings you have in your build system. The section 7. Aspect Oriented Programming with Spring from the Spring Reference is also very helpful.

Retro-actively add Java annotations to methods?

Is there a way to modify .class files in order to add Java annotations to certain methods? Basically I want to traverse methods of each class file in a jar file and annotate certain ones. Note that this is not at run-time while using the jar file. Rather, after I'm done I want to have modified class files with the annotations.
I do have access to the source code, so if there's an automatic source code modifier, that would work as well...
I'm assuming I'll need a tool such as Javassist or ASM. If so, which one should I use and how would I go about it?
Actually, this is a classic use case for AspectJ:
declare #method : public * BankAccount+.*(..) : #Secured(role="supervisor")
While I will grant you that direct byte code manipulation is more powerful, AspectJ is much more user-friendly, and it immediately gives you compiler warnings when you are doing something wrong.
Also, if you use Load Time Weaving, you can leave the original library jar unchanged, because the weaving happens at class-load time.
Reference:
Declare Annotation
AspectJ in Action (book)
Googling for an hour or so turned this article up which seems to completely answer my question: use ASM. To write class files using the changed bytecode, use ClassWriter.
Well, time to get to work then, I guess. :)

How do I strip the fluff out of a third party library?

It may not be best practice but are there ways of removing unsused classes from a third party's jar files. Something that looks at the way in which my classes are using the library and does some kind of coverage analysis, then spits out another jar with all of the untouched classes removed.
Obviously there are issues with this. Specifically, the usage scenario I put it though may not use all classes all the time.
But neglecting these problems, can it be done in principle?
There is a way.
The JarJar project does this AFAIR. The first goal of the JarJar project is to allow one to embed third party libraries in your own jar, changing the package structure if necessary. Doing so it can strip out the classes that are not needed.
Check it out at http://code.google.com/p/jarjar/.
Here is a link about shrinking jars: http://sixlegs.com/blog/java/jarjar-keep.html
There is a tool in Ant called a classfileset. You specify the list of root classes that you know you need, and then the classfileset recursively analyzes their code to find all dependencies.
Alternatively, you could develop a good test suite that exercises all of the functions that you need, then run your tests under a test coverage tool. The tool will tell you which classes (and statement in them) were actually utilized. This could give you an even smaller set of code than what you'd find with static analysis.
I use ProGuard for this. As well as being an excellent obfuscator, it has a code shrinking phase which can combine multiple JARs and then strip out any unused classes or class members. It does an excellent job at shrinking.
At a previous job, I used a Java obfuscator that as well as obfuscating the code, also removed classes and methods that weren't being used. If you were doing "Class.byName" or any other type of reflection stuff, you needed to tell the obfuscator because it couldn't tell by inspecting the code what classes or methods called by reflection.
The problem, of course, is that you don't know if other parts of the third party library are doing any reflection, and so removing an "unused" class might cause things to break in an obscure case that you haven't tested.
jar is just a zip file, so I guess you can. If you could get to the source, it's cleaner. Maybe try disassembling the class?
Adding to this question, can that improve performance? Since the classes not used would not be JIT compiled improving startup time or does the java automatically detect that while compiling to bytecode and do not even deal with the code that is not used?
This would be an interesting project (has anyone done it already?)
I presume you'd give the tool your jar(s) as a starting point, and the library jar to clean up. It could use reflection to determine which classes your jar(s) reference directly, and which are used indirectly down the call tree (this is not trivial at all, but doable). If it encounters any reflection code in any of the two places, it should give a very loud warning.

Categories

Resources