It was claimed somewhere in the last week or so that it is impossible to do AspectOrientedProgramming
in a language that doesn't support it without having the source code for all dependent libraries in the program.
I beg to differ. I have done it. I am one of those who voted AssemblyLanguage
. This is why. --JoshuaHudson
You don't need the source code to do AspectOrientedProgramming. I've done it with ClassLoader byte code manipulation in the JavaLanguage. I've done AOP behavior modification because I could not change the source code who's behavior I needed to modify. -- JeffGrigg
Sounds interesting. How do you go about validating such a system? Or is it just click and pray?
Through which methods have you "done it?" Assembly language is the epitome of an early-bound programming environments. There is just no way in heck you could implement aspects without some kind of macro expansion or other kind of source file preprocessing step.
I'd be interested in hearing more about doing AspectOrientedProgramming "The Hard Way." What is that? And what's hard about it? And what has worked for you, to get it done anyway, in spite of the difficulty. -- JeffGrigg
I used a method similar to JeffGrigg
's method with native code. -- JoshuaHudson
So ... you're hot-patching binaries then. This really isn't AOP though.
And why not?
For example, (quite a few years ago)
I wrote a product we called dLock-II, in AssemblyLanguage
It hot-patched itself in, between dBase-II and the operating system (8-bit CP/M), doing a DecoratorPattern
on application to operating system calls to change the semantics of file operations.
I can describe this in AspectOrientedProgramming
- I defined a PointCut? at the client program to operating system call location.
- And introduced advice at that location to change the semantics of file operations.
How's that not
I see your point, but, to me, hand-rolled AOP just doesn't count as AOP, any more than hand-rolled OOP in assembly language counts as OOP. You can use procedure pointers in assembly language to implement OOP at that level too. Due to the manual-ness of the project, you're not so much doing AOP as AOM: Aspect-Oriented Monotony.
AOP depends on your ability to define under which conditions code flow changes occur. In other words, your software is written more or less declaratively: any time we execute an SQL query on the Foosball table, call this logger procedure first, and that logger procedure afterwards.
You really don't know where all the call sites are for making an SQL query; your aspects could well be affecting code you have no knowledge about. You'd have to literally find some way of examining machine language for heuristically correct
tell-tale signs that might involve calling the SQL interpreter. You might not get all of them. You might even get some which aren't related, in which case you run the risk of crashing the program when you attempt to verify the arguments refer to the Foosball table.
To summarize, AOP involves more than just hot-patching. It also involves a system of notation specifying clearly what to hotpatch and how. I concede that Java ByteCode
s might make this process easier; I know for a fact that SmallTalk ByteCode
s absolutely do. But assembly language?
Especially considering what comes out of today's optimizers? That's tough.
- Not so tough. Cross-module function calls cannot be optimized away and Microsoft's function prolog/epilog code in x86 seems designed for this. --JoshuaHudson
Nope: No heuristics were used. And no knowledge (or memory addresses) of <program-being-modified> code or subroutines was used either.
It's easy to capture (pointcut) and modify (advise) behavior at well-defined interfaces.
The interface between an application and the operating system is typically very well defined.
As is the interface between and application and a 3rd party library.
So in 8-bit CP/M, it was simply a matter of intercepting calls to memory address 5 -- where ALL
application calls to CP/M system functions must pass -- interpret the requests, and take appropriate action.
To intercept SQL calls, I typically "cut" somewhere close to the industry standard JDBC interfaces.
JDBC itself is annoyingly complex, so I typically "back off" a layer or two into the application, standardize the pattern of usage, and then cut there.
, for example, is a good place to "cut" to insert "advice" on SQL / RelationalDatabase
One could even argue that the SpringFramework
's API is designed
to support such point cuts.
supports and encourages uses of several forms of AspectOrientedProgramming