go实现java虚拟机01
前段时间看了一本书,说的是用go语言实现java虚拟机,很有意思,于是就花了一段时间学习了一下go语言,虽然对go的底层理解不是很深,但是写代码还是可以的,就当做个读书笔记吧!
链接在这里,另外还有一本《go程序设计语言》,有需要的直接一起拿走,链接:https://pan.baidu.com/s/152ZX7cLf5IcOzUk1C_Q8JQ 提取码:3ktm
首先我们知道java能够跨平台的原因就是class字节码文件在不同的jvm中都可以运行,每个计算机都可以安装符合自己操作系统的jvm,然后class文件就可以通用了,而class文件被包装的形式有很多种,最常见的应该就是jar包,有兴趣的可以看看打开自己的jdk中随便的个jar包,里面其实就是一些class字节码文件;
我们就简单一点,我们自己把一个java源码文件手动打包成一个jar包,下面的注释已经很清楚了
//javac HelloWorld.java将一个java源码文件编译成class文件
//java手动将class文件打成jar包命令:jar cvf hello.jar HelloWorld.class
//执行java -classpath hello.jar HelloWorld,表示执行hello中的jar包中HelloWorld中的main方法
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, world!");
}
}
打成jar包之后,我们现在手中的文件有两个,一个是HelloWorld.class字节码文件,一个是hello.jar文件(jar包其实就是一个压缩包),我们分别用两条命令执行这两个文件,不知道大家有没有看出来什么?
如果是字节码文件的话,就是直接用java xxx执行就行了;如果是jar包的形式,那么我们必须要指定jar包的全路径,以及jar包里面main方法所在的字节码文件,这样jvm才能找到入口,就会在jar包中找到该文件,然后运行;我们可以实现一下命令行的处理方式:

不知道大家还记不记得查看jdk版本的命令,就是java -version;在go语言中,对这种命令行参数的处理有两种,一种是os.Args这个切片来处理,另外一种通过一个flag包,选用后者,flag包封装了很多操作;
main.go代码如下:
package main
import "fmt"
func main() {
//同一个包下,私有方法也可以调用,如果是不同包,那就需要把parseCmd函数首字母大写
cmd := parseCmd()
//例如java -version,那么此时在parseCmd函数中解析version的值位true,然后赋值给versionFlag,就打印版本号
if cmd.versionFlag {
fmt.Println("version 1.0.0")
//例如输入的是java -help或者是java -classpath hello.jar ,没有加后面的类名,那么就调用printUsage函数
//打印提示信息
} else if cmd.helpFlag || cmd.class == "" {
printUsage()
//当参数都输入正确,那么就调用startJVM函数启动jvm,这里暂时就打印一句话,将输入的命令各部分参数都打印出来
} else {
startJVM(cmd)
}
}
func startJVM(cmd *Cmd) {
fmt.Printf("classpath:%s class:%s args:%v\n", cmd.cpOption, cmd.class, cmd.args)
}
cmd.go文件内容:
package main import (
"flag"
"fmt"
"os"
) //简单的定义一个结构体,这里保存命令行中输入的参数
type Cmd struct {
helpFlag bool
versionFlag bool
cpOption string
class string
args []string
} func parseCmd() *Cmd {
cmd := &Cmd{}
//这里的意思就是如果解析失败的话,就调用printUsage函数
flag.Usage = printUsage
//解析命令行中输入,例如java -help,那么这里help就是true,然后把true赋值给cmd结构体中helpFlag保存起来
//最后一个是默认信息
flag.BoolVar(&cmd.helpFlag, "help", false, "print help message")
//例如java -version,那么version就是true,赋值给cmd中的versionFlag
flag.BoolVar(&cmd.versionFlag, "version", false, "print version and exit ")
//例如java -classpath hello.jar HelloWorld,这里classpath就是hello.jar,然后赋值给cpOption保存起来
flag.StringVar(&cmd.cpOption, "classpath", "", "classpath") //上面是定义解析规则,调用Parse函数才是真正开始解析
flag.Parse() //解析成功的话,那就继续获取后面的参数,注意这里的args是一个切片类型的
//例如java -classpath hello.jar HelloWorld arg1,arg2,这里的args[0]表示HelloWorld,args[1:]表示arg1和arg2,
//就是传给main方法形参字符串数组的参数
args := flag.Args()
if len(args) > 0 {
cmd.class = args[0]
cmd.args = args[1:]
}
return cmd
} //这里传进去的参数,解析错误的话就显示第一个参数的提示信息
func printUsage() {
fmt.Printf("Usage:%s [-options] class [args]\n", os.Args[0])
}
其实很容易,然后我们可以测试一下,目录结构如下,其中main.go和cmd.go都在ch01中,我们进入到src目录下,打开终端,输入go install jvmgo\ch01,就会在workspace/bin下生成一个ch01.exe可执行文件;


