作者:<span class="vcard">℃冻番茄</span>

博客被人挂马了还被利用发垃圾邮件

前几天博客搬家时,本来搬家是因为buyvm的vps不稳定,老是offline,直到昨天才发现原来是博客被人黑了。

被人挂上了后门用于发送垃圾邮件,导致CPU负载猛增服务掉线。找到问题就好办了,搜索所有的代码,把有嫌疑的文件全部干掉,删除不用的主题和插件。分析访问日志查到POST方式请求的文件删除。把不该有写入权限的文件夹去除写入权限,并修改ssh密码等。

去年也发现一个事,域名被人劫持了。现到在百度上都有一些乱七八糟的信息。

看来安全问题还是得注意了。


博客搬家了啦

之前博客放置在buyvm的vps上,但最近几个月非常不稳定,老是offline.

所以今天把博客搬到了在hostshare上购买的16.5元的vps上,速度还不错,先用用。不行只能再搬家了

http://www.hostshare.cn

HostShare是一个主机分享组织,成立于2008年,目前主力经营低价VPS;数据中心位于洛杉矶mc,2014新年全场促销码:2014OFF 

全场超低折扣,以下为2套特价方案:

  • 核心:1核CPU
  • 内存:512MB
  • 硬盘:10GB
  • 流量:300GB
  • 端口:100M
  • 架构:OpenVZ
  • 价格:16.50元/月
  • 核心:1核CPU
  • 内存:256MB
  • 硬盘:10GB
  • 流量:300GB
  • 端口:100M
  • 架构:Xen
  • 价格:16.50元/月

至今仍保持hostloc最低价格记录,性价比一流;由loc多位资深会员投资,目前由单手摘月妹子负责运营。本次优惠适用于openvz和xen全系列架构。


祝大家2014马上有钱

今年算起来是博客成立的第6个年头,非常惭愧的是很长时间不写博客了。

2013年算是比较有意义的一年,在这年中主要是学习java,所有的项目都是用java开发,从php转java了,转变还是挺大的。

今天是年前在公司的最后一天,下午就要回南昌过春节了。一年真快,在生活中最大的喜事是俺家又有一个新娃了。现在是俩娃的爹了,顿感亚力山大。在这里感谢我的媳妇,媳妇辛苦了,两娃都是你在操心,等我回家一定给你惊喜。

另晒几张照片,阳光大好啊!

 

PANO_20140124_095721 PANO_20131228_132758 PANO_20131228_133409

西溪湿地

西溪湿地


Java Exception性能问题[转]

背景:
大学里学java,老师口口声声,言之凿凿,告诫我们,Java千万别用异常控制业务流程,只有系统级别的问题,才能使用异常;
(当时,我们都不懂为什么不能用异常,只知道老师这么说,我们就这么做,考试才不会错 🙂 )
公司里,有两派.异常拥护者说,使用业务异常,代码逻辑更清晰,更OOP;反之者说,使用异常,性能非常糟糕;
(当然,我是拥护者)
论坛上,争论得更多,仁者见仁智者见智,口水很多;
(我不发表意见,其实怎么用,真的都可以)

那么,为什么反对异常呢?貌似大多数人的原因都只有一个:性能差!
使用异常性能真的差吗? 是的!
是什么原因,导致性能问题呢? 那么请看下文…

根本原因在于:
异常基类Throwable.java的public synchronized native Throwable fillInStackTrace()方法
方法介绍:
Fills in the execution stack trace. This method records within this Throwable object information about the current state of the stack frames for the current thread.
性能开销在于:
1. 是一个synchronized方法(主因)
2. 需要填充线程运行堆栈信息

但是对于业务异常来说,它只代表业务分支;压根儿不需要stack信息的.如果去掉这个过程,是不是有性能提升呢?

于是做了一个简单的测试对比,对比主体:
1。 创建普通Java对象              (CustomObject extends HashMap)
2。 创建普通Java异常对象          (CustomException extends Exception)
3。 创建改进的Java业务异常对象    (CustomException extends Exception,覆写fillInStackTrace方法,并且去掉同步)

测试结果:
(运行环境:xen虚拟机,5.5G内存,8核;jdk1.6.0_18)
(10个线程,创建10000000个对象所需时间)
普通Java对象         45284 MS
普通java异常        205482 MS
改进的Java业务异常   16731 MS

