写了可执行文件启动器Launcher.jar及一些批处理,通过它们就可以自动的以一定的时间间隔提取Hprof和进程的内存信息;
一、需要的库
可执行文件启动器:lib\Launcher.jar
注:关于Launcher.jar的源码如下:
源码包含2个文件Worker.java和Launcher.java
Worker.java文件:
package com.teleca.robin;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.swing.JLabel;
import javax.swing.JTextField;
public class Worker extends Thread {
private boolean loop=true;
private boolean paused=false;
private int cnt=0;
final private JLabel consoleText;
Worker(JLabel lable)
{
consoleText=lable;
}
private long interval=1000;
void
setInterval(long interval)
{
this.interval=interval;
}
private String executableFileName;
void setExecutableFileName(String
file)
{
if(executableFileName!=null&&file!=null)
{
if(!executableFileName.equals(file))
cnt=0;
}
executableFileName=file;
}
public void
doPause()
{
paused=true;
}
public void doResume()
{
paused=false;
interrupt();
}
public void die()
{
loop=false;
}
public void run()
{
while(loop)
{
if(paused||executableFileName==null)
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
}
}
else
{
BufferedReader stdout = null;
try {
Process p = null;
String line = null;
p =
Runtime.getRuntime().exec(executableFileName, null, null);
stdout = new BufferedReader(new
InputStreamReader(p
.getInputStream()));
while ((line = stdout.readLine()) != null) {
System.out.println(line);
}
stdout.close();
stdout=null;
} catch (IOException e) {
e.printStackTrace();
}finally{
if(stdout!=null)
try {
stdout.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
cnt++;
if(consoleText!=null)
consoleText.setText("Execute the file "+cnt+"
times");
try {
Thread.sleep(interval);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
}
}
}
System.out.println("exit!");
}
}
源码文件2:Launcher.java
package
com.teleca.robin;
import
java.awt.event.WindowEvent;
import
java.awt.event.WindowListener;
import
java.io.BufferedReader;
import
java.io.File;
import
java.io.IOException;
import
java.io.InputStreamReader;
import
javax.swing.JFrame;
import
javax.swing.JTextField;
import
javax.swing.SwingConstants;
public class Launcher extends
JFrame implements WindowListener{
private
long interval;
private
String executableFileName;
Launcher(String file,long
time)
{
if(file==null)
executableFileName="";
else
executableFileName=file;
interval=time;
initComponents();
this.addWindowListener(this);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
/** This method is called from within the constructor
to
*
initialize the form.
* WARNING:
Do NOT modify this code. The content of this method is
* always
regenerated by the Form Editor.
*/
//
<editor-fold defaultstate="collapsed" desc="Generated
Code">//GEN-BEGIN:initComponents
private void initComponents() {
jButtonStart = new javax.swing.JButton();
jButtonPause = new javax.swing.JButton();
jButtonExit = new javax.swing.JButton();
jTextFieldFile = new
javax.swing.JTextField(20);
jTextFieldTime = new
javax.swing.JTextField(5);
jLabelFile = new javax.swing.JLabel();
jLabelTime = new javax.swing.JLabel();
jLabelTip = new javax.swing.JLabel();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setName("Form"); // NOI18N
jButtonStart.setText("Start"); // NOI18N
jButtonStart.setName("jButtonStart"); // NOI18N
jButtonStart.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent evt)
{
start();
}
});
jButtonPause.setText("Pause"); // NOI18N
jButtonPause.setName("jButtonPause"); // NOI18N
jButtonPause.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent evt)
{
pause();
}
});
jButtonExit.setText("Exit"); // NOI18N
jButtonExit.setName("jButtonExit"); // NOI18N
jButtonExit.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent evt)
{
stop();
System.exit(0);
}
});
jButtonStart.setEnabled(true);
jButtonPause.setEnabled(false);
jTextFieldFile.setText(executableFileName);
// NOI18N
jTextFieldFile.setName("jTextFieldFile"); // NOI18N
jTextFieldFile.setHorizontalAlignment(JTextField.CENTER);
jTextFieldTime.setText(""+interval); //
NOI18N
jTextFieldTime.setName("jTextFieldTime"); // NOI18N
jTextFieldTime.setHorizontalAlignment(JTextField.CENTER);
jLabelFile.setText("the executable file"); // NOI18N
jLabelFile.setName("jLabelFile"); // NOI18N
jLabelTime.setText("the interval time(millisecond)"); //
NOI18N
jLabelTime.setName("jLabelTime"); // NOI18N
jLabelTip.setText("idle"); // NOI18N
jLabelTip.setName("jLabelTip"); // NOI18N
jLabelTip.setHorizontalAlignment(SwingConstants.CENTER);
javax.swing.GroupLayout layout = new
javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(71, 71, 71)
.addComponent(jLabelTime))
.addGroup(layout.createSequentialGroup()
.addGap(70, 70, 70)
.addComponent(jLabelFile))
.addGroup(layout.createSequentialGroup()
.addGap(90, 90, 90)
.addComponent(jButtonStart)))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(100, 100, 100)
.addComponent(jTextFieldTime,
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addComponent(jTextFieldFile,
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
)
.addGroup(layout.createSequentialGroup()
.addGap(10, 10, 10)
.addComponent(jButtonPause)
)
.addGroup(layout.createSequentialGroup()
.addGap(20, 20, 20)
.addComponent(jLabelTip)
)
.addGroup(layout.createSequentialGroup()
.addGap(180, 180, 180)
.addComponent(jButtonExit)
)
))
)
.addContainerGap(151,
Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(63, 63, 63)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabelFile)
.addComponent(jTextFieldFile,
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(29, 29, 29)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabelTime)
.addComponent(jTextFieldTime,
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(62, 62, 62)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jButtonStart)
.addComponent(jButtonPause)
.addComponent(jButtonExit))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 34,
Short.MAX_VALUE)
.addComponent(jLabelTip)
.addGap(32, 32, 32))
);
pack();
}//
</editor-fold>//GEN-END:initComponents
Worker worker;
private void stop() {//GEN-FIRST:event_stop
// TODO add your handling code here:
if(worker!=null)
{
worker.die();
worker=null;
}
}//GEN-LAST:event_stop
private
void pause() {//GEN-FIRST:event_pause
// TODO add your handling code here:
worker.doPause();
jButtonStart.setEnabled(true);
jButtonPause.setEnabled(false);
jTextFieldFile.setEditable(true);
jTextFieldTime.setEditable(true);
}//GEN-LAST:event_pause
private
void start() {//GEN-FIRST:event_start
// TODO add your handling code here:
String
fileName=jTextFieldFile.getText().trim();
if(checkFileName(fileName))
{
executableFileName=fileName;
}
else
{
return;
}
String
time=jTextFieldTime.getText();
if(time.length()==0)
{
interval=defaultInterval;
}
else
{
try{
long
t=Long.parseLong(time);
interval=t;
}catch(NumberFormatException
e)
{
jLabelTip.setText("the
time "+time+"is not correct!");
return;
}
}
if(worker==null)
{
worker=new Worker(this.jLabelTip);
worker.setExecutableFileName(executableFileName);
worker.setInterval(interval);
worker.start();
jLabelTip.setText("start
to execute file");
}
else
{
worker.setExecutableFileName(executableFileName);
worker.setInterval(interval);
worker.doResume();
jLabelTip.setText("Restart
to execute file");
}
jButtonStart.setEnabled(false);
jButtonPause.setEnabled(true);
jTextFieldFile.setEditable(false);
jTextFieldTime.setEditable(false);
}//GEN-LAST:event_start
final
static long defaultInterval=1000;
/**
* @param args
*/
public
static void main(String[]
args) {
String
fileName="";
long
time=defaultInterval;
if(args.length>0)
{
fileName=args[0];
if(!checkFileName(fileName))
{
fileName="";
}
}
if(args.length>1)
{
time=Long.parseLong(args[1]);
}
//
TODO Auto-generated method stub
new
Launcher(fileName,time).setVisible(true);
}
static boolean checkFileName(String fileName)
{
if(fileName==null)
{
return
false;
}
if(!(fileName.endsWith(".exe")||fileName.endsWith(".bat")||fileName.endsWith(".cmd")))
{
System.out.println("the
file must be a executable file!");
System.out.println("Now
only support *.exe , *.bat,*.cmd");
System.out.println("Please
check the file again");
return
false;
}
File
file=new File(fileName);
if(!file.exists())
{
System.out.println("the
file:"+fileName+" is not exists");
return
false;
}
return
true;
}
// Variables
declaration - do not modify//GEN-BEGIN:variables
private
javax.swing.JButton jButtonExit;
private
javax.swing.JButton jButtonPause;
private
javax.swing.JButton jButtonStart;
private
javax.swing.JLabel jLabelFile;
private
javax.swing.JLabel jLabelTime;
private
javax.swing.JLabel jLabelTip;
private
javax.swing.JTextField jTextFieldFile;
private
javax.swing.JTextField jTextFieldTime;
// End of
variables declaration//GEN-END:variables
public void
windowDeactivated(WindowEvent e)
{
//System.out.println("window is deactivated");
}
public void
windowDeiconified(WindowEvent e)
{
//System.out.println("window is Deiconified");
}
public void
windowActivated(WindowEvent e)
{
//System.out.println("window is actived");
}
public void
windowOpened(WindowEvent e)
{
//System.out.println("window is Opened");
}
public void windowClosing(WindowEvent
e)
{
stop();
}
public void
windowClosed(WindowEvent e)
{
//System.out.println("window is Closed");
}
public void
windowIconified(WindowEvent e)
{
//System.out.println("window is Closing");
}
}
用源代码生成的jar文件为:Launcher.jar。
则可以用如下的DOS命令运行它:
java -jar lib\Launcher.jar
getProcessState.bat 5000
5000表示每隔5000毫秒执行一次getProcessState.bat 文件。
二、自动提取Hprof。
runHprofPicker.bat文件:
java
-jar lib\Launcher.jar getHprof.bat 5000
5000表示5000毫秒执行一次 getHprof.bat来从手机提取Hprof文件。
getHprof.bat文件如下:
@echo off
call config.bat
if exist %hpInputFile%
(
del %hpInputFile% /q
)
adb pull
%hpInputFileDir%/%hpInputFile% .
if not exist %hpInputFile%
(
echo fail to pull
%hpInputFile%
exit 1
)
if not exist %hpRoot%
(
md %hpRoot%
)
Setlocal
enabledelayedexpansion
set
path=%path%;%cd%\lib
call genSerial
set
serial=!genSerial~result!
set
hpOutFile=%serial%.hprof
%tools%\hprof-conv.exe %hpInputFile%
%hpRoot%\%hpOutFile%
echo success!
endlocal
前提:
1生成批处理配置文件config.bat:
批处理配置文件config.bat如下:
rem the following var is for getProcessState.bat
set rawDatadir=rawData
set processName=android.process.acore;com.android.systemui
rem set processShortName=a;b;c
set processShortName=
set outRoot=out
set statFilePrefix=stat
rem the following var is for getHprof.bat
set tools=D:\SDK\android-sdk4.0\tools
set hpInputFileDir=/sdcard
set hpInputFile=input.hprof
set hpRoot=hpTemp
注1:rawDatadir为“ps -x”提取出来的文件的目录
注2:processName需要统计RSS的进程的名字,可以同时统计多个,进程名之间用“;”进行分割。
注3:processShortName需要统计RSS的进程的名字的缩写形式,如果不坐设置或设置为空,这程序会根据processName自动生成。
注4:outRoot为对进程的RSS进行统计最后的生成文件的存放目录。
注5:statFilePrefix为对进程的RSS进行统计最后的生成文件的前缀。
注6:tools为hprof-conv.exe所在的目录。
注7:hpInputFileDir为手机中我们生成的hprof文件所在的目录。
注8:hpInputFileDir为手机中我们生成的hprof文件的名字。
2.在代码中生成Hprof文件
在android代码,可以使用如下代码把hprof文件生成到sd卡上。
Debug.dumpHprofData("/sdcard/input.hprof");
可以不用sd卡,而将hprof文件直接生成在手机上,但是只能在"/data/data/"+packageName的目录下。
实例1:
void
generateHprof()
{
String
packageName=getApplicationInfo().packageName;
String
hpFilePath="/data/data/"+packageName+"/input.hprof";
try {
//Debug.dumpHprofData("/sdcard/input.hprof");
Debug.dumpHprofData(hpFilePath);
} catch (IOException e)
{
// TODO Auto-generated catch
block
e.printStackTrace();
}
}
注1:需要在代码中先生成hprof文件,而且config.bat中配置的路径要和在代码中先生成hprof文件的路径一致。
注
2:需要把bat库genSerial.bat,getSubStr.bat放在子目录lib中。(如下实例)
getSubStr.bat源码
@echo off
set %0~string=%string%
set
%0~position=%position%
set %0~count=%count%
set %0~result=
set string=%1
set /a position=%2
set /a count=0
set string=%string:"=%
if %position% LSS 0 (
for %%i in (%string%) do
(
set /a count=!count!+1
)
set /a
position=%position%+!count!
)
set /a count=0
for %%i in (%string%) do
(
if !count! EQU %position%
(
set %0~result=%%i
)
set /a count=!count!+1
)
set string=!%0~string!
set
position=!%0~position!
set count=!%0~count!
使用实例1:
@echo off
Setlocal
enabledelayedexpansion
set
path=%path%;%cd%\lib
call getSubStr "a,b,c,d"
0
set
result=!getSubStr~result!
echo the first subString is
%result%
call getSubStr "a;b;c;d"
1
set
result=!getSubStr~result!
echo the second subString is
%result%
call getSubStr "a b c d"
-1
set
result=!getSubStr~result!
echo the firest subString from
right is %result%
pause
genSerial.bat文件
@echo off
set %0~SNFile=%SNFile%
set %0~SN=%SN%
set %0~result=
set SNFile=SN.txt
if "%1" =="reset" (
set /a SN=0
goto save
)
if exist %SNFile% (
for /f %%i in (%SNFile%) do set /a SN=%%i
set /a SN+=1
) else (
set /a SN=0
)
:save
echo %SN% >%SNFile%
set %0~result=%SN%
set SNFile=!%0~SNFile!
set SN=!%0~SN!
使用实例1:
@echo off
Setlocal
enabledelayedexpansion
set
path=%path%;%cd%\lib
call genSerial
set
serial=%genSerial~result%
echo the serial is
%serial%
call genSerial
set
serial=!genSerial~result!
echo the serial is
%serial%
call genSerial reset
set
serial=!genSerial~result!
echo after reset,the serial is
%serial%
pause
三、自动提取进程的RSS
runProcessStatePicker.bat文件:
java
-jar lib\Launcher.jar getProcessState.bat 5000
5000表示5000毫秒执行一次 getProcessState.bat来从手机提取进程的RSS,输出到一个以进程名命名的文本文件,以便在excel中生产图表文件。
前言:RSS(Resident Set
Size)表示实际使用物理内存(包含共享库占用的内存)。
因为它包含了共享内存,所以他的意义不及PSS。所以现在查看内存使用情况一般参照PSS。
提取进程的RSS
文件:getProcessState.bat
@echo off
call config.bat
set processNameCol=9
set RSSCol=5
Setlocal
enabledelayedexpansion
set path=%path%;%cd%\lib
set /a processNo=0
for %%i in (%processName%) do (
set /a processNo+=1
)
set /a cnt=0
set str=
if "%processShortName%"=="" (
set /a cnt=0
for %%i in (%processName%) do
(
set str=%%i
set str=!str:.= !
call getSubStr "!str!"
-1
set
result=!getSubStr~result!
if !cnt! EQU 0 (
set
processShortName=!result!
) else (
set
processShortName=!processShortName!;!result!
)
set /a cnt+=1
)
) else (
set /a cnt=0
for %%i in (%processShortName%) do (
set /a cnt=!cnt!+1
)
if not !cnt! EQU %processNo% (
echo the number of process Name is
%processNo%
echo the number of process Short
Name is !cnt!
echo they should be equal.Please
check again!
exit 0
)
)
if not exist %rawDatadir%
(
md %rawDatadir%
)
if not exist %outRoot%
(
md %outRoot%
)
call genSerial
set
serial=!genSerial~result!
set
psFile=%rawDatadir%\ps%serial%.txt
adb shell "ps
-x" >%psFile%
adb shell exit
set /a cnt=0
FOR /F "skip=1 tokens=%RSSCol%,%processNameCol%"
%%i in (%psFile%) do (
set /a cnt=0
for %%a in (%processName%) do
(
if "%%a"=="%%j" (
call getSubStr "%processShortName%"
!cnt!
set
result=!getSubStr~result!
set
statFile=%outRoot%\%statFilePrefix%_!result!.txt
if exist !statFile! (
>>!statFile!
set/p=,%%i<nul
) else (
>>!statFile!
set/p=%%i<nul
)
)
set /a cnt=!cnt!+1
)
)
echo success!
endlocal
四、自动提取进程的NativeSize,DalvikSize,NativeAllocated,DalvikAllocated,NativePSS,DalvikPSS
runMemoryPicker.bat文件:
java -jar lib\Launcher.jar getMemoryState.bat 2000
2000表示2000毫秒执行一次 getMemoryState.bat来从手机提取进程的内存信息到一个以进程名命名的文本文件,以便在excel中生产图表文件。
前言:
我们可以通过adb shell "dumpsys meminfo
%curProcessName%"命令得到某个进程的内存使用情况。
getMemoryState.bat主要用于解析该命令返回的内存,得到NativeSize,DalvikSize,NativeAllocated,DalvikAllocated,NativePSS,DalvikPSS等。它把不同时期得到的数据按时间前后为顺序以逗号作为分隔符的排列输出到一个以进程名命名的文本文件,以便在excel中生产图表。
getMemoryState.bat文件源码
@echo off
call config.bat
set typeNameCol=1
set nativeValueCol=2
set dalvikValueCol=3
set dalvikOtherCol=4
Setlocal
enabledelayedexpansion
set
path=%path%;%cd%\lib
set /a processNo=0
for %%i in (%processName%) do
(
set /a processNo+=1
)
set /a cnt=0
set str=
if "%processShortName%"==""
(
set /a cnt=0
for %%i in (%processName%) do
(
set str=%%i
set str=!str:.= !
call getSubStr "!str!"
-1
set
result=!getSubStr~result!
if !cnt! EQU 0 (
set
processShortName=!result!
) else (
set
processShortName=!processShortName!;!result!
)
set /a cnt+=1
)
) else (
set /a cnt=0
for %%i in (%processShortName%) do
(
set /a cnt=!cnt!+1
)
if not !cnt! EQU %processNo%
(
echo the number of process Name is
%processNo%
echo the number of process Short
Name is !cnt!
echo they should be equal.Please
check again!
exit 0
)
)
if not exist %rawDatadir%
(
md %rawDatadir%
)
if not exist %outRoot%
(
md %outRoot%
)
call genSerial
set
serial=!genSerial~result!
set
meminfoFile=%rawDatadir%\meminfo%serial%.txt
set slipChar=,
:Loop0Start:
set /a
processTotalNumber=cnt
set /a processNo=0
:Loop0Head
call getSubStr "%processShortName%"
%processNo%
set
curProcessShortName=%getSubStr~result%
call getSubStr "%processName%"
%processNo%
set
curProcessName=%getSubStr~result%
:GetRawMemInfoFile
set
statFile=%outRoot%\%statFilePrefix%_Memory_%curProcessShortName%.txt
adb shell "dumpsys meminfo
%curProcessName%" >%meminfoFile%
if not exist %statFile%
(
set slipChar=
goto
ReadRawMemInfoFile
)
:ReadMemInfoStatisticFile
set NativeSize=
set DalvikSize=
set OtherSize=
set TotalSize=
set NativeAllocated=
set DalvikAllocated=
set OtherAllocated=
set TotalAllocated=
set NativePSS=
set DalvikPSS=
set OtherPSS=
set TotalPSS=
set NativeFree=
set DalvikFree=
set OtherFree=
set TotalFree=
set /a cnt=0
FOR /F "delims=: tokens=2" %%i in
(%statFile%) do (
if !cnt! EQU 0 (
set NativeSize=%%i
)
if !cnt! EQU 1 (
set DalvikSize=%%i
)
if !cnt! EQU 2 (
set
NativeAllocated=%%i
)
if !cnt! EQU 3 (
set
DalvikAllocated=%%i
)
if !cnt! EQU 4 (
set NativePSS=%%i
)
if !cnt! EQU 5 (
set DalvikPSS=%%i
)
set /a cnt+=1
)
:ReadRawMemInfoFile
set /a cnt=0
FOR /F "skip=1
tokens=1,2,3,4,5,6,7,8" %%i in (%meminfoFile%) do (
if !cnt! EQU 4 (
set
NativeSize=!NativeSize!%slipChar%%%j
set
DalvikSize=!DalvikSize!%slipChar%%%k
set
OtherSize=!OtherSize!%slipChar%%%l
set
TotalSize=!TotalSize!%slipChar%%%m
)
if !cnt! EQU 5 (
set
NativeAllocated=!NativeAllocated!%slipChar%%%j
set
DalvikAllocated=!DalvikAllocated!%slipChar%%%k
set
OtherAllocated=!OtherAllocated!%slipChar%%%l
set
TotalAllocated=!TotalAllocated!%slipChar%%%m
)
if !cnt! EQU 6 (
set
NativeFree=!NativeFree!%slipChar%%%j
set
DalvikFree=!DalvikFree!%slipChar%%%k
set
OtherFree=!OtherFree!%slipChar%%%l
set
TotalFree=!TotalFree!%slipChar%%%m
)
if !cnt! EQU 7 (
set
NativePSS=!NativePSS!%slipChar%%%k
set
DalvikPSS=!DalvikPSS!%slipChar%%%l
set
OtherPSS=!OtherPSS!%slipChar%%%m
set
TotalPSS=!TotalPSS!%slipChar%%%n
)
set /a cnt+=1
)
:SaveToMemInfoStatisticFile
echo
NativeSize:%NativeSize%>%statFile%
echo
DalvikSize:%DalvikSize%>>%statFile%
echo
NativeAllocated:%NativeAllocated%>>%statFile%
echo
DalvikAllocated:%DalvikAllocated%>>%statFile%
echo
NativePSS:%NativePSS%>>%statFile%
echo
DalvikPSS:%DalvikPSS%>>%statFile%
:Loop0Tail
set /a processNo+=1
if %processNo% LSS
%processTotalNumber% (
goto Loop0Head
)
:Loop0End
echo success!
endlocal
本文来自:http://hubingforever.blog.163.com/blog/static/1710405792011324114317115/
Android内存泄露(全自动篇),布布扣,bubuko.com
Android内存泄露(全自动篇)