mirror of
https://github.com/fenixsoft/jvm_book.git
synced 2025-01-14 22:30:37 +08:00
init
init
This commit is contained in:
parent
3f6f07166a
commit
767555f87f
BIN
lib/cglib-2.2.2.jar
Normal file
BIN
lib/cglib-2.2.2.jar
Normal file
Binary file not shown.
22
src/org/fenixsoft/jvm/chapter10/AutoBoxing.java
Normal file
22
src/org/fenixsoft/jvm/chapter10/AutoBoxing.java
Normal file
@ -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));
|
||||
}
|
||||
}
|
180
src/org/fenixsoft/jvm/chapter10/NameChecker.java
Normal file
180
src/org/fenixsoft/jvm/chapter10/NameChecker.java
Normal file
@ -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;
|
||||
|
||||
/**
|
||||
* 程序名称规范的编译器插件:<br>
|
||||
* 如果程序命名不合规范,将会输出一个编译器的WARNING信息
|
||||
*/
|
||||
public class NameChecker {
|
||||
private final Messager messager;
|
||||
|
||||
NameCheckScanner nameCheckScanner = new NameCheckScanner();
|
||||
|
||||
NameChecker(ProcessingEnvironment processsingEnv) {
|
||||
this.messager = processsingEnv.getMessager();
|
||||
}
|
||||
|
||||
/**
|
||||
* 对Java程序命名进行检查,根据《Java语言规范》第三版第6.8节的要求,Java程序命名应当符合下列格式:
|
||||
*
|
||||
* <ul>
|
||||
* <li>类或接口:符合驼式命名法,首字母大写。
|
||||
* <li>方法:符合驼式命名法,首字母小写。
|
||||
* <li>字段:
|
||||
* <ul>
|
||||
* <li>类、实例变量: 符合驼式命名法,首字母小写。
|
||||
* <li>常量: 要求全部大写。
|
||||
* </ul>
|
||||
* </ul>
|
||||
*/
|
||||
public void checkNames(Element element) {
|
||||
nameCheckScanner.scan(element);
|
||||
}
|
||||
|
||||
/**
|
||||
* 名称检查器实现类,继承了JDK 6中新提供的ElementScanner6<br>
|
||||
* 将会以Visitor模式访问抽象语法树中的元素
|
||||
*/
|
||||
private class NameCheckScanner extends ElementScanner6<Void, Void> {
|
||||
|
||||
/**
|
||||
* 此方法用于检查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);
|
||||
}
|
||||
}
|
||||
}
|
38
src/org/fenixsoft/jvm/chapter12/VolatileTest.java
Normal file
38
src/org/fenixsoft/jvm/chapter12/VolatileTest.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
40
src/org/fenixsoft/jvm/chapter13/AtomicTest.java
Normal file
40
src/org/fenixsoft/jvm/chapter13/AtomicTest.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
|
44
src/org/fenixsoft/jvm/chapter13/VectorTestCase_1.java
Normal file
44
src/org/fenixsoft/jvm/chapter13/VectorTestCase_1.java
Normal file
@ -0,0 +1,44 @@
|
||||
package org.fenixsoft.jvm.chapter13;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* @author zzm
|
||||
*/
|
||||
public class VectorTestCase_1 {
|
||||
|
||||
private static Vector<Integer> vector = new Vector<Integer>();
|
||||
|
||||
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) ;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
48
src/org/fenixsoft/jvm/chapter13/VectorTestCase_2.java
Normal file
48
src/org/fenixsoft/jvm/chapter13/VectorTestCase_2.java
Normal file
@ -0,0 +1,48 @@
|
||||
package org.fenixsoft.jvm.chapter13;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* @author zzm
|
||||
*/
|
||||
public class VectorTestCase_2 {
|
||||
|
||||
private static Vector<Integer> vector = new Vector<Integer>();
|
||||
|
||||
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) ;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
24
src/org/fenixsoft/jvm/chapter2/DirectMemoryOOM.java
Normal file
24
src/org/fenixsoft/jvm/chapter2/DirectMemoryOOM.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
24
src/org/fenixsoft/jvm/chapter2/HeapOOM.java
Normal file
24
src/org/fenixsoft/jvm/chapter2/HeapOOM.java
Normal file
@ -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<OOMObject> list = new ArrayList<OOMObject>();
|
||||
|
||||
while (true) {
|
||||
list.add(new OOMObject());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
32
src/org/fenixsoft/jvm/chapter2/JavaMethodAreaOOM.java
Normal file
32
src/org/fenixsoft/jvm/chapter2/JavaMethodAreaOOM.java
Normal file
@ -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 {
|
||||
}
|
||||
}
|
31
src/org/fenixsoft/jvm/chapter2/JavaVMStackOOM.java
Normal file
31
src/org/fenixsoft/jvm/chapter2/JavaVMStackOOM.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
26
src/org/fenixsoft/jvm/chapter2/JavaVMStackSOF_1.java
Normal file
26
src/org/fenixsoft/jvm/chapter2/JavaVMStackSOF_1.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
26
src/org/fenixsoft/jvm/chapter2/JavaVMStackSOF_2.java
Normal file
26
src/org/fenixsoft/jvm/chapter2/JavaVMStackSOF_2.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
66
src/org/fenixsoft/jvm/chapter2/JavaVMStackSOF_3.java
Normal file
66
src/org/fenixsoft/jvm/chapter2/JavaVMStackSOF_3.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
22
src/org/fenixsoft/jvm/chapter2/RuntimeConstantPoolOOM_1.java
Normal file
22
src/org/fenixsoft/jvm/chapter2/RuntimeConstantPoolOOM_1.java
Normal file
@ -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<String> set = new HashSet<String>();
|
||||
// 在short范围内足以让6MB的PermSize产生OOM了
|
||||
short i = 0;
|
||||
while (true) {
|
||||
set.add(String.valueOf(i++).intern());
|
||||
}
|
||||
}
|
||||
}
|
12
src/org/fenixsoft/jvm/chapter2/RuntimeConstantPoolOOM_2.java
Normal file
12
src/org/fenixsoft/jvm/chapter2/RuntimeConstantPoolOOM_2.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
50
src/org/fenixsoft/jvm/chapter3/FinalizeEscapeGC.java
Normal file
50
src/org/fenixsoft/jvm/chapter3/FinalizeEscapeGC.java
Normal file
@ -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 :(");
|
||||
}
|
||||
}
|
||||
}
|
31
src/org/fenixsoft/jvm/chapter3/ReferenceCountingGC.java
Normal file
31
src/org/fenixsoft/jvm/chapter3/ReferenceCountingGC.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
78
src/org/fenixsoft/jvm/chapter3/TestSerialGCAllocation.java
Normal file
78
src/org/fenixsoft/jvm/chapter3/TestSerialGCAllocation.java
Normal file
@ -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];
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
48
src/org/fenixsoft/jvm/chapter4/BTraceTest.java
Normal file
48
src/org/fenixsoft/jvm/chapter4/BTraceTest.java
Normal file
@ -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)));
|
||||
}
|
||||
}
|
||||
*/
|
29
src/org/fenixsoft/jvm/chapter4/JConsoleTestCase.java
Normal file
29
src/org/fenixsoft/jvm/chapter4/JConsoleTestCase.java
Normal file
@ -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<OOMObject> list = new ArrayList<OOMObject>();
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
24
src/org/fenixsoft/jvm/chapter4/JHSDBTestCase.java
Normal file
24
src/org/fenixsoft/jvm/chapter4/JHSDBTestCase.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
52
src/org/fenixsoft/jvm/chapter4/ThreadDeadLockTestCase_1.java
Normal file
52
src/org/fenixsoft/jvm/chapter4/ThreadDeadLockTestCase_1.java
Normal file
@ -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);
|
||||
}
|
||||
|
||||
}
|
36
src/org/fenixsoft/jvm/chapter4/ThreadDeadLockTestCase_2.java
Normal file
36
src/org/fenixsoft/jvm/chapter4/ThreadDeadLockTestCase_2.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
Binary file not shown.
42
src/org/fenixsoft/jvm/chapter7/ClassLoaderTest.java
Normal file
42
src/org/fenixsoft/jvm/chapter7/ClassLoaderTest.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
14
src/org/fenixsoft/jvm/chapter7/ConstClass.java
Normal file
14
src/org/fenixsoft/jvm/chapter7/ConstClass.java
Normal file
@ -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";
|
||||
}
|
34
src/org/fenixsoft/jvm/chapter7/DeadLoopTestCase.java
Normal file
34
src/org/fenixsoft/jvm/chapter7/DeadLoopTestCase.java
Normal file
@ -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();
|
||||
}
|
||||
|
||||
}
|
31
src/org/fenixsoft/jvm/chapter7/FieldResolution.java
Normal file
31
src/org/fenixsoft/jvm/chapter7/FieldResolution.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
12
src/org/fenixsoft/jvm/chapter7/NotInitialization_1.java
Normal file
12
src/org/fenixsoft/jvm/chapter7/NotInitialization_1.java
Normal file
@ -0,0 +1,12 @@
|
||||
package org.fenixsoft.jvm.chapter7;
|
||||
|
||||
/**
|
||||
* 非主动使用类字段演示
|
||||
**/
|
||||
public class NotInitialization_1 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(SubClass.value);
|
||||
}
|
||||
|
||||
}
|
13
src/org/fenixsoft/jvm/chapter7/NotInitialization_2.java
Normal file
13
src/org/fenixsoft/jvm/chapter7/NotInitialization_2.java
Normal file
@ -0,0 +1,13 @@
|
||||
package org.fenixsoft.jvm.chapter7;
|
||||
|
||||
/**
|
||||
* 被动使用类字段演示二:
|
||||
* 通过数组定义来引用类,不会触发此类的初始化
|
||||
**/
|
||||
public class NotInitialization_2 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SuperClass[] sca = new SuperClass[10];
|
||||
}
|
||||
|
||||
}
|
11
src/org/fenixsoft/jvm/chapter7/NotInitialization_3.java
Normal file
11
src/org/fenixsoft/jvm/chapter7/NotInitialization_3.java
Normal file
@ -0,0 +1,11 @@
|
||||
package org.fenixsoft.jvm.chapter7;
|
||||
|
||||
/**
|
||||
* 非主动使用类字段演示
|
||||
**/
|
||||
public class NotInitialization_3 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(ConstClass.HELLOWORLD);
|
||||
}
|
||||
}
|
11
src/org/fenixsoft/jvm/chapter7/SubClass.java
Normal file
11
src/org/fenixsoft/jvm/chapter7/SubClass.java
Normal file
@ -0,0 +1,11 @@
|
||||
package org.fenixsoft.jvm.chapter7;
|
||||
|
||||
/**
|
||||
* @author zzm
|
||||
*/
|
||||
public class SubClass extends SuperClass {
|
||||
|
||||
static {
|
||||
System.out.println("SubClass init!");
|
||||
}
|
||||
}
|
14
src/org/fenixsoft/jvm/chapter7/SuperClass.java
Normal file
14
src/org/fenixsoft/jvm/chapter7/SuperClass.java
Normal file
@ -0,0 +1,14 @@
|
||||
package org.fenixsoft.jvm.chapter7;
|
||||
|
||||
/**
|
||||
* 被动使用类字段演示一:
|
||||
* 通过子类引用父类的静态字段,不会导致子类初始化
|
||||
**/
|
||||
public class SuperClass {
|
||||
|
||||
static {
|
||||
System.out.println("SuperClass init!");
|
||||
}
|
||||
|
||||
public static int value = 123;
|
||||
}
|
39
src/org/fenixsoft/jvm/chapter8/Dispatch.java
Normal file
39
src/org/fenixsoft/jvm/chapter8/Dispatch.java
Normal file
@ -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());
|
||||
}
|
||||
}
|
35
src/org/fenixsoft/jvm/chapter8/DynamicDispatch.java
Normal file
35
src/org/fenixsoft/jvm/chapter8/DynamicDispatch.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
39
src/org/fenixsoft/jvm/chapter8/FieldHasNoPolymorphic.java
Normal file
39
src/org/fenixsoft/jvm/chapter8/FieldHasNoPolymorphic.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
41
src/org/fenixsoft/jvm/chapter8/GrandFatherTestCase_1.java
Normal file
41
src/org/fenixsoft/jvm/chapter8/GrandFatherTestCase_1.java
Normal file
@ -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();
|
||||
}
|
||||
|
||||
}
|
43
src/org/fenixsoft/jvm/chapter8/GrandFatherTestCase_2.java
Normal file
43
src/org/fenixsoft/jvm/chapter8/GrandFatherTestCase_2.java
Normal file
@ -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();
|
||||
}
|
||||
|
||||
}
|
37
src/org/fenixsoft/jvm/chapter8/InvokeDynamicTest.java
Normal file
37
src/org/fenixsoft/jvm/chapter8/InvokeDynamicTest.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
33
src/org/fenixsoft/jvm/chapter8/MethodHandleTest.java
Normal file
33
src/org/fenixsoft/jvm/chapter8/MethodHandleTest.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
41
src/org/fenixsoft/jvm/chapter8/Overload.java
Normal file
41
src/org/fenixsoft/jvm/chapter8/Overload.java
Normal file
@ -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');
|
||||
}
|
||||
}
|
37
src/org/fenixsoft/jvm/chapter8/StaticDispatch.java
Normal file
37
src/org/fenixsoft/jvm/chapter8/StaticDispatch.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
19
src/org/fenixsoft/jvm/chapter8/StaticResolution.java
Normal file
19
src/org/fenixsoft/jvm/chapter8/StaticResolution.java
Normal file
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
44
src/org/fenixsoft/jvm/chapter9/ByteUtils.java
Normal file
44
src/org/fenixsoft/jvm/chapter9/ByteUtils.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
74
src/org/fenixsoft/jvm/chapter9/ClassModifier.java
Normal file
74
src/org/fenixsoft/jvm/chapter9/ClassModifier.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
43
src/org/fenixsoft/jvm/chapter9/DynamicProxyTest.java
Normal file
43
src/org/fenixsoft/jvm/chapter9/DynamicProxyTest.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
54
src/org/fenixsoft/jvm/chapter9/HackSystem.java
Normal file
54
src/org/fenixsoft/jvm/chapter9/HackSystem.java
Normal file
@ -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的对应方法
|
||||
// 因版面原因,省略了其他方法
|
||||
}
|
20
src/org/fenixsoft/jvm/chapter9/HotSwapClassLoader.java
Normal file
20
src/org/fenixsoft/jvm/chapter9/HotSwapClassLoader.java
Normal file
@ -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);
|
||||
}
|
||||
|
||||
}
|
34
src/org/fenixsoft/jvm/chapter9/JavaclassExecuter.java
Normal file
34
src/org/fenixsoft/jvm/chapter9/JavaclassExecuter.java
Normal file
@ -0,0 +1,34 @@
|
||||
package org.fenixsoft.jvm.chapter9;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Javaclass执行工具
|
||||
*
|
||||
* @author zzm
|
||||
*/
|
||||
public class JavaclassExecuter {
|
||||
|
||||
/**
|
||||
* 执行外部传过来的代表一个Java类的Byte数组<br>
|
||||
* 将输入类的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();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user