Skip to content

duyanning/ropevm

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

-*- mode: org;-*- 为了方便阅读,请在emacs下启用org模式

编译ropevm需要GCC 4.7.0以上

安装GNU Classpath 0.97.2

(可用GCC 4.7编译) ./configure –disable-Werror –disable-gtk-peer –disable-gconf-peer –disable-plugin make sudo make install

结束后,GNU Classpath被安装到默认位置/usr/local/classpath/。

–disable-Werror选项是为了避免GCC 4.6报错。 其他选项是禁用某些功能,以避免安装一些库。

如果配置jamvm时,用了–disable-zip选项,jamvm将无法读取zip文件中的类,ropevm也不行。 所以到GNU Classpath的安装目录/usr/local/classpath/share/classpath下 将glibj.zip解开: sudo unzip glibj.zip

error: dereferencing type-punned pointer will break strict-aliasing rules

gcc4.6在编译native/jni/native-lib/cpnet.c时报错 cpnet.c: In function ‘cpnet_addMembership’: cpnet.c:583:32: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing] cpnet.c: In function ‘cpnet_dropMembership’: cpnet.c:598:32: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing]

GNU Classpath 0.97.2有这个问题,GNU Classpath 0.98依然有这个问题。 不光gcc 4.6编译时是这样,ubuntu 9.10自带的gcc编译也是这样。

解决办法一:禁止报错

我还曾经为此写了一篇日志 http://marxistprogrammer.blog.163.com/blog/static/4719898120101632058207/

运行configure时加上选项–disable-Werror ./configure –disable-Werror –disable-gtk-peer –disable-gconf-peer –disable-plugin

解决办法二:修改cpnet.c

http://old.nabble.com/Fix-%27-dereferencing-type-punned-pointer-will-break-strict-aliasing-rules%27-td26012951.html 给出了一个办法修改代码

The warning is bogus. Fixed thusly.

Andrew.

2009-10-22 Andrew Haley <aph@…>

  • native/jni/native-lib/cpnet.c (cpnet_addMembership): Fix

aliasing warning. (cpnet_dropMembership): Likewise.

