前几天看到国外有报道说js实现了大部分的jvm功能,最近也一直在考虑如何用js实现一个jvm功能。
后来想了下,还是可行的,其实只是用js实现jvm规范,例如对于java来说有一个System.out,println("test");这样的语句一出现就会在控制台输出:"test"
这个语法对应javascript也就是
var System ={};
System.out={
println:function(val){
//实现具体的功能
alert(val);
}
}
如java中java.lang.String 也可以参照上术方式实现,api按此方式慢慢实现
那对于如何转换一个java bean对象也是今天所要讲的重点,不知道如果将一个java bean转换为javascript object的方法,那么即使实现了api也没有环境让java语言运行起来。
接着将介绍转换方法:
首先我们先来看一个简单的java bean和javascript object有什么区别
public class Test{
private int a;
public int getA(){
reutrn a;
}
}
function Test{
}
Test.prototype.a = 0;
Test.prototype.getA = function(){
return this.a;
}
看到这2种写法,应该能比较清楚的看出朝着这个方法转变就行。
好了,现在开始进行解析
解析过程:
1.类名的提取
根据java规范,我们知道一个类的命名必须是class name{...}这种方式,前面要有修饰符,内部类也是这种方式
可以写一个正则匹配这种内容,只需要匹配第一个出现{的字符串,提取里面的classname
或者采用正则(public|private|protected)?\s*class\s*\w+?{ 或者 class(.+?){ 匹配出所有符合规则的数据,将内部类名字也匹配出来
具体代码可参考Class.getName();
2.属性的提取
也可以采用正则方法处理,java成员变量的特点:修饰符(可有可无)+变量类型+成员名称+";"(注意后面还有一个;结束符)
和局部变量的区别在于有返回值类型,和method的区别在于没有(){...}代码片段
所以属性的提取可以采用正则
/(private|public)?\s+(void|int|float|boolean|double|String)[A-Za-z0-9|\s|_]+;
在处理属性的过程中,我们需要对变量类型做处理,如java中int类型的成员变量默认值是0等等。。。
于是我们定义一个于成员变量类型对应的var Type = {
"int":0,
"boolean":false
}
假设我们匹配到了"public int a;"这个字符串
接着我们就可以处理成这样了
classname.prototype.a =Type[int];
3.方法的提取(先介绍主函数main方法的处理)
method的提取相对比较麻烦点,需要考虑{}标签闭合的处理
main方法也是主入口函数,如果存在则会执行里面的内容,必须是public void static main(String[] args)...{....}这种方式,而且在一个类中只有一个,期中args是参数入口,对应arguments
转换成对应的js就是
classname.prototype.ininv = function(){....};
对于复杂方法的提取,这里暂时先不展开。
4.执行转换后代码
以Test.java为例
public class Test{
public void static main(String[] args){
System.out.println("test");
}
}
转换成js后的var source = "function Test(){};"
source += "Test.prototype.initv = function(){System.out.println(\"test\")}";
然后<script>document.write(source)</script>,
这样就能在window["Test"]下拿到这个Test对象,执行他的方法了。
具体源码可以参考Class._creatInitV()
另外还需要模拟一个很重要的入口,Class.forname方法,实现这个方法可以帮助我们很好的寻找处理java类
源码:
<script>
/*
* 扩展jtrim方法,使用方法有下面几种
* trim() 去除字符串左右两端的空格
* trim("xyz") 去除字符串左右两端的字符xyz
* trim(/[0-9]/g) 去除字符串左右两端的数字
* trim(2) 去除字符串左端2个字符
* trim(0,3) 去除字符串右端3个字符
* trim(2,3) 去除字符串左端2个字符右端3个字符
*/
String.prototype.trim = function(){
var _argument = arguments[0] == undefined ? " " : arguments[0];
if(typeof(_argument) == "string"){
if (_argument == " ") {
return this.replace(/(^(\s|\u3000)*)|((\s|\u3000)*$)/g, "");
} else {
return this.replace(new RegExp("(^" + _argument + "*)|(" + _argument + "*$)", "g"), "");
}
}else if(typeof(_argument) == "object"){
return this.replace(_argument, "");
}else if(typeof(_argument) == "number"){
if (arguments.length == 1) {
return this.substring(arguments[0])
} else if(typeof(arguments[1]) == "number") {
return this.substring(arguments[0], this.length-arguments[1]);
}
}
return this;
};
//对应java种的system类,这种类的功能只需要按下面这种格式逐个翻译成js class即可
var System = {}
System.out ={
println:function(val){
this.print(val + "\r\n");
},
print:function(val){
val = val == undefined ? "undefined" : val;
if(typeof(val) == "string"){
alert(val);
}
}
}
//js jvm对应的基础类型,目前先支持这4种基础类型
var Type = {
"int" : 0,
"boolean" : false,
"float" : 0.0,
"double" : 0.0,
"String" : null,
"void" : null,
}
//获取解析java对象核心的功能,相当于java中的class.forname获得一个对象
var Class = {
source : "",
//处理初始化对象
javasource : "",
forName:function(javasource){
this.javasource = javasource;//记录javasource,分析过程中会需要原始数据
var classname = this.getName();
this.source += "function "+classname+"(){}";//类名解析,转换到js obj上的时候classname是创建jsobj的关键
//this.source += classname+"prototype."+
this.source += this._createInitV(classname);//主main方法识别创建
this.source += this._createAttributes(classname);//创建属性
//this.getDeclaredFields();
this.source += this._createMethods(classname);//todo 创建方法
return this;
},
//初始化函数的创建,检测是否存在public static void main方法
_createInitV:function(classname){
var str = "";
var initv = String.trim(this.javasource).match(/public static void main\(String\[\].+?\){(.+?)}/);
if(initv.length >= 1){
str += classname+".prototype.initv=function(){";
str += (initv.length == 2)? initv[1]:"";//init[1]是匹配后main方法内的数据
str += "};";
}
return str;
},
//创建对象属性
//这个正则对方法内的变量申明不能很好识别
//todo public void getXXX(){int xxx;}这里的int xxx;也会被识别,需要先处理method后再处理attribute
//todo 还不支持abstract字段
_createAttributes : function(classname){
var value = "";
var attrs = String.trim(this.javasource).match(/(private|public)?\s+(void|int|float|boolean|double|String)[A-Za-z0-9|\s|_]+;/g);
var attr="";
for(var i=0,length=attrs.length;i<length;i++){
attr = String.trim(attrs[i]);
if(attr != ""){
//先去除开头的public private protected,以及末尾的;符号
if(attr.indexOf("public") == 0){
attr = attr.substring("public".length,attr.length-1).trim();
}else if(attr.indexOf("private") == 0){
attr = attr.substring("private".length,attr.length-1).trim();
}else if(attr.indexOf("protected")){
attr = attr.substring("protected".length,attr.length-1).trim();
}
//接着剩下的都是类型+名称的变量字符串了。。。
//根据类型要赋一些初始值
var typevalue = Type[attr.substring(0,attr.indexOf(" "))];//获取type对应的默认value
var attrname = attr.substring(attr.indexOf(" ")).trim();//获取attribute name
//开始组装js对应的属性
value += classname + ".prototype."+ attrname;
value += "=";
value += typevalue;
value += ";";
}
}
return value;
},
//为对象创建method
//(private|public)?\s+(void|int|float|boolean|double|String)[A-Za-z0-9|\s]+\((void|int|float|boolean|double|String)?(.+)?\)\s+{\s+([\r|\n|\t])?.+\s+([\r|\n|\t])?}
//理论上只需要转换public方法即可,private方法无法调用转换,转换后采用_methodname表示私有方法
_createMethods : function(classname){
var value = "";
//处理public方法
var methods = String.trim(this.javasource).match(/(public)?\s+(void|int|float|boolean|double|String)[A-Za-z0-9|\s]+\((void|int|float|boolean|double|String)?(.+)?\)\s+{\s+([\r|\n|\t])?.+\s+([\r|\n|\t])?}/ig);
if(methods){
for(var i=0,length = methods.length;i<length;i++){
value = this.javaMethodTojsFunction(methods[i]);
}
}
//处理private方法
return "";
},
//java method转为js function
//public int getXXX(){} --> getXXX : function(){}
//todo 如果不带修饰符的时候如何处理?目前当作public处理,也是符合java规范的
_javaMethodTojsFunction : function(val){
if(val.indexOf("public") == 0){
val = val.substring("public".length).trim();//去掉开始的public,public在js中没有这种关键字,默认已经是public
}
val = val.substring(val.indexOf(" ")).trim();//去除type
var methodname = val.substring(0,val.indexOf("(")).trim();//根据(符合决定方法名,因为method定义后面必须要有()
var functioncontent = val.substring(val.indexOf("(")).trim();//除方法名外,其他都是function内容
functioncontent = "function"+ functioncontent;//改变为function(){} (){}这种之后在java中是执行代码片段,这种代码可以直接转换为js代码片段
},
//解析return方法
_returnCompile : function(val){
},
getDeclaredFields:function(){
this.source += "Test.prototype = {";
this.source += "initv:function(){";
//initv逻辑解析-->检测入口,方法,字段等等
//...
//处理system.out.println method -->alert
this.source += "alert(\"hello world\");";
this.source += "}";
this.source += "}";
},
//获取对象名字
getName:function(){
//类的名字可以根据 class name {匹配,找到第1个就是类名,
//如果有多个,那么后面的属于内部类
var names = String.trim(this.javasource).match(/class(.+?){/g);
var name = names[0].substring("class".length,names[0].length-1);
return String.trim(name);
}
}
function JVM(){
}
JVM.prototype ={
compile:function(javasource){
var obj = new Object();
obj = Class.forName(javasource);
//obj = eval(obj.source);
///obj.initv();
document.write("<script>"+obj.source+"<\/script>");//todo 需要改进为在自己的package下,引入namespaces后再扩展这部分
return window[obj.getName()]; //classname还是比较好分析获取的
}
}
var javasource = "public class Test { ";
javasource += "private int tmpa;";
javasource += "private boolean tmpb;";
javasource += "private float tmpc;";
javasource += "private double tmpd;";
javasource += "private String tmpe;";
javasource += "private Object tmpf;";
javasource += "public int getTmpa(){";
javasource += " return tmpa;";
javasource += "}";
javasource += "public static void main(String[] args){";
javasource += "System.out.println(\"hello world\");";
javasource += "System.out.println(\"world is round\");";
javasource += "}";
javasource += "class Test2 {";
javasource += "private int tmpz;";
javasource += "};"
javasource += "}";
//创建一个jsjvm
var jsjvm = new JVM();
//编译java源代码
var obj = jsjvm.compile(javasource);
//创建对象
var tes = new obj();
//调用方法,main方法转为init方法,改天写这个解析逻辑
tes.initv();
alert(tes.tmpb);
alert(tes.tmpe);
//alert(" 123".trim())
//(public)?\s*(void|int|float|boolean|double|String)[A-Za-z0-9|\s]+\((void|int|float|boolean|double|String)?(.+)?\)\s*{\s*([\r|\n|\t])*.+\s*([\r|\n|\t])?*}
</script>
今天先介绍到这里,下周继续介绍如何处理成员方法和控制bean对象的加载卸载
如果没周写一篇这样贴代码的文章,然后后面再跟着http://ditu.alibaba.com,不知道又能赚多少外链。
Google 作者:陈旭东 email:wzucxd@gmail.com 2011.12.25
分享到:
相关推荐
此外,还引入了动态类型语言支持,通过JSR 223(Java Scripting API)允许在Java程序中嵌入和执行其他脚本语言,如JavaScript和Groovy。 在类库和API方面,JDK 6提供了许多增强,例如NIO.2(非阻塞I/O),它扩展了...
20. **EJB部署文件**:包含ejb-jar.xml和jboss.xml等,描述EJB的元数据,如bean的类型、接口、事务属性等。App Server根据部署文件管理EJB实例。 21. **设计模式**:如单例模式、工厂模式、观察者模式、策略模式、...
在有状态SessionBean中,用累加器,以对话状态存储起来,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用完毕,从内存中清除…… Java Socket 聊天...
203、编程用JAVA解析XML的方式. 49 204、EJB2.0有哪些内容?分别用在什么场合? EJB2.0和EJB1.1的区别? 51 205、EJB与JAVA BEAN的区别? 51 206、EJB的基本架构 51 207、MVC的各个部分都有那些技术来实现?如何实现? 52...
给一个 Bean 的 message 属性, 字符串类型, 注入值为 "Hello" 的 XML 配置文件该怎么写? 125 19、Jdo是什么? 125 20、什么是spring的IOC AOP 126 21、STRUTS的工作流程! 126 22、spring 与EJB的区别!! 126 八. ...
给一个 Bean 的 message 属性, 字符串类型, 注入值为 "Hello" 的 XML 配置文件该怎么写? 125 19、Jdo是什么? 125 20、什么是spring的IOC AOP 126 21、STRUTS的工作流程! 126 22、spring 与EJB的区别!! 126 八. ...
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,被广泛用于Web服务和应用程序之间的数据传输。在Java开发中,处理JSON数据是常见的任务,为此需要特定的库支持。"json工具jar包(java)"是针对Java...
【描述】提到的“可完全做为毕业设计、课程设计使用”,表明这个项目适合学生用于完成学业中的实践项目,其设计和功能已经相当成熟,能够满足基本的在线医疗系统需求。"界面美观、功能齐全"意味着该系统不仅在用户...
在企业级Java相关的面试中,面试官通常会考察求职者的多方面能力,包括基础理论、实战经验、技术框架的理解和应用以及对前端和数据库的掌握程度。以下是对这些知识点的详细解析: 一、Java基础知识面试题 Java是...
### Java面试题详解 #### 一、Java基础知识 1. **您看过哪些Java方面的书籍...以上是对给定文件中的知识点进行了详细的解释和扩展,涵盖了Java基础知识、Web开发、JavaScript/Ajax、Struts以及Hibernate等多个方面。
【Java软件开发简历模板】是IT领域中针对Java程序员求职时使用的一种标准格式,用于展示个人的专业技能、项目经验和教育背景。以下是对Java软件开发的关键知识点的详细解析: 1. **Java语言特性**: - **简单性**...
给一个 Bean 的 message 属性, 字符串类型, 注入值为 "Hello" 的 XML 配置文件该怎么写? 125 19、Jdo是什么? 125 20、什么是spring的IOC AOP 126 21、STRUTS的工作流程! 126 22、spring 与EJB的区别!! 126 八. ...
- Getter和Setter方法: 用于访问Bean的属性。 18. **JSP开发模式**: - JSP + JavaBean: 最简单的模式,适合小型项目。 - JSP + JavaBean + Servlet: 适用于中大型项目,提高了代码的重用性和维护性。 #### 二、...
8. **DOM编程**:理解和使用DOM解析XML文档,处理和操作XML数据。 9. **Servlet和JSP**:Servlet是Java Web开发的核心,用于处理HTTP请求,JSP则提供了更便捷的视图层开发方式。 10. **AJAX**:异步JavaScript和...
- **发展方向**: 包括JAVASE(Java Standard Edition,标准版)、JAVAME(Java Micro Edition,小型版)和JAVAEE(Java Enterprise Edition,企业版)。 - **Java语言特点**: - **简单性**: Java简化了许多C++中的...
给一个 Bean 的 message 属性, 字符串类型, 注入值为 "Hello" 的 XML 配置文件该怎么写? 137 19、Jdo是什么? 137 20、什么是spring的IOC AOP 137 21、STRUTS的工作流程! 137 22、spring 与EJB的区别!! 137 八. ...