测试代码如下:

  1 /**
2  * <pre>
3  * xen虚拟机,5.5G内存;8核CPU
4  * LOOP = 10000000
5  * THREADS = 10
6  * o:       45284
7  * e:       205482
8  * exte:    16731
9  * </pre>
10  *
11  * k
12  *
13  * @author li.jinl 2010-7-9 上午09:16:14
14  */
15 public class NewExceptionTester {
16
17     private static final int             LOOP                 = 10000000;                        // 单次循环数量
18     private static final int             THREADS              = 10;                              // 并发线程数量
19
20     private static final List<Long>      newObjectTimes       = new ArrayList<Long>(THREADS);
21     private static final List<Long>      newExceptionTimes    = new ArrayList<Long>(THREADS);
22     private static final List<Long>      newExtExceptionTimes = new ArrayList<Long>(THREADS);
23
24     private static final ExecutorService POOL                 = Executors.newFixedThreadPool(30);
25
26     public static void main(String[] args) throws Exception {
27         List<Callable<Boolean>> all = new ArrayList<Callable<Boolean>>();
28         all.addAll(tasks(new NewObject()));
29         all.addAll(tasks(new NewException()));
30         all.addAll(tasks(new NewExtException()));
31
32         POOL.invokeAll(all);
33
34         System.out.println(“o:\t\t” + total(newObjectTimes));
35         System.out.println(“e:\t\t” + total(newExceptionTimes));
36         System.out.println(“exte:\t\t” + total(newExtExceptionTimes));
37
38         POOL.shutdown();
39     }
40
41     private static List<Callable<Boolean>> tasks(Callable<Boolean> c) {
42         List<Callable<Boolean>> list = new ArrayList<Callable<Boolean>>(THREADS);
43         for (int i = 0; i < THREADS; i++) {
44             list.add(c);
45         }
46         return list;
47     }
48
49     private static long total(List<Long> list) {
50         long sum = 0;
51         for (Long v : list) {
52             sum += v;
53         }
54         return sum;
55     }
56
57     public static class NewObject implements Callable<Boolean> {
58
59         @Override
60         public Boolean call() throws Exception {
61             long start = System.currentTimeMillis();
62             for (int i = 0; i < LOOP; i++) {
63                 new CustomObject(“”);
64             }
65             newObjectTimes.add(System.currentTimeMillis() – start);
66             return true;
67         }
68
69     }
70
71     public static class NewException implements Callable<Boolean> {
72
73         @Override
74         public Boolean call() throws Exception {
75             long start = System.currentTimeMillis();
76             for (int i = 0; i < LOOP; i++) {
77                 new CustomException(“”);
78             }
79             newExceptionTimes.add(System.currentTimeMillis() – start);
80             return true;
81         }
82
83     }
84
85     public static class NewExtException implements Callable<Boolean> {
86
87         @Override
88         public Boolean call() throws Exception {
89             long start = System.currentTimeMillis();
90             for (int i = 0; i < LOOP; i++) {
91                 new ExtCustomException(“”);
92             }
93             newExtExceptionTimes.add(System.currentTimeMillis() – start);
94             return true;
95         }
96
97     }
98
99     /**
100      * 自定义java对象.
101      *
102      * @author li.jinl 2010-7-9 上午11:28:27
103      */
104     public static class CustomObject extends HashMap {
105
106         private static final long serialVersionUID = 5176739397156548105L;
107
108         private String            message;
109
110         public CustomObject(String message){
111             this.message = message;
112         }
113
114         public String getMessage() {
115             return message;
116         }
117
118         public void setMessage(String message) {
119             this.message = message;
120         }
121
122     }
123
124     /**
125      * 自定义普通的Exception对象
126      *
127      * @author li.jinl 2010-7-9 上午11:28:58
128      */
129     public static class CustomException extends Exception {
130
131         private static final long serialVersionUID = -6879298763723247455L;
132
133         private String            message;
134
135         public CustomException(String message){
136             this.message = message;
137         }
138
139         public String getMessage() {
140             return message;
141         }
142
143         public void setMessage(String message) {
144             this.message = message;
145         }
146
147     }
148
149     /**
150      * <pre>
151      * 自定义改进的Exception对象 覆写了 fillInStackTrace方法
152      * 1. 不填充stack
153      * 2. 取消同步
154      * </pre>
155      *
156      * @author li.jinl 2010-7-9 上午11:29:12
157      */
158     public static class ExtCustomException extends Exception {
159
160         private static final long serialVersionUID = -6879298763723247455L;
161
162         private String            message;
163
164         public ExtCustomException(String message){
165             this.message = message;
166         }
167
168         public String getMessage() {
169             return message;
170         }
171
172         public void setMessage(String message) {
173             this.message = message;
174         }
175
176         @Override
177         public Throwable fillInStackTrace() {
178             return this;
179         }
180     }
181 }

所以,如果我们业务异常的基类,一旦覆写fillInStackTrace,并且去掉同步,那么异常性能有大幅度提升(因为业务异常本身也不需要堆栈信息)