go实现java虚拟机01的更多相关文章
- 带着新人看java虚拟机01
1.前言(基于JDK1.7) 最近想把一些java基础的东西整理一下,但是又不知道从哪里开始!想了好久,还是从最基本的jvm开始吧!这一节就简单过一遍基础知识,后面慢慢深入... 水平有限,我自己也是 ...
- 深入理解java虚拟机-01 走进java
第一章是对java的产生,历史的整体介绍 java的使用很广泛,安装jdk的时候会看到一句广告语runs in 10 billions machines.使用java的设备多达几十亿台 1.概述 优点 ...
- 深入理解Java虚拟机 #01# 自己编译JDK
x 首先用书上的脚本尝试,失败. 之后根据源文件的 README 编译,抛出: root@linux:/opt/openjdk# sh ./get_source.sh ERROR: Need init ...
- Java虚拟机JVM学习01 流程概述
Java虚拟机JVM学习01 流程概述 Java虚拟机与程序的生命周期 一个运行时的Java虚拟机(JVM)负责运行一个Java程序. 当启动一个Java程序时,一个虚拟机实例诞生:当程序关闭退出,这 ...
- 《深入理解Java虚拟机》笔记01 -- 运行时数据区
运行时数据区示意图 1. 程序计数器 占用一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器.主要用来记录线程执行到哪条语句了,分支.循环.跳转.异常处理.线程恢复等功能都需要依赖这个 ...
- Java虚拟机一看就懂01
Jvm内存结构 --- 线程隔离区域说明: 1.1.程序计数器 线程私有 是一块内存空间 唯一的一个在Java虚拟机规范中没有规定任何OOM情况的区域(不会OOM?) 1.2.Java虚拟机栈 线程私 ...
- java虚拟机开篇01
一直以来对java 基础设施都啥都不知道啊,感觉有时候挺费力,挺吃劲的. 一下是一些很好的参考资料: http://blog.csdn.net/bingduanlbd/article/details/ ...
- 实战Java虚拟机之三“G1的新生代GC”
今天开始实战Java虚拟机之三:“G1的新生代GC”. 总计有5个系列 实战Java虚拟机之一“堆溢出处理” 实战Java虚拟机之二“虚拟机的工作模式” 实战Java虚拟机之三“G1的新生代GC” 实 ...
- Java虚拟机5:Java垃圾回收(GC)机制详解
哪些内存需要回收? 哪些内存需要回收是垃圾回收机制第一个要考虑的问题,所谓“要回收的垃圾”无非就是那些不可能再被任何途径使用的对象.那么如何找到这些对象? 1.引用计数法 这个算法的实现是,给对象中添 ...
随机推荐
- lisp学习总结(一)
lisp太简单 lisp核心太简单了只有几个简单的逻辑定理,简单到你会认为他啥事都做不了. lisp语法太简单了,只有符号,参数,以及括号,组成一种万能的表达式. 由于上述lisp的简单,所以对于初学 ...
- Elastcisearch.Nest 7.x 系列`伪`官方翻译:通过 NEST 来快捷试用 Elasticsearch
本系列已经已经全部完成,完整版可见:https://blog.zhuliang.ltd/categories/Elasticsearch/ 本系列博文是"伪"官方文档翻译(更加本土 ...
- linux 安装virtualbox5.2
一.安装 1.下载package https://www.virtualbox.org/wiki/Linux_Downloads 2.添加源. $ cat /etc/lsb-release DISTR ...
- 基于云开发开发 Web 应用(一):项目介绍 & 初始化
基于云开发开发 Web 应用(一):项目介绍 & 初始化 背景描述 Linux 中国曾在过去的 1 - 2 年内长期运行了一个 TL;DR 的中国版.不过当时做的版本是小程序的版本,一直以来, ...
- SpringMVC 中的异常处理
目录 1.搭建编码分析 2.编写异常类 3.编写自定义异常处理器 4.在springmvc.xml中配置异常处理器 5.编写Error.jsp.index.jsp页面 6.编写collector代码模 ...
- 【WPF学习】第二十五章 日期控件
WPF包含两个日期控件:Calender和DatePicker.这两个控件都被设计为允许用户选择日期. Calendar控件显示日期,在与Windows操作系统中看到的日历(例如,当配置系统日期时看到 ...
- HDU-2841 Visible Trees(莫比乌斯反演)
Visible Trees 传送门 解题思路: 实际上的答案就是1~n与1~m之间互质的数的对数,写出式子就是 \(ans=\sum^{n}_{i=1}\sum^{m}_{j=1}[gcd(i,j)= ...
- windows RabbitMQ安装与配置
windows RabbitMQ安装与配置 1.安装Erlang 下载地址: http://www.erlang.org/downloads 注意: 右键以管理员身份进行安装,否则将导致后续无法启动 ...
- innobackupex 恢复脚本
此脚本需要与我前几天写的备份脚本配套才能使用 这里也对innobackupex吐槽下,当使用innobackupex进行恢复的时候,必须要清除所有原数据文件,但是一旦恢复失败,则连实例都将丢失,不成功 ...
- 分享数百个 HT 工业互联网 2D 3D 可视化应用案例之 2019 篇
继<分享数百个 HT 工业互联网 2D 3D 可视化应用案例>2018 篇,图扑软件定义 2018 为国内工业互联网可视化的元年后,2019 年里我们与各行业客户进行了更深度合作,拓展了H ...