This commit is contained in:
wangxiang
2023-07-22 16:45:02 +08:00
parent 02fa4ffe23
commit 38e512e0ef
52 changed files with 152 additions and 281 deletions

View File

@@ -9,10 +9,10 @@ import org.apache.commons.cli.Options;
import haidnor.jvm.classloader.ClassLoader; import haidnor.jvm.classloader.ClassLoader;
import haidnor.jvm.core.JavaExecutionEngine; import haidnor.jvm.core.JavaExecutionEngine;
import haidnor.jvm.rtda.heap.Klass; import haidnor.jvm.rtda.Klass;
import haidnor.jvm.rtda.heap.KlassMethod; import haidnor.jvm.rtda.KlassMethod;
import haidnor.jvm.rtda.metaspace.Metaspace; import haidnor.jvm.rtda.Metaspace;
import haidnor.jvm.runtime.JvmThread; import haidnor.jvm.runtime.JVMThread;
import haidnor.jvm.util.JavaClassUtil; import haidnor.jvm.util.JavaClassUtil;
import haidnor.jvm.util.JvmThreadHolder; import haidnor.jvm.util.JvmThreadHolder;
import lombok.SneakyThrows; import lombok.SneakyThrows;
@@ -53,11 +53,11 @@ public class Main {
if (!entry.isDirectory() && entry.getName().endsWith(".class")) { if (!entry.isDirectory() && entry.getName().endsWith(".class")) {
String className = entry.getName().replace('/', '.').substring(0, entry.getName().length() - 6); String className = entry.getName().replace('/', '.').substring(0, entry.getName().length() - 6);
if (className.equals(mainClass)) { if (className.equals(mainClass)) {
JvmThreadHolder.set(new JvmThread()); JvmThreadHolder.set(new JVMThread());
Klass mainMeteKlass = bootClassLoader.loadClass(jarFile, entry); Klass mainMeteKlass = bootClassLoader.loadClass(jarFile, entry);
KlassMethod mainKlassMethod = JavaClassUtil.getMainMethod(mainMeteKlass); KlassMethod mainKlassMethod = JavaClassUtil.getMainMethod(mainMeteKlass);
Metaspace.registerJavaClass(mainMeteKlass); Metaspace.registerJavaClass(mainMeteKlass);
JavaExecutionEngine.callMainStaticMethod(mainKlassMethod); JavaExecutionEngine.callMainMethod(mainKlassMethod);
return; return;
} }
} }
@@ -65,14 +65,14 @@ public class Main {
} }
} }
if (cmd.hasOption("class")) { if (cmd.hasOption("class")) {
JvmThreadHolder.set(new JvmThread()); JvmThreadHolder.set(new JVMThread());
String path = cmd.getOptionValue("class"); String path = cmd.getOptionValue("class");
ClassLoader bootClassLoader = new ClassLoader("ApplicationClassLoader"); ClassLoader bootClassLoader = new ClassLoader("ApplicationClassLoader");
Klass mainMeteKlass = bootClassLoader.loadClassWithAbsolutePath(path); Klass mainMeteKlass = bootClassLoader.loadClassWithAbsolutePath(path);
KlassMethod mainKlassMethod = JavaClassUtil.getMainMethod(mainMeteKlass); KlassMethod mainKlassMethod = JavaClassUtil.getMainMethod(mainMeteKlass);
Metaspace.registerJavaClass(mainMeteKlass); Metaspace.registerJavaClass(mainMeteKlass);
JavaExecutionEngine.callMainStaticMethod(mainKlassMethod); JavaExecutionEngine.callMainMethod(mainKlassMethod);
} }
} }

View File

@@ -1,6 +1,6 @@
package haidnor.jvm.classloader; package haidnor.jvm.classloader;
import haidnor.jvm.rtda.heap.Klass; import haidnor.jvm.rtda.Klass;
import org.apache.bcel.classfile.ClassParser; import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.JavaClass; import org.apache.bcel.classfile.JavaClass;

View File