如果说,创建异常的性能开销大家已经有些感觉了,那么TryCatch是否也存在性能开销呢?
接下来,做了一次try…catch 和 if…esle的性能比较

测试结果(运行环境和上面一样):
20个线程,100000000,所消耗的时间:
try…catch:  101412MS
if…else:    100749MS

备注:
在我自己的开发机器上(xp和ubuntu下,单核),try…catch耗时是if…else的2倍(在同一数量级)
具体原因还未知,之后会使用专业的性能测试工具进行分析

测试代码如下:

  1 /**
2  * <pre>
3  * xen虚拟机,5.5G内存;8核CPU
4  * LOOP = 100000000
5  * THREADS = 20
6  *
7  * tc:  101412
8  * ie:  100749
9  * </pre>
10  *
11  * @author li.jinl 2010-7-9 上午10:47:56
12  */
13 public class ProcessTester {
14
15     private static final int             LOOP          = 100000000;
16     private static final int             THREADS       = 20;
17
18     private static final List<Long>      tryCatchTimes = new ArrayList<Long>(THREADS);
19     private static final List<Long>      ifElseTimes   = new ArrayList<Long>(THREADS);
20
21     private static final ExecutorService POOL          = Executors.newFixedThreadPool(40);
22
23     public static void main(String[] args) throws Exception {
24         List<Callable<Boolean>> all = new ArrayList<Callable<Boolean>>();
25         all.addAll(tasks(new TryCatch()));
26         all.addAll(tasks(new IfElse()));
27
28         POOL.invokeAll(all);
29
30         System.out.println(“tc:\t\t” + total(tryCatchTimes));
31         System.out.println(“ie:\t\t” + total(ifElseTimes));
32
33         POOL.shutdown();
34     }
35
36     private static List<Callable<Boolean>> tasks(Callable<Boolean> c) {
37         List<Callable<Boolean>> list = new ArrayList<Callable<Boolean>>(THREADS);
38         for (int i = 0; i < THREADS; i++) {
39             list.add(c);
40         }
41         return list;
42     }
43
44     private static long total(List<Long> list) {
45         long sum = 0;
46         for (Long v : list) {
47             sum += v;
48         }
49         return sum;
50     }
51
52     public static class TryCatch implements Callable<Boolean> {
53
54         @Override
55         public Boolean call() throws Exception {
56             long start = System.currentTimeMillis();
57             for (int i = 0; i < LOOP; i++) {
58                 try {
59                     exception();
60                     // 
61                 } catch (ExtCustomException e) {
62                     // 
63                 }
64             }
65             tryCatchTimes.add(System.currentTimeMillis() – start);
66             return true;
67         }
68
69         private void exception() throws ExtCustomException {
70             throw new ExtCustomException(“”);
71         }
72
73     }
74
75     public static class IfElse implements Callable<Boolean> {
76
77         @Override
78         public Boolean call() throws Exception {
79             long start = System.currentTimeMillis();
80             for (int i = 0; i < LOOP; i++) {
81                 Exception e = exception();
82                 if (e instanceof ExtCustomException) {
83                     // 
84                 }
85             }
86             ifElseTimes.add(System.currentTimeMillis() – start);
87             return true;
88         }
89
90         private Exception exception() {
91             return new ExtCustomException(“”);
92         }
93
94     }
95
96     public static class ExtCustomException extends Exception {
97
98         private static final long serialVersionUID = -6879298763723247455L;
99
100         private String            message;
101
102         public ExtCustomException(String message){
103             this.message = message;
104         }
105
106         public String getMessage() {
107             return message;
108         }
109
110         public void setMessage(String message) {
111             this.message = message;
112         }
113
114         @Override
115         public Throwable fillInStackTrace() {
116             return this;
117         }
118
119     }
120
121 }

结论:
1。Exception的性能是差,原因在于ThrowablefillInStackTrace()方法
2. 可以通过改写业务异常基类的方法,提升性能
3。try…catch和if…else的性能开销在同一数量级

4。至于是否使用异常进行业务逻辑的控制,主要看代码风格.(我个人挺喜欢业务异常的)

备注:
以上测试比较简单,写得也比较急.此文也写得比较急(工作时间偷偷写).如果分析不到位的地方,请指出.


HttpClient容易忽视的细节连接关闭

