#
懒惰,直接上代码,用法见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)