forked from fakereplace/fakereplace
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhacking.txt
More file actions
94 lines (73 loc) · 3.56 KB
/
Copy pathhacking.txt
File metadata and controls
94 lines (73 loc) · 3.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
Basic Architecture
-------------------------
Fakereplace registers a Java Agent that allows it to transform classes as
they are loaded and swap the bytecode of a method. The agent entry point
is org.fakereplace.Agent, and it registers an instance of
org.fakereplace.Transformer to transform loaded classes.
General Javaagent tips
------------------------
Any class loaded by the javaagent will not be transformed. Also, there is no
guarantee that when a class comes through the transformer that its superclass
has been loaded.
If you really need to force a class to be loaded but still have it transformed
you can use ThreadLoader which spawns another thread and loads the class. It is
not possible to wait for this thread to finish however, as class loading is a
syncronsised process, so a deadlock would result.
The Default Transformations
-------------------------
All classes that are loaded undergo some transformations, these are:
- Reflection calls are replaced with INVOKESTATIC calls on ReflectionDelegate
and friends
- Final methods have the final modifier removed (this is hidden by the
reflection API)
Classes that are replaceable have more changes made:
- An Object[] field is added
- Two methods are added with the signature Object __ADDED_METHOD(int, Object[])
a static version, and a non static version
- A constructor with the signature Constructor(int,Object[],ConstructorArgument)
is added to the class
- A static constructor is added if it is missing.
- As far as the objects type hierarchy is known virtual methods are added that call
the corresponding superclass method
for example the class
class SomeClass {}
would be modified to:
class SomeClass
{
public boolean equals(Object o)
{
return super.equals(o);
}
public int hashCode()
{
return super.hashCode();
}
}
when the type hierarchy becomes undefined (due to a superclass not being loaded yet)
then only the methods from java/lang/Object are added.
This is why all methods have the final modifier removed (not just replaceable classes).
If the superclass is loaded and it has declared say a final equals() method, then
the class would not load.
How classes are replaced
---------------------------
Every type of modification requires a different approach. The most important thing is
to change the class schema back to an exact match with the original schema, including
all annotations. In most cases there are two parts to it, the modification of the
replaced class, and registering a transformation with a Manipulator. This transformation
is then applied to all classes are they are loaded.
Replacing a static field is the simplest example of this:
The static field is removed from the class definition. A new class is created to hold the
static field. A transformation is registered with StaticFieldManipulator. No bytecode
rewriting occurs at this stage.
Now the classes are passed through the manipulators, including StaticFieldManipulator.
The StaticFieldManipulator replaces all references to the added field with references
to the new field on the other class. This happens to all classes from now on, so
if other classes are loaded that reference this field, it will be re-written to access
the field on the generated class.
Testing
------------------------------
You have to write tests for any changes (if only to save you from having to fire up an
app server and start modifying classes to test your changes).
Testing a change is quite simple, you create a before and an after class, and use
ClassReplacer to write the contents of one class over the other. Have a look at the
existing tests for more details.