Java代码  收藏代码
  1. HttpClient client = new HttpClient();
  2. HttpMethod method = new GetMethod(“http://www.apache.org”);
  3. try {
  4.   client.executeMethod(method);
  5.   byte[] responseBody = null;
  6.   responseBody = method.getResponseBody();
  7. } catch (HttpException e) {
  8.   // TODO Auto-generated catch block
  9.   e.printStackTrace();
  10. } catch (IOException e) {
  11.   // TODO Auto-generated catch block
  12.   e.printStackTrace();
  13. }finally{
  14.   method.releaseConnection();
  15. }

大部分人使用HttpClient都是使用类似上面的事例代码,包括Apache官方的例子也是如此。最近我在使用HttpClient是发现一次循环发送大量请求到服务器会导致APACHE服务器的链接被占满,后续的请求便排队等待。
我服务器端APACHE的配置

Java代码  收藏代码
  1. Timeout 30
  2. KeepAlive On   #表示服务器端不会主动关闭链接
  3. MaxKeepAliveRequests 100
  4. KeepAliveTimeout 180

因此这样的配置就会导致每个链接至少要过180S才会被释放,这样在大量请求访问时就必然会造成链接被占满,请求等待的情况。
在通过DEBUH后发现HttpClient在method.releaseConnection()后并没有把链接关闭,这个方法只是将链接返回给connection manager。如果使用HttpClient client = new HttpClient()实例化一个HttpClient connection manager默认实现是使用SimpleHttpConnectionManager。SimpleHttpConnectionManager有个构造函数如下

Java代码  收藏代码
  1. /**
  2.  * The connection manager created with this constructor will try to keep the
  3.  * connection open (alive) between consecutive requests if the alwaysClose
  4.  * parameter is set to <tt>false</tt>. Otherwise the connection manager will
  5.  * always close connections upon release.
  6.  *
  7.  * @param alwaysClose if set <tt>true</tt>, the connection manager will always
  8.  *    close connections upon release.
  9.  */
  10. public SimpleHttpConnectionManager(boolean alwaysClose) {
  11.     super();
  12.     this.alwaysClose = alwaysClose;
  13. }

看方法注释我们就可以看到如果alwaysClose设为true在链接释放之后connection manager 就会关闭链。在我们HttpClient client = new HttpClient()这样实例化一个client时connection manager是这样被实例化的

Java代码  收藏代码
  1. this.httpConnectionManager = new SimpleHttpConnectionManager();

因此alwaysClose默认是false,connection是不会被主动关闭的,因此我们就有了一个客户端关闭链接的方法。
方法一:
把事例代码中的第一行实例化代码改为如下即可,在method.releaseConnection();之后connection manager会关闭connection 。

Java代码  收藏代码
  1. HttpClient client = new HttpClient(new HttpClientParams(),new SimpleHttpConnectionManager(true) );

方法二:
实例化代码使用:HttpClient client = new HttpClient();
在method.releaseConnection();之后加上

Java代码  收藏代码
  1. ((SimpleHttpConnectionManager)client.getHttpConnectionManager()).shutdown();

shutdown源代码很简单,看了一目了然

Java代码  收藏代码
  1. public void shutdown() {
  2.     httpConnection.close();
  3. }

方法三:
实例化代码使用:HttpClient client = new HttpClient();
在method.releaseConnection();之后加上
client.getHttpConnectionManager().closeIdleConnections(0);此方法源码代码如下:

Java代码  收藏代码
  1. public void closeIdleConnections(long idleTimeout) {
  2.     long maxIdleTime = System.currentTimeMillis() – idleTimeout;
  3.     if (idleStartTime <= maxIdleTime) {
  4.         httpConnection.close();
  5.     }
  6. }

将idleTimeout设为0可以确保链接被关闭。
以上这三种方法都是有客户端主动关闭TCP链接的方法。下面再介绍由服务器端自动关闭链接的方法。
方法四:
代码实现很简单,所有代码就和最上面的事例代码一样。只需要在HttpMethod method = new GetMethod(“http://www.apache.org”);加上一行HTTP头的设置即可

Java代码  收藏代码
  1. method.setRequestHeader(“Connection”, “close”);

看一下HTTP协议中关于这个属性的定义:
HTTP/1.1 defines the “close” connection option for the sender to signal that the connection will be closed after completion of the response. For example,
Connection: close
现在再说一下客户端关闭链接和服务器端关闭链接的区别。如果采用客户端关闭链接的方法,在客户端的机器上使用netstat –an命令会看到很多TIME_WAIT的TCP链接。如果服务器端主动关闭链接这中情况就出现在服务器端。
参考WIKI上的说明http://wiki.apache.org/HttpComponents/FrequentlyAskedConnectionManagementQuestions
The TIME_WAIT state is a protection mechanism in TCP. The side that closes a socket connection orderly will keep the connection in state TIME_WAIT for some time, typically between 1 and 4 minutes.
TIME_WAIT的状态会出现在主动关闭链接的这一端。TCP协议中TIME_WAIT状态主要是为了保证数据的完整传输。具体可以参考此文档:
http://www.softlab.ntua.gr/facilities/documentation/unix/unix-socket-faq/unix-socket-faq-2.html#ss2.7
另外强调一下使用上面这些方法关闭链接是在我们的应用中明确知道不需要重用链接时可以主动关闭链接来释放资源。如果你的应用是需要重用链接的话就没必要这么做,使用原有的链接还可以提供性能。


请关注我的来往号

来往与微信大火拼啦,请关注我厂来往

http://laiwang.com

04fb2539-4569-4e02-a7a1-daac10507aa5


Android 编程:calledfromWrongThreadException 的原因

子线程更新UI会发生android.view.ViewRoot$CalledFromWrongThreadException异常的解决方法

子线程更新UI

显然假如你的程序需要执行耗时的操作的话,假如像上例一样由主线程来负责执行该操作是错误的。所以我们需要在onClick方法中创建一个新的子线程来负责调用GOOGLE API来获得天气数据。刚接触Android的开发者最轻易想到的方式就是如下:


public void onClick(View v) {

//创建一个子线程执行耗时的从网络上获得天气信息的操作

new Thread() {

@Override

public void run() {

//获得用户输入的城市名称

String city = editText.getText().toString();

//调用Google 天气API查询指定城市的当日天气情况

String weather = getWetherByCity(city);

//把天气信息显示在title上

setTitle(weather);

}

}.start();

}

但是很不幸,你会发现Android会提示程序由于异常而终止。为什么在其他平台上看起来很简单的代码在Android上运行的时候依然会出错呢?假如你观察LogCat中打印的日志信息就会发现这样的错误日志:

android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

从错误信息不难看出Android禁止其他子线程来更新由UI thread创建的试图。本例中显示天气信息的title实际是就是一个由UI thread所创建的TextView,所以参试在一个子线程中去更改TextView的时候就出错了。这显示违反了单线程模型的原则:Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行

2.2 Message Queue

在单线程模型下,为了解决类似的问题,Android设计了一个Message Queue(消息队列),线程间可以通过该Message Queue并结合Handler和Looper组件进行信息交换。下面将对它们进行分别介绍:

l Message Queue

Message Queue是一个消息队列,用来存放通过Handler发布的消息。消息队列通常附属于某一个创建它的线程,可以通过Looper.myQueue()得到当前线程的消息队列。Android在第一启动程序时会默认会为UI thread创建一个关联的消息队列,用来管理程序的一些上层组件,activities,broadcast receivers 等等。你可以在自己的子线程中创建Handler与UI thread通讯。

l Handler

通过Handler你可以发布或者处理一个消息或者是一个Runnable的实例。没个Handler都会与唯一的一个线程以及该线程的消息队列管理。当你创建一个新的Handler时候,默认情况下,它将关联到创建它的这个线程和该线程的消息队列。也就是说,假如你通过Handler发布消息的话,消息将只会发送到与它关联的这个消息队列,当然也只能处理该消息队列中的消息。

主要的方法有:

1)   public final boolean sendMessage(Message msg)

把消息放入该Handler所关联的消息队列,放置在所有当前时间前未被处理的消息后。

2)   public void handleMessage(Message msg)

