Skip to content

Commit

Permalink
Merge pull request onlyliuxin#51 from Wrecksoul/master
Browse files Browse the repository at this point in the history
完成jvm第一次作业与LRU
  • Loading branch information
luoziyihao authored Apr 9, 2017
2 parents 407435f + 983e4a8 commit 9d47036
Show file tree
Hide file tree
Showing 5 changed files with 382 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package com.coderising.jvm.loader;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class ClassFileLoader {
private static final int BUFFERSIZE = 1024;
private List<String> clzPaths = new ArrayList<String>();

public byte[] readBinaryCode(String className) {
if (clzPaths.size()<=0){
return null;
}
for (int i = 0; i < clzPaths.size(); i++) {
String path = clzPaths.get(i) + convertName(className);
File f = new File(path);
if(f.exists()){
try {
return readFile(f);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}else{
f = null;
continue;
}
}
System.err.println("classpath:" +getClassPath()+ "class:" + convertName(className)+" not found.");
return null;
}
/**
* 文件读取二进制字节流
* @param f
* @return
* @throws FileNotFoundException
*/
private byte[] readFile(File f) throws FileNotFoundException {
FileInputStream fis = new FileInputStream(f);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] b = new byte[BUFFERSIZE];
try {
int len = 0;
while((len = fis.read(b))!=-1){
baos.write(b,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally{
try {
fis.close();
baos.flush();
baos.close();
} catch (IOException e) {
e.printStackTrace();
}

}
return baos.toByteArray();
}

public void addClassPath(String path) {
clzPaths.add(path);
}

public String getClassPath() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < clzPaths.size(); i++) {
sb.append(clzPaths.get(i)).append(";");
}
int len = sb.length();
if(len!=0){
sb.deleteCharAt(len-1);
}
return sb.toString();
}

/**
* convert className to FilePath style className <br/>
* For example:com.sun.lang to \com\sun\lang
*
* @param className
* @return FilePath style className
*/
private String convertName(String className) {
StringBuilder sb = new StringBuilder();
String[] pack = className.split("\\.");
for (int i = 0; i < pack.length; i++) {
sb.append("\\").append(pack[i]);
}
sb.append(".class");
return sb.toString();
}

public static void main(String[] args) {
String d = "com.taiji.array.Load";
ClassFileLoader cc = new ClassFileLoader();
System.out.print(cc.convertName(d));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.coderising.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();

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package com.coding.basic.LRU;

public class LRUPageFrame {
private int capacity;
private Node first;// 链表头
private Node last;// 链表尾
private int length = 0;

public LRUPageFrame(int capacity) {
this.capacity = capacity;
}

/**
* 获取缓存中对象
*
* @param key
* @return
*/
public void access(int pageNum) {
// this loop select for pageNum,grow it first when 'found'.
for (Node n = first; n != null; n = n.next) {
if (n.pageNum == pageNum) {
growFirst(n);
return;
}
}
// if didn't found it
if (ensureFull()) {
removeLast();
}
add(pageNum);
}

private void add(int pageNum) {
if (isEmpty()) {
Node newNode = new Node(null, null, pageNum);
first = newNode;
last = newNode;
length++;
} else {
addToFirst(pageNum);
}
}

private void addToFirst(int pageNum) {
Node newNode = new Node(null, null, pageNum);
newNode.next = first;
first.prev = newNode;
first = newNode;
length++;
}

/**
* ensure the LRUPageFrame is full or Not
*
* @return if full return true,else false
*/
private boolean ensureFull() {
if (length < capacity) {
return false;
} else {
return true;
}
}

/**
* grow the Node'position to first
*
* @param n
*/
private void growFirst(Node n) {
// if the node is already first ,return.
if (first.pageNum == n.pageNum) {
return;
}
remove(n);
addToFirst(n.pageNum);
}

private void remove(Node n) {
if (isEmpty()) {
return;
}
if (n.next == null) {
removeLast();
return;
}
if (n.prev == null) {
removeFirst();
return;
}
Node prev = n.prev;
Node next = n.next;
n.next = null;
n.prev = null;
prev.next = next;
next.prev = prev;
length--;
}

private void removeFirst() {
Node next = first.next;
first.next = null;
first = next;
}

private void removeLast() {
Node prev = last.prev;
prev.next = null;
last.prev = null;
last = prev;
length--;
}
/**
* ensure the LRUPageFrame is empty or Not.
* @return
*/
public boolean isEmpty() {
return length < 1;
}

public String toString() {
StringBuilder buffer = new StringBuilder();
Node node = first;
while (node != null) {
buffer.append(node.pageNum);

node = node.next;
if (node != null) {
buffer.append(",");
}
}
return buffer.toString();
}

private static class Node {
Node prev;
Node next;
int pageNum;

Node(Node prev, Node next, int pageNum) {
this.prev = prev;
this.next = next;
this.pageNum = pageNum;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.coderising.jvm.loader;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class ClassFileLoaderTest {
static String path1 = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\bin";
static String path2 = "D:\\workProgram\\GitRepo\\coding2017\\group17\\82427129\\JavaUtil\\target\\classes";
@Before
public void setUp() throws Exception {
}

@After
public void tearDown() throws Exception {
}

@Test
public void testClassFileLength() {

ClassFileLoader loader = new ClassFileLoader();
loader.addClassPath(path2);

String className = "com.coderising.jvm.test.EmployeeV1";

byte[] byteCodes = loader.readBinaryCode(className);

// 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大
Assert.assertEquals(1056, byteCodes.length);

}

@Test
public void testGetClassPath() {
ClassFileLoader loader = new ClassFileLoader();
loader.addClassPath(path1);
loader.addClassPath(path2);

String clzPath = loader.getClassPath();

Assert.assertEquals(path1+";"+path2,clzPath);
}

@Test
public void testMagicNumber(){
ClassFileLoader loader = new ClassFileLoader();
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 < codes.length; i++) {
byte b = codes[i];
int value = b & 0xFF;
String strHex = Integer.toHexString(value);
if (strHex.length() < 2) {
strHex = "0" + strHex;
}
buffer.append(strHex);
}
return buffer.toString();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.coding.basic.LRU;

import org.junit.Assert;
import org.junit.Test;

public class LRUPageFrameTest {

@Test
public void testAccess() {
LRUPageFrame frame = new LRUPageFrame(3);
frame.access(7);
frame.access(0);
frame.access(1);
Assert.assertEquals("1,0,7", frame.toString());
frame.access(2);
Assert.assertEquals("2,1,0", frame.toString());
frame.access(0);
Assert.assertEquals("0,2,1", frame.toString());
frame.access(0);
Assert.assertEquals("0,2,1", frame.toString());
frame.access(3);
Assert.assertEquals("3,0,2", frame.toString());
frame.access(0);
Assert.assertEquals("0,3,2", frame.toString());
frame.access(4);
Assert.assertEquals("4,0,3", frame.toString());
}

}

0 comments on commit 9d47036

Please sign in to comment.