2. Who the hell are you?
Programmer
Entrepeneur
CTO of import.io
Geek
Ex-mathematician
Long-suffering Java user (yay, lambdas!)
Proud father of two :)
2 / 21
3. So what's the plan?
1. What?
2. Why?
3. How?
4. Codez
5. Q&A
6. Beer!
3 / 21
5. Per JVM
Heap for objects
PermGen/Metaspace
Per Thread
PC (Program Counter) tracks instruction position in a register
Stack (as in trace) of Frames (method invocations)
Native stack
Per frame
Local variable 32bit array ([0]=this)
Operand 32bit stack
Constant pool reference for the class
5 / 21
6. Operand stack
The Java stack is a last-in, first-out stack of 32-bit slots. Because each slot in the
stack occupies 32 bits, all stack variables occupy at least 32 bits - even a byte.
Longs/Doubles take 2 slots.
"We chose a stack organization so that it would be easy to emulate the
machine efficiently on machines with few or irregular registers such
as the Intel 486."
Local variable array
Zero-indexed, 32 bit slots.
6 / 21
7. Bytecode
"Understanding bytecode and what bytecode is likely to be generated
by a Java compiler helps the Java programmer in the same way that
knowledge of assembly helps the C or C++ programmer."
When a JVM loads a class file, it gets a stream of bytecodes that represent the
logic for each method that are interpreted or JIT compiled.
One byte opcode (mnemonics, action) and its operands.
7 / 21
10. What is bytecode weaving?
Changing byte code for a class either up front or dynamically at run-time.
10 / 21
11. Why should I want to weave bytecode?
Proxy creation
Aspect-orientated programming
Logging
Sandboxing
Code coverage
Adding in features like co-routines
Anything else you can dream up :)
11 / 21
12. How to weave
WTF is a Java agent?
An agent is just an interceptor in front of your main method,
executed in the same JVM and loaded by the same system classloader,
and governed by the same security policy and context.
Need a class with a premainmethod:
publicstaticvoidpremain(StringagentArgs,Instrumentationinst);
... and some special MANIFEST.MF lines:
Manifest-Version:1.0
Premain-Class:my.package.MyJavaAgent
Boot-Class-Path:some-dependency.jar
... a command line option:
-javaagent:<jarpath>[=<options>]
loadJavaprogramminglanguageagent,seejava.lang.instrument
... to hook into the Instrumentationclass
12 / 21
13. Getting funky with Instrumentation
Lets you hook in ClassFileTransformerinstances - which are what they sound
like.
byte[]
transform( ClassLoader loader,
String className,
Class classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer)
throwsIllegalClassFormatException;
But what's in the byte arrays?
13 / 21
15. How do you modify the bytes?
Manually (Super scary)
Javassist
ASM
Other libraries may be available... :)
15 / 21
16. Javassist: a quick aside
It'll parse Java source strings - no bytecode required.
publicbyte[]transform(ClassLoaderloader,StringclassName,ClassclassBeingRedefined,
ProtectionDomainprotectionDomain,byte[]classfileBuffer)throwsIllegalClassFormatException{
pool.insertClassPath(newByteArrayClassPath(className,classfileBuffer));
CtClasscclass=pool.get(className.replaceAll("/","."));
if(cclass.isFrozen()){
returnnull;//useuninstrumentedclass,alreadyprocessed
}
for(CtMethodcurrentMethod:cclass.getDeclaredMethods()){
currentMethod.insertBefore("System.err.println('foo');");
}
returncclass.toBytecode();
}
Easy, but not the quickest.
Not so good as a learning exercise either :)
16 / 21
17. ASM: total control, but like writing
assembler.
Event model, similar to SAX.
Extend abstract class:
classClassVisitor{
voidvisit(intversion,intaccess,Stringname,Stringsignature,StringsuperName,
String[]interfaces)
voidvisitSource(Stringsource,Stringdebug)
voidvisitOuterClass(Stringowner,Stringname,Stringdesc)
AnnotationVisitorvisitAnnotation(Stringdesc,booleanvisible)
AnnotationVisitorvisitTypeAnnotation(inttypeRef,TypePathtypePath,Stringdesc,
booleanvisible)
voidvisitAttribute(Attributeattr)
voidvisitInnerClass(Stringname,StringouterName,StringinnerName,intaccess)
FieldVisitorvisitField(intaccess,Stringname,Stringdesc,Stringsignature,
Objectvalue)
MethodVisitorvisitMethod(intaccess,Stringname,Stringdesc,Stringsignature,
String[]exceptions)
voidvisitEnd()
}
17 / 21
18. and hook in
to your ClassFileTransformer
publicbyte[]transform(ClassLoaderloader,StringclassName,
ClassclassBeingRedefined,ProtectionDomainprotectionDomain,
byte[]classfileBuffer)throwsIllegalClassFormatException{
ClassReadercr=newClassReader(classfileBuffer);
ClassWritercw=newClassWriter(cr,ClassWriter.COMPUTE_FRAMES);
cr.accept(cw,0);
returncw.toByteArray();
}
Easy!
18 / 21
19. sio2box
A memory sandbox that counts allocations.
Add annotations to classes (SiO2Class) and methods (SiO2Method) to limit the
total amount of memory allocated by untrusted code.
Don't take GC into account, interested in memory churn - could use
ReferenceQueueif we were.
Tracks:
Array.newInstance
type[].clone
Object instantiation
new type[] - ANEWARRAY, NEWARRAY, MULTIANEWARRAY
Object.clone
ArrayList.clone (TODO)
19 / 21
20. Quick example
Pass through a MemoryStoreobject as the first argument (this is a convention).
MemoryStorememoryStore=newMemoryStore(maxMemory);
myMethod(memoryStore,arg0,arg1);
Annotate the class and method:
@SiO2Class
publicclassMyClass{
@SiO2Method
publicvoidmyMethod(MemoryStorem,Stringarg0,Objectarg1){
...
}
}
If more memory is allocated than you specify, a MemoryExceededException
exception is thrown.
20 / 21