关联该消息队列的线程将通过调用Handler的handleMessage方法来接收和处理消息,通常需要子类化Handler来实现handleMessage。

l Looper

Looper扮演着一个Handler和消息队列之间通讯桥梁的角色。程序组件首先通过Handler把消息传送给Looper,Looper把消息放入队列。Looper也把消息队列里的消息广播给所有的Handler,Handler接受到消息后调用handleMessage进行处理。

1)   可以通过Looper类的静态方法Looper.myLooper得到当前线程的Looper实例,假如当前线程未关联一个Looper实例,该方法将返回空。

2)   可以通过静态方法Looper. getMainLooper方法得到主线程的Looper实例

线程,消息队列,Handler,Looper之间的关系可以通过一个图来展现:

在了解了消息队列及其相关组件的设计思想后,我们将把天气预告的案例通过消息队列来重新实现:

在了解了消息队列及其相关组件的设计思想后,我们将把天气预告的案例通过消息队列来重新实现:


private EditText editText;

private Handler messageHandler;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

editText = (EditText) findViewById(R.id.weather_city_edit);

Button button = (Button) findViewById(R.id.goQuery);

button.setOnClickListener(this);

//得到当前线程的Looper实例,由于当前线程是UI线程也可以通过Looper.getMainLooper()得到

Looper looper = Looper.myLooper();

//此处甚至可以不需要设置Looper,因为 Handler默认就使用当前线程的Looper

messageHandler = new MessageHandler(looper);

}

&nbsp;

@Override