Index: cpnet.c =================================================================== RCS file: /sources/classpath/classpath/native/jni/native-lib/cpnet.c,v retrieving revision 1.10 diff -u -p -r1.10 cpnet.c — cpnet.c 25 Jun 2007 09:44:36 -0000 1.10 +++ cpnet.c 22 Oct 2009 16:18:07 -0000 @@ -578,9 +578,10 @@ jint cpnet_addMembership (JNIEnv *env UN { struct ip_mreq req; int ret;

  • struct sockaddr_in *sockaddr = (struct sockaddr_in *)addr->data;

    memset(&req, 0, sizeof(req));

  • req.imr_multiaddr = ((struct sockaddr_in *)addr->data)->sin_addr;
  • req.imr_multiaddr = sockaddr->sin_addr; req.imr_interface.s_addr = INADDR_ANY; ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &req, sizeof(req)); if (ret != 0)

@@ -593,9 +594,10 @@ jint cpnet_dropMembership (JNIEnv *env U { struct ip_mreq req; int ret;

  • struct sockaddr_in *sockaddr = (struct sockaddr_in *)addr->data;

    memset(&req, 0, sizeof(req));

  • req.imr_multiaddr = ((struct sockaddr_in *)addr->data)->sin_addr;
  • req.imr_multiaddr = sockaddr->sin_addr; req.imr_interface.s_addr = INADDR_ANY; ret = setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &req, sizeof(req)); if (ret != 0)

安装jamvm 1.5.1 (ropevm现在已经不依赖jamvm,但是我的参考实现fixed-jamvm仍然依赖)

./configure make sudo make install

为给ropevm使用,去安装目录/usr/local/jamvm/share/jamvm下 将压缩包classes.zip解开 sudo unzip -d classes classes.zip

如果./configure时加了–disable-zip,就已经是解开的。

安装epm

RopeVM使用epm进行工程管理 https://github.com/duyanning/epm

安装cpps

一些脚本是C++写的,安装了cpps才能执行。 https://github.com/duyanning/cpps

安装RopeVM

下载

从仓库中签出 svn co https://ropevm.svn.sourceforge.net/svnroot/ropevm/trunk/ropevm ropevm

配置

根据所在位置修改config.h中的宏定义INSTALL_DIR。 根据所在位置修改env-vars中的环境变量ROPEVM_ROOT。

编译

执行make

注意: - 为了编译ropevm,必须用gcc 4.7.0及更高版本。 - 必须在运行make之前先执行’. env-vars’。 - 因为在Makefile中调用了epm,epm的位置在.profile中必须通过绝对路径的形式指出。

安装

不需要安装,RopeVM是一个自包含的绿色软件。 执行 . env-vars 即可设置好。(env-vars在ropevm目录下)

为了方便使用,在.profile中添加下面这句: . “$HOME/ropevm/env-vars” # 假设你把ropevm放在了~下。

运行

当前目录.也必须加入PATH,因为 javajavac和ropejavac 都要 . cmd cmd在各个test目录下(不过因为我们已经. env-vars了,所以这个已经是设置好的)

运行. env-vars 然后在各个测试目录下执行usejavac进行编译。 然后用执行javajavac和ropejavac运行。

三种执行模型

支持三种执行模型:1-串行模型;2-退化的rope模型;3-rope模型。 1-串行模型:唯一的初始spmt线程负责所有的对象。 2-退化的rope模型:多个spmt线程,各自负责不同的一组对象。但是spmt线程失去确定控制后不推测执行。 3-rope模型:多个spmt线程,各自负责不同的一组对象。spmt线程失去确定控制后推测执行。

从模型2开始,消息就登上了舞台。bug可能因为消息传递而引起。

环境变量与命令行参数

model用来选择执行模型 log控制日志开关 graph控制是否输出对象协作图 event控制是否输出事件历史

还应该搞一个变量来控制phase.sh是否生成可视化的pdf文件。不然对于大一点的程序,生成pdf太慢了。

环境变量 export model=1 export log=1 export graph=1

命令行参数 -Xmodel:<1/2/3> -Xlog:<on/off> -Xgraph:<on/off> -Xevent:<on/off>

目录结构

env-vars 一些环境变量,每次使用之前要 . env-vars classes/ 用于标注分组策略的java annotation mini-classpath/ 取自GNU Classpath的一些类,进行了rope特有的标注 lib/ ropevm自带的java类 tools/ 一些脚本 eb 运行ebrowse genlog 同ropejavac,不同的是它会把日志输出重定向到文件 javajavac 用java运行javac编译出来的代码 ropejavac 用ropevm运行javac编译出来的代码 show 查看class文件的字节码 usejavac 用javac编译 genlog 运行ropejavac,产生日志 phase/ 探索阶段划分用的小例子

开发调试

虚拟机在解释过程中,可能会使用库中的java代码,如ClassLoader 在调试过程中看着这些java代码的字节码是很有帮助的。 这些java类位于 /usr/local/classpath/share/classpath/java/lang 这是安装classpath所产生的,可用show查看其字节码。 最好在emacs的shell中查看,方便查找。

对应的classpath的源代码位于 classpath-0,97.2/java/lang 以及 classpath-0.97.2/vm/reference/java/lang 由于这些代码的缩进,在emacs中看有些乱,用gedit看。

gdb的设置

set env CLASSPATH=/home/duyanning/work/ropevm/classes:/home/duyanning/work/ropevm/mini-classpath:bin-javac set env model=3 set env log=0

虚拟机后门

java代码中通往虚拟机的后门 都是一些静态方法

RopeVMBackdoor.turn_on_probe() RopeVMBackdoor.turn_off_probe() RopeVMBackdoor.turn_on_log() RopeVMBackdoor.turn_off_log()

model=3时,在调用这些方法前,必须设置推测路障。

epmacs的设置

例子: M-x epm-set-gdb-dir jolden/health-revised (包含.java文件的目录) M-x epm-set-gdb-args Health -l 3 -t 16 -s 1 -m (因ropevm的命令行较长,推荐在gdb中通过环境变量控制,而不是用命令行)

一些工具

class editor http://classeditor.sourceforge.net/

按照其安装帮助,解压后得一目录,在该目录中运行一次: java -jar ce.jar 以便创建相关配置文件。 然后在~/bin中新建一脚本ce,内容如下 #!/usr/bin/env sh java -jar ~/ce2.23/ce.jar 以后运行ce即可。

与JamVM的关系

RopeVM是在JamVM 1.5.1的基础上修改 JamVM根据配置,可以生成好几种解释器。 RopeVM所基于的是其中最简单的一种,即最幼稚的采用loop+switch的decode-and-dispatch解释器。 即配置JamVM时执行configure –disable-int-threading所得到的解释器。 也就是说,THREADED、DIRECT、INLINING都没有定义。

jamvm 1.5.1可以跟GNU Classpath 0.97.2配合工作,但听说无法跟GNU Classpath 0.98配合(据说jamvm 1.5.2可以跟GNU Classpath 0.98f配合,但不能跟低于0.98的版本配合)。

tools

社区发现工具

graph=1剖测运行后会生成两个日志文件: graph.txt 记录着运行时对象的交互情况 timeline.txt 记录着运行时对象产生的顺序

graph2net.cpps根据graph.txt生成graph.net 调用infomap根据graph.net生成graph.map find-leaders.cpps根据graph.map和timeline.txt将需要标记的类输出到控制台 (以上过程由discover.sh驱动。)

阶段发现工具(未完工)

event=1剖测运行后会生成日志文件: event.txt 记录着事件(即操作)历史

event2net.cpps根据event.txt生成event.net 调用infomap根据event.net生成event.map find-story.cpps根据event.map得到story的起止位置(可能还包含其他信息),放在story.txt中。 story2net.cpps根据story.txt生成story.net 调用infomap根据story.net生成story.map find-phase.cpps根据story.map输出阶段划分到控制台(以及phase.txt) (以上过程由phase.sh驱动)

程序命名

xxx2net.cpps 确定xxx.txt中各xxx节点之间的联系,并将其表达成infomap .net格式的网络 infomap 不管.net文件的内容是什么,社区发现都只用同一个程序Infomap find-yyy.cpps 从代表社区发现结果的.map中获知都有哪些模块,每个模块包含哪些节点。

就以上所述,yyy为模块所表达的概念,xxx为模块中的节点所表达的概念。

yyy首次出现,是在find-yyy.cpps中。find-yyy.cpps会把所有的yyy输出到yyy.txt中。 yyy2net.cpps 会读入yyy.txt的内容。 yyy.txt的作用就是在脚本之间传递信息。它就是find-yyy.cpps发现的yyy的持久化。(不光是做持久化之用,yyy.txt还要适合人类阅读)

能否让find-yyy.cpps不产生yyy.txt而直接生成本来是yyy2net生成的yyy.net呢? 别!因为.net受格式限制,关于yyy的信息只能编码在节点的label中,比较受限。而且最初的event.net不是什么find-event.cpps的结果,而是event2net.cpps从日志信息event.txt生成的。

(继续讨论程序命名) 程序如何命名,与程序处理加工的对象、程序所反映的过程,这二者的本质是紧密相关的。 给程序命名,以及给程序中的类命名,其实就是在给这些过程,还有对象命名。

(下面讨论对象协作图、阶段等的命名。其实在项目申请书中会遇到这些命名问题,似乎在那里更容易脱离技术细节,起出更反映事情本质,也更具有对称性的名字来)

概念: 人物网络(即对象网络)、团体(即对象组) 历史事件(简称事件)、历史故事(简称故事)、历史阶段(简称阶段)

利用社区发现技术,从 人物网络 中,发现 团体。 利用社区发现技术,从 事件网络 中,发现 历史故事。 利用社区发现技术,从 故事网络 中,发现 历史阶段。

过程: 所有的社区发现,都用infomap来做。 准备infomap需要的xxx.net格式文件: xxx2net.cpps从xxx.txt生成xxx.net 从infomap产生的xxx.map文件中提取信息:findYyy.cpps生成yyy.txt

阶段是phase还是stage呢?

两个词义很接近 不过我在《现代英汉综合大辞典》中发现一个例句: a phase of history 考虑到我也用了history的概念,所以用phase。

todo

现在做到什么程度了? 阶段已经识别出来了,每个阶段包括的故事编号也知道。 每个故事包含哪些操作编号也知道。 现在想把这些编号转换为更具体的信息显示给程序员看。 要显示成这样: 每个阶段从程序中哪一行开始,到哪一行结束。

为了实现这一功能,需要拿着故事号能很快查出该故事包含的操作号。 >>>这些信息从story.txt中能得到。但story.txt目前是给人看的格式。程序读写都不是很方便。而且不容易扩充。

yyy.txt适合人看,并不适合代码从中提取信息。不光解码不容易,编码更多信息也不容易。我希望直接在各种工具之间传递便于程序访问的数据结构。可以借助boost的serialization。

现在做什么? 在生成story.txt的同时,生成一个story2.txt,该文件用boost的serialization生成。 同理,在生成phase.txt的同时,生成一个phase2.txt。 然后再做一个叫map-phase-to-program的程序,读取phase2.txt、story2.txt,输出各个阶段在程序中的起始位置。