#
懶惰,直接上代碼,用法見JAVA DOC.
1 package com.alibaba.stonelab.javalab.jvm.sizeof;
2
3 import java.lang.instrument.Instrumentation;
4 import java.lang.reflect.Array;
5 import java.lang.reflect.Field;
6 import java.lang.reflect.Modifier;
7 import java.util.IdentityHashMap;
8 import java.util.Map;
9 import java.util.Stack;
10
11 /**
12 * <pre>
13 * 1. MANIFEST.MF
14 * Premain-Class: xxx.yyy.zzz.JavaSizeOf
15 *
16 * 2. MAIN.JAVA
17 * System.out.println(JavaSizeOf.sizeof(new ConcurrentHashMap<Object, Object>()));
18 * System.out.println(JavaSizeOf.sizeof(new String("1234567")));
19 * System.out.println(JavaSizeOf.sizeof(new String("1234")));
20 * System.out.println(JavaSizeOf.sizeof(new Object()));
21 * System.out.println(JavaSizeOf.sizeof(new int[] { 1, 2, 3 }));
22 * System.out.println(JavaSizeOf.sizeof(new CopyOnWriteArrayList<Object>()));
23 * System.out.println(JavaSizeOf.sizeof(null));
24 *
25 * 3. USAGE:
26 * java -javaagent:sizeof.jar xxx.yyy.zzz.Main
27 * </pre>
28 *
29 * @author <a href="mailto:li.jinl@alibaba-inc.com">Stone.J</a> 2013-6-8
30 */
31 public class JavaSizeOf {
32
33 private static Instrumentation inst;
34
35 public static void premain(String agentArgs, Instrumentation inst) {
36 JavaSizeOf.inst = inst;
37 }
38
39 /**
40 * get size of java object.
41 *
42 * @param o
43 * @return
44 */
45 public static long sizeof(Object o) {
46 assert inst != null;
47 Map<Object, Object> visited = new IdentityHashMap<Object, Object>();
48 Stack<Object> visiting = new Stack<Object>();
49 visiting.add(o);
50 long size = 0;
51 while (!visiting.isEmpty()) {
52 size += analysis(visiting, visited);
53 }
54 return size;
55 }
56
57 /**
58 * analysis java object size recursively.
59 *
60 * @param visiting
61 * @param visited
62 * @return
63 */
64 protected static long analysis(Stack<Object> visiting, Map<Object, Object> visited) {
65 Object o = visiting.pop();
66 if (skip(o, visited)) {
67 return 0;
68 }
69 visited.put(o, null);
70 // array.
71 if (o.getClass().isArray() && !o.getClass().getComponentType().isPrimitive()) {
72 if (o.getClass().getName().length() != 2) {
73 for (int i = 0; i < Array.getLength(o); i++) {
74 visiting.add(Array.get(o, i));
75 }
76 }
77 }
78 // object.
79 else {
80 Class<?> clazz = o.getClass();
81 while (clazz != null) {
82 Field[] fields = clazz.getDeclaredFields();
83 for (Field field : fields) {
84 if (Modifier.isStatic(field.getModifiers())) {
85 continue;
86 }
87 if (field.getType().isPrimitive()) {
88 continue;
89 }
90 field.setAccessible(true);
91 try {
92 visiting.add(field.get(o));
93 } catch (Exception e) {
94 assert false;
95 }
96 }
97 clazz = clazz.getSuperclass();
98 }
99 }
100 return inst.getObjectSize(o);
101 }
102
103 /**
104 * <pre>
105 * skip statistics.
106 * </pre>
107 *
108 * @param o
109 * @param visited
110 * @return
111 */
112 protected static boolean skip(Object o, Map<Object, Object> visited) {
113 if (o instanceof String) {
114 if (o == ((String) o).intern()) {
115 return true;
116 }
117 }
118 return o == null || visited.containsKey(o);
119 }
120
121 }
122
軟件已更新,最新請查看:https://code.google.com/p/stonelab/wiki/pdbx
原文:https://code.google.com/p/stonelab/wiki/RemotePDB
軟件介紹
rpdb:遠(yuǎn)程PDB調(diào)試工具,是對pdb的擴(kuò)展。
在pdb基礎(chǔ)上,做了功能加強(qiáng),主要特性如下:
1. 兼容pdb一切語法和使用習(xí)慣
2. 增加了遠(yuǎn)程調(diào)試功能, 允許你客戶端通過telnet連接到指定調(diào)試端口,進(jìn)行遠(yuǎn)程調(diào)試
3. 增加了rq/rquit命令,支持安全退出模式,避免默認(rèn)的quik會導(dǎo)致python程序異常退出的情況
4. 允許多次調(diào)試
5. 增加suspend模式,在啟動時強(qiáng)制或者非強(qiáng)制進(jìn)入斷點(diǎn)
軟件已更新,最新請查看:https://code.google.com/p/stonelab/wiki/pdbx
軟件介紹
rpdb擴(kuò)展了pdb,讓pdb支持遠(yuǎn)程調(diào)試功能。
使用了rpdb的python腳本在遠(yuǎn)程啟動,本地通過telnet方式連接上rpdb提供的調(diào)試端口,接下來的操作和本地完全一致。
使用說明
pdb = Rpdb() # 類似于pdb=Pdb()
pdb = Rpdb(8787) # 指定遠(yuǎn)程調(diào)試端口號
pdb.set_trace() #設(shè)置斷點(diǎn)
如example.py中程序:#!/usr/bin/python
from rpdb import Rpdb
from random import randint
from time import sleep
def add(i, j):
r = i + j
return r
def main():
pdb = Rpdb()
# pdb = Rpdb(9999) # debug port:9999
pdb.set_trace()
while True:
i = randint(1,10)
j = randint(1,10)
r = add(i, j)
print r
sleep(1)
if __name__ == '__main__':
main()
本地終端輸入: telnet xxx.xxx.xxx.xxx 8787telnet 127.0.0.1 8787
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
> /Users/stone/Tmp/baidu/rpdb/example.py(15)main()
-> while True:
(Pdb) l
10
11 def main():
12 pdb = Rpdb()
13 # pdb = Rpdb(9999) # debug port:9999
14 pdb.set_trace()
15 -> while True:
16 i = randint(1,10)
17 j = randint(1,10)
18 r = add(i, j)
19 print r
20 sleep(1)
(Pdb) n
> /Users/stone/Tmp/baidu/rpdb/example.py(16)main()
-> i = randint(1,10)
(Pdb) b 19
Breakpoint 1 at /Users/stone/Tmp/baidu/rpdb/example.py:19
(Pdb) c
> /Users/stone/Tmp/baidu/rpdb/example.py(19)main()
-> print r
(Pdb) p r
11
(Pdb) q
Connection closed by foreign host.
操作和pdb完全一致。
PDB常用命令
命令 | 介紹 |
h(elp) command? | 輸入h或者h(yuǎn)elp 列出pdb支持的所有命令, h command? 介紹指定命令 |
w(here) | 列出當(dāng)前調(diào)試所在行,一般會使用 l(ist) |
l(ist) [first[, last]] | 列出源代碼信息 |
s(tep) | 進(jìn)入函數(shù)體 |
n(ext) | 執(zhí)行下一行代碼 |
c(ont(inue)) | 繼續(xù),直到遇到下一個斷點(diǎn) |
r(eturn) | 執(zhí)行到函數(shù)體結(jié)束那行 |
b(reak) | 設(shè)置斷點(diǎn),可以是代碼行號,方法名, 還可以加進(jìn)入條件 |
tbreak | 設(shè)置臨時斷點(diǎn),進(jìn)入一次后,自動消失 |
cl(ear) | 取消斷點(diǎn) |
disable | 讓斷點(diǎn)失效 |
enable | 讓斷點(diǎn)生效 |
ignore | 忽略斷點(diǎn)n次 |
condition | 給斷點(diǎn)添加條件,符合條件的才進(jìn)入斷點(diǎn) |
j(ump) lineno | 跳掉指定行 |
a(rgs) | 打印函數(shù)體參數(shù)信息 |
p expression | 打印變量 |
pp expression | 同上,打印得漂亮一些 |
! statement | 執(zhí)行代碼,非常有用,可用來修改變量值 |
q(uit) | 退出調(diào)試(pdb的quit很黃很暴力) |
自己寫的幾個小工具,分享給需要的人:
https://code.google.com/p/stonelab/wiki/BaiduMp3
百度MP3批量下載工具
https://code.google.com/p/stonelab/wiki/FileConvertor
文件編碼轉(zhuǎn)換工具
https://code.google.com/p/stonelab/wiki/MyZip
擴(kuò)展zip命令,支持文件名編碼
https://code.google.com/p/stonelab/wiki/Translate
命令行下的翻譯軟件
https://code.google.com/p/stonelab/wiki/HostsX
擴(kuò)展Hosts,別名DnsProxy,DNS代理服務(wù)
原文:https://code.google.com/p/stonelab/wiki/BaiduMp3
軟件介紹
BaiduMp3,基于命令行下的百度MP3歌曲批量下載工具。
主要支持功能:
- 搜索 根據(jù)關(guān)鍵詞搜索匹配的歌曲
- 下載 根據(jù)搜索出來的歌曲ID,下載到本地指定目錄
- 批量下載 根據(jù)關(guān)鍵詞,批量下載匹配的歌曲,到本地指定目錄
軟件使用
Usage: baidump3.py [options]
Options:
-h, --help show this help message and exit
-m MODE, --mode=MODE specifies the command mode
[list|download|multidownload]
-o OUTPUT, --output=OUTPUT
specifies the output dir for download
-p PAGE, --page=PAGE specifies the list page
-k KEY, --key=KEY specifies the mp3 keyworld
-f FROMPAGE, --from=FROMPAGE
specifies the from page for multidownload
-t TOPAGE, --to=TOPAGE
specifies the end page for multidownload
- 搜索
通過-m list指定為搜索模式 -k參數(shù)指定搜索關(guān)鍵詞,-p關(guān)鍵詞指定分頁頁面號,默認(rèn)一頁顯示20條數(shù)據(jù)。
比如:./baidump3.py -m list -k 70后 -p 2
效果:./baidump3.py -m list -k 70后 -p 2
Total: 1000 Page:2
1007797 劉若英 為愛癡狂
2067170 姜育恒 別讓我一個人醉
209442 彭佳慧 相見恨晚
2121730 楊鈺瑩,毛寧 心雨
216206 許美靜 蔓延
226444 陳淑樺 問
253833 張學(xué)友 秋意濃
274172 張學(xué)友 三天兩夜
580824 孟庭葦 傷了你的心的我傷心
582858 莫文蔚 電臺情歌
650924 姜育恒 其實(shí)我真的很在乎
7274415 滿文軍 我需要你
7277793 林志炫 單身情歌
7280177 林志炫 離人
7302437 李壽全 張三的歌
844889 陳淑樺 流光飛舞
1039139 王菲 容易受傷的女人
1243712 羅大佑 戀曲1980
2076242 李宗盛 我是一只小小鳥
2121739 楊鈺瑩 輕輕的告訴你
- 下載
通過-m download指定為下載模式 -k參數(shù)指定下載歌曲ID號 -o參數(shù)指定下載路徑,默認(rèn)為當(dāng)前目錄。
比如:./baidump3.py -m download -k 1007797 -o ~/Tmp/
效果:Downloading >>> 為愛癡狂.mp3
增加網(wǎng)絡(luò)視頻播放功能:
使用百度視頻搜索
支持優(yōu)酷,迅雷看看,PPS,樂視,CNTV,電影網(wǎng),風(fēng)行網(wǎng)視頻

