diff --git a/group02/812350401/.gitignore b/group02/812350401/.gitignore index 8380fddb34..75d046d6bc 100644 --- a/group02/812350401/.gitignore +++ b/group02/812350401/.gitignore @@ -1,7 +1,5 @@ target/ .idea/ -src/main/java/train/ !src/main/resources/**/*.class !src/main/resources/**/*.xml src/main/resources/**/*.png -src/main/java/assignments diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java index 640250343f..89f4a6f0c2 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/attr/CodeAttr.java @@ -89,7 +89,7 @@ public String toString(ConstantPool pool){ StringBuilder buffer = new StringBuilder(); buffer.append("Code:").append(code).append("\n"); for(int i=0;i stack = new Stack(); + private Stack stack = new Stack(); // 函数栈帧 public ExecutorEngine() { } - + + /** + * 这是一个对函数栈帧的操作过程 + * @param mainMethod + */ public void execute(Method mainMethod){ } - - - + + + /** + * 把当前栈帧的参数给下一个函数栈帧 + * @param currentFrame + * @param nextFrame + */ private void setupFunctionCallParams(StackFrame currentFrame,StackFrame nextFrame) { diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/engine/Heap.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/engine/Heap.java index 3e346a1a6d..f99d46c3d1 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/engine/Heap.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/engine/Heap.java @@ -4,12 +4,14 @@ public class Heap { /** * 没有实现垃圾回收, 所以对于下面新创建的对象, 并没有记录到一个数据结构当中 + * 所以说Heap只具有创建javaObject的功能 */ private static Heap instance = new Heap(); private Heap() { } public static Heap getInstance(){ + return instance; } public JavaObject newObject(String clzName){ diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/engine/JavaObject.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/engine/JavaObject.java index aaf606464b..a2a4498b39 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/engine/JavaObject.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/engine/JavaObject.java @@ -21,30 +21,39 @@ public class JavaObject { private float floatValue; public void setFieldValue(String fieldName, JavaObject fieldValue){ + fieldValues.put(fieldName, fieldValue); } public JavaObject(int type){ + this.type = type; } public void setClassName(String className){ + this.className = className; } public void setStringValue(String value){ + stringValue = value; } public String getStringValue(){ + return this.stringValue; } public void setIntValue(int value) { - this.intValue = value; + + this.intValue = value; } public int getIntValue(){ + return this.intValue; } public int getType(){ + return type; } public JavaObject getFieldValue(String fieldName){ + return this.fieldValues.get(fieldName); } public String toString(){ @@ -62,10 +71,12 @@ public String toString(){ } } public String getClassName(){ + return this.className; } public void setFloatValue(float value) { - this.floatValue = value; + + this.floatValue = value; } } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/engine/MethodArea.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/engine/MethodArea.java index dded057e1d..7c90e955f0 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/engine/MethodArea.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/engine/MethodArea.java @@ -55,14 +55,27 @@ public ClassFile findClassFile(String className){ public Method getMethod(String className, String methodName, String paramAndReturnType){ - - return null; + ClassFile clz = findClassFile(className); + Method m = clz.getMethod(methodName, paramAndReturnType); + if(m == null){ + + throw new RuntimeException("method can't be found : \n" + + "class: " + className + + "method: " + methodName + + "paramAndReturnType: " + paramAndReturnType); + } + return m; } - public Method getMethod(MethodRefInfo methodRef){ - - return null; - + public Method getMethod(MethodRefInfo methodRef){ + ClassFile clz = findClassFile(methodRef.getClassName()); + String methodName = methodRef.getMethodName(); + String paramAndReturnType = methodRef.getParamAndReturnType(); + Method m = clz.getMethod(methodName, paramAndReturnType); + if (m == null) { + throw new RuntimeException("method can't be found : " + methodRef.toString()); + } + return m; } } diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/engine/MiniJVM.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/engine/MiniJVM.java index fa88ff2235..c85fe188c6 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/engine/MiniJVM.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/engine/MiniJVM.java @@ -7,7 +7,7 @@ public class MiniJVM { - public void run(String[]classPaths , String className) throws FileNotFoundException, IOException{ + public void run(String[]classPaths , String className) throws IOException{ ClassFileLoader loader = new ClassFileLoader(); for(int i=0;i localVariableTable = new ArrayList(); - private Stack oprandStack = new Stack(); + private List localVariableTable = new ArrayList<>(); + private Stack oprandStack = new Stack<>(); - int index = 0; + int index = 0; // 保存接下来要执行的那个命令的下标 - private Method m = null; + private Method m = null; // 栈帧和函数绑定 private StackFrame callerFrame = null; @@ -25,9 +25,6 @@ public StackFrame getCallerFrame() { public void setCallerFrame(StackFrame callerFrame) { this.callerFrame = callerFrame; } - - - public static StackFrame create(Method m){ @@ -41,10 +38,9 @@ private StackFrame(Method m) { this.m = m; } - - - + public JavaObject getLocalVariableValue(int index){ + return this.localVariableTable.get(index); } @@ -62,7 +58,12 @@ public int getNextCommandIndex(int offset){ } throw new RuntimeException("Can't find next command"); } - + + /** + * 从某个index位置继续执行函数,返回结果。 + * 有可能直接运行到return结束,也有可能运行到中间调用了一个新函数,那么就保留现场,待下次执行 + * @return + */ public ExecutionResult execute(){ return null; diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/ClassFileloaderTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/ClassFileloaderTest.java index b2b06459f8..1e8d2f3faa 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/ClassFileloaderTest.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/ClassFileloaderTest.java @@ -20,14 +20,14 @@ public class ClassFileloaderTest { private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; static String path1 = ClassFileloaderTest.class.getClassLoader().getResource("struts").getPath(); - static String path2 = ClassFileloaderTest.class.getClassLoader().getResource("jvm").getPath(); + static String path2 = ClassFileloaderTest.class.getClassLoader().getResource("classfile").getPath(); static ClassFile clzFile = null; static { ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path1); loader.addClassPath(path2); - String className = "com.github.miniyk2012.coding2017.jvm.test.EmployeeV1"; + String className = "com.coderising.jvm.test.EmployeeV1"; clzFile = loader.loadClass(className); // clzFile.print(); @@ -61,7 +61,7 @@ public void testClassFileLength() { loader.addClassPath(path1); loader.addClassPath(path2); - String className = "com.github.miniyk2012.coding2017.jvm.test.EmployeeV1"; + String className = "com.coderising.jvm.test.EmployeeV1"; byte[] byteCodes = loader.readBinaryCode(className); @@ -75,7 +75,7 @@ public void testMagicNumber(){ ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path1); loader.addClassPath(path2); - String className = "com.github.miniyk2012.coding2017.jvm.test.EmployeeV1"; + String className = "com.coderising.jvm.test.EmployeeV1"; byte[] byteCodes = loader.readBinaryCode(className); byte[] codes = new byte[]{byteCodes[0],byteCodes[1],byteCodes[2],byteCodes[3]}; diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/EmployeeV2.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/EmployeeV2.java new file mode 100644 index 0000000000..923a757069 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/EmployeeV2.java @@ -0,0 +1,54 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.test; + +public class EmployeeV2 { + + public final static String TEAM_NAME = "Dev Team"; + private String name; + private int age; + public EmployeeV2(String name, int age) { + this.name = name; + this.age = age; + } + + public void sayHello() { + System.out.println("Hello , this is class Employee "); + System.out.println(TEAM_NAME); + System.out.println(this.name); + } + + public void setName(String name) { + this.name = name; + } + + public void setAge(int age) { + this.age = age; + } + + + + public void isYouth() { + if (age < 40) { + System.out.println("You're still young"); + } else { + System.out.println("You're old"); + } + } + + + + public void testAdd() { + int sum = 0; + for (int i = 1; i <= 100; i++) { + sum += i; + } + System.out.println(sum); + } + + + public static void main(String[] args) { + EmployeeV2 p = new EmployeeV2("Andy", 35); + p.sayHello(); + p.isYouth(); + p.testAdd(); + } +} \ No newline at end of file diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/Example.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/Example.java new file mode 100644 index 0000000000..5e05f29ff9 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/Example.java @@ -0,0 +1,16 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.test; + +public class Example{ + public void disp(char c){ + System.out.println(c); + } + public void disp(int c){ + System.out.println(c ); + } + public static void main(String args[]){ + Example obj = new Example(); + obj.disp('a'); + obj.disp(5); + } +} + diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/HourlyEmployee.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/HourlyEmployee.java new file mode 100644 index 0000000000..4b1985c3c2 --- /dev/null +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/HourlyEmployee.java @@ -0,0 +1,27 @@ +package com.github.miniyk2012.coding2017.coderising.jvm.test; + +public class HourlyEmployee extends EmployeeV2 { + + int hourlySalary; + + public HourlyEmployee(String name, + int age, int hourlySalary) { + super(name, age); + this.hourlySalary = hourlySalary; + } + + public void sayHello(){ + System.out.println("Hello , this is Hourly Employee"); + } + public static void main(String[] args){ + EmployeeV2 e = new HourlyEmployee("Lisa", 20, 40); + e.sayHello(); + } + + public int getHourlySalary(){ + return this.hourlySalary; + } + + + +} diff --git a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/MiniJVMTest.java b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/MiniJVMTest.java index f05f973294..724dbeb679 100644 --- a/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/MiniJVMTest.java +++ b/group02/812350401/src/main/java/com/github/miniyk2012/coding2017/coderising/jvm/test/MiniJVMTest.java @@ -9,6 +9,9 @@ public class MiniJVMTest { static final String PATH = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\answer\\bin"; + static String PATH1 = MiniJVMTest.class.getClassLoader().getResource("struts").getPath(); + static String PATH2 = MiniJVMTest.class.getClassLoader().getResource("jvm").getPath(); + @Before public void setUp() throws Exception { } @@ -19,9 +22,9 @@ public void tearDown() throws Exception { @Test public void testMain() throws Exception{ - String[] classPaths = {PATH}; + String[] classPaths = {PATH, PATH1, PATH2}; MiniJVM jvm = new MiniJVM(); - jvm.run(classPaths, "com.coderising.jvm.test.EmployeeV1"); + jvm.run(classPaths, "com.github.miniyk2012.coding2017.jvm.test.EmployeeV1"); } diff --git a/group02/812350401/src/main/java/train/CollectionAsLifoQueue.java b/group02/812350401/src/main/java/train/CollectionAsLifoQueue.java new file mode 100644 index 0000000000..52dcaa74be --- /dev/null +++ b/group02/812350401/src/main/java/train/CollectionAsLifoQueue.java @@ -0,0 +1,27 @@ +package train; + +/** + * Created by thomas_young on 10/6/2017. + */ +import java.util.ArrayDeque; +import java.util.Collections; +import java.util.Deque; +import java.util.Queue; + +public class CollectionAsLifoQueue { + + public static void main(String args[]) { + + Deque dq = new ArrayDeque(5); + dq.add("java"); + dq.add("c"); + dq.add("c++"); + dq.add("unix"); + dq.push("perl"); + Queue q = Collections.asLifoQueue(dq); + System.out.println("returned queue is: "+q); + q.add("last1"); + q.add("last2"); + System.out.println(q); + } +} diff --git a/group02/812350401/src/main/java/train/GCTest.java b/group02/812350401/src/main/java/train/GCTest.java new file mode 100644 index 0000000000..34a912d51f --- /dev/null +++ b/group02/812350401/src/main/java/train/GCTest.java @@ -0,0 +1,17 @@ +package train; + +/** + * Created by thomas_young on 23/5/2017. + */ +public class GCTest { + public static void main(String[] args) { + + test(); + } + public static void test() { + String s; + while (true) { + s = new String("abc"); + } + } +} diff --git a/group02/812350401/src/main/java/train/Main.java b/group02/812350401/src/main/java/train/Main.java new file mode 100644 index 0000000000..6a2a72b5f7 --- /dev/null +++ b/group02/812350401/src/main/java/train/Main.java @@ -0,0 +1,147 @@ +package train; + +import io.reactivex.Flowable; +import io.reactivex.schedulers.Schedulers; + +import java.util.Arrays; + +/** + * Created by blind on 2017/4/14 0014. + */ +public class Main { + + + /** + * 线程同步 + */ + public static void threadSwithExample() { + Flowable.range(1, 10) + .subscribeOn(Schedulers.computation()) + .map(x -> { + System.out.println( + "上层" + + Thread.currentThread().getId() + " " + + Thread.currentThread().getName() + " " + + x); + return x; + }) + .observeOn(Schedulers.computation()) //这行注释掉就会退化成单线程 + .map(x -> { + System.out.println( + "下层" + + Thread.currentThread().getId() + " " + + Thread.currentThread().getName() + " " + + x); + return x; + }) + .subscribe((x) -> System.out.println( + Thread.currentThread().getId() + + " " + + Thread.currentThread().getName() + + " " + x + " main") + , Throwable::printStackTrace); + } + + /** + * 偶数 + */ + public static void filterExample() { + Flowable.range(1, 10) + .subscribeOn(Schedulers.newThread()) + .filter(x -> x % 2 == 0) + .subscribe(System.out::println, Throwable::printStackTrace); + + } + + + /** + * 质数 + */ + public static void filterExample2() { + Flowable.range(2, 20) + .subscribeOn(Schedulers.newThread()) + .filter(x -> Flowable.range(2, x - 2) + .filter(y -> x % y == 0) + .isEmpty() + .blockingGet() + ) + .subscribe(System.out::println, Throwable::printStackTrace); + } + + + /** + * 并行计算平方 + */ + public static void parallelExample() { + Flowable.range(1, 20) + .parallel() + .runOn(Schedulers.computation()) + .map(v ->{ + Thread.sleep(300); + return v*v; + }) + .sequential() + .subscribe(System.out::println); + } + + + /** + * 遍历一个整数数字字符串数组,把每个字符串按它的数值大小重复相应次数后,输出 + * + * @throws InterruptedException + */ + public static void flatMapExample() throws InterruptedException { + String[] strs = {"1", "3", "2", "10"}; + Flowable.fromArray(strs) + .subscribeOn(Schedulers.newThread()) + .flatMap(s -> Flowable.just(s) + .repeat(Integer.parseInt(s))) + .subscribe(System.out::println, Throwable::printStackTrace); + } + + /** + * 把一个字符串数组中的每个字符串末尾加上句号 + * + * @throws InterruptedException + */ + public static void mapExample2() throws InterruptedException { + String[] strs = {"1", "2", "3", "4"}; + Flowable.fromArray(strs) + .subscribeOn(Schedulers.newThread()) + .map(s -> s + ".") + .subscribe(System.out::println, Throwable::printStackTrace); + } + + /** + * 模拟耗时任务 + */ + public static void longTimeMissionExample() { + Flowable.just("1", "2", "3") + .subscribeOn(Schedulers.newThread()) + .map(x -> { + System.out.println("耗时任务开始……"); + Thread.sleep(300); + return x; + }) + .subscribe(x -> System.out.println("耗时任务结束……" + x)); + } + + public static void main(String[] args) throws InterruptedException { + + //longTimeMissionExample(); + + //parallelExample(); + //threadSwithExample(); + + //filterExample(); + filterExample2(); + + //mapExample(); + //flatMapExample(); + + // 模拟主线程的工作 + System.out.println("主线程去做其他事情"); + Thread.sleep(3000); // <--- wait for the flow to finish + System.out.println("主线程结束"); + } +} diff --git a/group02/812350401/src/main/java/train/Visitor_Pattern/ChrysanthemumConreteElement.java b/group02/812350401/src/main/java/train/Visitor_Pattern/ChrysanthemumConreteElement.java new file mode 100644 index 0000000000..35a3bb48d8 --- /dev/null +++ b/group02/812350401/src/main/java/train/Visitor_Pattern/ChrysanthemumConreteElement.java @@ -0,0 +1,12 @@ +package train.Visitor_Pattern; + +/** + * Created by thomas_young on 1/5/2017. + */ +public class ChrysanthemumConreteElement implements FlowerElement { + @Override + public void accept(final Visitor visitor) + { + visitor.visit(this); + } +} diff --git a/group02/812350401/src/main/java/train/Visitor_Pattern/ChrysanthemumVisitor.java b/group02/812350401/src/main/java/train/Visitor_Pattern/ChrysanthemumVisitor.java new file mode 100644 index 0000000000..a777e4fb6e --- /dev/null +++ b/group02/812350401/src/main/java/train/Visitor_Pattern/ChrysanthemumVisitor.java @@ -0,0 +1,17 @@ +package train.Visitor_Pattern; + +/** + * Created by thomas_young on 1/5/2017. + */ +public class ChrysanthemumVisitor implements Visitor { + + @Override + public void visit(GladiolusConcreteElement gladiolus) { + System.out.println(this.getClass().getSimpleName() + " access " + gladiolus.getClass().getSimpleName()); + } + + @Override + public void visit(ChrysanthemumConreteElement chrysanthemum) { + System.out.println(this.getClass().getSimpleName() + " access " + chrysanthemum.getClass().getSimpleName()); + } +} diff --git a/group02/812350401/src/main/java/train/Visitor_Pattern/Client.java b/group02/812350401/src/main/java/train/Visitor_Pattern/Client.java new file mode 100644 index 0000000000..04c3ff4acf --- /dev/null +++ b/group02/812350401/src/main/java/train/Visitor_Pattern/Client.java @@ -0,0 +1,22 @@ +package train.Visitor_Pattern; + +/** + * Created by thomas_young on 1/5/2017. + */ +public class Client +{ + public static void main(final String[] args) + { + final ObjectStructure os = new ObjectStructure(); + os.addElement(new GladiolusConcreteElement()); + os.addElement(new ChrysanthemumConreteElement()); + + final GladiolusVisitor gVisitor = new GladiolusVisitor(); + final ChrysanthemumVisitor chVisitor = new ChrysanthemumVisitor(); + + os.accept(gVisitor); + os.accept(chVisitor); + + } + +} diff --git a/group02/812350401/src/main/java/train/Visitor_Pattern/FlowerElement.java b/group02/812350401/src/main/java/train/Visitor_Pattern/FlowerElement.java new file mode 100644 index 0000000000..19c3b3c1cd --- /dev/null +++ b/group02/812350401/src/main/java/train/Visitor_Pattern/FlowerElement.java @@ -0,0 +1,8 @@ +package train.Visitor_Pattern; + +/** + * Created by thomas_young on 1/5/2017. + */ +public interface FlowerElement { + public void accept(Visitor visitor); +} diff --git a/group02/812350401/src/main/java/train/Visitor_Pattern/GladiolusConcreteElement.java b/group02/812350401/src/main/java/train/Visitor_Pattern/GladiolusConcreteElement.java new file mode 100644 index 0000000000..2160f44abe --- /dev/null +++ b/group02/812350401/src/main/java/train/Visitor_Pattern/GladiolusConcreteElement.java @@ -0,0 +1,12 @@ +package train.Visitor_Pattern; + +/** + * Created by thomas_young on 1/5/2017. + */ +public class GladiolusConcreteElement implements FlowerElement { + @Override + public void accept(final Visitor visitor) + { + visitor.visit(this); + } +} diff --git a/group02/812350401/src/main/java/train/Visitor_Pattern/GladiolusVisitor.java b/group02/812350401/src/main/java/train/Visitor_Pattern/GladiolusVisitor.java new file mode 100644 index 0000000000..57367d8605 --- /dev/null +++ b/group02/812350401/src/main/java/train/Visitor_Pattern/GladiolusVisitor.java @@ -0,0 +1,19 @@ +package train.Visitor_Pattern; + +/** + * Created by thomas_young on 1/5/2017. + */ +public class GladiolusVisitor implements Visitor { + @Override + public void visit(final GladiolusConcreteElement gladiolus) + { + System.out.println(this.getClass().getSimpleName() + " access " + gladiolus.getClass().getSimpleName()); + } + + @Override + public void visit(final ChrysanthemumConreteElement chrysanthemum) + { + System.out.println(this.getClass().getSimpleName() + " access " + chrysanthemum.getClass().getSimpleName()); + } + +} diff --git a/group02/812350401/src/main/java/train/Visitor_Pattern/ObjectStructure.java b/group02/812350401/src/main/java/train/Visitor_Pattern/ObjectStructure.java new file mode 100644 index 0000000000..e6c5fdbf75 --- /dev/null +++ b/group02/812350401/src/main/java/train/Visitor_Pattern/ObjectStructure.java @@ -0,0 +1,29 @@ +package train.Visitor_Pattern; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by thomas_young on 1/5/2017. + */ +public class ObjectStructure { + private final List elements = new ArrayList<>(); + + public void addElement(final FlowerElement e) + { + elements.add(e); + } + + public void removeElement(final FlowerElement e) + { + elements.remove(e); + } + + public void accept(final Visitor visitor) + { + for (final FlowerElement e : elements) + { + e.accept(visitor); + } + } +} diff --git a/group02/812350401/src/main/java/train/Visitor_Pattern/Visitor.java b/group02/812350401/src/main/java/train/Visitor_Pattern/Visitor.java new file mode 100644 index 0000000000..69cc3974da --- /dev/null +++ b/group02/812350401/src/main/java/train/Visitor_Pattern/Visitor.java @@ -0,0 +1,10 @@ +package train.Visitor_Pattern; + +/** + * Created by thomas_young on 1/5/2017. + */ +public interface Visitor { + public void visit(GladiolusConcreteElement gladiolus); + + public void visit(ChrysanthemumConreteElement chrysanthemum); +} diff --git a/group02/812350401/src/main/java/train/jvm/attr/AttributeInfo.java b/group02/812350401/src/main/java/train/jvm/attr/AttributeInfo.java new file mode 100755 index 0000000000..1d2b0f0a57 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package train.jvm.attr; + +public abstract class AttributeInfo { + public static final String CODE = "Code"; + public static final String CONST_VALUE = "ConstantValue"; + public static final String EXCEPTIONS = "Exceptions"; + public static final String LINE_NUM_TABLE = "LineNumberTable"; + public static final String LOCAL_VAR_TABLE = "LocalVariableTable"; + public static final String STACK_MAP_TABLE = "StackMapTable"; + int attrNameIndex; + int attrLen ; + public AttributeInfo(int attrNameIndex, int attrLen) { + + this.attrNameIndex = attrNameIndex; + this.attrLen = attrLen; + } + + +} diff --git a/group02/812350401/src/main/java/train/jvm/attr/CodeAttr.java b/group02/812350401/src/main/java/train/jvm/attr/CodeAttr.java new file mode 100755 index 0000000000..81b9a232f3 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/attr/CodeAttr.java @@ -0,0 +1,121 @@ +package train.jvm.attr; + + +import train.jvm.clz.ClassFile; +import train.jvm.cmd.ByteCodeCommand; +import train.jvm.cmd.CommandParser; +import train.jvm.constant.ConstantPool; +import train.jvm.loader.ByteCodeIterator; + +public class CodeAttr extends AttributeInfo { + private int maxStack ; + private int maxLocals ; + private int codeLen ; + private String code; + public String getCode() { + return code; + } + + private ByteCodeCommand[] cmds ; + public ByteCodeCommand[] getCmds() { + return cmds; + } + private LineNumberTable lineNumTable; + private LocalVariableTable localVarTable; + private StackMapTable stackMapTable; + + public CodeAttr(int attrNameIndex, int attrLen, int maxStack, int maxLocals, int codeLen,String code ,ByteCodeCommand[] cmds) { + super(attrNameIndex, attrLen); + this.maxStack = maxStack; + this.maxLocals = maxLocals; + this.codeLen = codeLen; + this.code = code; + this.cmds = cmds; + } + + public void setLineNumberTable(LineNumberTable t) { + this.lineNumTable = t; + } + + public void setLocalVariableTable(LocalVariableTable t) { + this.localVarTable = t; + } + + public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ + + int attrNameIndex = iter.nextU2ToInt(); + int attrLen = iter.nextU4ToInt(); + int maxStack = iter.nextU2ToInt(); + int maxLocals = iter.nextU2ToInt(); + int codeLen = iter.nextU4ToInt(); + + String code = iter.nextUxToHexString(codeLen); + + + ByteCodeCommand[] cmds = CommandParser.parse(clzFile,code); + + CodeAttr codeAttr = new CodeAttr(attrNameIndex,attrLen, maxStack,maxLocals,codeLen,code,cmds); + + int exceptionTableLen = iter.nextU2ToInt(); + //TODO 处理exception + if(exceptionTableLen>0){ + String exTable = iter.nextUxToHexString(exceptionTableLen); + System.out.println("Encountered exception table , just ignore it :" + exTable); + + } + + + int subAttrCount = iter.nextU2ToInt(); + + for(int x=1; x<=subAttrCount; x++){ + int subAttrIndex = iter.nextU2ToInt(); + String subAttrName = clzFile.getConstantPool().getUTF8String(subAttrIndex); + + //已经向前移动了U2, 现在退回去。 + iter.back(2); + //line item table + if(AttributeInfo.LINE_NUM_TABLE.equalsIgnoreCase(subAttrName)){ + + LineNumberTable t = LineNumberTable.parse(iter); + codeAttr.setLineNumberTable(t); + } + else if(AttributeInfo.LOCAL_VAR_TABLE.equalsIgnoreCase(subAttrName)){ + LocalVariableTable t = LocalVariableTable.parse(iter); + codeAttr.setLocalVariableTable(t); + } + else if (AttributeInfo.STACK_MAP_TABLE.equalsIgnoreCase(subAttrName)){ + StackMapTable t = StackMapTable.parse(iter); + codeAttr.setStackMapTable(t); + } + else{ + throw new RuntimeException("Need code to process " + subAttrName); + } + + + } + + return codeAttr; + } + + + public String toString(ConstantPool pool){ + StringBuilder buffer = new StringBuilder(); + //buffer.append("Code:").append(code).append("\n"); + for(int i=0;i items = new ArrayList(); + + private static class LineNumberItem{ + int startPC; + int lineNum; + public int getStartPC() { + return startPC; + } + public void setStartPC(int startPC) { + this.startPC = startPC; + } + public int getLineNum() { + return lineNum; + } + public void setLineNum(int lineNum) { + this.lineNum = lineNum; + } + } + public void addLineNumberItem(LineNumberItem item){ + this.items.add(item); + } + public LineNumberTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + + } + + public static LineNumberTable parse(ByteCodeIterator iter){ + + int index = iter.nextU2ToInt(); + int len = iter.nextU4ToInt(); + + LineNumberTable table = new LineNumberTable(index,len); + + int itemLen = iter.nextU2ToInt(); + + for(int i=1; i<=itemLen; i++){ + LineNumberItem item = new LineNumberItem(); + item.setStartPC(iter.nextU2ToInt()); + item.setLineNum(iter.nextU2ToInt()); + table.addLineNumberItem(item); + } + return table; + } + + public String toString(){ + StringBuilder buffer = new StringBuilder(); + buffer.append("Line Number Table:\n"); + for(LineNumberItem item : items){ + buffer.append("startPC:"+item.getStartPC()).append(","); + buffer.append("lineNum:"+item.getLineNum()).append("\n"); + } + buffer.append("\n"); + return buffer.toString(); + + } + + + +} diff --git a/group02/812350401/src/main/java/train/jvm/attr/LocalVariableItem.java b/group02/812350401/src/main/java/train/jvm/attr/LocalVariableItem.java new file mode 100755 index 0000000000..8f82cc8e5d --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package train.jvm.attr; + +public class LocalVariableItem { + private int startPC; + private int length; + private int nameIndex; + private int descIndex; + private int index; + public int getStartPC() { + return startPC; + } + public void setStartPC(int startPC) { + this.startPC = startPC; + } + public int getLength() { + return length; + } + public void setLength(int length) { + this.length = length; + } + public int getNameIndex() { + return nameIndex; + } + public void setNameIndex(int nameIndex) { + this.nameIndex = nameIndex; + } + public int getDescIndex() { + return descIndex; + } + public void setDescIndex(int descIndex) { + this.descIndex = descIndex; + } + public int getIndex() { + return index; + } + public void setIndex(int index) { + this.index = index; + } +} diff --git a/group02/812350401/src/main/java/train/jvm/attr/LocalVariableTable.java b/group02/812350401/src/main/java/train/jvm/attr/LocalVariableTable.java new file mode 100755 index 0000000000..2435152194 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/attr/LocalVariableTable.java @@ -0,0 +1,58 @@ +package train.jvm.attr; + + +import train.jvm.constant.ConstantPool; +import train.jvm.loader.ByteCodeIterator; + +import java.util.ArrayList; +import java.util.List; + + +public class LocalVariableTable extends AttributeInfo{ + + List items = new ArrayList(); + + public LocalVariableTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + } + + + private void addLocalVariableItem(LocalVariableItem item) { + this.items.add(item); + } + + public static LocalVariableTable parse(ByteCodeIterator iter){ + + int index = iter.nextU2ToInt(); + int len = iter.nextU4ToInt(); + + LocalVariableTable table = new LocalVariableTable(index,len); + + int itemLen = iter.nextU2ToInt(); + + for(int i=1; i<=itemLen; i++){ + LocalVariableItem item = new LocalVariableItem(); + item.setStartPC(iter.nextU2ToInt()); + item.setLength(iter.nextU2ToInt()); + item.setNameIndex(iter.nextU2ToInt()); + item.setDescIndex(iter.nextU2ToInt()); + item.setIndex(iter.nextU2ToInt()); + table.addLocalVariableItem(item); + } + return table; + } + + + public String toString(ConstantPool pool){ + StringBuilder buffer = new StringBuilder(); + buffer.append("Local Variable Table:\n"); + for(LocalVariableItem item : items){ + buffer.append("startPC:"+item.getStartPC()).append(","); + buffer.append("name:"+pool.getUTF8String(item.getNameIndex())).append(","); + buffer.append("desc:"+pool.getUTF8String(item.getDescIndex())).append(","); + buffer.append("slotIndex:"+ item.getIndex()).append("\n"); + } + buffer.append("\n"); + return buffer.toString(); + } +} diff --git a/group02/812350401/src/main/java/train/jvm/attr/StackMapTable.java b/group02/812350401/src/main/java/train/jvm/attr/StackMapTable.java new file mode 100755 index 0000000000..38d47badea --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package train.jvm.attr; + + +import train.jvm.loader.ByteCodeIterator; + +public class StackMapTable extends AttributeInfo{ + + private String originalCode; + + public StackMapTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + } + + public static StackMapTable parse(ByteCodeIterator iter){ + int index = iter.nextU2ToInt(); + int len = iter.nextU4ToInt(); + StackMapTable t = new StackMapTable(index,len); + + //后面的StackMapTable太过复杂, 不再处理, 只把原始的代码读进来保存 + String code = iter.nextUxToHexString(len); + t.setOriginalCode(code); + + return t; + } + + private void setOriginalCode(String code) { + this.originalCode = code; + + } +} diff --git a/group02/812350401/src/main/java/train/jvm/clz/AccessFlag.java b/group02/812350401/src/main/java/train/jvm/clz/AccessFlag.java new file mode 100755 index 0000000000..77b160ae17 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package train.jvm.clz; + +public class AccessFlag { + private int flagValue; + + public AccessFlag(int value) { + this.flagValue = value; + } + + public int getFlagValue() { + return flagValue; + } + + public void setFlagValue(int flag) { + this.flagValue = flag; + } + + public boolean isPublicClass(){ + return (this.flagValue & 0x0001) != 0; + } + public boolean isFinalClass(){ + return (this.flagValue & 0x0010) != 0; + } + +} \ No newline at end of file diff --git a/group02/812350401/src/main/java/train/jvm/clz/ClassFile.java b/group02/812350401/src/main/java/train/jvm/clz/ClassFile.java new file mode 100755 index 0000000000..42b42ceaa4 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/clz/ClassFile.java @@ -0,0 +1,112 @@ +package train.jvm.clz; + + +import train.jvm.constant.ClassInfo; +import train.jvm.constant.ConstantPool; +import train.jvm.field.Field; +import train.jvm.method.Method; + +import java.util.ArrayList; +import java.util.List; + +public class ClassFile { + + private int minorVersion; + private int majorVersion; + + private AccessFlag accessFlag; + private ClassIndex clzIndex; + private ConstantPool pool; + private List fields = new ArrayList<>(); + private List methods = new ArrayList<>(); + + public ClassIndex getClzIndex() { + return clzIndex; + } + public AccessFlag getAccessFlag() { + return accessFlag; + } + public void setAccessFlag(AccessFlag accessFlag) { + this.accessFlag = accessFlag; + } + + + + public ConstantPool getConstantPool() { + return pool; + } + public int getMinorVersion() { + return minorVersion; + } + public void setMinorVersion(int minorVersion) { + this.minorVersion = minorVersion; + } + public int getMajorVersion() { + return majorVersion; + } + public void setMajorVersion(int majorVersion) { + this.majorVersion = majorVersion; + } + public void setConstPool(ConstantPool pool) { + this.pool = pool; + + } + public void setClassIndex(ClassIndex clzIndex) { + this.clzIndex = clzIndex; + } + + public void addField(Field f){ + this.fields.add(f); + } + public List getFields(){ + return this.fields; + } + public void addMethod(Method m){ + this.methods.add(m); + } + public List getMethods() { + return methods; + } + + + public void print(){ + + if(this.accessFlag.isPublicClass()){ + System.out.println("Access flag : public "); + } + System.out.println("Class Name:"+ getClassName()); + + System.out.println("Super Class Name:"+ getSuperClassName()); + + + } + + public String getClassName(){ + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + public String getSuperClassName(){ + ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } + + public Method getMethod(String methodName, String paramAndReturnType){ + + for(Method m :methods){ + + int nameIndex = m.getNameIndex(); + int descriptionIndex = m.getDescriptorIndex(); + + String name = this.getConstantPool().getUTF8String(nameIndex); + String desc = this.getConstantPool().getUTF8String(descriptionIndex); + if(name.equals(methodName) && desc.equals(paramAndReturnType)){ + return m; + } + } + return null; + } + public Method getMainMethod(){ + return getMethod("main","([Ljava/lang/String;)V"); + } +} diff --git a/group02/812350401/src/main/java/train/jvm/clz/ClassIndex.java b/group02/812350401/src/main/java/train/jvm/clz/ClassIndex.java new file mode 100755 index 0000000000..025fe96a44 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package train.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int superClassIndex; + + public int getThisClassIndex() { + return thisClassIndex; + } + public void setThisClassIndex(int thisClassIndex) { + this.thisClassIndex = thisClassIndex; + } + public int getSuperClassIndex() { + return superClassIndex; + } + public void setSuperClassIndex(int superClassIndex) { + this.superClassIndex = superClassIndex; + } +} \ No newline at end of file diff --git a/group02/812350401/src/main/java/train/jvm/cmd/BiPushCmd.java b/group02/812350401/src/main/java/train/jvm/cmd/BiPushCmd.java new file mode 100755 index 0000000000..3f50be793b --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/cmd/BiPushCmd.java @@ -0,0 +1,29 @@ +package train.jvm.cmd; + + +import train.jvm.clz.ClassFile; +import train.jvm.engine.ExecutionResult; +import train.jvm.engine.Heap; +import train.jvm.engine.JavaObject; +import train.jvm.engine.StackFrame; + +public class BiPushCmd extends OneOperandCmd { + + public BiPushCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString() { + + return this.getOffset()+":"+ this.getOpCode()+" " + this.getReadableCodeText() + " " + this.getOperand(); + } + public void execute(StackFrame frame, ExecutionResult result){ + int value = this.getOperand(); + JavaObject jo = Heap.getInstance().newInt(value); + frame.getOprandStack().push(jo); + } + + +} diff --git a/group02/812350401/src/main/java/train/jvm/cmd/ByteCodeCommand.java b/group02/812350401/src/main/java/train/jvm/cmd/ByteCodeCommand.java new file mode 100755 index 0000000000..0d4f8384cd --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,158 @@ +package train.jvm.cmd; + +import train.jvm.clz.ClassFile; +import train.jvm.constant.ConstantInfo; +import train.jvm.constant.ConstantPool; +import train.jvm.engine.ExecutionResult; +import train.jvm.engine.StackFrame; + +import java.util.HashMap; +import java.util.Map; + + + + +public abstract class ByteCodeCommand { + + String opCode; + ClassFile clzFile; + private int offset; + + public static final String aconst_null = "01"; + public static final String new_object = "BB"; + public static final String lstore = "37"; + public static final String invokespecial = "B7"; + public static final String invokevirtual = "B6"; + public static final String getfield = "B4"; + public static final String putfield = "B5"; + public static final String getstatic = "B2"; + public static final String ldc = "12"; + public static final String dup = "59"; + public static final String bipush = "10"; + public static final String aload_0 = "2A"; + public static final String aload_1 = "2B"; + public static final String aload_2 = "2C"; + public static final String iload = "15"; + public static final String iload_1 = "1B"; + public static final String iload_2 = "1C"; + public static final String iload_3 = "1D"; + public static final String fload_3 = "25"; + + public static final String voidreturn = "B1"; + public static final String ireturn = "AC"; + public static final String freturn = "AE"; + + public static final String astore_1 = "4C"; + public static final String if_icmp_ge = "A2"; + public static final String if_icmple = "A4"; + public static final String goto_no_condition = "A7"; + public static final String iconst_0 = "03"; + public static final String iconst_1 = "04"; + public static final String istore_1 = "3C"; + public static final String istore_2 = "3D"; + public static final String iadd = "60"; + public static final String iinc = "84"; + private static Map codeMap = new HashMap(); + + static{ + codeMap.put("01", "aconst_null"); + + codeMap.put("A2", "if_icmp_ge"); + codeMap.put("A4", "if_icmple"); + codeMap.put("A7", "goto"); + + codeMap.put("BB", "new"); + codeMap.put("37", "lstore"); + codeMap.put("B7", "invokespecial"); + codeMap.put("B6", "invokevirtual"); + codeMap.put("B4", "getfield"); + codeMap.put("B5", "putfield"); + codeMap.put("B2", "getstatic"); + + codeMap.put("2A", "aload_0"); + codeMap.put("2B", "aload_1"); + codeMap.put("2C", "aload_2"); + + codeMap.put("10", "bipush"); + codeMap.put("15", "iload"); + codeMap.put("1A", "iload_0"); + codeMap.put("1B", "iload_1"); + codeMap.put("1C", "iload_2"); + codeMap.put("1D", "iload_3"); + + codeMap.put("25", "fload_3"); + + codeMap.put("1E", "lload_0"); + + codeMap.put("24", "fload_2"); + codeMap.put("4C", "astore_1"); + + codeMap.put("A2", "if_icmp_ge"); + codeMap.put("A4", "if_icmple"); + + codeMap.put("A7", "goto"); + + codeMap.put("B1", "return"); + codeMap.put("AC", "ireturn"); + codeMap.put("AE", "freturn"); + + codeMap.put("03", "iconst_0"); + codeMap.put("04", "iconst_1"); + + codeMap.put("3C", "istore_1"); + codeMap.put("3D", "istore_2"); + + codeMap.put("59", "dup"); + + codeMap.put("60", "iadd"); + codeMap.put("84", "iinc"); + + codeMap.put("12", "ldc"); + } + + + + + + protected ByteCodeCommand(ClassFile clzFile, String opCode){ + this.clzFile = clzFile; + this.opCode = opCode; + } + + protected ClassFile getClassFile() { + return clzFile; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + protected ConstantInfo getConstantInfo(int index){ + return this.getClassFile().getConstantPool().getConstantInfo(index); + } + + protected ConstantPool getConstantPool(){ + return this.getClassFile().getConstantPool(); + } + + + + public String getOpCode() { + return opCode; + } + + public abstract int getLength(); + + public String getReadableCodeText(){ + String txt = codeMap.get(opCode); + if(txt == null){ + return opCode; + } + return txt; + } + + public abstract void execute(StackFrame frame, ExecutionResult result); +} diff --git a/group02/812350401/src/main/java/train/jvm/cmd/CommandParser.java b/group02/812350401/src/main/java/train/jvm/cmd/CommandParser.java new file mode 100755 index 0000000000..75c00c8eea --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/cmd/CommandParser.java @@ -0,0 +1,149 @@ +package train.jvm.cmd; + +import train.jvm.clz.ClassFile; + +import java.util.ArrayList; +import java.util.List; + + +public class CommandParser { + + + + public static ByteCodeCommand[] parse(ClassFile clzFile, String codes) { + + if ((codes == null) || (codes.length() == 0) || (codes.length() % 2) != 0) { + throw new RuntimeException("the orignal code is not correct"); + + } + + codes = codes.toUpperCase(); + + CommandIterator iter = new CommandIterator(codes); + List cmds = new ArrayList(); + + while (iter.hasNext()) { + String opCode = iter.next2CharAsString(); + + if (ByteCodeCommand.new_object.equals(opCode)) { + NewObjectCmd cmd = new NewObjectCmd(clzFile, opCode); + + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + + cmds.add(cmd); + } else if (ByteCodeCommand.invokespecial.equals(opCode)) { + InvokeSpecialCmd cmd = new InvokeSpecialCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + // System.out.println( cmd.toString(clzFile.getConstPool())); + cmds.add(cmd); + } else if (ByteCodeCommand.invokevirtual.equals(opCode)) { + InvokeVirtualCmd cmd = new InvokeVirtualCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + + cmds.add(cmd); + } else if (ByteCodeCommand.getfield.equals(opCode)) { + GetFieldCmd cmd = new GetFieldCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (ByteCodeCommand.getstatic.equals(opCode)) { + GetStaticFieldCmd cmd = new GetStaticFieldCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (ByteCodeCommand.putfield.equals(opCode)) { + PutFieldCmd cmd = new PutFieldCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (ByteCodeCommand.ldc.equals(opCode)) { + LdcCmd cmd = new LdcCmd(clzFile, opCode); + cmd.setOperand(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (ByteCodeCommand.bipush.equals(opCode)) { + BiPushCmd cmd = new BiPushCmd(clzFile, opCode); + cmd.setOperand(iter.next2CharAsInt()); + cmds.add(cmd); + }else if(ByteCodeCommand.if_icmp_ge.equals(opCode) + || ByteCodeCommand.if_icmple.equals(opCode) + || ByteCodeCommand.goto_no_condition.equals(opCode)){ + ComparisonCmd cmd = new ComparisonCmd(clzFile,opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if(ByteCodeCommand.iinc.equals(opCode)){ + IncrementCmd cmd = new IncrementCmd(clzFile,opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } + else if (ByteCodeCommand.dup.equals(opCode) + || ByteCodeCommand.aload_0.equals(opCode) + || ByteCodeCommand.aload_1.equals(opCode) + || ByteCodeCommand.aload_2.equals(opCode) + || ByteCodeCommand.iload_1.equals(opCode) + || ByteCodeCommand.iload_2.equals(opCode) + || ByteCodeCommand.iload_3.equals(opCode) + || ByteCodeCommand.fload_3.equals(opCode) + || ByteCodeCommand.iconst_0.equals(opCode) + || ByteCodeCommand.iconst_1.equals(opCode) + || ByteCodeCommand.istore_1.equals(opCode) + || ByteCodeCommand.istore_2.equals(opCode) + || ByteCodeCommand.voidreturn.equals(opCode) + || ByteCodeCommand.iadd.equals(opCode) + || ByteCodeCommand.astore_1.equals(opCode) + || ByteCodeCommand.ireturn.equals(opCode)) { + + NoOperandCmd cmd = new NoOperandCmd(clzFile, opCode); + cmds.add(cmd); + } else { + throw new RuntimeException("Sorry, the java instruction " + opCode + " has not been implemented"); + } + + } + + calcuateOffset(cmds); + + ByteCodeCommand[] result = new ByteCodeCommand[cmds.size()]; + cmds.toArray(result); + return result; + } + + private static void calcuateOffset(List cmds) { + + int offset = 0; + for (ByteCodeCommand cmd : cmds) { + cmd.setOffset(offset); + offset += cmd.getLength(); + } + + } + + private static class CommandIterator { + String codes = null; + int pos = 0; + + CommandIterator(String codes) { + this.codes = codes; + } + + public boolean hasNext() { + return pos < this.codes.length(); + } + + public String next2CharAsString() { + String result = codes.substring(pos, pos + 2); + pos += 2; + return result; + } + + public int next2CharAsInt() { + String s = this.next2CharAsString(); + return Integer.valueOf(s, 16).intValue(); + } + + } +} diff --git a/group02/812350401/src/main/java/train/jvm/cmd/ComparisonCmd.java b/group02/812350401/src/main/java/train/jvm/cmd/ComparisonCmd.java new file mode 100755 index 0000000000..9f74b91e9d --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/cmd/ComparisonCmd.java @@ -0,0 +1,79 @@ +package train.jvm.cmd; + + +import train.jvm.clz.ClassFile; +import train.jvm.engine.ExecutionResult; +import train.jvm.engine.JavaObject; +import train.jvm.engine.StackFrame; + +public class ComparisonCmd extends TwoOperandCmd { + + protected ComparisonCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + + } + + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + if(ByteCodeCommand.if_icmp_ge.equals(this.getOpCode())){ + //注意次序 + JavaObject jo2 = frame.getOprandStack().pop(); + JavaObject jo1 = frame.getOprandStack().pop(); + + if(jo1.getIntValue() >= jo2.getIntValue()){ + + this.setJumpResult(result); + + } + + } else if(ByteCodeCommand.if_icmple.equals(this.getOpCode())){ + //注意次序 + JavaObject jo2 = frame.getOprandStack().pop(); + JavaObject jo1 = frame.getOprandStack().pop(); + + if(jo1.getIntValue() <= jo2.getIntValue()){ + this.setJumpResult(result); + } + + } else if(ByteCodeCommand.goto_no_condition.equals(this.getOpCode())){ + this.setJumpResult(result); + + } else{ + throw new RuntimeException(this.getOpCode() + "has not been implemented"); + } + + + + + } + + private int getOffsetFromStartCmd(){ + //If the comparison succeeds, the unsigned branchbyte1 and branchbyte2 + //are used to construct a signed 16-bit offset, where the offset is calculated + //to be (branchbyte1 << 8) | branchbyte2. Execution then proceeds at that + //offset from the address of the opcode of this if_icmp instruction + + + int index1 = this.getOprand1(); + int index2 = this.getOprand2(); + short offsetFromCurrent = (short)(index1 << 8 | index2); + return this.getOffset() + offsetFromCurrent ; + } + private void setJumpResult(ExecutionResult result){ + + int offsetFromStartCmd = this.getOffsetFromStartCmd(); + + result.setNextAction(ExecutionResult.JUMP); + result.setNextCmdOffset(offsetFromStartCmd); + } + + @Override + public String toString() { + int index = this.getIndex(); + String text = this.getReadableCodeText(); + return this.getOffset()+":"+ this.getOpCode() + " "+text + " " + this.getOffsetFromStartCmd(); + } + +} diff --git a/group02/812350401/src/main/java/train/jvm/cmd/GetFieldCmd.java b/group02/812350401/src/main/java/train/jvm/cmd/GetFieldCmd.java new file mode 100755 index 0000000000..a2423fa087 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,37 @@ +package train.jvm.cmd; + + +import train.jvm.clz.ClassFile; +import train.jvm.constant.FieldRefInfo; +import train.jvm.engine.ExecutionResult; +import train.jvm.engine.JavaObject; +import train.jvm.engine.StackFrame; + +public class GetFieldCmd extends TwoOperandCmd { + + public GetFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString() { + + return super.getOperandAsField(); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + FieldRefInfo fieldRef = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + String fieldName = fieldRef.getFieldName(); + JavaObject jo = frame.getOprandStack().pop(); + JavaObject fieldValue = jo.getFieldValue(fieldName); + + frame.getOprandStack().push(fieldValue); + + + + } + + +} diff --git a/group02/812350401/src/main/java/train/jvm/cmd/GetStaticFieldCmd.java b/group02/812350401/src/main/java/train/jvm/cmd/GetStaticFieldCmd.java new file mode 100755 index 0000000000..b9d7ab0bc4 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,39 @@ +package train.jvm.cmd; + + +import train.jvm.clz.ClassFile; +import train.jvm.constant.FieldRefInfo; +import train.jvm.engine.ExecutionResult; +import train.jvm.engine.Heap; +import train.jvm.engine.JavaObject; +import train.jvm.engine.StackFrame; + +public class GetStaticFieldCmd extends TwoOperandCmd { + + public GetStaticFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString() { + + return super.getOperandAsField(); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + FieldRefInfo info = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + String className = info.getClassName(); + String fieldName = info.getFieldName(); + String fieldType = info.getFieldType(); + + if("java/lang/System".equals(className) + && "out".equals(fieldName) + && "Ljava/io/PrintStream;".equals(fieldType)){ + JavaObject jo = Heap.getInstance().newObject(className); + frame.getOprandStack().push(jo); + } + //TODO 处理非System.out的情况 + } +} diff --git a/group02/812350401/src/main/java/train/jvm/cmd/IncrementCmd.java b/group02/812350401/src/main/java/train/jvm/cmd/IncrementCmd.java new file mode 100755 index 0000000000..f76dbaf392 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/cmd/IncrementCmd.java @@ -0,0 +1,39 @@ +package train.jvm.cmd; + + +import train.jvm.clz.ClassFile; +import train.jvm.engine.ExecutionResult; +import train.jvm.engine.Heap; +import train.jvm.engine.JavaObject; +import train.jvm.engine.StackFrame; + +public class IncrementCmd extends TwoOperandCmd { + + public IncrementCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + + } + + @Override + public String toString() { + + return this.getOffset()+":"+this.getOpCode()+ " " +this.getReadableCodeText(); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + int index = this.getOprand1(); + + int constValue = this.getOprand2(); + + int currentValue = frame.getLocalVariableValue(index).getIntValue(); + + JavaObject jo = Heap.getInstance().newInt(constValue+currentValue); + + frame.setLocalVariableValue(index, jo); + + + } + +} \ No newline at end of file diff --git a/group02/812350401/src/main/java/train/jvm/cmd/InvokeSpecialCmd.java b/group02/812350401/src/main/java/train/jvm/cmd/InvokeSpecialCmd.java new file mode 100755 index 0000000000..8ef2dc5f04 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,46 @@ +package train.jvm.cmd; + + +import train.jvm.clz.ClassFile; +import train.jvm.constant.MethodRefInfo; +import train.jvm.engine.ExecutionResult; +import train.jvm.engine.MethodArea; +import train.jvm.engine.StackFrame; +import train.jvm.method.Method; + +public class InvokeSpecialCmd extends TwoOperandCmd { + + public InvokeSpecialCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString() { + + return super.getOperandAsMethod(); + } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + MethodRefInfo methodRefInfo = (MethodRefInfo)this.getConstantInfo(this.getIndex()); + + // 我们不用实现jang.lang.Object 的init方法 + if(methodRefInfo.getClassName().equals("java/lang/Object") + && methodRefInfo.getMethodName().equals("")){ + return ; + + } + Method nextMethod = MethodArea.getInstance().getMethod(methodRefInfo); + + + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + result.setNextMethod(nextMethod); + + + + } + + +} diff --git a/group02/812350401/src/main/java/train/jvm/cmd/InvokeVirtualCmd.java b/group02/812350401/src/main/java/train/jvm/cmd/InvokeVirtualCmd.java new file mode 100755 index 0000000000..02f9eb4a50 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,85 @@ +package train.jvm.cmd; + + +import train.jvm.clz.ClassFile; +import train.jvm.constant.MethodRefInfo; +import train.jvm.engine.ExecutionResult; +import train.jvm.engine.JavaObject; +import train.jvm.engine.MethodArea; +import train.jvm.engine.StackFrame; +import train.jvm.method.Method; + +public class InvokeVirtualCmd extends TwoOperandCmd { + + public InvokeVirtualCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString() { + + return super.getOperandAsMethod(); + } + + private boolean isSystemOutPrintlnMethod(String className, String methodName){ + return "java/io/PrintStream".equals(className) + && "println".equals(methodName); + } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + //先得到对该方法的描述 + MethodRefInfo methodRefInfo = (MethodRefInfo)this.getConstantInfo(this.getIndex()); + + String className = methodRefInfo.getClassName(); + String methodName = methodRefInfo.getMethodName(); + + // 我们没有实现System.out.println方法, 所以也不用建立新的栈帧, 直接调用Java的方法, 打印出来即可。 + if(isSystemOutPrintlnMethod(className,methodName)){ + JavaObject jo = frame.getOprandStack().pop(); + String value = jo.toString(); + System.err.println("-------------------"+value+"----------------"); + + // 这里就是那个out对象, 因为是个假的,直接pop出来 + frame.getOprandStack().pop(); + + return; + } + + //注意:多态, 这才是真正的对象, 先从该对象的class 中去找对应的方法,找不到的话再去找父类的方法 + JavaObject jo = frame.getOprandStack().peek(); + + MethodArea ma = MethodArea.getInstance(); + + Method m = null; + + String currentClassName = jo.getClassName(); + + while(currentClassName != null){ + + ClassFile currentClassFile = ma.findClassFile(currentClassName); + + m = currentClassFile.getMethod(methodRefInfo.getMethodName(), + methodRefInfo.getParamAndReturnType()); + if(m != null){ + + break; + + } else{ + //查找父类 + currentClassName = currentClassFile.getSuperClassName(); + } + } + + if(m == null){ + throw new RuntimeException("Can't find method for :" + methodRefInfo.toString()); + } + + + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + + result.setNextMethod(m); + } + + +} diff --git a/group02/812350401/src/main/java/train/jvm/cmd/LdcCmd.java b/group02/812350401/src/main/java/train/jvm/cmd/LdcCmd.java new file mode 100755 index 0000000000..abf25cc3cd --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/cmd/LdcCmd.java @@ -0,0 +1,51 @@ +package train.jvm.cmd; + + +import train.jvm.clz.ClassFile; +import train.jvm.constant.ConstantInfo; +import train.jvm.constant.ConstantPool; +import train.jvm.constant.StringInfo; +import train.jvm.engine.ExecutionResult; +import train.jvm.engine.Heap; +import train.jvm.engine.JavaObject; +import train.jvm.engine.StackFrame; + +public class LdcCmd extends OneOperandCmd { + + public LdcCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString() { + + ConstantInfo info = getConstantInfo(this.getOperand()); + + String value = "TBD"; + if(info instanceof StringInfo){ + StringInfo strInfo = (StringInfo)info; + value = strInfo.toString(); + } + + return this.getOffset()+":"+this.getOpCode()+" " + this.getReadableCodeText() + " "+ value; + + } + public void execute(StackFrame frame, ExecutionResult result){ + + ConstantPool pool = this.getConstantPool(); + ConstantInfo info = (ConstantInfo)pool.getConstantInfo(this.getOperand()); + + if(info instanceof StringInfo){ + StringInfo strInfo = (StringInfo)info; + String value = strInfo.toString(); + JavaObject jo = Heap.getInstance().newString(value); + frame.getOprandStack().push(jo); + } + else{ + //TBD 处理其他类型 + throw new RuntimeException("Only support StringInfo constant"); + } + + + } +} diff --git a/group02/812350401/src/main/java/train/jvm/cmd/NewObjectCmd.java b/group02/812350401/src/main/java/train/jvm/cmd/NewObjectCmd.java new file mode 100755 index 0000000000..7f8fc9e351 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,42 @@ +package train.jvm.cmd; + + +import train.jvm.clz.ClassFile; +import train.jvm.constant.ClassInfo; +import train.jvm.engine.ExecutionResult; +import train.jvm.engine.Heap; +import train.jvm.engine.JavaObject; +import train.jvm.engine.StackFrame; + +/** + * 创建一个对象,并将引用入栈 + */ +public class NewObjectCmd extends TwoOperandCmd{ + + public NewObjectCmd(ClassFile clzFile, String opCode){ + super(clzFile,opCode); + } + + @Override + public String toString() { + + return super.getOperandAsClassInfo(); + } + public void execute(StackFrame frame, ExecutionResult result){ + + int index = this.getIndex(); + + ClassInfo info = (ClassInfo)this.getConstantInfo(index); + + String clzName = info.getClassName(); + + //在Java堆上创建一个实例 + JavaObject jo = Heap.getInstance().newObject(clzName); + + frame.getOprandStack().push(jo); + + + + } + +} diff --git a/group02/812350401/src/main/java/train/jvm/cmd/NoOperandCmd.java b/group02/812350401/src/main/java/train/jvm/cmd/NoOperandCmd.java new file mode 100755 index 0000000000..13c25c058e --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,147 @@ +package train.jvm.cmd; + + +import train.jvm.clz.ClassFile; +import train.jvm.engine.ExecutionResult; +import train.jvm.engine.Heap; +import train.jvm.engine.JavaObject; +import train.jvm.engine.StackFrame; + +public class NoOperandCmd extends ByteCodeCommand{ + + public NoOperandCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + @Override + public String toString() { + return this.getOffset()+":" +this.getOpCode() + " "+ this.getReadableCodeText(); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + String opCode = this.getOpCode(); + + if(ByteCodeCommand.aload_0.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(0); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.aload_1.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.aload_2.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + }else if(ByteCodeCommand.iload_1.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_2.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_3.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + }else if (ByteCodeCommand.fload_3.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + } + else if (ByteCodeCommand.voidreturn.equals(opCode)){ + + result.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME); + + } else if(ByteCodeCommand.ireturn.equals(opCode)){ + // 结束方法,并返回一个 int 类型数据 + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.freturn.equals(opCode)){ + + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + } + + else if(ByteCodeCommand.astore_1.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if(ByteCodeCommand.dup.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().peek(); + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.iconst_0.equals(opCode)){ + + JavaObject jo = Heap.getInstance().newInt(0); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.iconst_1.equals(opCode)){ + + JavaObject jo = Heap.getInstance().newInt(1); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.istore_1.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if(ByteCodeCommand.istore_2.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(2, jo); + + } else if(ByteCodeCommand.iadd.equals(opCode)){ + + JavaObject jo1 = frame.getOprandStack().pop(); + JavaObject jo2 = frame.getOprandStack().pop(); + + JavaObject sum = Heap.getInstance().newInt(jo1.getIntValue()+jo2.getIntValue()); + + frame.getOprandStack().push(sum); + + } else if (ByteCodeCommand.aconst_null.equals(opCode)){ + + frame.getOprandStack().push(null); + + } + else{ + throw new RuntimeException("you must forget to implement the operation :" + opCode); + } + + + } + + + public int getLength(){ + return 1; + } + +} diff --git a/group02/812350401/src/main/java/train/jvm/cmd/OneOperandCmd.java b/group02/812350401/src/main/java/train/jvm/cmd/OneOperandCmd.java new file mode 100755 index 0000000000..361e0ab20b --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,28 @@ +package train.jvm.cmd; + + +import train.jvm.clz.ClassFile; + +public abstract class OneOperandCmd extends ByteCodeCommand { + + private int operand; + + public OneOperandCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + + } + public int getOperand() { + + return this.operand; + } + + public void setOperand(int oprand1) { + this.operand = oprand1; + + } + public int getLength(){ + return 2; + } + + +} diff --git a/group02/812350401/src/main/java/train/jvm/cmd/PutFieldCmd.java b/group02/812350401/src/main/java/train/jvm/cmd/PutFieldCmd.java new file mode 100755 index 0000000000..42ec34a5a8 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,44 @@ +package train.jvm.cmd; + + +import train.jvm.clz.ClassFile; +import train.jvm.constant.ClassInfo; +import train.jvm.constant.FieldRefInfo; +import train.jvm.constant.NameAndTypeInfo; +import train.jvm.engine.ExecutionResult; +import train.jvm.engine.JavaObject; +import train.jvm.engine.StackFrame; + +public class PutFieldCmd extends TwoOperandCmd { + + public PutFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString() { + + return super.getOperandAsField(); + } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + FieldRefInfo fieldRef = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + + ClassInfo clzInfo = (ClassInfo)this.getConstantInfo(fieldRef.getClassInfoIndex()); + NameAndTypeInfo nameTypeInfo = (NameAndTypeInfo)this.getConstantInfo(fieldRef.getNameAndTypeIndex()); + // for example : name + String fieldName = nameTypeInfo.getName(); + // for example : Ljava/lang/String : 注意:我们不再检查类型 + String fieldType = nameTypeInfo.getTypeInfo(); + + JavaObject fieldValue = frame.getOprandStack().pop(); + JavaObject objectRef = frame.getOprandStack().pop(); + + objectRef.setFieldValue(fieldName, fieldValue); + + } + + + +} diff --git a/group02/812350401/src/main/java/train/jvm/cmd/TwoOperandCmd.java b/group02/812350401/src/main/java/train/jvm/cmd/TwoOperandCmd.java new file mode 100755 index 0000000000..cdb54a3153 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,67 @@ +package train.jvm.cmd; + + +import train.jvm.clz.ClassFile; +import train.jvm.constant.ClassInfo; +import train.jvm.constant.ConstantInfo; +import train.jvm.constant.FieldRefInfo; +import train.jvm.constant.MethodRefInfo; + +public abstract class TwoOperandCmd extends ByteCodeCommand{ + + int oprand1 = -1; + int oprand2 = -1; + + public int getOprand1() { + return oprand1; + } + + public void setOprand1(int oprand1) { + this.oprand1 = oprand1; + } + + public void setOprand2(int oprand2) { + this.oprand2 = oprand2; + } + + public int getOprand2() { + return oprand2; + } + + public TwoOperandCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + public int getIndex(){ + int oprand1 = this.getOprand1(); + int oprand2 = this.getOprand2(); + int index = oprand1 << 8 | oprand2; + return index; + } + + protected String getOperandAsClassInfo(){ + int index = getIndex(); + String codeTxt = getReadableCodeText(); + ClassInfo info = (ClassInfo)getConstantInfo(index); + return this.getOffset()+":"+this.getOpCode()+" "+ codeTxt +" "+ info.getClassName(); + } + + protected String getOperandAsMethod(){ + int index = getIndex(); + String codeTxt = getReadableCodeText(); + ConstantInfo constInfo = this.getConstantInfo(index); + MethodRefInfo info = (MethodRefInfo)this.getConstantInfo(index); + return this.getOffset()+":"+this.getOpCode()+" " + codeTxt +" "+ info.toString(); + } + + protected String getOperandAsField(){ + int index = getIndex(); + + String codeTxt = getReadableCodeText(); + FieldRefInfo info = (FieldRefInfo)this.getConstantInfo(index); + return this.getOffset()+":"+this.getOpCode()+" " + codeTxt +" "+ info.toString(); + } + public int getLength(){ + return 3; + } +} diff --git a/group02/812350401/src/main/java/train/jvm/constant/ClassInfo.java b/group02/812350401/src/main/java/train/jvm/constant/ClassInfo.java new file mode 100755 index 0000000000..5021524d95 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/constant/ClassInfo.java @@ -0,0 +1,28 @@ +package train.jvm.constant; + +public class ClassInfo extends ConstantInfo { + private int type = ConstantInfo.CLASS_INFO; + private int utf8Index ; + public ClassInfo(ConstantPool pool) { + super(pool); + } + public int getUtf8Index() { + return utf8Index; + } + public void setUtf8Index(int utf8Index) { + this.utf8Index = utf8Index; + } + public int getType() { + return type; + } + + public String getClassName() { + int index = getUtf8Index(); + UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); + return utf8Info.getValue(); + } + @Override + public void accept(Visitor visitor) { + visitor.visitClassInfo(this); + } +} diff --git a/group02/812350401/src/main/java/train/jvm/constant/ConstantInfo.java b/group02/812350401/src/main/java/train/jvm/constant/ConstantInfo.java new file mode 100755 index 0000000000..43aac9a7fe --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/constant/ConstantInfo.java @@ -0,0 +1,40 @@ +package train.jvm.constant; + +public abstract class ConstantInfo { + public static final int UTF8_INFO = 1; + public static final int FLOAT_INFO = 4; + public static final int CLASS_INFO = 7; + public static final int STRING_INFO = 8; + public static final int FIELD_INFO = 9; + public static final int METHOD_INFO = 10; + public static final int NAME_AND_TYPE_INFO = 12; + protected ConstantPool constantPool; + + public ConstantInfo(){ + + } + + public ConstantInfo(ConstantPool pool) { + this.constantPool = pool; + } + public abstract int getType(); + + public ConstantPool getConstantPool() { + return constantPool; + } + public ConstantInfo getConstantInfo(int index){ + return this.constantPool.getConstantInfo(index); + } + + public abstract void accept(Visitor visitor); + + public static interface Visitor{ + public void visitClassInfo(ClassInfo info); + public void visitFieldRef(FieldRefInfo info); + public void visitMethodRef(MethodRefInfo info); + public void visitNameAndType(NameAndTypeInfo info); + public void visitString(StringInfo info); + public void visistUTF8(UTF8Info info); + + } +} diff --git a/group02/812350401/src/main/java/train/jvm/constant/ConstantPool.java b/group02/812350401/src/main/java/train/jvm/constant/ConstantPool.java new file mode 100755 index 0000000000..0df62fa3c5 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/constant/ConstantPool.java @@ -0,0 +1,31 @@ +package train.jvm.constant; + +import java.util.ArrayList; +import java.util.List; + +public class ConstantPool { + + private List constantInfos = new ArrayList(); + + + public ConstantPool(){ + + } + public void addConstantInfo(ConstantInfo info){ + + this.constantInfos.add(info); + + } + + public ConstantInfo getConstantInfo(int index){ + return this.constantInfos.get(index); + } + public String getUTF8String(int index){ + return ((UTF8Info)this.constantInfos.get(index)).getValue(); + } + public int getSize() { + return this.constantInfos.size() -1; + } + + +} diff --git a/group02/812350401/src/main/java/train/jvm/constant/FieldRefInfo.java b/group02/812350401/src/main/java/train/jvm/constant/FieldRefInfo.java new file mode 100755 index 0000000000..94c2a64c3e --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/constant/FieldRefInfo.java @@ -0,0 +1,58 @@ +package train.jvm.constant; + +public class FieldRefInfo extends ConstantInfo{ + private int type = ConstantInfo.FIELD_INFO; + private int classInfoIndex; + private int nameAndTypeIndex; + + public FieldRefInfo(ConstantPool pool) { + super(pool); + } + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString(){ + + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + + return getClassName() +" : "+ typeInfo.getName() + ":" + typeInfo.getTypeInfo() +"]"; + } + + public String getClassName(){ + + ClassInfo classInfo = (ClassInfo) this.getConstantInfo(this.getClassInfoIndex()); + + UTF8Info utf8Info = (UTF8Info)this.getConstantInfo(classInfo.getUtf8Index()); + + return utf8Info.getValue(); + + } + + public String getFieldName(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getFieldType(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } + @Override + public void accept(Visitor visitor) { + visitor.visitFieldRef(this); + } +} diff --git a/group02/812350401/src/main/java/train/jvm/constant/MethodRefInfo.java b/group02/812350401/src/main/java/train/jvm/constant/MethodRefInfo.java new file mode 100755 index 0000000000..cd820f739e --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/constant/MethodRefInfo.java @@ -0,0 +1,63 @@ +package train.jvm.constant; + +import java.util.ArrayList; +import java.util.List; + +public class MethodRefInfo extends ConstantInfo { + + private int type = ConstantInfo.METHOD_INFO; + + private int classInfoIndex; + private int nameAndTypeIndex; + + public MethodRefInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public String toString(){ + + return getClassName() +" : "+ this.getMethodName() + " : " + this.getParamAndReturnType() ; + } + public String getClassName(){ + ConstantPool pool = this.getConstantPool(); + ClassInfo clzInfo = (ClassInfo)pool.getConstantInfo(this.getClassInfoIndex()); + return clzInfo.getClassName(); + } + + public String getMethodName(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName(); + } + + public String getParamAndReturnType(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getTypeInfo(); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitMethodRef(this); + } + + + +} diff --git a/group02/812350401/src/main/java/train/jvm/constant/NameAndTypeInfo.java b/group02/812350401/src/main/java/train/jvm/constant/NameAndTypeInfo.java new file mode 100755 index 0000000000..09153ed4fa --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,51 @@ +package train.jvm.constant; + +public class NameAndTypeInfo extends ConstantInfo{ + public int type = ConstantInfo.NAME_AND_TYPE_INFO; + + private int index1; + private int index2; + + public NameAndTypeInfo(ConstantPool pool) { + super(pool); + } + + public int getIndex1() { + return index1; + } + public void setIndex1(int index1) { + this.index1 = index1; + } + public int getIndex2() { + return index2; + } + public void setIndex2(int index2) { + this.index2 = index2; + } + public int getType() { + return type; + } + + + public String getName(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info1 = (UTF8Info)pool.getConstantInfo(index1); + return utf8Info1.getValue(); + } + + public String getTypeInfo(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info2 = (UTF8Info)pool.getConstantInfo(index2); + return utf8Info2.getValue(); + } + + public String toString(){ + return "(" + getName() + "," + getTypeInfo()+")"; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitNameAndType(this); + + } +} diff --git a/group02/812350401/src/main/java/train/jvm/constant/NullConstantInfo.java b/group02/812350401/src/main/java/train/jvm/constant/NullConstantInfo.java new file mode 100755 index 0000000000..32e71c6d4c --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/constant/NullConstantInfo.java @@ -0,0 +1,17 @@ +package train.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + @Override + public void accept(Visitor visitor) { + + } + +} diff --git a/group02/812350401/src/main/java/train/jvm/constant/StringInfo.java b/group02/812350401/src/main/java/train/jvm/constant/StringInfo.java new file mode 100755 index 0000000000..2b29f175f5 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/constant/StringInfo.java @@ -0,0 +1,32 @@ +package train.jvm.constant; + +public class StringInfo extends ConstantInfo{ + private int type = ConstantInfo.STRING_INFO; + private int index; + public StringInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getIndex() { + return index; + } + public void setIndex(int index) { + this.index = index; + } + + + public String toString(){ + return this.getConstantPool().getUTF8String(index); + } + + @Override + public void accept(Visitor visitor) { + visitor.visitString(this); + + } + +} diff --git a/group02/812350401/src/main/java/train/jvm/constant/UTF8Info.java b/group02/812350401/src/main/java/train/jvm/constant/UTF8Info.java new file mode 100755 index 0000000000..dea9d42eff --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/constant/UTF8Info.java @@ -0,0 +1,37 @@ +package train.jvm.constant; + +public class UTF8Info extends ConstantInfo{ + private int type = ConstantInfo.UTF8_INFO; + private int length ; + private String value; + public UTF8Info(ConstantPool pool) { + super(pool); + } + public int getLength() { + return length; + } + public void setLength(int length) { + this.length = length; + } + public int getType() { + return type; + } + @Override + public String toString() { + return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value +")]"; + } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + @Override + public void accept(Visitor visitor) { + visitor.visistUTF8(this); + + } + + + +} diff --git a/group02/812350401/src/main/java/train/jvm/engine/ExecutionResult.java b/group02/812350401/src/main/java/train/jvm/engine/ExecutionResult.java new file mode 100755 index 0000000000..f0873233a6 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/engine/ExecutionResult.java @@ -0,0 +1,57 @@ +package train.jvm.engine; + + +import train.jvm.method.Method; + +public class ExecutionResult { + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + + private int nextCmdOffset = 0; + + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + + + public void setNextAction(int action){ + this.nextAction = action; + } + public boolean isPauseAndRunNewFrame(){ + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + public boolean isExitCurrentFrame(){ + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd(){ + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump(){ + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } + + + + + +} diff --git a/group02/812350401/src/main/java/train/jvm/engine/ExecutorEngine.java b/group02/812350401/src/main/java/train/jvm/engine/ExecutorEngine.java new file mode 100755 index 0000000000..f6b4bdd995 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/engine/ExecutorEngine.java @@ -0,0 +1,81 @@ +package train.jvm.engine; + +import train.jvm.method.Method; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + + + +public class ExecutorEngine { + + private Stack stack = new Stack(); + + public ExecutorEngine() { + + } + + public void execute(Method mainMethod){ + + StackFrame mainFrame = StackFrame.create(mainMethod); + stack.push(mainFrame); + + while(!stack.empty()){ + + StackFrame frame = stack.peek(); + + ExecutionResult result = frame.execute(); + + if(result.isPauseAndRunNewFrame()){ + + Method nextMethod = result.getNextMethod(); + StackFrame nextFrame = StackFrame.create(nextMethod); + nextFrame.setCallerFrame(frame); + setupFunctionCallParams(frame, nextFrame); + + stack.push(nextFrame); + + } else { + + stack.pop(); + + } + } + + } + + + + private void setupFunctionCallParams(StackFrame currentFrame,StackFrame nextFrame) { + + Method nextMethod = nextFrame.getMethod(); + + + List paramList = nextMethod.getParameterList(); + + //加上1 是因为要把this也传递过去, todo 对于invokestatic,不传this,不能加1 + + int paramNum = paramList.size() + 1; + + + List values = new ArrayList(); + + //数据结构知识: 从栈中取出栈顶的x个元素 + while(paramNum>0){ + values.add(currentFrame.getOprandStack().pop()); + paramNum --; + } + //数据结构知识: 把一个列表倒序排列 + List params = new ArrayList(); + + for(int i=values.size()-1; i>=0 ;i--){ + params.add(values.get(i)); + } + + + nextFrame.setLocalVariableTable(params); + + } + +} diff --git a/group02/812350401/src/main/java/train/jvm/engine/Heap.java b/group02/812350401/src/main/java/train/jvm/engine/Heap.java new file mode 100755 index 0000000000..a61fd6ed5f --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/engine/Heap.java @@ -0,0 +1,39 @@ +package train.jvm.engine; + +public class Heap { + + /** + * 没有实现垃圾回收, 所以对于下面新创建的对象, 并没有记录到一个数据结构当中 + */ + + private static Heap instance = new Heap(); + private Heap() { + } + public static Heap getInstance(){ + return instance; + } + public JavaObject newObject(String clzName){ + + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + + public JavaObject newString(String value){ + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + return jo; + } + + public JavaObject newFloat(float value){ + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + public JavaObject newInt(int value){ + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } + +} diff --git a/group02/812350401/src/main/java/train/jvm/engine/JavaObject.java b/group02/812350401/src/main/java/train/jvm/engine/JavaObject.java new file mode 100755 index 0000000000..41e0e41ef3 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/engine/JavaObject.java @@ -0,0 +1,71 @@ +package train.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + + private Map fieldValues = new HashMap(); + + private String stringValue; + + private int intValue; + + private float floatValue; + + public void setFieldValue(String fieldName, JavaObject fieldValue){ + fieldValues.put(fieldName, fieldValue); + } + public JavaObject(int type){ + this.type = type; + } + public void setClassName(String className){ + this.className = className; + } + public void setStringValue(String value){ + stringValue = value; + } + public String getStringValue(){ + return this.stringValue; + } + public void setIntValue(int value) { + this.intValue = value; + } + public int getIntValue(){ + return this.intValue; + } + public int getType(){ + return type; + } + public JavaObject getFieldValue(String fieldName){ + return this.fieldValues.get(fieldName); + } + public String toString(){ + switch(this.getType()){ + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className +":"+ this.fieldValues; + case FLOAT : + return String.valueOf(this.floatValue); + default: + return null; + } + } + public String getClassName(){ + return this.className; + } + public void setFloatValue(float value) { + this.floatValue = value; + } + +} diff --git a/group02/812350401/src/main/java/train/jvm/engine/MethodArea.java b/group02/812350401/src/main/java/train/jvm/engine/MethodArea.java new file mode 100755 index 0000000000..d6b7e9cfa3 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/engine/MethodArea.java @@ -0,0 +1,90 @@ +package train.jvm.engine; + +import train.jvm.clz.ClassFile; +import train.jvm.constant.MethodRefInfo; +import train.jvm.loader.ClassFileLoader; +import train.jvm.method.Method; + +import java.util.HashMap; +import java.util.Map; + + + +public class MethodArea { + + public static final MethodArea instance = new MethodArea(); + + /** + * 注意:我们做了极大的简化, ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型 + */ + + private ClassFileLoader clzLoader = null; + + Map map = new HashMap(); + + private MethodArea(){ + } + + public static MethodArea getInstance(){ + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader){ + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className){ + + ClassFile clzFile = this.findClassFile(className); + + return clzFile.getMainMethod(); + } + + + public ClassFile findClassFile(String className){ + + if(map.get(className) != null){ + return map.get(className); + } + // 看来该class 文件还没有load过 + ClassFile clzFile = this.clzLoader.loadClass(className); + + map.put(className, clzFile); + + return clzFile; + + } + + + public Method getMethod(String className, String methodName, String paramAndReturnType){ + + ClassFile clz = this.findClassFile(className); + + Method m = clz.getMethod(methodName, paramAndReturnType); + + if(m == null){ + + throw new RuntimeException("method can't be found : \n" + + "class: " + className + + "method: " + methodName + + "paramAndReturnType: " + paramAndReturnType); + } + + return m; + } + + + public Method getMethod(MethodRefInfo methodRef){ + + ClassFile clz = this.findClassFile(methodRef.getClassName()); + + Method m = clz.getMethod(methodRef.getMethodName(), methodRef.getParamAndReturnType()); + + if(m == null){ + throw new RuntimeException("method can't be found : " + methodRef.toString()); + } + + return m; + + } +} diff --git a/group02/812350401/src/main/java/train/jvm/engine/MiniJVM.java b/group02/812350401/src/main/java/train/jvm/engine/MiniJVM.java new file mode 100755 index 0000000000..31a35c0552 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/engine/MiniJVM.java @@ -0,0 +1,29 @@ +package train.jvm.engine; +import train.jvm.loader.ClassFileLoader; + +import java.io.FileNotFoundException; +import java.io.IOException; + + + +public class MiniJVM { + + public void run(String[]classPaths , String className) throws FileNotFoundException, IOException{ + + ClassFileLoader loader = new ClassFileLoader(); + for(int i=0;i operands = new ArrayList(); + + public void push(JavaObject jo){ + operands.add(jo); + } + public JavaObject pop(){ + int index = size()-1; + JavaObject jo = (JavaObject)operands.get(index); + operands.remove(index); + return jo; + + } + public JavaObject top(){ + int index = size()-1; + return (JavaObject)operands.get(index); + } + public int size(){ + return operands.size(); + } +} diff --git a/group02/812350401/src/main/java/train/jvm/engine/StackFrame.java b/group02/812350401/src/main/java/train/jvm/engine/StackFrame.java new file mode 100755 index 0000000000..54eb3abd97 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/engine/StackFrame.java @@ -0,0 +1,133 @@ +package train.jvm.engine; + +import train.jvm.cmd.ByteCodeCommand; +import train.jvm.method.Method; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + + + +public class StackFrame { + + private List localVariableTable = new ArrayList(); + private Stack oprandStack = new Stack(); + + int index = 0; + + private Method m = null; + + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + + + + public static StackFrame create(Method m){ + + StackFrame frame = new StackFrame( m ); + + return frame; + } + + + private StackFrame(Method m) { + this.m = m; + + } + + + + public JavaObject getLocalVariableValue(int index){ + return this.localVariableTable.get(index); + } + + public Stack getOprandStack(){ + return this.oprandStack; + } + + public int getNextCommandIndex(int offset){ + + ByteCodeCommand[] cmds = m.getCodeAttr().getCmds(); + for(int i=0;i values){ + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo){ + //问题: 为什么要这么做?? 因为一开始局部变量表是空的 + if(this.localVariableTable.size()-1 < index){ + for(int i=this.localVariableTable.size(); i<=index; i++){ + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + + + } + + public Method getMethod(){ + return m; + } + + +} diff --git a/group02/812350401/src/main/java/train/jvm/field/Field.java b/group02/812350401/src/main/java/train/jvm/field/Field.java new file mode 100755 index 0000000000..903350102a --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/field/Field.java @@ -0,0 +1,64 @@ +package train.jvm.field; + + +import train.jvm.attr.AttributeInfo; +import train.jvm.attr.ConstantValue; +import train.jvm.constant.ConstantPool; +import train.jvm.constant.UTF8Info; +import train.jvm.loader.ByteCodeIterator; + +public class Field { + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + + private ConstantPool pool; + private ConstantValue constValue; + + public Field( int accessFlag, int nameIndex, int descriptorIndex,ConstantPool pool) { + + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + this.pool = pool; + } + + public String toString() { + String name = ((UTF8Info)pool.getConstantInfo(this.nameIndex)).getValue(); + + String desc = ((UTF8Info)pool.getConstantInfo(this.descriptorIndex)).getValue(); + return name +":"+ desc; + } + + + public static Field parse(ConstantPool pool, ByteCodeIterator iter){ + + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descIndex = iter.nextU2ToInt(); + int attribCount = iter.nextU2ToInt(); + //System.out.println("field attribute count:"+ attribCount); + + Field f = new Field(accessFlag, nameIndex, descIndex,pool); + + for( int i=1; i<= attribCount; i++){ + int attrNameIndex = iter.nextU2ToInt(); + String attrName = pool.getUTF8String(attrNameIndex); + + if(AttributeInfo.CONST_VALUE.equals(attrName)){ + int attrLen = iter.nextU4ToInt(); + ConstantValue constValue = new ConstantValue(attrNameIndex, attrLen); + constValue.setConstValueIndex(iter.nextU2ToInt()); + f.setConstantValue(constValue); + } else{ + throw new RuntimeException("the attribute " + attrName + " has not been implemented yet."); + } + } + + return f; + } + public void setConstantValue(ConstantValue constValue) { + this.constValue = constValue; + } + +} diff --git a/group02/812350401/src/main/java/train/jvm/loader/ByteCodeIterator.java b/group02/812350401/src/main/java/train/jvm/loader/ByteCodeIterator.java new file mode 100755 index 0000000000..cf71a96d22 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,58 @@ +package train.jvm.loader; + +import train.jvm.util.Util; + +import java.util.Arrays; + + +public class ByteCodeIterator { + byte[] codes; + int pos = 0; + + ByteCodeIterator(byte[] codes) { + this.codes = codes; + } + + + + public byte[] getBytes(int len) { + if (pos + len >= codes.length) { + throw new ArrayIndexOutOfBoundsException(); + } + + byte[] data = Arrays.copyOfRange(codes, pos, pos + len); + pos += len; + return data; + } + + public int nextU1toInt() { + + return Util.byteToInt(new byte[] { codes[pos++] }); + } + + public int nextU2ToInt() { + return Util.byteToInt(new byte[] { codes[pos++], codes[pos++] }); + } + + public int nextU4ToInt() { + return Util.byteToInt(new byte[] { codes[pos++], codes[pos++], codes[pos++], codes[pos++] }); + } + + public String nextU4ToHexString() { + return Util.byteToHexString((new byte[] { codes[pos++], codes[pos++], codes[pos++], codes[pos++] })); + } + + public String nextUxToHexString(int len) { + byte[] tmp = new byte[len]; + + for (int i = 0; i < len; i++) { + tmp[i] = codes[pos++]; + } + return Util.byteToHexString(tmp).toLowerCase(); + + } + + public void back(int n) { + this.pos -= n; + } +} diff --git a/group02/812350401/src/main/java/train/jvm/loader/ClassFileLoader.java b/group02/812350401/src/main/java/train/jvm/loader/ClassFileLoader.java new file mode 100755 index 0000000000..909eb64f66 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/loader/ClassFileLoader.java @@ -0,0 +1,137 @@ +package train.jvm.loader; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import train.jvm.clz.ClassFile; + + +public class ClassFileLoader { + + private List clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) { + + className = className.replace('.', File.separatorChar) +".class"; + + for(String path : this.clzPaths){ + + String clzFileName = path + File.separatorChar + className; + byte[] codes = loadClassFile(clzFileName); + if(codes != null){ + return codes; + } + } + + return null; + + + + } + + private byte[] loadClassFile(String clzFileName) { + + File f = new File(clzFileName); + + try { + + return IOUtils.toByteArray(new FileInputStream(f)); + + } catch (IOException e) { + System.out.println(String.format("no class found in %s", clzFileName)); + System.out.println(); + return null; + } + } + + + + public void addClassPath(String path) { + if(this.clzPaths.contains(path)){ + return; + } + + this.clzPaths.add(path); + + } + + + + public String getClassPath(){ + return StringUtils.join(this.clzPaths,";"); + } + + public ClassFile loadClass(String className) { + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(codes); + + } + + + + // ------------------------------backup------------------------ + public String getClassPath_V1(){ + + StringBuffer buffer = new StringBuffer(); + for(int i=0;i getParameterList(){ + + // e.g. (Ljava/util/List;Ljava/lang/String;II)V + String paramAndType = getParamAndReturnType(); + + int first = paramAndType.indexOf("("); + int last = paramAndType.lastIndexOf(")"); + // e.g. Ljava/util/List;Ljava/lang/String;II + String param = paramAndType.substring(first+1, last); + + List paramList = new ArrayList(); + + if((null == param) || "".equals(param)){ + return paramList; + } + + while(!param.equals("")){ + + int pos = 0; + // 这是一个对象类型 + if(param.charAt(pos) == 'L'){ + + int end = param.indexOf(";"); + + if(end == -1){ + throw new RuntimeException("can't find the ; for a object type"); + } + paramList.add(param.substring(pos+1,end)); + + pos = end + 1; + + } + else if(param.charAt(pos) == 'I'){ + // int + paramList.add("I"); + pos ++; + + } + else if(param.charAt(pos) == 'F'){ + // float + paramList.add("F"); + pos ++; + + } else{ + throw new RuntimeException("the param has unsupported type:" + param); + } + + param = param.substring(pos); + + } + return paramList; + + } +} diff --git a/group02/812350401/src/main/java/train/jvm/print/ClassFilePrinter.java b/group02/812350401/src/main/java/train/jvm/print/ClassFilePrinter.java new file mode 100755 index 0000000000..da64c32ce7 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/print/ClassFilePrinter.java @@ -0,0 +1,46 @@ +package train.jvm.print; + + +import train.jvm.clz.ClassFile; +import train.jvm.loader.ClassFileLoader; + +public class ClassFilePrinter { + ClassFile clzFile = null; + public ClassFilePrinter(ClassFile clzFile){ + this.clzFile = clzFile; + } + + public void print(){ + + if(clzFile.getAccessFlag().isPublicClass()){ + System.out.println("Access flag : public "); + } + System.out.println("Class Name:"+ clzFile.getClassName()); + + System.out.println("Super Class Name:"+ clzFile.getSuperClassName()); + + System.out.println("minor version:" + clzFile.getMinorVersion()); + + System.out.println("major version:" + clzFile.getMinorVersion()); + + ConstantPoolPrinter cnstPoolPrinter = new ConstantPoolPrinter(clzFile.getConstantPool()); + cnstPoolPrinter.print(); + + + + + } + + public static void main(String[] args){ + String path = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\answer\\bin"; + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path); + String className = "com.coderising.jvm.test.EmployeeV1"; + + ClassFile clzFile = loader.loadClass(className); + + ClassFilePrinter printer = new ClassFilePrinter(clzFile); + + printer.print(); + } +} diff --git a/group02/812350401/src/main/java/train/jvm/print/ConstantPoolPrinter.java b/group02/812350401/src/main/java/train/jvm/print/ConstantPoolPrinter.java new file mode 100755 index 0000000000..7e74edb4c3 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/print/ConstantPoolPrinter.java @@ -0,0 +1,77 @@ +package train.jvm.print; + + +import train.jvm.constant.*; + +public class ConstantPoolPrinter { + ConstantPool pool; + ConstantPoolPrinter(ConstantPool pool){ + this.pool = pool; + } + public void print(){ + + System.out.println("Constant Pool:"); + + ConstantInfo.Visitor visitor = new ConstantInfo.Visitor() { + + @Override + public void visitString(StringInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("String #").append(info.getIndex()); + System.out.println(buffer); + + } + + @Override + public void visitNameAndType(NameAndTypeInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("NameAndType #").append(info.getIndex1()).append(":#") + .append(info.getIndex2()); + System.out.println(buffer); + + } + + @Override + public void visitMethodRef(MethodRefInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("MethodRef #").append(info.getClassInfoIndex()).append(".#") + .append(info.getNameAndTypeIndex()); + System.out.println(buffer); + + } + + @Override + public void visitFieldRef(FieldRefInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("FieldRef #").append(info.getClassInfoIndex()).append(".#") + .append(info.getNameAndTypeIndex()); + System.out.println(buffer); + + } + + @Override + public void visitClassInfo(ClassInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("Class #").append(info.getUtf8Index()) + .append(" ").append(info.getClassName()); + + System.out.println(buffer); + + } + + @Override + public void visistUTF8(UTF8Info info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("UTF8 ").append(info.getValue()); + System.out.println(buffer); + + } + }; + + for(int i=1; i<=pool.getSize(); i++){ + ConstantInfo constantInfo = pool.getConstantInfo(i); + System.out.print("#"+i+"="); + constantInfo.accept(visitor); + } + } +} diff --git a/group02/812350401/src/main/java/train/jvm/print/ConstantPoolPrinterBad.java b/group02/812350401/src/main/java/train/jvm/print/ConstantPoolPrinterBad.java new file mode 100755 index 0000000000..a382aae84c --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/print/ConstantPoolPrinterBad.java @@ -0,0 +1,41 @@ +package train.jvm.print; + + +import train.jvm.constant.ClassInfo; +import train.jvm.constant.ConstantInfo; +import train.jvm.constant.ConstantPool; +import train.jvm.constant.UTF8Info; + +public class ConstantPoolPrinterBad { + ConstantPool pool; + ConstantPoolPrinterBad(ConstantPool pool){ + this.pool = pool; + } + public void print(){ + + System.out.println("Constant Pool:"); + + for(int i=1; i<=pool.getSize(); i++){ + ConstantInfo cnstInfo = pool.getConstantInfo(i); + + System.out.print("#"+i+"="); + if(cnstInfo instanceof ClassInfo){ + ClassInfo info = (ClassInfo)cnstInfo; + // Class #2 com/coderising/jvm/test/EmployeeV1 + StringBuilder buffer = new StringBuilder(); + buffer.append("Class #").append(info.getUtf8Index()) + .append(" ").append(info.getClassName()); + + System.out.println(buffer); + } + if(cnstInfo instanceof UTF8Info){ + //UTF8 com/coderising/jvm/test/EmployeeV1 + UTF8Info info = (UTF8Info)cnstInfo; + StringBuilder buffer = new StringBuilder(); + buffer.append("UTF8 ").append(info.getValue()); + System.out.println(buffer); + } + //其他的if else + } + } +} diff --git a/group02/812350401/src/main/java/train/jvm/test/ClassFileloaderTest.java b/group02/812350401/src/main/java/train/jvm/test/ClassFileloaderTest.java new file mode 100755 index 0000000000..49757d9e6c --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,348 @@ +package train.jvm.test; + +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import train.jvm.clz.ClassFile; +import train.jvm.clz.ClassIndex; +import train.jvm.cmd.BiPushCmd; +import train.jvm.cmd.ByteCodeCommand; +import train.jvm.cmd.OneOperandCmd; +import train.jvm.cmd.TwoOperandCmd; +import train.jvm.constant.*; +import train.jvm.field.Field; +import train.jvm.loader.ClassFileLoader; +import train.jvm.method.Method; + + +public class ClassFileloaderTest { + + + private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; + static String path1 = ClassFileloaderTest.class.getClassLoader().getResource("struts").getPath(); + static String path2 = ClassFileloaderTest.class.getClassLoader().getResource("classfile").getPath(); + static ClassFile clzFile = null; + + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + loader.addClassPath(path2); + String className = "com.coderising.jvm.test.EmployeeV1"; + + clzFile = loader.loadClass(className); + + } + + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testClassPath(){ + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + loader.addClassPath(path2); + + String clzPath = loader.getClassPath(); + + Assert.assertEquals(path1+";"+path2,clzPath); + + } + + @Test + public void testClassFileLength() { + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + loader.addClassPath(path2); + + String className = "com.coderising.jvm.test.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1056, byteCodes.length); + + } + + + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + loader.addClassPath(path2); + String className = "com.coderising.jvm.test.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + byte[] codes = new byte[]{byteCodes[0],byteCodes[1],byteCodes[2],byteCodes[3]}; + + + String acctualValue = this.byteToHexString(codes); + + Assert.assertEquals("cafebabe", acctualValue); + } + + + + private String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(10); + Assert.assertEquals("(Ljava/lang/String;I)V", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(11); + Assert.assertEquals("Code", utf8Info.getValue()); + } + + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(12); + Assert.assertEquals(3, methodRef.getClassInfoIndex()); + Assert.assertEquals(13, methodRef.getNameAndTypeIndex()); + } + + { + NameAndTypeInfo nameAndType = (NameAndTypeInfo) pool.getConstantInfo(13); + Assert.assertEquals(9, nameAndType.getIndex1()); + Assert.assertEquals(14, nameAndType.getIndex2()); + } + //抽查几个吧 + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(45); + Assert.assertEquals(1, methodRef.getClassInfoIndex()); + Assert.assertEquals(46, methodRef.getNameAndTypeIndex()); + } + + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(53); + Assert.assertEquals("EmployeeV1.java", utf8Info.getValue()); + } + } + @Test + public void testClassIndex(){ + + ClassIndex clzIndex = clzFile.getClzIndex(); + ClassInfo thisClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getThisClassIndex()); + ClassInfo superClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getSuperClassIndex()); + + + Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, thisClassInfo.getClassName()); + Assert.assertEquals("java/lang/Object", superClassInfo.getClassName()); + } + + /** + * 下面是第三次JVM课应实现的测试用例 + */ + @Test + public void testReadFields(){ + + List fields = clzFile.getFields(); + Assert.assertEquals(2, fields.size()); + { + Field f = fields.get(0); + Assert.assertEquals("name:Ljava/lang/String;", f.toString()); + } + { + Field f = fields.get(1); + Assert.assertEquals("age:I", f.toString()); + } + } + @Test + public void testMethods(){ + + List methods = clzFile.getMethods(); + ConstantPool pool = clzFile.getConstantPool(); + + { + Method m = methods.get(0); + assertMethodEquals(pool,m, + "", + "(Ljava/lang/String;I)V", + "2ab7000c2a2bb5000f2a1cb50011b1"); + + } + { + Method m = methods.get(1); + assertMethodEquals(pool,m, + "setName", + "(Ljava/lang/String;)V", + "2a2bb5000fb1"); + + } + { + Method m = methods.get(2); + assertMethodEquals(pool,m, + "setAge", + "(I)V", + "2a1bb50011b1"); + } + { + Method m = methods.get(3); + assertMethodEquals(pool,m, + "sayHello", + "()V", + "b2001c1222b60024b1"); + + } + { + Method m = methods.get(4); + assertMethodEquals(pool,m, + "main", + "([Ljava/lang/String;)V", + "bb000159122b101db7002d4c2bb6002fb1"); + } + } + + private void assertMethodEquals(ConstantPool pool,Method m , String expectedName, String expectedDesc,String expectedCode){ + String methodName = pool.getUTF8String(m.getNameIndex()); + String methodDesc = pool.getUTF8String(m.getDescriptorIndex()); + String code = m.getCodeAttr().getCode(); + Assert.assertEquals(expectedName, methodName); + Assert.assertEquals(expectedDesc, methodDesc); + Assert.assertEquals(expectedCode, code); + } + + @Test + public void testByteCodeCommand(){ + { + Method initMethod = this.clzFile.getMethod("", "(Ljava/lang/String;I)V"); + ByteCodeCommand [] cmds = initMethod.getCmds(); + + assertOpCodeEquals("0: aload_0", cmds[0]); + assertOpCodeEquals("1: invokespecial #12", cmds[1]); + assertOpCodeEquals("4: aload_0", cmds[2]); + assertOpCodeEquals("5: aload_1", cmds[3]); + assertOpCodeEquals("6: putfield #15", cmds[4]); + assertOpCodeEquals("9: aload_0", cmds[5]); + assertOpCodeEquals("10: iload_2", cmds[6]); + assertOpCodeEquals("11: putfield #17", cmds[7]); + assertOpCodeEquals("14: return", cmds[8]); + } + + { + Method setNameMethod = this.clzFile.getMethod("setName", "(Ljava/lang/String;)V"); + ByteCodeCommand [] cmds = setNameMethod.getCmds(); + + assertOpCodeEquals("0: aload_0", cmds[0]); + assertOpCodeEquals("1: aload_1", cmds[1]); + assertOpCodeEquals("2: putfield #15", cmds[2]); + assertOpCodeEquals("5: return", cmds[3]); + + } + + { + Method sayHelloMethod = this.clzFile.getMethod("sayHello", "()V"); + ByteCodeCommand [] cmds = sayHelloMethod.getCmds(); + + assertOpCodeEquals("0: getstatic #28", cmds[0]); + assertOpCodeEquals("3: ldc #34", cmds[1]); + assertOpCodeEquals("5: invokevirtual #36", cmds[2]); + assertOpCodeEquals("8: return", cmds[3]); + + } + + { + Method mainMethod = this.clzFile.getMainMethod(); + + ByteCodeCommand[] cmds = mainMethod.getCmds(); + + assertOpCodeEquals("0: new #1", cmds[0]); + assertOpCodeEquals("3: dup", cmds[1]); + assertOpCodeEquals("4: ldc #43", cmds[2]); + assertOpCodeEquals("6: bipush 29", cmds[3]); + assertOpCodeEquals("8: invokespecial #45", cmds[4]); + assertOpCodeEquals("11: astore_1", cmds[5]); + assertOpCodeEquals("12: aload_1", cmds[6]); + assertOpCodeEquals("13: invokevirtual #47", cmds[7]); + assertOpCodeEquals("16: return", cmds[8]); + } + + } + + private void assertOpCodeEquals(String expected, ByteCodeCommand cmd){ + + String acctual = cmd.getOffset()+": "+cmd.getReadableCodeText(); + + if(cmd instanceof OneOperandCmd){ + if(cmd instanceof BiPushCmd){ + acctual += " " + ((OneOperandCmd)cmd).getOperand(); + } else{ + acctual += " #" + ((OneOperandCmd)cmd).getOperand(); + } + } + if(cmd instanceof TwoOperandCmd){ + acctual += " #" + ((TwoOperandCmd)cmd).getIndex(); + } + Assert.assertEquals(expected, acctual); + } + +} diff --git a/group02/812350401/src/main/java/train/jvm/test/EmployeeV1.java b/group02/812350401/src/main/java/train/jvm/test/EmployeeV1.java new file mode 100755 index 0000000000..6e4dd0a543 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package train.jvm.test; + +public class EmployeeV1 { + + + private String name; + private int age; + + public EmployeeV1(String name, int age) { + this.name = name; + this.age = age; + } + + public void setName(String name) { + this.name = name; + } + public void setAge(int age){ + this.age = age; + } + public void sayHello() { + System.out.println("Hello , this is class Employee "); + } + public static void main(String[] args){ + EmployeeV1 p = new EmployeeV1("Andy",29); + p.sayHello(); + + } +} \ No newline at end of file diff --git a/group02/812350401/src/main/java/train/jvm/test/EmployeeV2.java b/group02/812350401/src/main/java/train/jvm/test/EmployeeV2.java new file mode 100755 index 0000000000..75ad361a30 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/test/EmployeeV2.java @@ -0,0 +1,54 @@ +package train.jvm.test; + +public class EmployeeV2 { + + public final static String TEAM_NAME = "Dev Team"; + private String name; + private int age; + public EmployeeV2(String name, int age) { + this.name = name; + this.age = age; + } + + public void sayHello() { + System.out.println("Hello , this is class Employee "); + System.out.println(TEAM_NAME); + System.out.println(this.name); + } + + public void setName(String name) { + this.name = name; + } + + public void setAge(int age) { + this.age = age; + } + + + + public void isYouth() { + if (age < 40) { + System.out.println("You're still young"); + } else { + System.out.println("You're old"); + } + } + + + + public void testAdd() { + int sum = 0; + for (int i = 1; i <= 100; i++) { + sum += i; + } + System.out.println(sum); + } + + + public static void main(String[] args) { + EmployeeV2 p = new EmployeeV2("Andy", 35); + p.sayHello(); + p.isYouth(); + p.testAdd(); + } +} \ No newline at end of file diff --git a/group02/812350401/src/main/java/train/jvm/test/Example.java b/group02/812350401/src/main/java/train/jvm/test/Example.java new file mode 100755 index 0000000000..f2ad8090a8 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/test/Example.java @@ -0,0 +1,16 @@ +package train.jvm.test; + +public class Example{ + public void disp(char c){ + System.out.println(c); + } + public void disp(int c){ + System.out.println(c ); + } + public static void main(String args[]){ + Example obj = new Example(); + obj.disp('a'); + obj.disp(5); + } +} + diff --git a/group02/812350401/src/main/java/train/jvm/test/HourlyEmployee.java b/group02/812350401/src/main/java/train/jvm/test/HourlyEmployee.java new file mode 100755 index 0000000000..d1ff038106 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/test/HourlyEmployee.java @@ -0,0 +1,27 @@ +package train.jvm.test; + +public class HourlyEmployee extends EmployeeV2 { + + int hourlySalary; + + public HourlyEmployee(String name, + int age, int hourlySalary) { + super(name, age); + this.hourlySalary = hourlySalary; + } + + public void sayHello(){ + System.out.println("Hello , this is Hourly Employee"); + } + public static void main(String[] args){ + EmployeeV2 e = new HourlyEmployee("Lisa", 20, 40); + e.sayHello(); + } + + public int getHourlySalary(){ + return this.hourlySalary; + } + + + +} diff --git a/group02/812350401/src/main/java/train/jvm/test/MiniJVMTest.java b/group02/812350401/src/main/java/train/jvm/test/MiniJVMTest.java new file mode 100755 index 0000000000..6df3d6e448 --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/test/MiniJVMTest.java @@ -0,0 +1,33 @@ +package train.jvm.test; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import train.jvm.engine.MiniJVM; + + +public class MiniJVMTest { + static final String PATH = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\answer\\bin"; + static String PATH1 = MiniJVMTest.class.getClassLoader().getResource("struts").getPath(); + static String PATH2 = MiniJVMTest.class.getClassLoader().getResource("classfile").getPath(); + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testMain() throws Exception{ + String[] classPaths = {PATH, PATH2, PATH2}; + MiniJVM jvm = new MiniJVM(); + + jvm.run(classPaths, "com.coderising.jvm.test.EmployeeV1"); +// jvm.run(classPaths, "com.coderising.jvm.test.HourlyEmployee"); +// jvm.run(classPaths, "com.coderising.jvm.test.EmployeeV2"); + + } + +} diff --git a/group02/812350401/src/main/java/train/jvm/util/Util.java b/group02/812350401/src/main/java/train/jvm/util/Util.java new file mode 100755 index 0000000000..d5a5ec8f6f --- /dev/null +++ b/group02/812350401/src/main/java/train/jvm/util/Util.java @@ -0,0 +1,24 @@ +package train.jvm.util; + +public class Util { + public static int byteToInt(byte[] codes){ + String s1 = byteToHexString(codes); + return Integer.valueOf(s1, 16).intValue(); + } + + + + public static String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i