@@ -1,61 +0,0 @@
package haidnor.jvm.core;
import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.instruction.InstructionFactory;
import haidnor.jvm.instruction.control.RETURN;
import haidnor.jvm.runtime.Frame;
import haidnor.jvm.util.CodeStream;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import java.util.HashMap;
import java.util.Map;
/**
* 字节码执行解释器
*
* @author wang xiang
*/
@Slf4j
public class Interpreter {
@SneakyThrows
public static void executeFrame(Frame frame) {
int stackSize = frame.getJvmThread().stackSize();
StringBuilder blank = new StringBuilder();
blank.append(" ".repeat(stackSize - 1));
int index = 0;
for (int i = 0; i < stackSize - 1; i++) {
blank.replace(index, index + 1, "");
index += 20;
}
log.debug("{}┌──────────────────[{}] {} | {}", blank, stackSize, frame.klass.getClassName(), frame.getMethod());
// 解析方法中的字节码指令
Map<Integer, Instruction> instructionMap = new HashMap<>();
CodeStream codeStream = frame.getCodeStream();
while (codeStream.available() > 0) {
Instruction instruction = InstructionFactory.creatInstruction(codeStream);
log.debug("{}│> {}", blank, instruction);
instructionMap.put(instruction.index(), instruction);
}
log.debug("{}├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌", blank);
// 执行方法中的字节码指令 tip:(int i, 相当于程序计数器, 记录当前执行到的字节码指令的”行号“)
for (int i = 0; i < frame.getCodeLength(); ) {
Instruction instruction = instructionMap.get(i);
log.debug("{}│ {}", blank, instruction);
instruction.execute(frame);
if (instruction instanceof RETURN) {
break;
}
i += instruction.offSet();
}
log.debug("{}└──────────────────[{}] {} | {}", blank, stackSize, frame.klass.getClassName(), frame.getMethod());
}
}

View File

