关于ICS/JB下命令行启动程序segfault的问题

其实很多人研究过这个问题了,只是最近我碰到这次原因有些不同…… 症状是在命令行执行命令碰到segmentation fault,logcat里有: W/dalvikvm(12364): Exception Ljava/lang/NullPointerException; thrown while initializing Ljava/lang/System; W/dalvikvm(12364): Exception Ljava/lang/ExceptionInInitializerError; thrown while initializing Ljava/lang/ClassLoader$SystemClassLoader; …. I/dalvikvm(12364): java.lang.ExceptionInInitializerError: I/dalvikvm(12364): at java.lang.ClassLoader.getSystemClassLoader(ClassLoader.java:125) I/dalvikvm(12364): at dalvik.system.NativeStart.main(Native Method) I/dalvikvm(12364): Caused by: I/dalvikvm(12364): java.lang.ExceptionInInitializerError: I/dalvikvm(12364): at java.lang.ClassLoader.createSystemClassLoader(ClassLoader.java:100) …. I/dalvikvm(12364): Caused by: I/dalvikvm(12364): java.lang.NullPointerException: I/dalvikvm(12364): at java.util.Hashtable.put(Hashtable.java:365) I/dalvikvm(12364): at java.lang.System.initSystemProperties(System.java:286) I/dalvikvm(12364): at java.lang.System.getProperties(System.java:260) …. 原因大致上就是LD_LIBRARY_PATH里少了东西。ICS以后的系统,启动Android那套VM需要LD_LIBRARY_PATH里必须要有一些路径,默认是/vendor/lib和/system/lib,试下来至少要/system/lib,否则会找不到库,然后…… 不清楚之后发生了什么,反正最后就导致上面那个错误…… 但是默认情况是有的,啥时候没有呢?其实这次碰见bug是因为,我为了弄到root把shell(/system/bin/mksh) setuid了…… …

Continue reading ‘关于ICS/JB下命令行启动程序segfault的问题’ »

APK相关工具

昨天搞的时候很混乱,今天整理了一下,搞了个图: 具体可以参见wiki: APK (de)compile 大致上有很多办法可以改一个apk,总的来说有两个办法,一个是搞成 Dalvik VM 的汇编,然后改。一个是先从 Dalvik VM 的字节码搞成 JVM 的字节码,然后搞成 JVM 的汇编,甚至搞成 Java source code,然后改。改完了再倒回去,重新签名就是新apk了…… 另,Dia 真好用……

自己动手,丰衣足食