public void onClick(View v) {

//创建一个子线程去做耗时的网络连接工作

new Thread() {

@Override

public void run() {

//活动用户输入的城市名称

String city = editText.getText().toString();

//调用Google 天气API查询指定城市的当日天气情况

String weather = getWetherByCity(city);

//创建一个Message对象,并把得到的天气信息赋值给Message对象

Message message = Message.obtain();

message.obj = weather;

//通过Handler发布携带有天气情况的消息

messageHandler.sendMessage(message);

}

}.start();

}

&nbsp;

//子类化一个Handler

class MessageHandler extends Handler {

public MessageHandler(Looper looper) {

super(looper);

}

@Override

public void handleMessage(Message msg) {

//处理收到的消息,把天气信息显示在title上

setTitle((String) msg.obj);

}

}

通过消息队列改写过后的天气预告程序已经可以成功运行,因为Handler的handleMessage方法实际是由关联有该消息队列的UI thread调用,而在UI thread中更新title并没有违反Android的单线程模型的原则。


Linux C/C++ 内存泄漏检测工具:Valgrind

Valgrind 是一款 Linux下(支持 x86、x86_64和ppc32)程序的内存调试工具,它可以对编译后的二进制程序进行内存使用监测(C语言中的malloc和free,以及C++中的new和delete),找出内存泄漏问题。

Valgrind 中包含的 Memcheck 工具可以检查以下的程序错误:

使用未初始化的内存 (Use of uninitialised memory)
使用已经释放了的内存 (Reading/writing memory after it has been free’d)
使用超过malloc分配的内存空间(Reading/writing off the end of malloc’d blocks)
对堆栈的非法访问 (Reading/writing inappropriate areas on the stack)
申请的空间是否有释放 (Memory leaks – where pointers to malloc’d blocks are lost forever)
malloc/free/new/delete申请和释放内存的匹配(Mismatched use of malloc/new/new [] vs free/delete/delete [])
src和dst的重叠(Overlapping src and dst pointers in memcpy() and related functions)
重复free

1、编译安装 Valgrind:


wget http://valgrind.org/downloads/valgrind-3.4.1.tar.bz2
tar xvf valgrind-3.4.1.tar.bz2
cd valgrind-3.4.1/
./configure --prefix=/usr/local/webserver/valgrind
make
make install

2、使用示例:对“ls”程序进程检查,返回结果中的“definitely lost: 0 bytes in 0 blocks.”表示没有内存泄漏。


[root@xoyo42 /]#/usr/local/webserver/valgrind/bin/valgrind --tool=memcheck --leak-check=full ls /
==1157== Memcheck, a memory error detector.
==1157== Copyright (C) 2002-2008, and GNU GPL'd, by Julian Seward et al.
==1157== Using LibVEX rev 1884, a library for dynamic binary translation.
==1157== Copyright (C) 2004-2008, and GNU GPL'd, by OpenWorks LLP.
==1157== Using valgrind-3.4.1, a dynamic binary instrumentation framework.
==1157== Copyright (C) 2000-2008, and GNU GPL'd, by Julian Seward et al.
==1157== For more details, rerun with: -v
==1157==
bin   data0  dev  home  lib64       media  mnt  opt   root  selinux  sys       tcsql.db.idx.pkey.dec  ttserver.pid  var
boot  data1  etc  lib   lost+found  misc   net  proc  sbin  srv      tcsql.db  tmp                    usr
==1157==
==1157== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 5 from 1)
==1157== malloc/free: in use at exit: 28,471 bytes in 36 blocks.
==1157== malloc/free: 166 allocs, 130 frees, 51,377 bytes allocated.
==1157== For counts of detected errors, rerun with: -v
==1157== searching for pointers to 36 not-freed blocks.
==1157== checked 174,640 bytes.
==1157==
==1157== LEAK SUMMARY:
==1157==    definitely lost: 0 bytes in 0 blocks.
==1157==      possibly lost: 0 bytes in 0 blocks.
==1157==    still reachable: 28,471 bytes in 36 blocks.
==1157==         suppressed: 0 bytes in 0 blocks.
==1157== Reachable blocks (those to which a pointer was found) are not shown.
==1157== To see them, rerun with: --leak-check=full --show-reachable=yes

3、使用示例:对一个使用libevent库编写的“httptest”程序进程检查,返回结果中的“definitely lost: 255 bytes in 5 blocks.”表示发生内存泄漏。


