Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
@antonarhipov
Java class
The hitchhiker’s guide to
reloading
whoami
Anton Arhipov
@antonarhipov
https://zeroturnaround.com/rebellabs/java-ee-productivity-report-2011/
10%
20%
30%
0.5 1 2 3 4 5 6 7 8 10+ minutes
https://zeroturnaround.com/rebellabs/java-ee-productivity-report-2011/
10%
20%
30%
0.5 1 2 3 4 5 6 7 8 10+
The only effecti...
https://zeroturnaround.com/rebellabs/java-ee-productivity-report-2011/
10%
20%
30%
0.5 1 2 3 4 5 6 7 8 10+
How about those...
HotSwap
Class loaders
Java agents & instrumentation
Challenges
hotswapEST. 2001
HOW ABOUT…
refactoring?
instanceKlass constantPoolOop
constants()
constantPoolCacheOop
cache()
pool_holder()
klassVTable
Embedded
klassITable
Embe...
What if…
hotswap++
Dynamic Code Evolution for Java
T. Würthinger, C. Wimmer, L. Stadler. 2010
Statements
Methods Fields Hierarchy
+ + +
x x x...
Classloaders
Class<?> uc1 = User.class;
Class<?> uc2 = new DynamicClassLoader().load("com.zt.User");
out.println(uc1.getName()); // com...
Class<?> uc1 = User.class;
Class<?> uc2 = new DynamicClassLoader().load("com.zt.User");
out.println(uc1.getName()); // com...
Class<?> uc1 = User.class;
Class<?> uc2 = new DynamicClassLoader().load("com.zt.User");
out.println(uc1.getName()); // com...
Class<?> uc1 = User.class;
Class<?> uc2 = new DynamicClassLoader().load("com.zt.User");
out.println(uc1.getName()); // com...
Class<?> uc1 = User.class;
Class<?> uc2 = new DynamicClassLoader().load("com.zt.User");
out.println(uc1.getName()); // com...
while(true) {
Class<?> uc = new DynamicClassLoader().load("com.zt.User");
ReflectUtil.invokeStatic("getHobby", uc);
}
publ...
while(true) {
Class<?> uc = new DynamicClassLoader().load("com.zt.User");
ReflectUtil.invokeStatic("getHobby", uc);
}
publ...
public static class Context {
public HobbyService hobbyService = new HobbyService();
public void init() {
hobbyService.use...
public static class Context {
public HobbyService hobbyService = new HobbyService();
public AnyService anyService = new An...
public static class Context {
public HobbyService hobbyService = new HobbyService();
public AnyService anyService = new An...
DynamicClassLoader
Context class
HobbyService class
User class
Context object
HobbyService object
User object
Reloadable
“...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</sco...
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
public class Agent {
public...
ClassFileTransformer
ClassA
ClassA
ClassA0
+field1
+field2
+field3
+method1
+method2
+method3
+method1
+method2
+method3
+...
public class C extends X {
int y = 5;
int method1(int x) {
return x + y;
}
void method2(String s) {
System.out.println(s);...
public class C extends X {
int y = 5;
int method1(int x) {
Object[] o = new Object[1];
o[0] = x;
return Runtime.redirect(t...
public class C extends X {
int y = 5;
int method1(int x) {
Object[] o = new Object[1];
o[0] = x;
return Runtime.redirect(t...
public class C extends X {
int y = 5;
int method1(int x) {
Object[] o = new Object[1];
o[0] = x;
return Runtime.redirect(t...
public abstract class C0 {
public static int method1(C c, int x) {
int tmp1 = Runtime.getFieldValue(c, "C", "y", "I");
ret...
public abstract class C0 {
public static int method1(C c, int x) {
int tmp1 = Runtime.getFieldValue(c, "C", "y", "I");
ret...
public class C extends X {
int y = 5;
int method1(int x) {
return x + y;
}
//...
}
public class C extends X {
int y = 5;
i...
public class C1 {
public static int z(C c) {
return 10;
}
public static int method1(C c, int x) {
int tmp1 = Runtime.getFi...
WHAT ABOUT…
configuration?
DEMO
HotSwap
Class loaders
Java agents & instrumentation
anton@zeroturnaround.com
@antonarhipov
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading
Upcoming SlideShare
Loading in …5
×

Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading

1,884 views

Published on

Java class reloading

Published in: Technology
  • Be the first to comment

Riga DevDays 2017 - The hitchhiker’s guide to Java class reloading

  1. 1. @antonarhipov Java class The hitchhiker’s guide to reloading
  2. 2. whoami Anton Arhipov @antonarhipov
  3. 3. https://zeroturnaround.com/rebellabs/java-ee-productivity-report-2011/ 10% 20% 30% 0.5 1 2 3 4 5 6 7 8 10+ minutes
  4. 4. https://zeroturnaround.com/rebellabs/java-ee-productivity-report-2011/ 10% 20% 30% 0.5 1 2 3 4 5 6 7 8 10+ The only effective developers?? minutes
  5. 5. https://zeroturnaround.com/rebellabs/java-ee-productivity-report-2011/ 10% 20% 30% 0.5 1 2 3 4 5 6 7 8 10+ How about those? minutes
  6. 6. HotSwap Class loaders Java agents & instrumentation Challenges
  7. 7. hotswapEST. 2001
  8. 8. HOW ABOUT… refactoring?
  9. 9. instanceKlass constantPoolOop constants() constantPoolCacheOop cache() pool_holder() klassVTable Embedded klassITable Embedded Embedded statics nmethod code() method() constants() objArrayOop methodOop methods() M. Dmitriev. Safe class and data evolution in large and long-lived Java (тм) applications. Technical report, Mountain View. 2001
  10. 10. What if… hotswap++
  11. 11. Dynamic Code Evolution for Java T. Würthinger, C. Wimmer, L. Stadler. 2010 Statements Methods Fields Hierarchy + + + x x x Binary-compatible Binary-incompatible
  12. 12. Classloaders
  13. 13. Class<?> uc1 = User.class; Class<?> uc2 = new DynamicClassLoader().load("com.zt.User"); out.println(uc1.getName()); // com.zt.User out.println(uc2.getName()); // com.zt.User out.println(uc1.getClassLoader()); // sun.misc.Launcher$AppClassLoader@18b4aac2 out.println(uc2.getClassLoader()); // com.zt.DynamicClassLoader@22b4bba7 User.age = 11; out.println((int) ReflectUtil.getStaticFieldValue("age", uc1)); // 11 out.println((int) ReflectUtil.getStaticFieldValue("age", uc2)); // 10 public class User { public static int age = 10; }
  14. 14. Class<?> uc1 = User.class; Class<?> uc2 = new DynamicClassLoader().load("com.zt.User"); out.println(uc1.getName()); // com.zt.User out.println(uc2.getName()); // com.zt.User out.println(uc1.getClassLoader()); // sun.misc.Launcher$AppClassLoader@18b4aac2 out.println(uc2.getClassLoader()); // com.zt.DynamicClassLoader@22b4bba7 User.age = 11; out.println((int) ReflectUtil.getStaticFieldValue("age", uc1)); // 11 out.println((int) ReflectUtil.getStaticFieldValue("age", uc2)); // 10 public class User { public static int age = 10; }
  15. 15. Class<?> uc1 = User.class; Class<?> uc2 = new DynamicClassLoader().load("com.zt.User"); out.println(uc1.getName()); // com.zt.User out.println(uc2.getName()); // com.zt.User out.println(uc1.getClassLoader()); // sun.misc.Launcher$AppClassLoader@18b4aac2 out.println(uc2.getClassLoader()); // com.zt.DynamicClassLoader@22b4bba7 User.age = 11; out.println((int) ReflectUtil.getStaticFieldValue("age", uc1)); // 11 out.println((int) ReflectUtil.getStaticFieldValue("age", uc2)); // 10 public class User { public static int age = 10; }
  16. 16. Class<?> uc1 = User.class; Class<?> uc2 = new DynamicClassLoader().load("com.zt.User"); out.println(uc1.getName()); // com.zt.User out.println(uc2.getName()); // com.zt.User out.println(uc1.getClassLoader()); // sun.misc.Launcher$AppClassLoader@18b4aac2 out.println(uc2.getClassLoader()); // com.zt.DynamicClassLoader@22b4bba7 User.age = 11; out.println((int) ReflectUtil.getStaticFieldValue("age", uc1)); // 11 out.println((int) ReflectUtil.getStaticFieldValue("age", uc2)); // 10 public class User { public static int age = 10; }
  17. 17. Class<?> uc1 = User.class; Class<?> uc2 = new DynamicClassLoader().load("com.zt.User"); out.println(uc1.getName()); // com.zt.User out.println(uc2.getName()); // com.zt.User out.println(uc1.getClassLoader()); // sun.misc.Launcher$AppClassLoader@18b4aac2 out.println(uc2.getClassLoader()); // com.zt.DynamicClassLoader@22b4bba7 User.age = 11; out.println((int) ReflectUtil.getStaticFieldValue("age", uc1)); // 11 out.println((int) ReflectUtil.getStaticFieldValue("age", uc2)); // 10 public class User { public static int age = 10; }
  18. 18. while(true) { Class<?> uc = new DynamicClassLoader().load("com.zt.User"); ReflectUtil.invokeStatic("getHobby", uc); } public class User { public Hobby getHobby() { return Basketball(); } }
  19. 19. while(true) { Class<?> uc = new DynamicClassLoader().load("com.zt.User"); ReflectUtil.invokeStatic("getHobby", uc); } public class User { public Hobby getHobby() { return Basketball(); } }
  20. 20. public static class Context { public HobbyService hobbyService = new HobbyService(); public void init() { hobbyService.user = new User(); anyService.initialize() } }
  21. 21. public static class Context { public HobbyService hobbyService = new HobbyService(); public AnyService anyService = new AnyService(); public void init() { hobbyService.user = new User(); anyService.initialize() } }
  22. 22. public static class Context { public HobbyService hobbyService = new HobbyService(); public AnyService anyService = new AnyService(); public void init() { hobbyService.user = new User(); anyService.initialize() } } while(true) { Class<?> c = new DynamicClassLoader().load("com.zt.Context"); Object context = c.newInstance(); ReflectUtil.invokeMethod("init", context); invokeService(context); }
  23. 23. DynamicClassLoader Context class HobbyService class User class Context object HobbyService object User object Reloadable “region” Live thread
  24. 24. <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> DEMO
  25. 25. import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.Instrumentation; public class Agent { public static void premain(String args, Instrumentation inst) throws Exception { inst.addTransformer(new ClassFileTransformer { // here be dragons }); } } $> java –javaagent:agent.jar application.Main META-INF/MANIFEST.MF Premain-Class: Agent
  26. 26. ClassFileTransformer ClassA ClassA ClassA0 +field1 +field2 +field3 +method1 +method2 +method3 +method1 +method2 +method3 +field1 +field2 +field3 +proxy_methods A thousand years of productivity: the JRebel story E. Kabanov, V. Vene, 2012
  27. 27. public class C extends X { int y = 5; int method1(int x) { return x + y; } void method2(String s) { System.out.println(s); } }
  28. 28. public class C extends X { int y = 5; int method1(int x) { Object[] o = new Object[1]; o[0] = x; return Runtime.redirect(this, o, "C", "method1", "(I)I"); } void method2(String s) { Object[] o = new Object[1]; o[0] = s; return Runtime.redirect( this, o, "C", "method2", "(Ljava/lang/String;)V"); } }
  29. 29. public class C extends X { int y = 5; int method1(int x) { Object[] o = new Object[1]; o[0] = x; return Runtime.redirect(this, o, "C", "method1", "(I)I"); } void method2(String s) { Object[] o = new Object[1]; o[0] = s; return Runtime.redirect( this, o, "C", "method2", "(Ljava/lang/String;)V"); } }
  30. 30. public class C extends X { int y = 5; int method1(int x) { Object[] o = new Object[1]; o[0] = x; return Runtime.redirect(this, o, "C", "method1", "(I)I"); } void method2(String s) { Object[] o = new Object[1]; o[0] = s; return Runtime.redirect( this, o, "C", "method2", "(Ljava/lang/String;)V"); } }
  31. 31. public abstract class C0 { public static int method1(C c, int x) { int tmp1 = Runtime.getFieldValue(c, "C", "y", "I"); return x + tmp1; } public static void method2(C c, String s) { PrintStream tmp1 = Runtime.getFieldValue( null, "java/lang/System", "out", "Ljava/io/PrintStream;"); Object[] o = new Object[1]; o[0] = s; Runtime.redirect( tmp1, o, "java/io/PrintStream;", "println", "(Ljava/lang/String;)V"); } } int method1(int x) { return x + y; }
  32. 32. public abstract class C0 { public static int method1(C c, int x) { int tmp1 = Runtime.getFieldValue(c, "C", "y", "I"); return x + tmp1; } public static void method2(C c, String s) { PrintStream tmp1 = Runtime.getFieldValue( null, "java/lang/System", "out", "Ljava/io/PrintStream;"); Object[] o = new Object[1]; o[0] = s; Runtime.redirect( tmp1, o, "java/io/PrintStream;", "println", "(Ljava/lang/String;)V"); } }
  33. 33. public class C extends X { int y = 5; int method1(int x) { return x + y; } //... } public class C extends X { int y = 5; int z() { return 10; } int method1(int x) { return x + y + z(); } //... }
  34. 34. public class C1 { public static int z(C c) { return 10; } public static int method1(C c, int x) { int tmp1 = Runtime.getFieldValue(c, "C", "y", "I"); int tmp2 = Runtime.redirect(c, null, "C", "z", "(V)I"); return x + tmp1 + tmp2; } //... }
  35. 35. WHAT ABOUT… configuration?
  36. 36. DEMO
  37. 37. HotSwap Class loaders Java agents & instrumentation
  38. 38. anton@zeroturnaround.com @antonarhipov

×