最近虾米Android用得不甚顺畅。主要问题是,拿着虾米Android听电台,听着听着,自动就关了…… 一般都是在启动别的程序的时候挂掉。各种程序都可能引发,用内存多的概率更大。有时候没动手机也会自己挂掉。 之前就怀疑是Android低内存自动杀进程功能干的。近日研究了一下: 首先,用ps | grep xiami列xiami进程。每次挂掉之后,列进程可以发现com.xiami那个进程不见了。过一会儿,这进程又会被重新启动起来。但是音乐播放不会自动恢复。 看系统信息里面,虾米总共开了俩服务,一个是push message receiver,对应ps里面那个com.xiami:push。另一个就是music play service,对应那个被干掉的com.xiami。 我印象里,Android里面开了服务,就不应该会被干掉,至少会比那些后台程序更晚被干掉。利用adb shell dumpsys meminfo,可以发现后台还有好多进程啊…… 仔细看一眼dumpsys meminfo的输出,可以发现当从xiami切到别的程序之后,xiami被列在了Background分类里,而其他的还有A Services和B Services。xiami占的内存也不少,系统想杀进程的时候,挑大的杀,于是就杀了虾米…… 于是首先是这么个问题:既然xiami开了服务,为啥会被扔到Background里去?继续观察,可以发现xiami被杀并重启之后,居然跑到了A Services分类里…… 这样就不会被杀了,问题是音乐也停了…… 为了研究到底杀了重启是啥样的过程,我去网上找了个ServiceDemo。实验后发现,对于一个普通程序,就算开了服务,切到后台也是Background。等到内存不够,系统会先杀了你,之后再启动一个进程来仅仅跑服务。这样或许Activity那边的内存就能释放了?一般杀之前不调onDestroy(),杀完重启的时候调onCreate()和onStart()。所以要适应这种情况,可以在onStart()里处理被杀了重启的情况,并且继续之前的工作。 但是我觉得其他音乐播放器不是这样啊…… 于是随便找了个音乐播放器,开了之后切到别的程序,再看meminfo。这样可以注意到,那个程序并没有被扔到Background里,而是在Perceptible里面…… 于是去网上看啥样的程序会变成Perceptible。虽然找到了ActivityManager里面IMPORTANCE_PERCEPTIBLE这个常数定义,但是没有哪儿告诉我咋样可以变成Perceptible。 既然这样…… 只能看代码了。正好机子上有之前下下来的Android 4.0代码,在里面找PERCEPTIBLE,于是在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java里面找着了。 貌似成为PERCEPTIBLE的条件是,某调整值>=PERCEPTIBLE_APP_ADJ。但是继续看代码,发现这个调整值会因为各种理由而决定…… 通过继续研究dumpsys,发现还可以dump别的,例如dumpsys activity就可以dump出activitymanager这边的信息。在这个信息中,就包括了调整值设置的原因。观察那个靠谱的音乐播放器,发现他Perceptible的理由是foreground-service。 其实如果熟悉Android Service的话,或许已经知道这是啥了。但是我不太熟嘛…… 继续看ActivityManagerService,发现这个原因的触发条件是有foregroundServices,而这个值唯一会变成true的地方只有updateServiceForegroundLocked(true)。而这个东西会在setServiceForeground()里被调用。这个东西貌似只有外部引用。到这里我终于跑到网上去搜foreground service…… 发现Service类有个startForeground()方法,那基本上就是这个了…… 根据Android的描述,普通Service还是会被干掉的,只是日后由内存了可能会重开你。但是Foreground Service是这种只要你一干掉用户立马会有反应的,所以会尽可能不去干他。 我在ServiceDemo里加了startForeground()调用,果然他也成了Perceptible,咋样都没被干掉…… 那,虾米是不是没有调用这个startForeground()呢?我跑去搞了个最近看见的Android反编译器,ded,是PSU的人做的…… 反编译出来,貌似的确没有startForeground()。但是有一个对setForeground()的调用,可惜是false。另外,在新版Android里,setForeground()已经没用了…… 这样就知道是虾米写得烂了,我试了几个音乐播放器,都会变成foreground service…… 不过倒是有个也败了的,那就是豆瓣…… 既然如此嘛,要不改虾米,要不改系统。我尝试修改了/proc//oom_adj,但是貌似系统不care这个。我尝试修改了/sys/modules/lowmemorykiller/parameters/minfree,改小了点,希望系统不要没事情杀进程。但是问题依旧,而且chrome启动还更卡了…… 那只好改虾米。那个ded貌似反编译有些问题,编译回去也不太行。上网上找找apk反编译,找到了apktool。 这个东西能够把apk完整的反编译成dalvik VM的汇编码,还能编译回去,真是不错…… 于是反编译出来,找合适的地方加。因为startForeground()还需要提供一个Notification,而虾米本身就会显示Notification,我希望最好还是用虾米原来的。 找了一下,发现虾米的Notification都是NotificationsUtil管的。里面有个notifyOnGoing(),貌似就是显示平时歌曲信息那个Notification的。于是我篡改了NotificationsUtil.notifyOnGoing()里面显示Notification那句。startForeground()是Service类的函数,需要Service对象,正好MusicPlayService被传了进来,于是我直接把 invoke-virtual {v2, p3, …

Continue reading ‘自己动手,丰衣足食’ »

WordPress 多层菜单