@@ -1,32 +1,41 @@
package haidnor.jvm.core; package haidnor.jvm.core;
import haidnor.jvm.rtda.heap.KlassMethod; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.instruction.InstructionFactory;
import haidnor.jvm.instruction.control.RETURN;
import haidnor.jvm.rtda.KlassMethod;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.runtime.JvmThread; import haidnor.jvm.runtime.JVMThread;
import haidnor.jvm.runtime.StackValue; import haidnor.jvm.runtime.StackValue;
import haidnor.jvm.util.CodeStream;
import haidnor.jvm.util.JvmThreadHolder; import haidnor.jvm.util.JvmThreadHolder;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.bcel.classfile.LocalVariable; import org.apache.bcel.classfile.LocalVariable;
import org.apache.bcel.classfile.LocalVariableTable; import org.apache.bcel.classfile.LocalVariableTable;
import org.apache.bcel.classfile.Method; import org.apache.bcel.classfile.Method;
import org.apache.bcel.classfile.Utility; import org.apache.bcel.classfile.Utility;
import java.util.HashMap;
import java.util.Map;
/**
* JVM 执行引擎
*
* @author wang xiang
*/
@Slf4j @Slf4j
public class JavaExecutionEngine { public class JavaExecutionEngine {
public static void callMainStaticMethod(KlassMethod klassMethod) { public static void callMainMethod(KlassMethod klassMethod) {
JvmThread jvmThread = JvmThreadHolder.get(); callMethod(null, klassMethod);
// 每个栈帧中包含一个指向运行时常量池中该栈帧所属的方法的引用。包含这个引用的目的就是为了支持当前方法实现动态链接
// 有了这个引用,执行引擎就可以找到指定的方法,加载字节码指令
Frame frame = new Frame(jvmThread, klassMethod);
jvmThread.push(frame);
Interpreter.executeFrame(frame);
} }
public static void callMethod(Frame lastFrame, KlassMethod klassMethod) { public static void callMethod(Frame lastFrame, KlassMethod klassMethod) {
JvmThread jvmThread = JvmThreadHolder.get(); JVMThread jvmThread = JvmThreadHolder.get();
Frame newFrame = new Frame(jvmThread, klassMethod); Frame newFrame = new Frame(jvmThread, klassMethod);
// 如果有上一个栈帧, 代表需要传参 // 如果有上一个栈帧, 代表需要传参
if (lastFrame != null) { if (lastFrame != null) {
Method method = klassMethod.javaMethod; Method method = klassMethod.javaMethod;
@@ -53,7 +62,46 @@ public class JavaExecutionEngine {
} }
jvmThread.push(newFrame); jvmThread.push(newFrame);
Interpreter.executeFrame(newFrame); executeFrame(newFrame);
}
@SneakyThrows
public static void executeFrame(Frame frame) {
int stackSize = frame.getJvmThread().stackSize();
StringBuilder blank = new StringBuilder();
blank.append(" ".repeat(stackSize - 1));
int index = 0;
for (int i = 0; i < stackSize - 1; i++) {
blank.replace(index, index + 1, "");
index += 20;
}
log.debug("{}┌──────────────────[{}] {} | {}", blank, stackSize, frame.klass.getClassName(), frame.getMethod());
// 解析方法中的字节码指令
Map<Integer, Instruction> instructionMap = new HashMap<>();
CodeStream codeStream = frame.getCodeStream();
while (codeStream.available() > 0) {
Instruction instruction = InstructionFactory.creatInstruction(codeStream);
log.debug("{}│> {}", blank, instruction);
instructionMap.put(instruction.index(), instruction);
}
log.debug("{}├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌", blank);
// 执行方法中的字节码指令 tip:(int i, 相当于程序计数器, 记录当前执行到的字节码指令的”行号“)
for (int i = 0; i < frame.getCodeLength(); ) {
Instruction instruction = instructionMap.get(i);
log.debug("{}│ {}", blank, instruction);
instruction.execute(frame);
if (instruction instanceof RETURN) {
break;
}
i += instruction.offSet();
}
log.debug("{}└──────────────────[{}] {} | {}", blank, stackSize, frame.klass.getClassName(), frame.getMethod());
} }

View File

@@ -16,6 +16,9 @@ import haidnor.jvm.instruction.stores.*;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;
import org.apache.bcel.Const; import org.apache.bcel.Const;
/**
* @author wang xiang
*/
public abstract class InstructionFactory { public abstract class InstructionFactory {
public static Instruction creatInstruction(CodeStream codeStream) { public static Instruction creatInstruction(CodeStream codeStream) {

View File

@@ -1,8 +1,8 @@
package haidnor.jvm.instruction.loads; package haidnor.jvm.instruction.loads;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.Instance; import haidnor.jvm.rtda.Instance;
import haidnor.jvm.rtda.heap.InstanceArray; import haidnor.jvm.rtda.InstanceArray;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -1,7 +1,6 @@
package haidnor.jvm.instruction.loads; package haidnor.jvm.instruction.loads;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.Instance;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.runtime.StackValue; import haidnor.jvm.runtime.StackValue;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -1,7 +1,6 @@
package haidnor.jvm.instruction.loads; package haidnor.jvm.instruction.loads;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.Instance;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.runtime.StackValue; import haidnor.jvm.runtime.StackValue;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -1,7 +1,6 @@
package haidnor.jvm.instruction.loads; package haidnor.jvm.instruction.loads;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.Instance;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.runtime.StackValue; import haidnor.jvm.runtime.StackValue;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -1,7 +1,7 @@
package haidnor.jvm.instruction.loads; package haidnor.jvm.instruction.loads;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.BasicTypeArray; import haidnor.jvm.rtda.BasicTypeArray;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -1,7 +1,7 @@
package haidnor.jvm.instruction.loads; package haidnor.jvm.instruction.loads;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.BasicTypeArray; import haidnor.jvm.rtda.BasicTypeArray;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -1,7 +1,7 @@
package haidnor.jvm.instruction.loads; package haidnor.jvm.instruction.loads;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.BasicTypeArray; import haidnor.jvm.rtda.BasicTypeArray;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -1,7 +1,7 @@
package haidnor.jvm.instruction.loads; package haidnor.jvm.instruction.loads;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.BasicTypeArray; import haidnor.jvm.rtda.BasicTypeArray;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -1,7 +1,7 @@
package haidnor.jvm.instruction.loads; package haidnor.jvm.instruction.loads;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.BasicTypeArray; import haidnor.jvm.rtda.BasicTypeArray;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -1,7 +1,7 @@
package haidnor.jvm.instruction.loads; package haidnor.jvm.instruction.loads;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.BasicTypeArray; import haidnor.jvm.rtda.BasicTypeArray;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -1,7 +1,7 @@
package haidnor.jvm.instruction.loads; package haidnor.jvm.instruction.loads;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.BasicTypeArray; import haidnor.jvm.rtda.BasicTypeArray;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -1,10 +1,10 @@
package haidnor.jvm.instruction.references; package haidnor.jvm.instruction.references;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.Instance; import haidnor.jvm.rtda.Instance;
import haidnor.jvm.rtda.heap.InstanceArray; import haidnor.jvm.rtda.InstanceArray;
import haidnor.jvm.rtda.heap.Klass; import haidnor.jvm.rtda.Klass;
import haidnor.jvm.rtda.metaspace.Metaspace; import haidnor.jvm.rtda.Metaspace;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.runtime.StackValue; import haidnor.jvm.runtime.StackValue;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -1,7 +1,7 @@
package haidnor.jvm.instruction.references; package haidnor.jvm.instruction.references;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.ArrayInstance; import haidnor.jvm.rtda.ArrayInstance;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;
import lombok.SneakyThrows; import lombok.SneakyThrows;

View File

@@ -1,8 +1,8 @@
package haidnor.jvm.instruction.references; package haidnor.jvm.instruction.references;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.Instance; import haidnor.jvm.rtda.Instance;
import haidnor.jvm.rtda.heap.KlassField; import haidnor.jvm.rtda.KlassField;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;
import haidnor.jvm.util.ConstantPoolUtil; import haidnor.jvm.util.ConstantPoolUtil;

View File

@@ -1,9 +1,9 @@
package haidnor.jvm.instruction.references; package haidnor.jvm.instruction.references;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.Klass; import haidnor.jvm.rtda.Klass;
import haidnor.jvm.rtda.heap.KlassField; import haidnor.jvm.rtda.KlassField;
import haidnor.jvm.rtda.metaspace.Metaspace; import haidnor.jvm.rtda.Metaspace;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.runtime.StackValue; import haidnor.jvm.runtime.StackValue;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -1,7 +1,7 @@
package haidnor.jvm.instruction.references; package haidnor.jvm.instruction.references;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.Instance; import haidnor.jvm.rtda.Instance;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.runtime.StackValue; import haidnor.jvm.runtime.StackValue;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -3,9 +3,9 @@ package haidnor.jvm.instruction.references;
import haidnor.jvm.classloader.ClassLoader; import haidnor.jvm.classloader.ClassLoader;
import haidnor.jvm.core.JavaExecutionEngine; import haidnor.jvm.core.JavaExecutionEngine;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.Klass; import haidnor.jvm.rtda.Klass;
import haidnor.jvm.rtda.heap.KlassMethod; import haidnor.jvm.rtda.KlassMethod;
import haidnor.jvm.rtda.metaspace.Metaspace; import haidnor.jvm.rtda.Metaspace;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.runtime.StackValue; import haidnor.jvm.runtime.StackValue;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -2,9 +2,9 @@ package haidnor.jvm.instruction.references;
import haidnor.jvm.core.JavaExecutionEngine; import haidnor.jvm.core.JavaExecutionEngine;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.Klass; import haidnor.jvm.rtda.Klass;
import haidnor.jvm.rtda.heap.KlassMethod; import haidnor.jvm.rtda.KlassMethod;
import haidnor.jvm.rtda.metaspace.Metaspace; import haidnor.jvm.rtda.Metaspace;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.runtime.StackValue; import haidnor.jvm.runtime.StackValue;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -3,9 +3,9 @@ package haidnor.jvm.instruction.references;
import haidnor.jvm.classloader.ClassLoader; import haidnor.jvm.classloader.ClassLoader;
import haidnor.jvm.core.JavaExecutionEngine; import haidnor.jvm.core.JavaExecutionEngine;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.Klass; import haidnor.jvm.rtda.Klass;
import haidnor.jvm.rtda.heap.KlassMethod; import haidnor.jvm.rtda.KlassMethod;
import haidnor.jvm.rtda.metaspace.Metaspace; import haidnor.jvm.rtda.Metaspace;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.runtime.StackValue; import haidnor.jvm.runtime.StackValue;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -1,9 +1,9 @@
package haidnor.jvm.instruction.references; package haidnor.jvm.instruction.references;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.Instance; import haidnor.jvm.rtda.Instance;
import haidnor.jvm.rtda.heap.Klass; import haidnor.jvm.rtda.Klass;
import haidnor.jvm.rtda.metaspace.Metaspace; import haidnor.jvm.rtda.Metaspace;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.runtime.StackValue; import haidnor.jvm.runtime.StackValue;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -1,7 +1,7 @@
package haidnor.jvm.instruction.references; package haidnor.jvm.instruction.references;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.BasicTypeArray; import haidnor.jvm.rtda.BasicTypeArray;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;
import lombok.SneakyThrows; import lombok.SneakyThrows;

View File

@@ -1,8 +1,8 @@
package haidnor.jvm.instruction.references; package haidnor.jvm.instruction.references;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.Instance; import haidnor.jvm.rtda.Instance;
import haidnor.jvm.rtda.heap.KlassField; import haidnor.jvm.rtda.KlassField;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.runtime.StackValue; import haidnor.jvm.runtime.StackValue;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -1,9 +1,9 @@
package haidnor.jvm.instruction.references; package haidnor.jvm.instruction.references;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.Klass; import haidnor.jvm.rtda.Klass;
import haidnor.jvm.rtda.heap.KlassField; import haidnor.jvm.rtda.KlassField;
import haidnor.jvm.rtda.metaspace.Metaspace; import haidnor.jvm.rtda.Metaspace;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;
import haidnor.jvm.util.ConstantPoolUtil; import haidnor.jvm.util.ConstantPoolUtil;

View File

@@ -1,7 +1,7 @@
package haidnor.jvm.instruction.stack; package haidnor.jvm.instruction.stack;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.Instance; import haidnor.jvm.rtda.Instance;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;
import lombok.SneakyThrows; import lombok.SneakyThrows;

View File

@@ -1,8 +1,8 @@
package haidnor.jvm.instruction.stores; package haidnor.jvm.instruction.stores;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.Instance; import haidnor.jvm.rtda.Instance;
import haidnor.jvm.rtda.heap.InstanceArray; import haidnor.jvm.rtda.InstanceArray;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -1,7 +1,7 @@
package haidnor.jvm.instruction.stores; package haidnor.jvm.instruction.stores;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.BasicTypeArray; import haidnor.jvm.rtda.BasicTypeArray;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -1,7 +1,7 @@
package haidnor.jvm.instruction.stores; package haidnor.jvm.instruction.stores;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.BasicTypeArray; import haidnor.jvm.rtda.BasicTypeArray;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -1,7 +1,7 @@
package haidnor.jvm.instruction.stores; package haidnor.jvm.instruction.stores;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.BasicTypeArray; import haidnor.jvm.rtda.BasicTypeArray;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -1,7 +1,7 @@
package haidnor.jvm.instruction.stores; package haidnor.jvm.instruction.stores;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.BasicTypeArray; import haidnor.jvm.rtda.BasicTypeArray;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -1,7 +1,7 @@
package haidnor.jvm.instruction.stores; package haidnor.jvm.instruction.stores;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.BasicTypeArray; import haidnor.jvm.rtda.BasicTypeArray;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -1,7 +1,7 @@
package haidnor.jvm.instruction.stores; package haidnor.jvm.instruction.stores;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.BasicTypeArray; import haidnor.jvm.rtda.BasicTypeArray;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -1,7 +1,7 @@
package haidnor.jvm.instruction.stores; package haidnor.jvm.instruction.stores;
import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.heap.BasicTypeArray; import haidnor.jvm.rtda.BasicTypeArray;
import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.Frame;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;

View File

@@ -1,4 +1,4 @@
package haidnor.jvm.rtda.heap; package haidnor.jvm.rtda;
/** /**
* @author wang xiang * @author wang xiang

View File

@@ -1,4 +1,4 @@
package haidnor.jvm.rtda.heap; package haidnor.jvm.rtda;
/** /**
* @author wang xiang * @author wang xiang

View File

@@ -1,4 +1,4 @@
package haidnor.jvm.rtda.heap; package haidnor.jvm.rtda;
import java.util.ArrayList; import java.util.ArrayList;

View File

@@ -1,4 +1,4 @@
package haidnor.jvm.rtda.heap; package haidnor.jvm.rtda;
/** /**
* @author wang xiang * @author wang xiang

View File

@@ -1,8 +1,7 @@
package haidnor.jvm.rtda.heap; package haidnor.jvm.rtda;
import haidnor.jvm.classloader.ClassLoader; import haidnor.jvm.classloader.ClassLoader;
import haidnor.jvm.core.JavaExecutionEngine; import haidnor.jvm.core.JavaExecutionEngine;
import haidnor.jvm.rtda.metaspace.Metaspace;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import org.apache.bcel.classfile.Field; import org.apache.bcel.classfile.Field;
import org.apache.bcel.classfile.JavaClass; import org.apache.bcel.classfile.JavaClass;

View File

@@ -1,4 +1,4 @@
package haidnor.jvm.rtda.heap; package haidnor.jvm.rtda;
import haidnor.jvm.runtime.StackValue; import haidnor.jvm.runtime.StackValue;
import org.apache.bcel.Const; import org.apache.bcel.Const;

View File

@@ -1,4 +1,4 @@
package haidnor.jvm.rtda.heap; package haidnor.jvm.rtda;
import org.apache.bcel.classfile.Method; import org.apache.bcel.classfile.Method;

View File

@@ -1,6 +1,4 @@
package haidnor.jvm.rtda.metaspace; package haidnor.jvm.rtda;
import haidnor.jvm.rtda.heap.Klass;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;

View File

@@ -1,103 +0,0 @@
package haidnor.jvm.rtda;
import haidnor.jvm.rtda.heap.Instance;
import haidnor.jvm.runtime.Slot;
/**
* 用于字段的联合 Slot
*/
public class UnionSlot {
private Slot high;
private Slot low;
private UnionSlot(Slot high, Slot low) {
this.high = high;
this.low = low;
}
// 初始化
public static UnionSlot of(Slot high, Slot low) {
return new UnionSlot(high, low);
}
public static UnionSlot of(Slot high) {
return new UnionSlot(high, null);
}
public static UnionSlot of(Instance instance) {
return new UnionSlot(new Slot(instance), null);
}
public static UnionSlot of(int val) {
return new UnionSlot(new Slot(val), null);
}
public static UnionSlot of(float val) {
return of(Float.floatToIntBits(val));
}
public static UnionSlot of(long val) {
int high = (int) (val >> 32); //高32位
int low = (int) (val & 0x000000ffffffffL); //低32位
return new UnionSlot(new Slot(high), new Slot(low));
}
public static UnionSlot of(double val) {
return of(Double.doubleToLongBits(val));
}
// 存
public void setRef(Instance val) {
high.ref = val;
}
public void setInt(int val) {
high.num = val;
}
public void setFloat(float val) {
setInt(Float.floatToIntBits(val));
}
public void setLong(long val) {
int highV = (int) (val >> 32); //高32位
int lowV = (int) (val & 0x000000ffffffffL); //低32位
high.num = highV;
low.num = lowV;
}
public void setDouble(double val) {
setLong(Double.doubleToLongBits(val));
}
public void set(UnionSlot neo) {
this.high = neo.high;
this.low = neo.low;
}
// 取
public Object getRef() {
return high.ref;
}
public int getInt() {
return high.num;
}
public float getFloat() {
return Float.intBitsToFloat(getInt());
}
public long getLong() {
final int high = this.high.num;
final int low = this.low.num;
long l1 = (high & 0x000000ffffffffL) << 32;
long l2 = low & 0x00000000ffffffffL;
return l1 | l2;
}
public double getDouble() {
return Double.longBitsToDouble(getLong());
}
}

View File

@@ -1,7 +0,0 @@
package haidnor.jvm.rtda.heap;
/**
* 堆空间
*/
public class Heap {
}

View File

@@ -1,14 +1,13 @@
package haidnor.jvm.runtime; package haidnor.jvm.runtime;
import haidnor.jvm.rtda.heap.Instance; import haidnor.jvm.rtda.Instance;
import haidnor.jvm.rtda.heap.Klass; import haidnor.jvm.rtda.Klass;
import haidnor.jvm.rtda.heap.KlassMethod; import haidnor.jvm.rtda.KlassMethod;
import haidnor.jvm.util.CodeStream; import haidnor.jvm.util.CodeStream;
import haidnor.jvm.util.ConstantPoolUtil; import haidnor.jvm.util.ConstantPoolUtil;
import org.apache.bcel.Const; import org.apache.bcel.Const;
import org.apache.bcel.classfile.Code; import org.apache.bcel.classfile.Code;
import org.apache.bcel.classfile.ConstantPool; import org.apache.bcel.classfile.ConstantPool;
import org.apache.bcel.classfile.LocalVariableTable;
import java.util.Stack; import java.util.Stack;
@@ -21,7 +20,7 @@ public class Frame {
/** /**
* 当前栈帧所处于的 JVM 线程 * 当前栈帧所处于的 JVM 线程
*/ */
private final JvmThread jvmThread; private final JVMThread jvmThread;
/** /**
* 栈帧所属的方法 * 栈帧所属的方法
@@ -33,6 +32,10 @@ public class Frame {
private final KlassMethod klassMethod; private final KlassMethod klassMethod;
/**
* 每个栈帧中包含一个指向运行时常量池中该栈帧所属的方法的引用。包含这个引用的目的就是为了支持当前方法实现动态链接
* 有了这个引用,执行引擎就可以找到指定的方法,加载字节码指令
*/
public final Klass klass; public final Klass klass;
/** /**
@@ -51,17 +54,12 @@ public class Frame {
*/ */
private final Stack<StackValue> operandStack = new Stack<>(); private final Stack<StackValue> operandStack = new Stack<>();
/**
* 局部变量表
*/
private final LocalVariableTable localVariableTable;
/** /**
* 槽位 * 槽位
*/ */
private final Slot[] slots; private final Slot[] slots;
public Frame(JvmThread jvmThread, KlassMethod klassMethod) { public Frame(JVMThread jvmThread, KlassMethod klassMethod) {
this.jvmThread = jvmThread; this.jvmThread = jvmThread;
this.klass = klassMethod.aKlass; this.klass = klassMethod.aKlass;
this.klassMethod = klassMethod; this.klassMethod = klassMethod;
@@ -70,11 +68,10 @@ public class Frame {
this.constantPool = method.getConstantPool(); this.constantPool = method.getConstantPool();
this.constantPoolUtil = new ConstantPoolUtil(constantPool); this.constantPoolUtil = new ConstantPoolUtil(constantPool);
this.codeStream = new CodeStream(method.getCode()); this.codeStream = new CodeStream(method.getCode());
this.localVariableTable = code.getLocalVariableTable();
this.slots = new Slot[code.getMaxLocals()]; this.slots = new Slot[code.getMaxLocals()];
} }
public JvmThread getJvmThread() { public JVMThread getJvmThread() {
return jvmThread; return jvmThread;
} }

View File

@@ -7,7 +7,7 @@ import java.util.Stack;
* *
* @author wang xiang * @author wang xiang
*/ */
public class JvmThread extends Thread { public class JVMThread extends Thread {
/** /**
* JVM 线程栈 * JVM 线程栈

View File

@@ -1,7 +1,7 @@
package haidnor.jvm.util; package haidnor.jvm.util;
import haidnor.jvm.rtda.heap.Klass; import haidnor.jvm.rtda.Klass;
import haidnor.jvm.rtda.heap.KlassMethod; import haidnor.jvm.rtda.KlassMethod;
import org.apache.bcel.classfile.JavaClass; import org.apache.bcel.classfile.JavaClass;
/** /**

View File

@@ -1,19 +1,19 @@
package haidnor.jvm.util; package haidnor.jvm.util;
import haidnor.jvm.runtime.JvmThread; import haidnor.jvm.runtime.JVMThread;
/** /**
* @author wang xiang * @author wang xiang
*/ */
public abstract class JvmThreadHolder { public abstract class JvmThreadHolder {
private static final ThreadLocal<JvmThread> holder = new ThreadLocal<>(); private static final ThreadLocal<JVMThread> holder = new ThreadLocal<>();
public static void set(JvmThread thread) { public static void set(JVMThread thread) {
holder.set(thread); holder.set(thread);
} }
public static JvmThread get() { public static JVMThread get() {
return holder.get(); return holder.get();
} }

View File

@@ -2,10 +2,10 @@ package haidnor.jvm.test;
import haidnor.jvm.classloader.ClassLoader; import haidnor.jvm.classloader.ClassLoader;
import haidnor.jvm.core.JavaExecutionEngine; import haidnor.jvm.core.JavaExecutionEngine;
import haidnor.jvm.rtda.heap.Klass; import haidnor.jvm.rtda.Klass;
import haidnor.jvm.rtda.heap.KlassMethod; import haidnor.jvm.rtda.KlassMethod;
import haidnor.jvm.rtda.metaspace.Metaspace; import haidnor.jvm.rtda.Metaspace;
import haidnor.jvm.runtime.JvmThread; import haidnor.jvm.runtime.JVMThread;
import haidnor.jvm.test.demo.*; import haidnor.jvm.test.demo.*;
import haidnor.jvm.test.instruction.Array; import haidnor.jvm.test.instruction.Array;
import haidnor.jvm.test.instruction.DO_WHILE; import haidnor.jvm.test.instruction.DO_WHILE;
@@ -28,13 +28,13 @@ public class TestJVM {
@SneakyThrows @SneakyThrows
public static void runMainClass(java.lang.Class<?> mainClass) { public static void runMainClass(java.lang.Class<?> mainClass) {
JvmThreadHolder.set(new JvmThread()); JvmThreadHolder.set(new JVMThread());
ClassLoader bootClassLoader = new ClassLoader("ApplicationClassLoader"); ClassLoader bootClassLoader = new ClassLoader("ApplicationClassLoader");
Klass mainMeteKlass = bootClassLoader.loadClass(mainClass.getName().replace('.', '/')); Klass mainMeteKlass = bootClassLoader.loadClass(mainClass.getName().replace('.', '/'));
KlassMethod mainKlassMethod = JavaClassUtil.getMainMethod(mainMeteKlass); KlassMethod mainKlassMethod = JavaClassUtil.getMainMethod(mainMeteKlass);
Metaspace.registerJavaClass(mainMeteKlass); Metaspace.registerJavaClass(mainMeteKlass);
JavaExecutionEngine.callMainStaticMethod(mainKlassMethod); JavaExecutionEngine.callMainMethod(mainKlassMethod);
} }
/** /**
@@ -118,7 +118,7 @@ public class TestJVM {
public void test_jar() throws Exception { public void test_jar() throws Exception {
String jarFilePath = "D:/project_java/JvmDemo/target/JvmDemo-1.0-SNAPSHOT.jar"; String jarFilePath = "D:/project_java/JvmDemo/target/JvmDemo-1.0-SNAPSHOT.jar";
JvmThreadHolder.set(new JvmThread()); JvmThreadHolder.set(new JVMThread());
try (JarFile jarFile = new JarFile(jarFilePath)) { try (JarFile jarFile = new JarFile(jarFilePath)) {
ClassLoader bootClassLoader = new ClassLoader(jarFile, "ApplicationClassLoader"); ClassLoader bootClassLoader = new ClassLoader(jarFile, "ApplicationClassLoader");
@@ -135,7 +135,7 @@ public class TestJVM {
Klass mainMeteKlass = bootClassLoader.loadClass(jarFile, entry); Klass mainMeteKlass = bootClassLoader.loadClass(jarFile, entry);
KlassMethod mainKlassMethod = JavaClassUtil.getMainMethod(mainMeteKlass); KlassMethod mainKlassMethod = JavaClassUtil.getMainMethod(mainMeteKlass);
Metaspace.registerJavaClass(mainMeteKlass); Metaspace.registerJavaClass(mainMeteKlass);
JavaExecutionEngine.callMainStaticMethod(mainKlassMethod); JavaExecutionEngine.callMainMethod(mainKlassMethod);
break; break;
} }
} }