[root@xoyo42 tcsql-0.1]# /usr/local/webserver/valgrind/bin/valgrind --tool=memcheck --leak-check=full ./httptest
==1274== Memcheck, a memory error detector.
==1274== Copyright (C) 2002-2008, and GNU GPL'd, by Julian Seward et al.
==1274== Using LibVEX rev 1884, a library for dynamic binary translation.
==1274== Copyright (C) 2004-2008, and GNU GPL'd, by OpenWorks LLP.
==1274== Using valgrind-3.4.1, a dynamic binary instrumentation framework.
==1274== Copyright (C) 2000-2008, and GNU GPL'd, by Julian Seward et al.
==1274== For more details, rerun with: -v
==1274==
==1274== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1005 from 2)
==1274== malloc/free: in use at exit: 402,291 bytes in 74 blocks.
==1274== malloc/free: 15,939 allocs, 15,865 frees, 6,281,523 bytes allocated.
==1274== For counts of detected errors, rerun with: -v
==1274== searching for pointers to 74 not-freed blocks.
==1274== checked 682,468,160 bytes.
==1274==
==1274== 255 bytes in 5 blocks are definitely lost in loss record 17 of 32
==1274==    at 0x4A05FBB: malloc (vg_replace_malloc.c:207)
==1274==    by 0x3C1D809BC6: evhttp_decode_uri (http.c:2105)
==1274==    by 0x401C75: tcsql_handler (in /data0/tcsql/cankao/tcsql-0.1/tcsql)
==1274==    by 0x3C1D80C88F: evhttp_get_body (http.c:1582)
==1274==    by 0x3C1D8065F7: event_base_loop (event.c:392)
==1274==    by 0x403E2F: main (in /data0/tcsql/cankao/tcsql-0.1/tcsql)
==1274==
==1274== LEAK SUMMARY:
==1274==    definitely lost: 255 bytes in 5 blocks.
==1274==      possibly lost: 0 bytes in 0 blocks.
==1274==    still reachable: 402,036 bytes in 69 blocks.
==1274==         suppressed: 0 bytes in 0 blocks.
==1274== Reachable blocks (those to which a pointer was found) are not shown.
==1274== To see them, rerun with: --leak-check=full --show-reachable=yes

检查httptest程序,发现有一处“char *decode_uri = evhttp_decode_uri(evhttp_request_uri(req));”中的“decode_uri”没有被free,再程序处理完成后加上“free(decode_uri);”后,再使用Valgrind检查,结果已经是“definitely lost: 0 bytes in 0 blocks.”。

转自:http://www.s135.com/post/419/


实时查看linux网卡流量

将下列脚本保存为可执行脚本文件,比如叫traff.sh。

1、本脚本可自定义欲查看接口,精确到小数,并可根据流量大小灵活显示单位。
2、此脚本的采集间隔为1秒。
3、此脚本不需要额外再安装软件,可在急用情况下应付一下,比如临时想看一下是否有流量通过,大概为多少等。
4、一些流量查看软件由于计算的精确度不同,所以与此脚本显示的数值不可能一致,此脚本的显示结果与du meter对比过,相差很小。还有就是传输工具本身显示的传输速度并不准确。
用法为:
1、chmod +x ./traff.sh 将文件改成可执行脚本。
2、./traff.sh eth0即可开始监看接口eth0流量,按ctrl+c退出。


#!/bin/bash
 while [ "1" ]
 do
 eth=$1
 RXpre=$(cat /proc/net/dev | grep $eth | tr : " " | awk '{print $2}')
 TXpre=$(cat /proc/net/dev | grep $eth | tr : " " | awk '{print $10}')
 sleep 1
 RXnext=$(cat /proc/net/dev | grep $eth | tr : " " | awk '{print $2}')
 TXnext=$(cat /proc/net/dev | grep $eth | tr : " " | awk '{print $10}')
 clear
 echo -e "\t RX `date +%k:%M:%S` TX"
 RX=$((${RXnext}-${RXpre}))
 TX=$((${TXnext}-${TXpre}))

if [[ $RX -lt 1024 ]];then
 RX="${RX}B/s"
 elif [[ $RX -gt 1048576 ]];then
 RX=$(echo $RX | awk '{print $1/1048576 "MB/s"}')
 else
 RX=$(echo $RX | awk '{print $1/1024 "KB/s"}')
 fi

if [[ $TX -lt 1024 ]];then
 TX="${TX}B/s"
 elif [[ $TX -gt 1048576 ]];then
 TX=$(echo $TX | awk '{print $1/1048576 "MB/s"}')
 else
 TX=$(echo $TX | awk '{print $1/1024 "KB/s"}')
 fi

echo -e "$eth \t $RX $TX "
 done


jni内存泄露

在c++中new的对象,如果不返回java,必须用release掉,否则内存泄露。包括NewStringUTF,NewObject
。如果返回java不必release,java会自己回收。

jstring jstr = env->NewStringUTF((*p).sess_id);