下了个主题,发现只支持一级菜单…… 去网上,先找了一个Multi-level Navigation插件,但是主题不配合…… 继续找,找到那么一篇文章: WordPress Multi-Level Drop Down menu using jQuery | SEOAdsenseThemes.com 弄到WP里面去,竟然就好了…… 其实就是加: <script type=‘text/javascript’> jQuery(document).ready(function(){ jQuery(“#dropmenu ul”).css({display:”none”});// Opera Fix jQuery(“#dropmenu li”).hover( function(){ jQuery(this).find(‘ul:first’).css({visibility:”visible”,display:”none”}).show(268); }   ,function(){ jQuery(this).find(‘ul:first’).css({visibility:”hidden”}); } ); }); </script> <style type=“text/css”> #dropmenu, #dropmenu ul {list-style-type:none; list-style-position:outside; position:relative;z-index:300; width:100%;} </style> 到HTML页面的head部分里面,然后把原来的 <?phpwp_list_pages(‘title_li=&depth=10‘); ?> 换成 <ulid=“dropmenu”><?phpwp_list_pages(‘sort_column=menu_order&title_li=‘); ?></ul> 就行了……

英语46级查分的程序

昨天46级能够查分了,研究了一下…… 主页面调用了一段javascript,验证码竟然是本地验证的…… 这个不说,其实最后查分就是通过XMLHttpRequest直接查…… 就没什么加密一类的事情…… 之后找了一下,好像XMLHttpRequest这个东西还只有Javascript里面才有,python用起来还不方便…… 用FireBug试了一下,因为这个查分系统的请求里面没有数据,所以这个请求其实很简单,拿urllib糊弄一下就好了…… 另外关于FireFox里面不能查的问题,貌似是FireFox的XMLHttpRequest在send(null)的时候HTTP头里面没有Content Length字段,其实send(“”)就可以了…… 另外,最后这个系统还检查一下Referer,至少不是什么都不干……  1 import urllib  2 import urllib2  3  4 id = “Your ID“  5 t = “4“  6 url = ‘http://cet.99sushe.com/cetscore_99sushe0902.html?t=‘ + t + ‘&id=‘ + id  7 values = {}  8 headers = { “Referer“ : “http://cet.99sushe.com“ }  9 10 data = urllib.urlencode(values) 11 req = urllib2.Request(url, data, headers) 12 response = …

Continue reading ‘英语46级查分的程序’ »

长宽的 WS 以及我的自动登录/注销工具

虽然我家长宽不限时,但是每次还是要登录,是网页形式的。于是我搞了个java版的登录工具,还有图形界面版本,各平台都能用~某日,发现长宽无论如何登录不上去,显示登录用户名/密码错误,明显在瞎搞。打电话找长宽,很久以后来了一个人,说我的帐号被锁了? 打了个电话就好了。后经研究,发现长宽改变了策略:网页登录后,会自动弹出窗口,要求关机前按里面的钮注销。长宽来的那个人还推荐了一个软件,深圳某人出的,说什么自动登录/注销。 但是此软件很破烂。每次我手动用其注销都会导致非法操作,而重启进 BSD 的话,会发现还是登不进去,明显此软件没有自动注销…… 也就是说,和我写的东西功能差不多了……后来,通过一个下午的研发,我又搞出了注销工具,利用登录工具保存的信息来注销。我设置 BSD 开机时登录,关机时注销,工作得很好~长宽之后貌似又把策略改回去了:一段时间没有网络流量(应该是对于登录记录的IP),就自动注销。这样,每次 Win 转 BSD 后一段时间,就又可以登录了~ 打算以后 Win 也用我的工具,不用长宽那个~附:其实长宽判断注销的条件很简单,你登录的时候,它会给你一个序列号,注销的时候只是看你给的帐号和序列号是不是配对…… 连密码都不要,IP 好像也不管。理论上通过枚举,完全可以把别人注销掉~

长城宽带

五月份,家里的ADSL包年到期。鉴于电信因为近乎垄断而越来越霸道的行为和更加霸道的价格,打算换一种。 正好长城宽带(以下简称长宽)到家里附近来推销。长宽其实在我家那片铺好线已经很多时候了,但是从前听说长宽是整幢楼共用带宽,人多了就会很慢,而且从前担心长城宽带的生存能力,所以没有选择。现在,经过咨询,得知长宽现在技术进步了,05年以后就是限制并且独享带宽了,而价格又比电信便宜很多。 于是,家里现在就改用长城宽带了,1500元/15个月,带宽1Mbps(也就是128KBps)。长宽不用猫,使用网线直接连到门外的一个盒子里,再连到整幢楼的集线的地方,最后用光纤连接出去。地址采用DHCP动态分配,貌似是独立地址,eMule之类的可以以HighID模式运行,看来外面是能够访问我这边的端口的。 但是长宽每次上网,打开的第一个页面总是登陆页面,要登陆之后,才能畅通无阻。这个导致我在FreeBSD的命令行下面不能上网(命令行下的浏览器Links在处理这个页面的时候会崩溃掉),于是起念写一个自动登陆的东西。经过几天和Java的纠缠,写了一个命令行的和图形的,其实就是抓下那个登陆页面,提取信息,然后发送登陆信息,再抓结果,分析分析,看看能不能成功。目前这个东西已经比较稳定了,我在Windows和FreeBSD都令其自动启动,省事。否则爸妈会觉得麻烦的…… 长宽的下载速度还是不错的,常常能到118KBps,比电信的稍快一些。但是RTT(延迟时间)稍长一些,看来长宽还是借道而走啊。