# YVM
**Repository Path**: weizai118/YVM
## Basic Information
- **Project Name**: YVM
- **Description**: 中文 | English YVM是用C++写的一个Java虚拟机,现在支持Java大部分功能,以及一个基于"标记清除算法"的并发垃圾回收器. 不过还有很多bug等待修复
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 4
- **Created**: 2018-12-14
- **Last Updated**: 2020-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README

[中文](https://github.com/racaljk/yvm/blob/master/README.md) | [English](https://github.com/racaljk/yvm/blob/master/README.EN.md)
| [](https://travis-ci.org/racaljk/yvm) | [](https://www.codacy.com/app/racaljk/yvm?utm_source=github.com&utm_medium=referral&utm_content=racaljk/yvm&utm_campaign=Badge_Grade) |  | 
This is a homemade Java virtual machine written in c++, it supports most Java language features and includes a mark-sweep-based concurrent garbage collector. The main components of this VM are conform to [Java Virtual Machine Specification 8](https://docs.oracle.com/javase/specs/jvms/se8/jvms8.pdf). Now it is runnable and various language features will add into this VM progressively. I don't have enough time to write a full coverage unit tests to ensure that all aspects of yvm work well, so if you find any bugs, you can open an [Issue](https://github.com/racaljk/yvm/issues/new) or fix up in place and pull request directly.
# Available language features
Advanced language features will support later, you can also PR to contribute your awesome code.
+ Java arithmetic, flow control, object-oriented programming(virtual method, inherit,etc.)
+ [Runtime type identification](./javaclass/ydk/test/InstanceofTest.java)
+ [String concatenation](./javaclass/ydk/test/StringConcatenation.java)
+ [Exception handling](./javaclass/ydk/test/ThrowExceptionTest.java)
+ [Async native threads](./javaclass/ydk/test/CreateAsyncThreadsTest.java)
+ [Synchronized block with object lock](./javaclass/ydk/test/SynchronizedBlockTest.java)
+ [Garbage Collection(With mark-and-sweep policy)](./javaclass/ydk/test/GCTest.java)
# Build and run
+ Prerequisite
+ [Boost](https://www.boost.org/)(>=1.65) Please set Boost root directory in `CMakeLists.txt` manually if automatic cmake detecting failed
+ C++14
+ gcc/msvc/mingw
+ Stereotype
```bash
$ cd yvm
$ cmake .
$ make -j4
$ make test
```
```bash
$ ./yvm --help
Usage:
--help List help documentations and usages.
--runtime arg Attach java runtime libraries where yvm would lookup
classes at
--run arg Program which would be executed soon
You must specify the "runtime" flag to tell yvm where it could find jdk classes, and also program name is required.
$ ./yvm --runtime=C:\Users\Cthulhu\Desktop\yvm\bytecode ydk.test.QuickSort
```
# Running snapshots
+ helloworld


+ quick sort


+ print stack trace when exception occurred


+ native multithreading


+ multithreading with synchronized(){}


+ Garbage Collection


# Development docs
1. From bytecode to an object
`MethodArea` used to handle a complete lifecycle of JavaClass, its APIs are self-explanatory:
```cpp
class MethodArea {
public:
// Pass runtime libraries paths to tell virutal machine searches
// where to lookup dependent classes
MethodArea(const vector& libPaths);
~MethodArea();
// check whether it already exists or absents
JavaClass* findJavaClass(const string& jcName);
// load class which specified by jcName
bool loadJavaClass(const string& jcName);
// remove class which specified by jcName(Used for gc only)
bool removeJavaClass(const string& jcName);
// link class which specified by jcName,initialize its fields
void linkJavaClass(const string& jcName);
// initialize class specified by jcName,call the static{} block
void initJavaClass(CodeExecution& exec, const string& jcName);
public:
//auxiliary functions
JavaClass* loadClassIfAbsent(const string& jcName);
void linkClassIfAbsent(const string& jcName);
void initClassIfAbsent(CodeExecution& exec, const string& jcName);
}
```
For example, we have a bytecode file named `Test.class`,it would be available for jvm only if the following steps finished:
`Test.class[in the disk]`-> `loadJavaClass("Test.class")[in memory]` -> `linkJavaClass("Test.class")`->`initJavaClass("Test.class")`
Now we can create corresponding objects as soon as above steps accomplished:
```cpp
// yrt is a global runtime variable,ma stands for MethodArea module,jheap stands for JavaHeap module
JavaClass* testClass = yrt.ma->findJavaClass("Test.class");
JObject* testInstance = yrt.jheap->createObject(*testClass);
```
2.1 Inside the object
jvm stack only holds basic numeric data and object/array reference, which we call the JObject/JArray, they have the following structure:
```cpp
struct JObject {
std::size_t offset = 0;
const JavaClass* jc{};
};
```
`offset` stands for an object,all operations of object in heap required this `offset`。`jc` references to the JavaClass。
Every object in heap constructed with pair
```
[1] -> [field_a, field_b, field_c]
[2] -> []
[3] -> [field_a,field_b]
[4] -> [field_a]
[..] -> [...]
```
If we get the object's offset, we can do anything of that indirectly.
Array is almost the same as object, it has a length field instead of jc since it's unnecessary for array to hold a meta class reference.
```cpp
struct JArray {
int length = 0;
std::size_t offset = 0;
};
[1] -> <3, [field_a, field_b, field_c]>
[2] -> <0, []>
[3] -> <2, [field_a,field_b]>
[4] -> <1, [field_a]>
[..] -> <..,[...]>
```
2.2 From object creation to extinction
As above mentioned, a JObject holds`offset` and `jc`. `MethodArea` has responsible to manage `JavaClass` which referenced by `jc`, another `offset` field referenced to `JObject`, which in control of `JavaHeap`. `JavaHeap` provides a large number of self-explanatory APIs:
```cpp
class JavaHeap {
public:
// create and object/array
JObject* createObject(const JavaClass& javaClass);
JArray* createObjectArray(const JavaClass& jc, int length);
// get/set field
auto getFieldByName(const JavaClass* jc, const string& name,
const string& descriptor, JObject* object);
void putFieldByName(const JavaClass* jc, const string& name,
const string& descriptor, JObject* object,
JType* value);
// get/set specific element in the array
void putElement(const JArray& array, size_t index, JType* value);
auto getElement(const JArray& array, size_t index);
// remove an array/object from heap
void removeArray(size_t offset;
void removeObject(size_t offset);
};
```
Back to the above example again, assume its corresponding Java class structure is as follows:
```java
public class Test{
public int k;
private String hello;
}
```
In the first step, we've already got `testClass`, now we can do more things via it:
```cpp
const JavaClass* testClass = yrt.ma->findJavaClass("Test.class");
JObject* testInstance = yrt.jheap->createObject(*testClass);
// get the field hello
JObject* helloField = yrt.jheap->getFieldByName(testClass,"hello","Ljava/lang/String;",testInstance);
//set the field k
yrt.jheap->putFieldByName(testClass,"k","I",testInstance);
```
Ⅰ. About JDK
Any java virtual machines can not run a Java program without Java libraries. As you may know, some opcodes like `ldc`,`monitorenter/monitorexit`,`athrow` are internally requiring our virtual machine to operate JDK classes(`java.lang.Class`,`java.lang.String`,`java.lang.Throwable`,etc). Hence, I have to rewrite some [JDK classes](./javaclass) for building a runnable VM , because original JDK classes are so complicated that it's inconvenient for early developing.
Rewrote JDK classes are as follows:
+ `java.lang.String`
+ `java.lang.StringBuilder`
+ `java.lang.Throwable`
+ `java.lang.Math(::random())`
+ `java.lang.Runnable`
+ `java.lang.Thread`
For more development documentations, see its [Wiki](https://github.com/racaljk/yvm/wiki) or source code comments(recommend), which contains various contents with regard to its structures, usages, and design principles, etc.
# License
Code licensed under the MIT License.