env->DeleteLocalRef( jstr);

jobject jobj = env->NewObject(clazz,midInit);
return jobj;

内存泄露可以先从windows资源管理器中,看到随程序运行,内存不断增长的趋势,具体可以用hp jmeter检测在运行程序时,加jvm参数 -Xrunhprof:heap=all,cutoff=0 ,生成java.hprof.txt,用jmeter打开,Metric -> Residual Objects (Count),可以看到未回收的对象,选中要查看的对象,点Mark记录下要查看的对象,Window -> New Window 打开新窗口,用Metric -> Reference Graph Tree,然后点Find Immediately可以看到对象被哪里引用。

找出内存泄漏另一方法

程序有内存泄漏的第一个迹象通常是它抛出一个 DE>OutOfMemoryErrorDE>,或者因为频繁的垃圾收集而表现出糟糕的性能。幸运的是,垃圾收集可以提供能够用来诊断内存泄漏的大量信息。如果以 DE>-verbose:gcDE> 或者 DE>-XloggcDE> 选项调用 JVM,那么每次 GC 运行时在控制台上或者日志文件中会打印出一个诊断信息,包括它所花费的时间、当前堆使用情况以及恢复了多少内存。记录 GC 使用情况并不具有干扰性,因此如果需要分析内存问题或者调优垃圾收集器,在生产环境中默认启用 GC 日志是值得的。

有工具可以利用 GC 日志输出并以图形方式将它显示出来,JTune 就是这样的一种工具(请参阅 参考资料)。观察 GC 之后堆大小的图,可以看到程序内存使用的趋势。对于大多数程序来说,可以将内存使用分为两部分:baseline 使用和current load 使用。对于服务器应用程序,baseline 使用就是应用程序在没有任何负荷、但是已经准备好接受请求时的内存使用,current load 使用是在处理请求过程中使用的、但是在请求处理完成后会释放的内存。只要负荷大体上是恒定的,应用程序通常会很快达到一个稳定的内存使用水平。如果在应用程序已经完成了其初始化并且负荷没有增加的情况下,内存使用持续增加,那么程序就可能在处理前面的请求时保留了生成的对象。

 

图 1 显示  GC 之后应用程序堆大小随着时间的变化图。上升趋势是存在内存泄漏的警示信号。(在真实的应用程序中,坡度不会这么大,但是在收集了足够长时间的 GC 数据后,上升趋势通常会表现得很明显。)
图 1. 持续上升的内存使用趋势

确信有了内存泄漏后,下一步就是找出哪种对象造成了这个问题。所有内存分析器都可以生成按照对象类进行分解的堆快照。有一些很好的商业堆分析工具,但是找出内存泄漏不一定要花钱买这些工具 —— 内置的 DE>hprofDE> 工具也可完成这项工作。要使用 DE>hprofDE> 并让它跟踪内存使用,需要以 DE>-Xrunhprof:heap=sitesDE> 选项调用 JVM。

清单 3 显示分解了应用程序内存使用的 DE>hprofDE> 输出的相关部分。(DE>hprofDE> 工具在应用程序退出时,或者用 DE>kill -3DE> 或在 Windows 中按 Ctrl+Break 时生成使用分解。)注意两次快照相比,DE>Map.EntryDE>、DE>TaskDE> 和 DE>int[]DE> 对象有了显著增加。

请参阅 清单 3

清单 4 展示了 DE>hprofDE> 输出的另一部分,给出了 DE>Map.EntryDE> 对象的分配点的调用堆栈信息。这个输出告诉我们哪些调用链生成了 DE>Map.EntryDE> 对象,并带有一些程序分析,找出内存泄漏来源一般来说是相当容易的。
清单 4. HPROF 输出,显示 Map.Entry 对象的分配点

DE>    TRACE 300446:   java.util.HashMap$Entry.<init>(<Unknown Source>:Unknown line)   java.util.HashMap.addEntry(<Unknown Source>:Unknown line)   java.util.HashMap.put(<Unknown Source>:Unknown line)   java.util.Collections$SynchronizedMap.put(<Unknown Source>:Unknown line)   com.quiotix.dummy.MapLeaker.newTask(MapLeaker.java:48)   com.quiotix.dummy.MapLeaker.main(MapLeaker.java:64)  DE>

另外
jstring jstr = (jstring)env->CallObjectMethod(authenRequest, mid_authenReq_getSdId_S);
env->GetStringUTFRegion(jstr,0,env->GetStringLength(jstr),authenReq.sd_id);
当jstr是null时,env->GetStringLength(jstr)会出错,导致jvm崩溃

FROM: http://www.blogjava.net/neumqp/archive/2006/03/02/33152.html