主要功能界面:
轉(zhuǎn)自:https://code.google.com/p/stonelab/wiki/RaspCTL
COPY過來格式比較亂,將就地看吧。原文直接看googlecode wiki吧 :)
什么是RaspCTL
RaspCTL是Raspberry Pi和Control字母的組合,表示樹莓派控制端。 RaspCTL是一款通過手機(jī)終端(泛義上包括手機(jī),平板,電腦等設(shè)備)控制樹莓派的軟件。
目前,通過Raspberry&RaspCTL組合,打造成家庭多媒體播放機(jī)頂盒,在此場景中,RaspCTL非常類似XBMC平臺。未來,會不斷擴(kuò)展RaspCTL功能,成為控制家庭物聯(lián)網(wǎng)的設(shè)備中心,比如控制攝像頭,空調(diào)開關(guān)等。此乃后話,按下不表。
為什么選擇Raspberry Pi&RaspCTL
為什么選擇Raspberry Pi
我們先來看看Raspberry Pi的相關(guān)參數(shù):
CPU |
700 MHz, ARM1176JZF-S |
GPU(顯卡) |
Broadcom VideoCore? IV,OpenGL ES 2.0, 1080p30 h.264/MPEG-4 AVC high-profile decoder |
MEM(內(nèi)存) |
512M |
分辨率 |
1080P |
輸出接口 |
1*SD口 2*USB口 1*音頻口 1*HDMI口 1*網(wǎng)卡 |
尺寸 |
85.6 x 53.98 x 17mm (一張信用卡大小) |
價格 |
$35 |
好吧,一起來總結(jié)下Raspberry Pi的優(yōu)勢吧
- 小巧:只有一張信用卡大小
- GPU強(qiáng)悍: 硬解1080P,30幀/S,通俗地將,差不多是iphone4S手機(jī)的2倍性能
- 輸出接口豐富: 包括2*USB,1*HDMI
- 性價比高:$35
從這些特性看,Raspberry非常合適充當(dāng)高清視頻播放機(jī)頂盒,來替代目前的華數(shù)機(jī)頂盒(華數(shù)官方壟斷,費(fèi)用高,質(zhì)量差)。 家庭中,只要購置了Raspberry Pi和寬帶,高清電影電視,免費(fèi)看。 :)
為什么選擇RaspCTL
只有一個原因:Raspberry Pi CPU很弱:700MHZ。 同樣,我們來看一組數(shù)據(jù):
- Raspbian Terminal下 CPU LOAD在0.2左右
- Raspbian XWindows下, CPU占用率差不多在70%以上
- XBian下,CPU占用率在95%以上
如果,Raspberry Pi CPU能強(qiáng)悍那么一點(diǎn)點(diǎn),那么XBian一定是首選,我也不會重新創(chuàng)造RaspCTL這個輪子了。只是目前,XBMC在Raspberry Pi(XBian)上的性能太糟糕了。 從數(shù)據(jù)看,只有在Raspbian Terminal下的性能,才能符合用戶的期望,所以作者編寫了RaspCTL這個控制端。通過手機(jī)終端的界面,來操作Raspbian Terminal,實(shí)現(xiàn)多媒體播放的功能。
RaspCTL(V0.1.0)功能特性
- 支持視屏,音頻播放
- 支持播放,暫停,停止,快進(jìn),快退,播放列表,上一首,下一首等
- 支持本地文件查看
- 配置系統(tǒng)信息
- 視頻網(wǎng)站真實(shí)URL分析
- 支持包括優(yōu)酷,土豆,迅雷,百度等82個網(wǎng)站視頻URL分析
- 制定Plugins規(guī)范
使用者文檔
如何安裝RaspCTL
- 下載RaspCTL
- 下載,解壓到指定目錄
- 或者直接使用svn地址: svn co https://stonelab.googlecode.com/svn/tags/raspctl-0.1.0 RaspCTL
- 安裝RaspCTL
- chmox +x bin/install.sh; bin/install.sh
- 會自動安裝RaspCTL依賴的第三方庫,主要是python-webpy python-jinja2 python-pexpect依賴
如何使用RaspCTL
- 啟動RaspCTL服務(wù)
- 關(guān)閉RaspCTL服務(wù)
常見問題
- Q:如何自啟動RaspCTL服務(wù)
- 將 bin/start.sh 配置到樹莓派的/etc/rc.local exit之前。 同理,你在rc.local中可以啟動其他任何服務(wù);
- Q:如何使用80端口
- debian系統(tǒng)禁用了小于1024的端口,所以RaspCTL只有使用8000端口。可以通過iptable將80端口請求轉(zhuǎn)發(fā)到8000端口: iptables -t nat -A PREROUTING -p tcp --dport 81 -j REDIRECT --to-ports 8080
開發(fā)者文檔
類庫API
Omxplayer
play |
播放,可以指定播放列表中任一一個資源 |
pause |
暫停播放 |
resume |
恢復(fù)播放 |
stop |
停止播放 |
lseek |
快退, 快退30秒, 參數(shù)為True的話,快退10分鐘 |
rseek |
快進(jìn), 快進(jìn)30秒,參數(shù)為True的話,快進(jìn)10分鐘 |
prev |
播放上一首 |
next |
播放下一首 |
set_playlist |
設(shè)置播放列表 |
add_playitem |
添加多媒體資源到播放列表中, 參數(shù)為 ('url', 'name') 資源地址, 資源顯示名 |
del_playitem |
清空播放列表 |
sort_playitem |
播放列表排序 |
set_dev |
設(shè)置輸出設(shè)備, hdmi接口 或者 本地音頻接口 |
set_loop |
設(shè)置播放模式:順序,循環(huán) |
get_info |
獲取播放器信息,如播放狀態(tài)等 |
LocalFile?
get_mediapath |
獲得多媒體文件根目錄路徑 |
list |
獲取一個目錄下的所有資源 |
list_all |
遞歸獲取一個目錄下的所有資源 |
Config
load |
獲取raspctl.cnf中的配置信息 |
save |
更新raspctl.cnf中的配置信息 |
MediaUrl?
get_urls |
獲取網(wǎng)站url對應(yīng)的真實(shí)視屏url地址信息, fmt=high 獲取高清視屏地址 |
Ajax規(guī)范
使用Ajax的目的:為了RaspCTL提供的服務(wù)可以同時被WAP, Android APP, IOS APP使用,RaspCTL服務(wù)均以Ajax形式提供。希望Plugins開發(fā)者也遵照這個規(guī)約,但不強(qiáng)制。
類庫中,只要被標(biāo)志@classmethod的方法,會直接暴露成Ajax服務(wù),如:
class Foo:
@classmethod
def hello(cls, arg1, arg2):
return {msg: 'Hello Ajax[%s %s]' % (arg1, arg2)}
Ajax服務(wù)地址為:http://xxx.xxx.xxx.xxx:8000/api?data={"name":"Foo.hello", "args":["stone2083", "connie2083"]} 服務(wù)信息為:
{
status: "Success",
message: "Success",
api: {
args: [ ],
name: "Foo.hello"
},
result: {
msg: "Hello Ajax[stone2083 connie2083]"
}
}
Plugins規(guī)范
youku --> 插件名字
__init__.py --> 插件程序
index.html --> 插件模板 【可選擇】
init.py 內(nèi)容為:
from rasplib import Plugin
urls = (
'/', 'Index',
)
# 必須創(chuàng)建plugin實(shí)例,參數(shù)分別為插件名,作者名,版本號, 支持功能的urls
#其中,plugin中包含RaspCTL類庫的所有方法,可直接調(diào)用
plugin = Plugin('youku','stone2083', '0.1', urls)
#web.py寫法,插件規(guī)范并不引入新的學(xué)習(xí)成本。
class Index:
def GET(self):
return 'youku-NotSupported.' #可以直接輸出
#return plugin.render.index() #可以渲染某個模板信息
寫在最后
- RaspCTL作者聯(lián)系信息:stone2083#yahoo.cn 程序的任何問題可直接聯(lián)系這個郵箱
- 招募UED設(shè)計(jì)前端界面 0.1.0前端非常糟糕,急待重構(gòu)
- 招募Plugin開發(fā)者,豐富RaspCTL
- 期待小白鼠適用RaspCTL
感謝limodou,F(xiàn)elinx Lee,獲得了一個SAE Python邀請碼。
首次倒騰SAE,不熟悉,瞎搞,第一件干的事情,就是嘗試如何讓SAE支持web.py.
1. svn check out
svn co https://svn.sinaapp.com/stone2083 sae
2. 創(chuàng)建版本目錄
mkdir 1
cd 1/
3. copy web.py目錄到當(dāng)前目錄
scp -r /usr/share/pyshared/web web
4. 編寫正常的webpy應(yīng)用代碼
vi webpy.py
1 import web
2
3 urls = (
4 '/', 'Home',
5 )
6
7 class Home:
8 def GET(self):
9 web.header('Content-Type', 'text/html')
10 return 'Hello Web.py'
11
12 app = web.application(urls, globals())
5. 編寫index.wsgi
vi index.wsgi
1 import sae
2 from webpy import app
3 application = sae.create_wsgi_app(app.wsgifunc())
整體目錄結(jié)構(gòu)如下:
搞定:
背景之前利用笨重的Java寫過內(nèi)網(wǎng)訪問程序(SSL雙向認(rèn)證系統(tǒng)),今天才發(fā)現(xiàn)curl等命令對SSL都有良好的支持。
故記錄相關(guān)點(diǎn)滴。
創(chuàng)建CA根證書
#創(chuàng)建ca私鑰
openssl genrsa -out ca.key
#創(chuàng)建證書請求文件(Certificate Secure Request)
openssl req -new -key ca.key -out ca.csr
#創(chuàng)建CA根證書
openssl x509 -req -days 3650 -in ca.csr -signkey ca.key -out ca.crt
創(chuàng)建服務(wù)器證書
#創(chuàng)建服務(wù)器私鑰
openssl genrsa -out server.key
#創(chuàng)建服務(wù)器證書請求文件
openssl req -new -key server.key -out server.csr
#創(chuàng)建服務(wù)器證書
openssl ca -in server.csr -cert ca.crt -keyfile ca.key -out server.crt
PFX證書轉(zhuǎn)換
#pfx格式證書導(dǎo)出成pem格式證書
openssl pkcs12 -in jinli.pfx -nodes -out jinli.pem
#導(dǎo)出私鑰
openssl rsa -in jinli.pem -out jinli.key
#導(dǎo)出證書,公鑰
openssl x509 -in jinli.pem -out jinli.crt
curl訪問HTTPS命令
curl -E jinli.pem:${password} --cacert ca.crt https://www.cn.alibaba-inc.com/
curl --cacert gmail.pem https://mail.google.com/mail
curl --cert jinli.crt --key jinli.key --cacert ca.crt https://www.cn.alibaba-inc.com/
參數(shù)解釋:
--cacert <file> CA certificate to verify peer against (SSL)
--capath <directory> CA directory to verify peer against (SSL)
-E/--cert <cert[:passwd]> Client certificate file and password (SSL)
--cert-type <type> Certificate file type (DER/PEM/ENG) (SSL)
--key <key> Private key file name (SSL/SSH)
--key-type <type> Private key file type (DER/PEM/ENG) (SSL)
python訪問HTTPS代碼
from httplib import HTTPSConnection
con = HTTPSConnection('www.cn.alibaba-inc.com', cert_file='jinli.pem')
con.connect()
con.request('GET', '/xxx')
res = con.getresponse()
print res.status
print res.read()
res.close()
con.close()
python查看證書信息代碼
from OpenSSL import crypto
x509 = crypto.load_certificate(crypto.FILETYPE_PEM, open('cert_file').read())
print x509.get_issuer()
pkcs = crypto.load_pkcs12(open(pkcs_file).read(),passphrase)
print pkcs.get_certificate().get_issuer()
HTTPSConnection不理解的地方
def wrap_socket(sock, keyfile=None, certfile=None,
server_side=False, cert_reqs=CERT_NONE,
ssl_version=PROTOCOL_SSLv23, ca_certs=None,
do_handshake_on_connect=True,
suppress_ragged_eofs=True, ciphers=None):
return SSLSocket(sock, keyfile=keyfile, certfile=certfile,
server_side=server_side, cert_reqs=cert_reqs,
ssl_version=ssl_version, ca_certs=ca_certs,
do_handshake_on_connect=do_handshake_on_connect,
suppress_ragged_eofs=suppress_ragged_eofs,
ciphers=ciphers)
ssl wrap的函數(shù)是支持ca_certs參數(shù)的,但是HTTPSConnection不支持ca_certs參數(shù)
class HTTPSConnection(HTTPConnection):
"This class allows communication via SSL."
default_port = HTTPS_PORT
def __init__(self, host, port=None, key_file=None, cert_file=None,
strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
source_address=None):
HTTPConnection.__init__(self, host, port, strict, timeout,
source_address)
self.key_file = key_file
self.cert_file = cert_file
def connect(self):
"Connect to a host on a given (SSL) port."
sock = socket.create_connection((self.host, self.port),
self.timeout, self.source_address)
if self._tunnel_host:
self.sock = sock
self._tunnel()
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file)