#
懶惰,直接上代碼,用法見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:遠程PDB調試工具,是對pdb的擴展。
在pdb基礎上,做了功能加強,主要特性如下:
1. 兼容pdb一切語法和使用習慣
2. 增加了遠程調試功能, 允許你客戶端通過telnet連接到指定調試端口,進行遠程調試
3. 增加了rq/rquit命令,支持安全退出模式,避免默認的quik會導致python程序異常退出的情況
4. 允許多次調試
5. 增加suspend模式,在啟動時強制或者非強制進入斷點
軟件已更新,最新請查看:https://code.google.com/p/stonelab/wiki/pdbx
軟件介紹
rpdb擴展了pdb,讓pdb支持遠程調試功能。
使用了rpdb的python腳本在遠程啟動,本地通過telnet方式連接上rpdb提供的調試端口,接下來的操作和本地完全一致。
使用說明
pdb = Rpdb() # 類似于pdb=Pdb()
pdb = Rpdb(8787) # 指定遠程調試端口號
pdb.set_trace() #設置斷點
如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或者help 列出pdb支持的所有命令, h command? 介紹指定命令 |
w(here) | 列出當前調試所在行,一般會使用 l(ist) |
l(ist) [first[, last]] | 列出源代碼信息 |
s(tep) | 進入函數體 |
n(ext) | 執行下一行代碼 |
c(ont(inue)) | 繼續,直到遇到下一個斷點 |
r(eturn) | 執行到函數體結束那行 |
b(reak) | 設置斷點,可以是代碼行號,方法名, 還可以加進入條件 |
tbreak | 設置臨時斷點,進入一次后,自動消失 |
cl(ear) | 取消斷點 |
disable | 讓斷點失效 |
enable | 讓斷點生效 |
ignore | 忽略斷點n次 |
condition | 給斷點添加條件,符合條件的才進入斷點 |
j(ump) lineno | 跳掉指定行 |
a(rgs) | 打印函數體參數信息 |
p expression | 打印變量 |
pp expression | 同上,打印得漂亮一些 |
! statement | 執行代碼,非常有用,可用來修改變量值 |
q(uit) | 退出調試(pdb的quit很黃很暴力) |
自己寫的幾個小工具,分享給需要的人:
https://code.google.com/p/stonelab/wiki/BaiduMp3
百度MP3批量下載工具
https://code.google.com/p/stonelab/wiki/FileConvertor
文件編碼轉換工具
https://code.google.com/p/stonelab/wiki/MyZip
擴展zip命令,支持文件名編碼
https://code.google.com/p/stonelab/wiki/Translate
命令行下的翻譯軟件
https://code.google.com/p/stonelab/wiki/HostsX
擴展Hosts,別名DnsProxy,DNS代理服務
原文:https://code.google.com/p/stonelab/wiki/BaiduMp3
軟件介紹
BaiduMp3,基于命令行下的百度MP3歌曲批量下載工具。
主要支持功能:
- 搜索 根據關鍵詞搜索匹配的歌曲
- 下載 根據搜索出來的歌曲ID,下載到本地指定目錄
- 批量下載 根據關鍵詞,批量下載匹配的歌曲,到本地指定目錄
軟件使用
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參數指定搜索關鍵詞,-p關鍵詞指定分頁頁面號,默認一頁顯示20條數據。
比如:./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 張學友 秋意濃
274172 張學友 三天兩夜
580824 孟庭葦 傷了你的心的我傷心
582858 莫文蔚 電臺情歌
650924 姜育恒 其實我真的很在乎
7274415 滿文軍 我需要你
7277793 林志炫 單身情歌
7280177 林志炫 離人
7302437 李壽全 張三的歌
844889 陳淑樺 流光飛舞
1039139 王菲 容易受傷的女人
1243712 羅大佑 戀曲1980
2076242 李宗盛 我是一只小小鳥
2121739 楊鈺瑩 輕輕的告訴你
- 下載
通過-m download指定為下載模式 -k參數指定下載歌曲ID號 -o參數指定下載路徑,默認為當前目錄。
比如:./baidump3.py -m download -k 1007797 -o ~/Tmp/
效果:Downloading >>> 為愛癡狂.mp3
增加網絡視頻播放功能:
使用百度視頻搜索
支持優酷,迅雷看看,PPS,樂視,CNTV,電影網,風行網視頻

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