diff --git a/lib/cglib-2.2.2.jar b/lib/cglib-2.2.2.jar
new file mode 100644
index 0000000..564b9f8
Binary files /dev/null and b/lib/cglib-2.2.2.jar differ
diff --git a/src/org/fenixsoft/jvm/chapter10/AutoBoxing.java b/src/org/fenixsoft/jvm/chapter10/AutoBoxing.java
new file mode 100644
index 0000000..21968f2
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter10/AutoBoxing.java
@@ -0,0 +1,22 @@
+package org.fenixsoft.jvm.chapter10;
+
+/**
+ * @author zzm
+ */
+public class AutoBoxing {
+ public static void main(String[] args) {
+ Integer a = 1;
+ Integer b = 2;
+ Integer c = 3;
+ Integer d = 3;
+ Integer e = 321;
+ Integer f = 321;
+ Long g = 3L;
+ System.out.println(c == d);
+ System.out.println(e == f);
+ System.out.println(c == (a + b));
+ System.out.println(c.equals(a + b));
+ System.out.println(g == (a + b));
+ System.out.println(g.equals(a + b));
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter10/NameChecker.java b/src/org/fenixsoft/jvm/chapter10/NameChecker.java
new file mode 100644
index 0000000..9b1cfdd
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter10/NameChecker.java
@@ -0,0 +1,180 @@
+package org.fenixsoft.jvm.chapter10;
+
+import javax.annotation.processing.Messager;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.*;
+import javax.lang.model.util.ElementScanner6;
+import java.util.EnumSet;
+
+import static javax.lang.model.element.ElementKind.*;
+import static javax.lang.model.element.ElementKind.INTERFACE;
+import static javax.lang.model.element.Modifier.*;
+import static javax.tools.Diagnostic.Kind.WARNING;
+
+/**
+ * 程序名称规范的编译器插件:
+ * 如果程序命名不合规范,将会输出一个编译器的WARNING信息
+ */
+public class NameChecker {
+ private final Messager messager;
+
+ NameCheckScanner nameCheckScanner = new NameCheckScanner();
+
+ NameChecker(ProcessingEnvironment processsingEnv) {
+ this.messager = processsingEnv.getMessager();
+ }
+
+ /**
+ * 对Java程序命名进行检查,根据《Java语言规范》第三版第6.8节的要求,Java程序命名应当符合下列格式:
+ *
+ *
+ * - 类或接口:符合驼式命名法,首字母大写。
+ *
- 方法:符合驼式命名法,首字母小写。
+ *
- 字段:
+ *
+ * - 类、实例变量: 符合驼式命名法,首字母小写。
+ *
- 常量: 要求全部大写。
+ *
+ *
+ */
+ public void checkNames(Element element) {
+ nameCheckScanner.scan(element);
+ }
+
+ /**
+ * 名称检查器实现类,继承了JDK 6中新提供的ElementScanner6
+ * 将会以Visitor模式访问抽象语法树中的元素
+ */
+ private class NameCheckScanner extends ElementScanner6 {
+
+ /**
+ * 此方法用于检查Java类
+ */
+ @Override
+ public Void visitType(TypeElement e, Void p) {
+ scan(e.getTypeParameters(), p);
+ checkCamelCase(e, true);
+ super.visitType(e, p);
+ return null;
+ }
+
+ /**
+ * 检查方法命名是否合法
+ */
+ @Override
+ public Void visitExecutable(ExecutableElement e, Void p) {
+ if (e.getKind() == METHOD) {
+ Name name = e.getSimpleName();
+ if (name.contentEquals(e.getEnclosingElement().getSimpleName()))
+ messager.printMessage(WARNING, "一个普通方法 “" + name + "”不应当与类名重复,避免与构造函数产生混淆", e);
+ checkCamelCase(e, false);
+ }
+ super.visitExecutable(e, p);
+ return null;
+ }
+
+ /**
+ * 检查变量命名是否合法
+ */
+ @Override
+ public Void visitVariable(VariableElement e, Void p) {
+ // 如果这个Variable是枚举或常量,则按大写命名检查,否则按照驼式命名法规则检查
+ if (e.getKind() == ENUM_CONSTANT || e.getConstantValue() != null || heuristicallyConstant(e))
+ checkAllCaps(e);
+ else
+ checkCamelCase(e, false);
+ return null;
+ }
+
+ /**
+ * 判断一个变量是否是常量
+ */
+ private boolean heuristicallyConstant(VariableElement e) {
+ if (e.getEnclosingElement().getKind() == INTERFACE)
+ return true;
+ else if (e.getKind() == FIELD && e.getModifiers().containsAll(EnumSet.of(PUBLIC, STATIC, FINAL)))
+ return true;
+ else {
+ return false;
+ }
+ }
+
+ /**
+ * 检查传入的Element是否符合驼式命名法,如果不符合,则输出警告信息
+ */
+ private void checkCamelCase(Element e, boolean initialCaps) {
+ String name = e.getSimpleName().toString();
+ boolean previousUpper = false;
+ boolean conventional = true;
+ int firstCodePoint = name.codePointAt(0);
+
+ if (Character.isUpperCase(firstCodePoint)) {
+ previousUpper = true;
+ if (!initialCaps) {
+ messager.printMessage(WARNING, "名称“" + name + "”应当以小写字母开头", e);
+ return;
+ }
+ } else if (Character.isLowerCase(firstCodePoint)) {
+ if (initialCaps) {
+ messager.printMessage(WARNING, "名称“" + name + "”应当以大写字母开头", e);
+ return;
+ }
+ } else
+ conventional = false;
+
+ if (conventional) {
+ int cp = firstCodePoint;
+ for (int i = Character.charCount(cp); i < name.length(); i += Character.charCount(cp)) {
+ cp = name.codePointAt(i);
+ if (Character.isUpperCase(cp)) {
+ if (previousUpper) {
+ conventional = false;
+ break;
+ }
+ previousUpper = true;
+ } else
+ previousUpper = false;
+ }
+ }
+
+ if (!conventional)
+ messager.printMessage(WARNING, "名称“" + name + "”应当符合驼式命名法(Camel Case Names)", e);
+ }
+
+ /**
+ * 大写命名检查,要求第一个字母必须是大写的英文字母,其余部分可以是下划线或大写字母
+ */
+ private void checkAllCaps(Element e) {
+ String name = e.getSimpleName().toString();
+
+ boolean conventional = true;
+ int firstCodePoint = name.codePointAt(0);
+
+ if (!Character.isUpperCase(firstCodePoint))
+ conventional = false;
+ else {
+ boolean previousUnderscore = false;
+ int cp = firstCodePoint;
+ for (int i = Character.charCount(cp); i < name.length(); i += Character.charCount(cp)) {
+ cp = name.codePointAt(i);
+ if (cp == (int) '_') {
+ if (previousUnderscore) {
+ conventional = false;
+ break;
+ }
+ previousUnderscore = true;
+ } else {
+ previousUnderscore = false;
+ if (!Character.isUpperCase(cp) && !Character.isDigit(cp)) {
+ conventional = false;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!conventional)
+ messager.printMessage(WARNING, "常量“" + name + "”应当全部以大写字母或下划线命名,并且以字母开头", e);
+ }
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter12/VolatileTest.java b/src/org/fenixsoft/jvm/chapter12/VolatileTest.java
new file mode 100644
index 0000000..b216471
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter12/VolatileTest.java
@@ -0,0 +1,38 @@
+package org.fenixsoft.jvm.chapter12;
+
+/**
+ * volatile变量自增运算测试
+ *
+ * @author zzm
+ */
+public class VolatileTest {
+
+ public static volatile int race = 0;
+
+ public static void increase() {
+ race++;
+ }
+
+ private static final int THREADS_COUNT = 20;
+
+ public static void main(String[] args) {
+ Thread[] threads = new Thread[THREADS_COUNT];
+ for (int i = 0; i < THREADS_COUNT; i++) {
+ threads[i] = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ for (int i = 0; i < 10000; i++) {
+ increase();
+ }
+ }
+ });
+ threads[i].start();
+ }
+
+ // 等待所有累加线程都结束
+ while (Thread.activeCount() > 1)
+ Thread.yield();
+
+ System.out.println(race);
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter13/AtomicTest.java b/src/org/fenixsoft/jvm/chapter13/AtomicTest.java
new file mode 100644
index 0000000..0b53f7a
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter13/AtomicTest.java
@@ -0,0 +1,40 @@
+package org.fenixsoft.jvm.chapter13;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Atomic变量自增运算测试
+ *
+ * @author zzm
+ */
+public class AtomicTest {
+
+ public static AtomicInteger race = new AtomicInteger(0);
+
+ public static void increase() {
+ race.incrementAndGet();
+ }
+
+ private static final int THREADS_COUNT = 20;
+
+ public static void main(String[] args) throws Exception {
+ Thread[] threads = new Thread[THREADS_COUNT];
+ for (int i = 0; i < THREADS_COUNT; i++) {
+ threads[i] = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ for (int i = 0; i < 10000; i++) {
+ increase();
+ }
+ }
+ });
+ threads[i].start();
+ }
+
+ while (Thread.activeCount() > 1)
+ Thread.yield();
+
+ System.out.println(race);
+ }
+}
+
diff --git a/src/org/fenixsoft/jvm/chapter13/VectorTestCase_1.java b/src/org/fenixsoft/jvm/chapter13/VectorTestCase_1.java
new file mode 100644
index 0000000..37b92a1
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter13/VectorTestCase_1.java
@@ -0,0 +1,44 @@
+package org.fenixsoft.jvm.chapter13;
+
+import java.util.Vector;
+
+/**
+ * @author zzm
+ */
+public class VectorTestCase_1 {
+
+ private static Vector vector = new Vector();
+
+ public static void main(String[] args) {
+ while (true) {
+ for (int i = 0; i < 10; i++) {
+ vector.add(i);
+ }
+
+ Thread removeThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ for (int i = 0; i < vector.size(); i++) {
+ vector.remove(i);
+ }
+ }
+ });
+
+ Thread printThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ for (int i = 0; i < vector.size(); i++) {
+ System.out.println((vector.get(i)));
+ }
+ }
+ });
+
+ removeThread.start();
+ printThread.start();
+
+ //不要同时产生过多的线程,否则会导致操作系统假死
+ while (Thread.activeCount() > 20) ;
+ }
+ }
+
+}
diff --git a/src/org/fenixsoft/jvm/chapter13/VectorTestCase_2.java b/src/org/fenixsoft/jvm/chapter13/VectorTestCase_2.java
new file mode 100644
index 0000000..cbbcc72
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter13/VectorTestCase_2.java
@@ -0,0 +1,48 @@
+package org.fenixsoft.jvm.chapter13;
+
+import java.util.Vector;
+
+/**
+ * @author zzm
+ */
+public class VectorTestCase_2 {
+
+ private static Vector vector = new Vector();
+
+ public static void main(String[] args) {
+ while (true) {
+ for (int i = 0; i < 10; i++) {
+ vector.add(i);
+ }
+
+ Thread removeThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ synchronized (vector) {
+ for (int i = 0; i < vector.size(); i++) {
+ vector.remove(i);
+ }
+ }
+ }
+ });
+
+ Thread printThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ synchronized (vector) {
+ for (int i = 0; i < vector.size(); i++) {
+ System.out.println((vector.get(i)));
+ }
+ }
+ }
+ });
+
+ removeThread.start();
+ printThread.start();
+
+ //不要同时产生过多的线程,否则会导致操作系统假死
+ while (Thread.activeCount() > 20) ;
+ }
+ }
+
+}
diff --git a/src/org/fenixsoft/jvm/chapter2/DirectMemoryOOM.java b/src/org/fenixsoft/jvm/chapter2/DirectMemoryOOM.java
new file mode 100644
index 0000000..b6698d5
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter2/DirectMemoryOOM.java
@@ -0,0 +1,24 @@
+package org.fenixsoft.jvm.chapter2;
+
+import sun.misc.Unsafe;
+
+import java.lang.reflect.Field;
+
+/**
+ * VM Args:-Xmx20M -XX:MaxDirectMemorySize=10M
+ *
+ * @author zzm
+ */
+public class DirectMemoryOOM {
+
+ private static final int _1MB = 1024 * 1024;
+
+ public static void main(String[] args) throws Exception {
+ Field unsafeField = Unsafe.class.getDeclaredFields()[0];
+ unsafeField.setAccessible(true);
+ Unsafe unsafe = (Unsafe) unsafeField.get(null);
+ while (true) {
+ unsafe.allocateMemory(_1MB);
+ }
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter2/HeapOOM.java b/src/org/fenixsoft/jvm/chapter2/HeapOOM.java
new file mode 100644
index 0000000..0a814b7
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter2/HeapOOM.java
@@ -0,0 +1,24 @@
+package org.fenixsoft.jvm.chapter2;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * VM Args:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
+ *
+ * @author zzm
+ */
+public class HeapOOM {
+
+ static class OOMObject {
+ }
+
+ public static void main(String[] args) {
+ List list = new ArrayList();
+
+ while (true) {
+ list.add(new OOMObject());
+ }
+ }
+}
+
diff --git a/src/org/fenixsoft/jvm/chapter2/JavaMethodAreaOOM.java b/src/org/fenixsoft/jvm/chapter2/JavaMethodAreaOOM.java
new file mode 100644
index 0000000..2cbea4e
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter2/JavaMethodAreaOOM.java
@@ -0,0 +1,32 @@
+package org.fenixsoft.jvm.chapter2;
+
+import net.sf.cglib.proxy.Enhancer;
+import net.sf.cglib.proxy.MethodInterceptor;
+import net.sf.cglib.proxy.MethodProxy;
+
+import java.lang.reflect.Method;
+
+/**
+ * VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M
+ *
+ * @author zzm
+ */
+public class JavaMethodAreaOOM {
+
+ public static void main(String[] args) {
+ while (true) {
+ Enhancer enhancer = new Enhancer();
+ enhancer.setSuperclass(OOMObject.class);
+ enhancer.setUseCache(false);
+ enhancer.setCallback(new MethodInterceptor() {
+ public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
+ return proxy.invokeSuper(obj, args);
+ }
+ });
+ enhancer.create();
+ }
+ }
+
+ static class OOMObject {
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter2/JavaVMStackOOM.java b/src/org/fenixsoft/jvm/chapter2/JavaVMStackOOM.java
new file mode 100644
index 0000000..9c680b6
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter2/JavaVMStackOOM.java
@@ -0,0 +1,31 @@
+package org.fenixsoft.jvm.chapter2;
+
+/**
+ * VM Args:-Xss2M (这时候不妨设大些,请在32位系统下运行)
+ *
+ * @author zzm
+ */
+public class JavaVMStackOOM {
+
+ private void dontStop() {
+ while (true) {
+ }
+ }
+
+ public void stackLeakByThread() {
+ while (true) {
+ Thread thread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ dontStop();
+ }
+ });
+ thread.start();
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+ JavaVMStackOOM oom = new JavaVMStackOOM();
+ oom.stackLeakByThread();
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter2/JavaVMStackSOF_1.java b/src/org/fenixsoft/jvm/chapter2/JavaVMStackSOF_1.java
new file mode 100644
index 0000000..b3843a1
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter2/JavaVMStackSOF_1.java
@@ -0,0 +1,26 @@
+package org.fenixsoft.jvm.chapter2;
+
+/**
+ * VM Args:-Xss128k
+ *
+ * @author zzm
+ */
+public class JavaVMStackSOF_1 {
+
+ private int stackLength = 1;
+
+ public void stackLeak() {
+ stackLength++;
+ stackLeak();
+ }
+
+ public static void main(String[] args) {
+ JavaVMStackSOF_1 oom = new JavaVMStackSOF_1();
+ try {
+ oom.stackLeak();
+ } catch (Throwable e) {
+ System.out.println("stack length:" + oom.stackLength);
+ throw e;
+ }
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter2/JavaVMStackSOF_2.java b/src/org/fenixsoft/jvm/chapter2/JavaVMStackSOF_2.java
new file mode 100644
index 0000000..86d5710
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter2/JavaVMStackSOF_2.java
@@ -0,0 +1,26 @@
+package org.fenixsoft.jvm.chapter2;
+
+/**
+ * VM Args:-Xss128k
+ *
+ * @author zzm
+ */
+public class JavaVMStackSOF_2 {
+
+ private int stackLength = 1;
+
+ public void stackLeak() {
+ stackLength++;
+ stackLeak();
+ }
+
+ public static void main(String[] args) {
+ JavaVMStackSOF_2 oom = new JavaVMStackSOF_2();
+ try {
+ oom.stackLeak();
+ } catch (Throwable e) {
+ System.out.println("stack length:" + oom.stackLength);
+ throw e;
+ }
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter2/JavaVMStackSOF_3.java b/src/org/fenixsoft/jvm/chapter2/JavaVMStackSOF_3.java
new file mode 100644
index 0000000..8e16652
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter2/JavaVMStackSOF_3.java
@@ -0,0 +1,66 @@
+package org.fenixsoft.jvm.chapter2;
+
+/**
+ * VM: JDK 1.0.2, Sun Classic VM
+ *
+ * @author zzm
+ */
+public class JavaVMStackSOF_3 {
+ private static int stackLength = 0;
+
+ public static void test() {
+ long unused1, unused2, unused3, unused4, unused5,
+ unused6, unused7, unused8, unused9, unused10,
+ unused11, unused12, unused13, unused14, unused15,
+ unused16, unused17, unused18, unused19, unused20,
+ unused21, unused22, unused23, unused24, unused25,
+ unused26, unused27, unused28, unused29, unused30,
+ unused31, unused32, unused33, unused34, unused35,
+ unused36, unused37, unused38, unused39, unused40,
+ unused41, unused42, unused43, unused44, unused45,
+ unused46, unused47, unused48, unused49, unused50,
+ unused51, unused52, unused53, unused54, unused55,
+ unused56, unused57, unused58, unused59, unused60,
+ unused61, unused62, unused63, unused64, unused65,
+ unused66, unused67, unused68, unused69, unused70,
+ unused71, unused72, unused73, unused74, unused75,
+ unused76, unused77, unused78, unused79, unused80,
+ unused81, unused82, unused83, unused84, unused85,
+ unused86, unused87, unused88, unused89, unused90,
+ unused91, unused92, unused93, unused94, unused95,
+ unused96, unused97, unused98, unused99, unused100;
+
+ stackLength ++;
+ test();
+
+ unused1 = unused2 = unused3 = unused4 = unused5 =
+ unused6 = unused7 = unused8 = unused9 = unused10 =
+ unused11 = unused12 = unused13 = unused14 = unused15 =
+ unused16 = unused17 = unused18 = unused19 = unused20 =
+ unused21 = unused22 = unused23 = unused24 = unused25 =
+ unused26 = unused27 = unused28 = unused29 = unused30 =
+ unused31 = unused32 = unused33 = unused34 = unused35 =
+ unused36 = unused37 = unused38 = unused39 = unused40 =
+ unused41 = unused42 = unused43 = unused44 = unused45 =
+ unused46 = unused47 = unused48 = unused49 = unused50 =
+ unused51 = unused52 = unused53 = unused54 = unused55 =
+ unused56 = unused57 = unused58 = unused59 = unused60 =
+ unused61 = unused62 = unused63 = unused64 = unused65 =
+ unused66 = unused67 = unused68 = unused69 = unused70 =
+ unused71 = unused72 = unused73 = unused74 = unused75 =
+ unused76 = unused77 = unused78 = unused79 = unused80 =
+ unused81 = unused82 = unused83 = unused84 = unused85 =
+ unused86 = unused87 = unused88 = unused89 = unused90 =
+ unused91 = unused92 = unused93 = unused94 = unused95 =
+ unused96 = unused97 = unused98 = unused99 = unused100 = 0;
+ }
+
+ public static void main(String[] args) {
+ try {
+ test();
+ }catch (Error e){
+ System.out.println("stack length:" + stackLength);
+ throw e;
+ }
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter2/RuntimeConstantPoolOOM_1.java b/src/org/fenixsoft/jvm/chapter2/RuntimeConstantPoolOOM_1.java
new file mode 100644
index 0000000..e41e14d
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter2/RuntimeConstantPoolOOM_1.java
@@ -0,0 +1,22 @@
+package org.fenixsoft.jvm.chapter2;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * VM Args:-XX:PermSize=6M -XX:MaxPermSize=6M
+ *
+ * @author zzm
+ */
+public class RuntimeConstantPoolOOM_1 {
+
+ public static void main(String[] args) {
+ // 使用Set保持着常量池引用,避免Full GC回收常量池行为
+ Set set = new HashSet();
+ // 在short范围内足以让6MB的PermSize产生OOM了
+ short i = 0;
+ while (true) {
+ set.add(String.valueOf(i++).intern());
+ }
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter2/RuntimeConstantPoolOOM_2.java b/src/org/fenixsoft/jvm/chapter2/RuntimeConstantPoolOOM_2.java
new file mode 100644
index 0000000..c96bb21
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter2/RuntimeConstantPoolOOM_2.java
@@ -0,0 +1,12 @@
+package org.fenixsoft.jvm.chapter2;
+
+public class RuntimeConstantPoolOOM_2 {
+
+ public static void main(String[] args) {
+ String str1 = new StringBuilder("计算机").append("软件").toString();
+ System.out.println(str1.intern() == str1);
+
+ String str2 = new StringBuilder("ja").append("va").toString();
+ System.out.println(str2.intern() == str2);
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter3/FinalizeEscapeGC.java b/src/org/fenixsoft/jvm/chapter3/FinalizeEscapeGC.java
new file mode 100644
index 0000000..946bd9c
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter3/FinalizeEscapeGC.java
@@ -0,0 +1,50 @@
+package org.fenixsoft.jvm.chapter3;
+
+/**
+ * 此代码演示了两点:
+ * 1.对象可以在被GC时自我拯救。
+ * 2.这种自救的机会只有一次,因为一个对象的finalize()方法最多只会被系统自动调用一次
+ *
+ * @author zzm
+ */
+public class FinalizeEscapeGC {
+
+ public static FinalizeEscapeGC SAVE_HOOK = null;
+
+ public void isAlive() {
+ System.out.println("yes, i am still alive :)");
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ super.finalize();
+ System.out.println("finalize method executed!");
+ FinalizeEscapeGC.SAVE_HOOK = this;
+ }
+
+ public static void main(String[] args) throws Throwable {
+ SAVE_HOOK = new FinalizeEscapeGC();
+
+ //对象第一次成功拯救自己
+ SAVE_HOOK = null;
+ System.gc();
+ // 因为Finalizer方法优先级很低,暂停0.5秒,以等待它
+ Thread.sleep(500);
+ if (SAVE_HOOK != null) {
+ SAVE_HOOK.isAlive();
+ } else {
+ System.out.println("no, i am dead :(");
+ }
+
+ // 下面这段代码与上面的完全相同,但是这次自救却失败了
+ SAVE_HOOK = null;
+ System.gc();
+ // 因为Finalizer方法优先级很低,暂停0.5秒,以等待它
+ Thread.sleep(500);
+ if (SAVE_HOOK != null) {
+ SAVE_HOOK.isAlive();
+ } else {
+ System.out.println("no, i am dead :(");
+ }
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter3/ReferenceCountingGC.java b/src/org/fenixsoft/jvm/chapter3/ReferenceCountingGC.java
new file mode 100644
index 0000000..173bb21
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter3/ReferenceCountingGC.java
@@ -0,0 +1,31 @@
+package org.fenixsoft.jvm.chapter3;
+
+/**
+ * testGC()方法执行后,objA和objB会不会被GC呢?
+ *
+ * @author zzm
+ */
+public class ReferenceCountingGC {
+
+ public Object instance = null;
+
+ private static final int _1MB = 1024 * 1024;
+
+ /**
+ * 这个成员属性的唯一意义就是占点内存,以便在能在GC日志中看清楚是否有回收过
+ */
+ private byte[] bigSize = new byte[2 * _1MB];
+
+ public static void testGC() {
+ ReferenceCountingGC objA = new ReferenceCountingGC();
+ ReferenceCountingGC objB = new ReferenceCountingGC();
+ objA.instance = objB;
+ objB.instance = objA;
+
+ objA = null;
+ objB = null;
+
+ // 假设在这行发生GC,objA和objB是否能被回收?
+ System.gc();
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter3/TestSerialGCAllocation.java b/src/org/fenixsoft/jvm/chapter3/TestSerialGCAllocation.java
new file mode 100644
index 0000000..0ecb8af
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter3/TestSerialGCAllocation.java
@@ -0,0 +1,78 @@
+package org.fenixsoft.jvm.chapter3;
+
+/**
+ * VM参数:+XX:UseSerialGC
+ * @author zzm
+ */
+public class TestSerialGCAllocation {
+
+ private static final int _1MB = 1024 * 1024;
+
+ /**
+ * VM参数:-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8
+ */
+ public static void testAllocation() {
+ byte[] allocation1, allocation2, allocation3, allocation4;
+ allocation1 = new byte[2 * _1MB];
+ allocation2 = new byte[2 * _1MB];
+ allocation3 = new byte[2 * _1MB];
+ allocation4 = new byte[4 * _1MB]; // 出现一次Minor GC
+ }
+
+ /**
+ * VM参数:-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8
+ * -XX:PretenureSizeThreshold=3145728
+ */
+ public static void testPretenureSizeThreshold() {
+ byte[] allocation;
+ allocation = new byte[4 * _1MB]; //直接分配在老年代中
+ }
+
+ /**
+ * VM参数:-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=1
+ * -XX:+PrintTenuringDistribution
+ */
+ public static void testTenuringThreshold() {
+ byte[] allocation1, allocation2, allocation3;
+ allocation1 = new byte[_1MB / 4]; // 什么时候进入老年代决定于XX:MaxTenuringThreshold设置
+ allocation2 = new byte[4 * _1MB];
+ allocation3 = new byte[4 * _1MB];
+ allocation3 = null;
+ allocation3 = new byte[4 * _1MB];
+ }
+
+ /**
+ * VM参数:-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=15
+ * -XX:+PrintTenuringDistribution
+ */
+ public static void testTenuringThreshold2() {
+ byte[] allocation1, allocation2, allocation3, allocation4;
+ allocation1 = new byte[_1MB / 4]; // allocation1+allocation2大于survivo空间一半
+ allocation2 = new byte[_1MB / 4];
+ allocation3 = new byte[4 * _1MB];
+ allocation4 = new byte[4 * _1MB];
+ allocation4 = null;
+ allocation4 = new byte[4 * _1MB];
+ }
+
+ /**
+ * VM参数:-Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:-HandlePromotionFailure
+ */
+ public static void testHandlePromotion() {
+ byte[] allocation1, allocation2, allocation3, allocation4, allocation5, allocation6, allocation7;
+ allocation1 = new byte[2 * _1MB];
+ allocation2 = new byte[2 * _1MB];
+ allocation3 = new byte[2 * _1MB];
+ allocation1 = null;
+ allocation4 = new byte[2 * _1MB];
+ allocation5 = new byte[2 * _1MB];
+ allocation6 = new byte[2 * _1MB];
+ allocation4 = null;
+ allocation5 = null;
+ allocation6 = null;
+ allocation7 = new byte[2 * _1MB];
+ }
+
+
+
+}
diff --git a/src/org/fenixsoft/jvm/chapter4/BTraceTest.java b/src/org/fenixsoft/jvm/chapter4/BTraceTest.java
new file mode 100644
index 0000000..c187bb5
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter4/BTraceTest.java
@@ -0,0 +1,48 @@
+package org.fenixsoft.jvm.chapter4;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+/**
+ * @author zzm
+ */
+public class BTraceTest {
+
+ public int add(int a, int b) {
+ return a + b;
+ }
+
+ public static void main(String[] args) throws IOException {
+ BTraceTest test = new BTraceTest();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
+ for (int i = 0; i < 10; i++) {
+ reader.readLine();
+ int a = (int) Math.round(Math.random() * 1000);
+ int b = (int) Math.round(Math.random() * 1000);
+ System.out.println(test.add(a, b));
+ }
+ }
+}
+
+/* BTrace Script Template
+import com.sun.btrace.annotations.*;
+ import static com.sun.btrace.BTraceUtils.*;
+
+@BTrace
+public class TracingScript {
+ @OnMethod(
+ clazz="org.fenixsoft.monitoring.BTraceTest",
+ method="add",
+ location=@Location(Kind.RETURN)
+ )
+
+ public static void func(@Self org.fenixsoft.monitoring.BTraceTest instance,int a,int b,@Return int result) {
+ println("调用堆栈:");
+ jstack();
+ println(strcat("方法参数A:",str(a)));
+ println(strcat("方法参数B:",str(b)));
+ println(strcat("方法结果:",str(result)));
+ }
+}
+*/
\ No newline at end of file
diff --git a/src/org/fenixsoft/jvm/chapter4/JConsoleTestCase.java b/src/org/fenixsoft/jvm/chapter4/JConsoleTestCase.java
new file mode 100644
index 0000000..49d4c57
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter4/JConsoleTestCase.java
@@ -0,0 +1,29 @@
+package org.fenixsoft.jvm.chapter4;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class JConsoleTestCase {
+
+ /**
+ * 内存占位符对象,一个OOMObject大约占64K
+ */
+ static class OOMObject {
+ public byte[] placeholder = new byte[64 * 1024];
+ }
+
+ public static void fillHeap(int num) throws InterruptedException {
+ List list = new ArrayList();
+ for (int i = 0; i < num; i++) {
+ // 稍作延时,令监视曲线的变化更加明显
+ Thread.sleep(50);
+ list.add(new OOMObject());
+ }
+ System.gc();
+ }
+
+ public static void main(String[] args) throws Exception {
+ fillHeap(1000);
+ }
+
+}
diff --git a/src/org/fenixsoft/jvm/chapter4/JHSDBTestCase.java b/src/org/fenixsoft/jvm/chapter4/JHSDBTestCase.java
new file mode 100644
index 0000000..c9ec249
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter4/JHSDBTestCase.java
@@ -0,0 +1,24 @@
+package org.fenixsoft.jvm.chapter4;
+
+/**
+ * staticObj、instanceObj、localObj存放在哪里?
+ */
+public class JHSDBTestCase {
+
+ static class Test {
+ static ObjectHolder staticObj = new ObjectHolder();
+ ObjectHolder instanceObj = new ObjectHolder();
+
+ void foo() {
+ ObjectHolder localObj = new ObjectHolder();
+ System.out.println("done"); // 这里设一个断点
+ }
+ }
+
+ private static class ObjectHolder {}
+
+ public static void main(String[] args) {
+ Test test = new JHSDBTestCase.Test();
+ test.foo();
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter4/ThreadDeadLockTestCase_1.java b/src/org/fenixsoft/jvm/chapter4/ThreadDeadLockTestCase_1.java
new file mode 100644
index 0000000..5162b2c
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter4/ThreadDeadLockTestCase_1.java
@@ -0,0 +1,52 @@
+package org.fenixsoft.jvm.chapter4;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+/**
+ * @author zzm
+ */
+public class ThreadDeadLockTestCase_1 {
+ /**
+ * 线程死循环演示
+ */
+ public static void createBusyThread() {
+ Thread thread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ while (true) // 第41行
+ ;
+ }
+ }, "testBusyThread");
+ thread.start();
+ }
+
+ /**
+ * 线程锁等待演示
+ */
+ public static void createLockThread(final Object lock) {
+ Thread thread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ synchronized (lock) {
+ try {
+ lock.wait();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }, "testLockThread");
+ thread.start();
+ }
+
+ public static void main(String[] args) throws Exception {
+ BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
+ br.readLine();
+ createBusyThread();
+ br.readLine();
+ Object obj = new Object();
+ createLockThread(obj);
+ }
+
+}
diff --git a/src/org/fenixsoft/jvm/chapter4/ThreadDeadLockTestCase_2.java b/src/org/fenixsoft/jvm/chapter4/ThreadDeadLockTestCase_2.java
new file mode 100644
index 0000000..efd5a11
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter4/ThreadDeadLockTestCase_2.java
@@ -0,0 +1,36 @@
+package org.fenixsoft.jvm.chapter4;
+
+/**
+ * @author zzm
+ */
+public class ThreadDeadLockTestCase_2 {
+
+ /**
+ * 线程死锁等待演示
+ */
+ static class SynAddRunnalbe implements Runnable {
+ int a, b;
+ public SynAddRunnalbe(int a, int b) {
+ this.a = a;
+ this.b = b;
+ }
+
+ @Override
+ public void run() {
+ synchronized (Integer.valueOf(a)) {
+ synchronized (Integer.valueOf(b)) {
+ System.out.println(a + b);
+ }
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ for (int i = 0; i < 100; i++) {
+ new Thread(new SynAddRunnalbe(1, 2)).start();
+ new Thread(new SynAddRunnalbe(2, 1)).start();
+ }
+ }
+
+
+}
diff --git a/src/org/fenixsoft/jvm/chapter5/EclipseStartTime_1.0.0.201011281102.jar b/src/org/fenixsoft/jvm/chapter5/EclipseStartTime_1.0.0.201011281102.jar
new file mode 100644
index 0000000..828021a
Binary files /dev/null and b/src/org/fenixsoft/jvm/chapter5/EclipseStartTime_1.0.0.201011281102.jar differ
diff --git a/src/org/fenixsoft/jvm/chapter7/ClassLoaderTest.java b/src/org/fenixsoft/jvm/chapter7/ClassLoaderTest.java
new file mode 100644
index 0000000..bbf5fa1
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter7/ClassLoaderTest.java
@@ -0,0 +1,42 @@
+package org.fenixsoft.jvm.chapter7;
+
+/**
+ * @author zzm
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * 类加载器与instanceof关键字演示
+ *
+ * @author zzm
+ */
+public class ClassLoaderTest {
+
+ public static void main(String[] args) throws Exception {
+
+ ClassLoader myLoader = new ClassLoader() {
+ @Override
+ public Class> loadClass(String name) throws ClassNotFoundException {
+ try {
+ String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
+ InputStream is = getClass().getResourceAsStream(fileName);
+ if (is == null) {
+ return super.loadClass(name);
+ }
+ byte[] b = new byte[is.available()];
+ is.read(b);
+ return defineClass(name, b, 0, b.length);
+ } catch (IOException e) {
+ throw new ClassNotFoundException(name);
+ }
+ }
+ };
+
+ Object obj = myLoader.loadClass("org.fenixsoft.jvm.chapter7.ClassLoaderTest").newInstance();
+
+ System.out.println(obj.getClass());
+ System.out.println(obj instanceof org.fenixsoft.jvm.chapter7.ClassLoaderTest);
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter7/ConstClass.java b/src/org/fenixsoft/jvm/chapter7/ConstClass.java
new file mode 100644
index 0000000..44ab6bb
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter7/ConstClass.java
@@ -0,0 +1,14 @@
+package org.fenixsoft.jvm.chapter7;
+
+/**
+ * 被动使用类字段演示三:
+ * 常量在编译阶段会存入调用类的常量池中,本质上没有直接引用到定义常量的类,因此不会触发定义常量的类的初始化。
+ **/
+public class ConstClass {
+
+ static {
+ System.out.println("ConstClass init!");
+ }
+
+ public static final String HELLOWORLD = "hello world";
+}
diff --git a/src/org/fenixsoft/jvm/chapter7/DeadLoopTestCase.java b/src/org/fenixsoft/jvm/chapter7/DeadLoopTestCase.java
new file mode 100644
index 0000000..07caa71
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter7/DeadLoopTestCase.java
@@ -0,0 +1,34 @@
+package org.fenixsoft.jvm.chapter7;
+
+/**
+ * @author zzm
+ */
+public class DeadLoopTestCase {
+
+ static class DeadLoopClass {
+ static {
+ // 如果不加上这个if语句,编译器将提示“Initializer does not complete normally”并拒绝编译
+ if (true) {
+ System.out.println(Thread.currentThread() + "init DeadLoopClass");
+ while (true) {
+ }
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ Runnable script = new Runnable() {
+ public void run() {
+ System.out.println(Thread.currentThread() + "start");
+ DeadLoopClass dlc = new DeadLoopClass();
+ System.out.println(Thread.currentThread() + " run over");
+ }
+ };
+
+ Thread thread1 = new Thread(script);
+ Thread thread2 = new Thread(script);
+ thread1.start();
+ thread2.start();
+ }
+
+}
diff --git a/src/org/fenixsoft/jvm/chapter7/FieldResolution.java b/src/org/fenixsoft/jvm/chapter7/FieldResolution.java
new file mode 100644
index 0000000..049b42b
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter7/FieldResolution.java
@@ -0,0 +1,31 @@
+package org.fenixsoft.jvm.chapter7;
+
+/**
+ * @author zzm
+ */
+public class FieldResolution {
+
+ interface Interface0 {
+ int A = 0;
+ }
+
+ interface Interface1 extends Interface0 {
+ int A = 1;
+ }
+
+ interface Interface2 {
+ int A = 2;
+ }
+
+ static class Parent implements Interface1 {
+ public static int A = 3;
+ }
+
+ static class Sub extends Parent implements Interface2 {
+ public static int A = 4;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(Sub.A);
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter7/NotInitialization_1.java b/src/org/fenixsoft/jvm/chapter7/NotInitialization_1.java
new file mode 100644
index 0000000..17addca
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter7/NotInitialization_1.java
@@ -0,0 +1,12 @@
+package org.fenixsoft.jvm.chapter7;
+
+/**
+ * 非主动使用类字段演示
+ **/
+public class NotInitialization_1 {
+
+ public static void main(String[] args) {
+ System.out.println(SubClass.value);
+ }
+
+}
diff --git a/src/org/fenixsoft/jvm/chapter7/NotInitialization_2.java b/src/org/fenixsoft/jvm/chapter7/NotInitialization_2.java
new file mode 100644
index 0000000..89903af
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter7/NotInitialization_2.java
@@ -0,0 +1,13 @@
+package org.fenixsoft.jvm.chapter7;
+
+/**
+ * 被动使用类字段演示二:
+ * 通过数组定义来引用类,不会触发此类的初始化
+ **/
+public class NotInitialization_2 {
+
+ public static void main(String[] args) {
+ SuperClass[] sca = new SuperClass[10];
+ }
+
+}
diff --git a/src/org/fenixsoft/jvm/chapter7/NotInitialization_3.java b/src/org/fenixsoft/jvm/chapter7/NotInitialization_3.java
new file mode 100644
index 0000000..885f301
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter7/NotInitialization_3.java
@@ -0,0 +1,11 @@
+package org.fenixsoft.jvm.chapter7;
+
+/**
+ * 非主动使用类字段演示
+ **/
+public class NotInitialization_3 {
+
+ public static void main(String[] args) {
+ System.out.println(ConstClass.HELLOWORLD);
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter7/SubClass.java b/src/org/fenixsoft/jvm/chapter7/SubClass.java
new file mode 100644
index 0000000..ba82030
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter7/SubClass.java
@@ -0,0 +1,11 @@
+package org.fenixsoft.jvm.chapter7;
+
+/**
+ * @author zzm
+ */
+public class SubClass extends SuperClass {
+
+ static {
+ System.out.println("SubClass init!");
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter7/SuperClass.java b/src/org/fenixsoft/jvm/chapter7/SuperClass.java
new file mode 100644
index 0000000..6184cc3
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter7/SuperClass.java
@@ -0,0 +1,14 @@
+package org.fenixsoft.jvm.chapter7;
+
+/**
+ * 被动使用类字段演示一:
+ * 通过子类引用父类的静态字段,不会导致子类初始化
+ **/
+public class SuperClass {
+
+ static {
+ System.out.println("SuperClass init!");
+ }
+
+ public static int value = 123;
+}
\ No newline at end of file
diff --git a/src/org/fenixsoft/jvm/chapter8/Dispatch.java b/src/org/fenixsoft/jvm/chapter8/Dispatch.java
new file mode 100644
index 0000000..242fd7e
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter8/Dispatch.java
@@ -0,0 +1,39 @@
+package org.fenixsoft.jvm.chapter8;
+
+/**
+ * 单分派、多分派演示
+ * @author zzm
+ */
+public class Dispatch {
+
+ static class QQ {}
+
+ static class _360 {}
+
+ public static class Father {
+ public void hardChoice(QQ arg) {
+ System.out.println("father choose qq");
+ }
+
+ public void hardChoice(_360 arg) {
+ System.out.println("father choose 360");
+ }
+ }
+
+ public static class Son extends Father {
+ public void hardChoice(QQ arg) {
+ System.out.println("son choose qq");
+ }
+
+ public void hardChoice(_360 arg) {
+ System.out.println("son choose 360");
+ }
+ }
+
+ public static void main(String[] args) {
+ Father father = new Father();
+ Father son = new Son();
+ father.hardChoice(new _360());
+ son.hardChoice(new QQ());
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter8/DynamicDispatch.java b/src/org/fenixsoft/jvm/chapter8/DynamicDispatch.java
new file mode 100644
index 0000000..d1ee86b
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter8/DynamicDispatch.java
@@ -0,0 +1,35 @@
+package org.fenixsoft.jvm.chapter8;
+
+/**
+ * 方法动态分派演示
+ * @author zzm
+ */
+public class DynamicDispatch {
+
+ static abstract class Human {
+ protected abstract void sayHello();
+ }
+
+ static class Man extends Human {
+ @Override
+ protected void sayHello() {
+ System.out.println("man say hello");
+ }
+ }
+
+ static class Woman extends Human {
+ @Override
+ protected void sayHello() {
+ System.out.println("woman say hello");
+ }
+ }
+
+ public static void main(String[] args) {
+ Human man = new Man();
+ Human woman = new Woman();
+ man.sayHello();
+ woman.sayHello();
+ man = new Woman();
+ man.sayHello();
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter8/FieldHasNoPolymorphic.java b/src/org/fenixsoft/jvm/chapter8/FieldHasNoPolymorphic.java
new file mode 100644
index 0000000..b3509aa
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter8/FieldHasNoPolymorphic.java
@@ -0,0 +1,39 @@
+package org.fenixsoft.jvm.chapter8;
+
+/**
+ * 字段不参与多态
+ * @author zzm
+ */
+public class FieldHasNoPolymorphic {
+
+ static class Father {
+ public int money = 1;
+
+ public Father() {
+ money = 2;
+ showMeTheMoney();
+ }
+
+ public void showMeTheMoney() {
+ System.out.println("I am Father, i have $" + money);
+ }
+ }
+
+ static class Son extends Father {
+ public int money = 3;
+
+ public Son() {
+ money = 4;
+ showMeTheMoney();
+ }
+
+ public void showMeTheMoney() {
+ System.out.println("I am Son, i have $" + money);
+ }
+ }
+
+ public static void main(String[] args) {
+ Father gay = new Son();
+ System.out.println("This gay has $" + gay.money);
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter8/GrandFatherTestCase_1.java b/src/org/fenixsoft/jvm/chapter8/GrandFatherTestCase_1.java
new file mode 100644
index 0000000..ee9673d
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter8/GrandFatherTestCase_1.java
@@ -0,0 +1,41 @@
+package org.fenixsoft.jvm.chapter8;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodType;
+
+import static java.lang.invoke.MethodHandles.lookup;
+
+/**
+ * @author zzm
+ */
+public class GrandFatherTestCase_1 {
+
+ class GrandFather {
+ void thinking() {
+ System.out.println("i am grandfather");
+ }
+ }
+
+ class Father extends GrandFather {
+ void thinking() {
+ System.out.println("i am father");
+ }
+ }
+
+ class Son extends Father {
+ void thinking() {
+ try {
+ MethodType mt = MethodType.methodType(void.class);
+ MethodHandle mh = lookup().findSpecial(GrandFather.class,
+ "thinking", mt, getClass());
+ mh.invoke(this);
+ } catch (Throwable e) {
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ (new GrandFatherTestCase_1().new Son()).thinking();
+ }
+
+}
diff --git a/src/org/fenixsoft/jvm/chapter8/GrandFatherTestCase_2.java b/src/org/fenixsoft/jvm/chapter8/GrandFatherTestCase_2.java
new file mode 100644
index 0000000..0178cf7
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter8/GrandFatherTestCase_2.java
@@ -0,0 +1,43 @@
+package org.fenixsoft.jvm.chapter8;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Field;
+
+/**
+ * @author zzm
+ */
+public class GrandFatherTestCase_2 {
+
+ class GrandFather {
+ void thinking() {
+ System.out.println("i am grandfather");
+ }
+ }
+
+ class Father extends GrandFatherTestCase_2.GrandFather {
+ void thinking() {
+ System.out.println("i am father");
+ }
+ }
+
+ class Son extends GrandFatherTestCase_2.Father {
+ void thinking() {
+ try {
+ MethodType mt = MethodType.methodType(void.class);
+ Field lookupImpl = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
+ lookupImpl.setAccessible(true);
+ MethodHandle mh = ((MethodHandles.Lookup) lookupImpl.get(null)).findSpecial(GrandFather.class,"thinking", mt, GrandFather.class);
+ mh.invoke(this);
+ } catch (Throwable e) {
+ }
+ }
+
+ }
+
+ public static void main(String[] args) {
+ (new GrandFatherTestCase_2().new Son()).thinking();
+ }
+
+}
diff --git a/src/org/fenixsoft/jvm/chapter8/InvokeDynamicTest.java b/src/org/fenixsoft/jvm/chapter8/InvokeDynamicTest.java
new file mode 100644
index 0000000..c018633
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter8/InvokeDynamicTest.java
@@ -0,0 +1,37 @@
+package org.fenixsoft.jvm.chapter8;
+
+import java.lang.invoke.*;
+
+import static java.lang.invoke.MethodHandles.lookup;
+
+public class InvokeDynamicTest {
+
+ public static void main(String[] args) throws Throwable {
+ INDY_BootstrapMethod().invokeExact("icyfenix");
+ }
+
+ public static void testMethod(String s) {
+ System.out.println("hello String:" + s);
+ }
+
+ public static CallSite BootstrapMethod(MethodHandles.Lookup lookup, String name, MethodType mt) throws Throwable {
+ return new ConstantCallSite(lookup.findStatic(InvokeDynamicTest.class, name, mt));
+ }
+
+ private static MethodType MT_BootstrapMethod() {
+ return MethodType
+ .fromMethodDescriptorString(
+ "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;",
+ null);
+ }
+
+ private static MethodHandle MH_BootstrapMethod() throws Throwable {
+ return lookup().findStatic(InvokeDynamicTest.class, "BootstrapMethod", MT_BootstrapMethod());
+ }
+
+ private static MethodHandle INDY_BootstrapMethod() throws Throwable {
+ CallSite cs = (CallSite) MH_BootstrapMethod().invokeWithArguments(lookup(), "testMethod",
+ MethodType.fromMethodDescriptorString("(Ljava/lang/String;)V", null));
+ return cs.dynamicInvoker();
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter8/MethodHandleTest.java b/src/org/fenixsoft/jvm/chapter8/MethodHandleTest.java
new file mode 100644
index 0000000..2e5656f
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter8/MethodHandleTest.java
@@ -0,0 +1,33 @@
+package org.fenixsoft.jvm.chapter8;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodType;
+
+import static java.lang.invoke.MethodHandles.lookup;
+
+/**
+ * JSR 292 MethodHandle基础用法演示
+ * @author zzm
+ */
+public class MethodHandleTest {
+
+ static class ClassA {
+ public void println(String s) {
+ System.out.println(s);
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+ Object obj = System.currentTimeMillis() % 2 == 0 ? System.out : new ClassA();
+ // 无论obj最终是哪个实现类,下面这句都能正确调用到println方法。
+ getPrintlnMH(obj).invokeExact("icyfenix");
+ }
+
+ private static MethodHandle getPrintlnMH(Object reveiver) throws Throwable {
+ // MethodType:代表“方法类型”,包含了方法的返回值(methodType()的第一个参数)和具体参数(methodType()第二个及以后的参数)。
+ MethodType mt = MethodType.methodType(void.class, String.class);
+ // lookup()方法来自于MethodHandles.lookup,这句的作用是在指定类中查找符合给定的方法名称、方法类型,并且符合调用权限的方法句柄。
+ // 因为这里调用的是一个虚方法,按照Java语言的规则,方法第一个参数是隐式的,代表该方法的接收者,也即是this指向的对象,这个参数以前是放在参数列表中进行传递,现在提供了bindTo()方法来完成这件事情。
+ return lookup().findVirtual(reveiver.getClass(), "println", mt).bindTo(reveiver);
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter8/Overload.java b/src/org/fenixsoft/jvm/chapter8/Overload.java
new file mode 100644
index 0000000..63b4328
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter8/Overload.java
@@ -0,0 +1,41 @@
+package org.fenixsoft.jvm.chapter8;
+
+import java.io.Serializable;
+
+/**
+ * @author zzm
+ */
+public class Overload {
+
+ public static void sayHello(Object arg) {
+ System.out.println("hello Object");
+ }
+
+ public static void sayHello(int arg) {
+ System.out.println("hello int");
+ }
+
+ public static void sayHello(long arg) {
+ System.out.println("hello long");
+ }
+
+ public static void sayHello(Character arg) {
+ System.out.println("hello Character");
+ }
+
+ public static void sayHello(char arg) {
+ System.out.println("hello char");
+ }
+
+ public static void sayHello(char... arg) {
+ System.out.println("hello char ...");
+ }
+
+ public static void sayHello(Serializable arg) {
+ System.out.println("hello Serializable");
+ }
+
+ public static void main(String[] args) {
+ sayHello('a');
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter8/StaticDispatch.java b/src/org/fenixsoft/jvm/chapter8/StaticDispatch.java
new file mode 100644
index 0000000..acb1d49
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter8/StaticDispatch.java
@@ -0,0 +1,37 @@
+package org.fenixsoft.jvm.chapter8;
+
+/**
+ * 方法静态分派演示
+ * @author zzm
+ */
+public class StaticDispatch {
+
+ static abstract class Human {
+ }
+
+ static class Man extends Human {
+ }
+
+ static class Woman extends Human {
+ }
+
+ public void sayHello(Human guy) {
+ System.out.println("hello,guy!");
+ }
+
+ public void sayHello(Man guy) {
+ System.out.println("hello,gentleman!");
+ }
+
+ public void sayHello(Woman guy) {
+ System.out.println("hello,lady!");
+ }
+
+ public static void main(String[] args) {
+ Human man = new Man();
+ Human woman = new Woman();
+ StaticDispatch sr = new StaticDispatch();
+ sr.sayHello(man);
+ sr.sayHello(woman);
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter8/StaticResolution.java b/src/org/fenixsoft/jvm/chapter8/StaticResolution.java
new file mode 100644
index 0000000..74b63a9
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter8/StaticResolution.java
@@ -0,0 +1,19 @@
+package org.fenixsoft.jvm.chapter8;
+
+/**
+ * 方法静态解析演示
+ *
+ * @author zzm
+ */
+public class StaticResolution {
+
+ public static void sayHello() {
+ System.out.println("hello world");
+ }
+
+ public static void main(String[] args) {
+ StaticResolution.sayHello();
+ }
+
+}
+
diff --git a/src/org/fenixsoft/jvm/chapter9/ByteUtils.java b/src/org/fenixsoft/jvm/chapter9/ByteUtils.java
new file mode 100644
index 0000000..0aa80ad
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter9/ByteUtils.java
@@ -0,0 +1,44 @@
+package org.fenixsoft.jvm.chapter9;
+
+/**
+ * Bytes数组处理工具
+ *
+ * @author
+ */
+public class ByteUtils {
+
+ public static int bytes2Int(byte[] b, int start, int len) {
+ int sum = 0;
+ int end = start + len;
+ for (int i = start; i < end; i++) {
+ int n = ((int) b[i]) & 0xff;
+ n <<= (--len) * 8;
+ sum = n + sum;
+ }
+ return sum;
+ }
+
+ public static byte[] int2Bytes(int value, int len) {
+ byte[] b = new byte[len];
+ for (int i = 0; i < len; i++) {
+ b[len - i - 1] = (byte) ((value >> 8 * i) & 0xff);
+ }
+ return b;
+ }
+
+ public static String bytes2String(byte[] b, int start, int len) {
+ return new String(b, start, len);
+ }
+
+ public static byte[] string2Bytes(String str) {
+ return str.getBytes();
+ }
+
+ public static byte[] bytesReplace(byte[] originalBytes, int offset, int len, byte[] replaceBytes) {
+ byte[] newBytes = new byte[originalBytes.length + (replaceBytes.length - len)];
+ System.arraycopy(originalBytes, 0, newBytes, 0, offset);
+ System.arraycopy(replaceBytes, 0, newBytes, offset, replaceBytes.length);
+ System.arraycopy(originalBytes, offset + len, newBytes, offset + replaceBytes.length, originalBytes.length - offset - len);
+ return newBytes;
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter9/ClassModifier.java b/src/org/fenixsoft/jvm/chapter9/ClassModifier.java
new file mode 100644
index 0000000..95e951e
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter9/ClassModifier.java
@@ -0,0 +1,74 @@
+package org.fenixsoft.jvm.chapter9;
+
+/**
+ * 修改Class文件,暂时只提供修改常量池常量的功能
+ *
+ * @author zzm
+ */
+public class ClassModifier {
+
+ /**
+ * Class文件中常量池的起始偏移
+ */
+ private static final int CONSTANT_POOL_COUNT_INDEX = 8;
+
+ /**
+ * CONSTANT_Utf8_info常量的tag标志
+ */
+ private static final int CONSTANT_Utf8_info = 1;
+
+ /**
+ * 常量池中11种常量所占的长度,CONSTANT_Utf8_info型常量除外,因为它不是定长的
+ */
+ private static final int[] CONSTANT_ITEM_LENGTH = {-1, -1, -1, 5, 5, 9, 9, 3, 3, 5, 5, 5, 5};
+
+ private static final int u1 = 1;
+ private static final int u2 = 2;
+
+ private byte[] classByte;
+
+ public ClassModifier(byte[] classByte) {
+ this.classByte = classByte;
+ }
+
+ /**
+ * 修改常量池中CONSTANT_Utf8_info常量的内容
+ *
+ * @param oldStr 修改前的字符串
+ * @param newStr 修改后的字符串
+ * @return 修改结果
+ */
+ public byte[] modifyUTF8Constant(String oldStr, String newStr) {
+ int cpc = getConstantPoolCount();
+ int offset = CONSTANT_POOL_COUNT_INDEX + u2;
+ for (int i = 0; i < cpc; i++) {
+ int tag = ByteUtils.bytes2Int(classByte, offset, u1);
+ if (tag == CONSTANT_Utf8_info) {
+ int len = ByteUtils.bytes2Int(classByte, offset + u1, u2);
+ offset += (u1 + u2);
+ String str = ByteUtils.bytes2String(classByte, offset, len);
+ if (str.equalsIgnoreCase(oldStr)) {
+ byte[] strBytes = ByteUtils.string2Bytes(newStr);
+ byte[] strLen = ByteUtils.int2Bytes(newStr.length(), u2);
+ classByte = ByteUtils.bytesReplace(classByte, offset - u2, u2, strLen);
+ classByte = ByteUtils.bytesReplace(classByte, offset, len, strBytes);
+ return classByte;
+ } else {
+ offset += len;
+ }
+ } else {
+ offset += CONSTANT_ITEM_LENGTH[tag];
+ }
+ }
+ return classByte;
+ }
+
+ /**
+ * 获取常量池中常量的数量
+ *
+ * @return 常量池数量
+ */
+ public int getConstantPoolCount() {
+ return ByteUtils.bytes2Int(classByte, CONSTANT_POOL_COUNT_INDEX, u2);
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter9/DynamicProxyTest.java b/src/org/fenixsoft/jvm/chapter9/DynamicProxyTest.java
new file mode 100644
index 0000000..7d0573b
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter9/DynamicProxyTest.java
@@ -0,0 +1,43 @@
+package org.fenixsoft.jvm.chapter9;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+/**
+ * @author zzm
+ */
+public class DynamicProxyTest {
+
+ interface IHello {
+ void sayHello();
+ }
+
+ static class Hello implements IHello {
+ @Override
+ public void sayHello() {
+ System.out.println("hello world");
+ }
+ }
+
+ static class DynamicProxy implements InvocationHandler {
+
+ Object originalObj;
+
+ Object bind(Object originalObj) {
+ this.originalObj = originalObj;
+ return Proxy.newProxyInstance(originalObj.getClass().getClassLoader(), originalObj.getClass().getInterfaces(), this);
+ }
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ System.out.println("welcome");
+ return method.invoke(originalObj, args);
+ }
+ }
+
+ public static void main(String[] args) {
+ IHello hello = (IHello) new DynamicProxy().bind(new Hello());
+ hello.sayHello();
+ }
+}
diff --git a/src/org/fenixsoft/jvm/chapter9/HackSystem.java b/src/org/fenixsoft/jvm/chapter9/HackSystem.java
new file mode 100644
index 0000000..1588dcf
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter9/HackSystem.java
@@ -0,0 +1,54 @@
+package org.fenixsoft.jvm.chapter9;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.PrintStream;
+
+/**
+ * 为Javaclass劫持java.lang.System提供支持
+ * 除了out和err外,其余的都直接转发给System处理
+ *
+ * @author zzm
+ */
+public class HackSystem {
+
+ public final static InputStream in = System.in;
+
+ private static ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+
+ public final static PrintStream out = new PrintStream(buffer);
+
+ public final static PrintStream err = out;
+
+ public static String getBufferString() {
+ return buffer.toString();
+ }
+
+ public static void clearBuffer() {
+ buffer.reset();
+ }
+
+ public static void setSecurityManager(final SecurityManager s) {
+ System.setSecurityManager(s);
+ }
+
+ public static SecurityManager getSecurityManager() {
+ return System.getSecurityManager();
+ }
+
+ public static long currentTimeMillis() {
+ return System.currentTimeMillis();
+ }
+
+ public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) {
+ System.arraycopy(src, srcPos, dest, destPos, length);
+ }
+
+ public static int identityHashCode(Object x) {
+ return System.identityHashCode(x);
+ }
+
+ // 下面所有的方法都与java.lang.System的名称一样
+ // 实现都是字节转调System的对应方法
+ // 因版面原因,省略了其他方法
+}
diff --git a/src/org/fenixsoft/jvm/chapter9/HotSwapClassLoader.java b/src/org/fenixsoft/jvm/chapter9/HotSwapClassLoader.java
new file mode 100644
index 0000000..0c8dd6b
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter9/HotSwapClassLoader.java
@@ -0,0 +1,20 @@
+package org.fenixsoft.jvm.chapter9;
+
+/**
+ * 为了多次载入执行类而加入的加载器
+ * 把defineClass方法开放出来,只有外部显式调用的时候才会使用到loadByte方法
+ * 由虚拟机调用时,仍然按照原有的双亲委派规则使用loadClass方法进行类加载
+ *
+ * @author zzm
+ */
+public class HotSwapClassLoader extends ClassLoader {
+
+ public HotSwapClassLoader() {
+ super(HotSwapClassLoader.class.getClassLoader());
+ }
+
+ public Class loadByte(byte[] classByte) {
+ return defineClass(null, classByte, 0, classByte.length);
+ }
+
+}
diff --git a/src/org/fenixsoft/jvm/chapter9/JavaclassExecuter.java b/src/org/fenixsoft/jvm/chapter9/JavaclassExecuter.java
new file mode 100644
index 0000000..e7aef13
--- /dev/null
+++ b/src/org/fenixsoft/jvm/chapter9/JavaclassExecuter.java
@@ -0,0 +1,34 @@
+package org.fenixsoft.jvm.chapter9;
+
+import java.lang.reflect.Method;
+
+/**
+ * Javaclass执行工具
+ *
+ * @author zzm
+ */
+public class JavaclassExecuter {
+
+ /**
+ * 执行外部传过来的代表一个Java类的Byte数组
+ * 将输入类的byte数组中代表java.lang.System的CONSTANT_Utf8_info常量修改为劫持后的HackSystem类
+ * 执行方法为该类的static main(String[] args)方法,输出结果为该类向System.out/err输出的信息
+ *
+ * @param classByte 代表一个Java类的Byte数组
+ * @return 执行结果
+ */
+ public static String execute(byte[] classByte) {
+ HackSystem.clearBuffer();
+ ClassModifier cm = new ClassModifier(classByte);
+ byte[] modiBytes = cm.modifyUTF8Constant("java/lang/System", "org/fenixsoft/classloading/execute/HackSystem");
+ HotSwapClassLoader loader = new HotSwapClassLoader();
+ Class clazz = loader.loadByte(modiBytes);
+ try {
+ Method method = clazz.getMethod("main", new Class[]{String[].class});
+ method.invoke(null, new String[]{null});
+ } catch (Throwable e) {
+ e.printStackTrace(HackSystem.out);
+ }
+ return HackSystem.getBufferString();
+ }
+}