站内搜索: 请输入搜索关键词

当前页面: JAVA 编程资料牛鼻论坛Java 手机开发技术→如何使midlet提速?(征文)

如何使midlet提速?(征文)

发表新主题   回复此主题

第1楼 2002-10-11 19:44 asmair 写道:

如何使midlet提速?(征文)

各位高人请写些原创文章吧,手机的执行速度有限,如何在这有限的范围内更大限度地使程序提速,就成了大问题,非常想知道关于时间复杂度的编程经验,让大家共同提高代码质量.

第2楼 2013-08-31 12:44 Robot :

如何使midlet提速?(征文) 相关


第3楼 2002-10-11 21:13 rocks 写道:

好建议:)
我先提几条,大家补充,以后可以汇总起来。
1 非常general的,适用于所有java程序:少用字符串连接,多用StringBuffer
2 尽量用固定大小的数组代替使用Vector
3 如果可以不使用新class就能实现功能,就不要增加新的class,因为每个class都有一定的内存开销
4 使用有限的面向对象,因为纯粹的OO往往意味着更多的虚方法,更多的层次关系,更多的class
5 考虑使用public域(即数据成员)代替getter和setter
6 对确定不必被继承的方法使用final修饰符
7 使用BufferedInputStream或BufferedReader来包裹输入流
8 发行之前使用混淆器处理你的classes,除了能防止别人任意反编译偷窥你的程序,也能减小class文件的尺寸,因为混淆器往往用较短的字符串代替原来的变量或方法名。

第4楼 2002-10-11 22:23 sdujerome 写道:

以上的建议都挺好的,我再加一条:
是不是可以在适当的时候显式的调用gc

第5楼 2002-10-12 02:55 wersdfxcv 写道:

rocks正解~~~~受益匪浅哦!

第6楼 2002-10-15 07:28 asmair 写道:

如果有可能的话,考虑用西门子提供的一些库,如GAME、MMC等,能显著提高速度,但代价是兼容性不好。

第7楼 2002-10-23 23:54 blueshark 写道:

http://wireless.java.sun.com/midp/ttips/appsize/

第8楼 2002-10-24 16:24 crabtogoal 写道:

哈哈~~都被你说完了

第9楼 2002-10-24 17:03 rocks 写道:

"Optimizing J2ME Application Size"
很好的文章啊,有没有人给翻译一下?

第10楼 2002-10-24 20:30 crabtogoal 写道:

确实不错

第11楼 2002-10-24 22:59 asmair 写道:

翻译需要时间,有奖金吗?

第12楼 2002-10-29 13:41 rocks 写道:

奖金是没有,不过可以请你吃饭啊:)

第13楼 2002-11-11 13:52 jhere 写道:

提个问题:应该是程序设计完成之后考虑优化还是在编码设计的时候就考虑呢?

第14楼 2002-11-11 15:23 faun 写道:

你在整体设计的时候就应该考虑这些问题,在程序设计时也应该注意到这些问题,当然最后优化还是应该在程序设计完成之后再做!

第15楼 2002-11-13 18:58 leelong 写道:

我的原则是有这么其中两个:
1。对于哪些需要动态的复杂算法才能达成的目标,能否在pc机器上就预先处理一下,而形成静态的数据结构,然后再用简单算法来使用。
2。要重视的是:反复频繁的操作是性能的一个瓶颈。在这上面下功夫非常值得。比如:
某个循环一次操作只需耗费 10ms, 如果你一个不注意,让它耗费了 20ms (这时你可能不觉得有问题,才多了小小的 10ms嘛)。再假设这个循环很频繁,占软件运行总时间的 30%,那么,这样就会在不经意间严重降低了总体速度。
所以解决方案首先就是去查软件的性能瓶颈,再对症下药。

第16楼 2002-11-13 19:17 rocks 写道:

非常同意leelong的看法,您的“大眼睛”应该就是程序优化方面的典范之作了!
编程序和很多事物一样,有一个“20-80”的因素在里面,运行时往往是80%的时间在运行20%的代码,所以尽量的优化这20%的代码就显得异常重要。

第17楼 2002-11-15 21:49 zmg229 写道:

用Borland Optimizeit Suit Enterprise优化一下更好,请问各位有没有她的注册码呀,Borland给我的试用license到期了,不能用啦,也找过几个破解的东西,全都名不符实,火页!有注册码的请举手!!给我一个邮至:sunshiningboy@netscape.net,先谢谢过!

第18楼 2002-12-02 01:15 rocks 写道:

1.不是很明显的吧,但肯定是有影响,要分情况处理,主要解决显著影响性能的地方,细节上的优化应该是最后做的事情
2.应该是会降低运行速度,不过可以优化内存使用情况

第19楼 2002-12-05 18:39 anonimousboy 写道:

to rocks:
1.对于你的第三条:用inner class实现的话会增加内存开销吗?
2.对于你的第五条:因为我们做的是手机的程序,安全是第一的,所以我建议你把第五条去掉!

第20楼 2002-12-05 19:40 rocks 写道:

to anonimousboy:
1 inner class编译后就会生成一个单独的class文件,形如MyHostClass$MyInnerClass.class这样的,即使是匿名内嵌类也一样。
2 想象不出来public field会对安全性有何影响,呵呵,getter和setter的首要目的是增强对象的封装性,而并非考虑安全性。
3 如果真的安全性和性能发生抵触,那么就要根据具体问题来具体分析了,如果做的是证券软件,毫无疑问安全性是最重要的,如果是个即时的动作游戏的话,那性能应该是首要考虑的问题。
Just For Your Infomation
:)

第21楼 2002-12-12 18:17 violet 写道:

混淆反而会降低速度的.
再说本着开源的目的,大家不要混淆啊,不要混淆啊

第22楼 2002-12-18 11:25 rocks 写道:

“混淆反而会降低速度的”,何出此言?

第23楼 2002-12-19 17:15 jacksun 写道:

******************************************************
*终于翻译完了,没什么难度,就是慢,西西。。。。。。。。
******************************************************
优化J2ME程序大小
by Eric Giguere
February 27, 2002
要把J2ME程序与J2SE程序区分开来,其依据就是J2ME运行所处的受限环境。多数J2ME系统的主要受限条件就是可以存储和运行程序所需内存的大小。例如,许多MIDP设备限制应用程序的尺寸不大于50K,这远远不及Server端J2SE运行环境下那些成兆的程序。实际应用中,程序会很容易超出这些限制条件。通过本篇您将学到一些减小程序尺寸大小的技巧,并在下面的例子中实践这些技术。这个例子MIDlet仅仅显示一个文本框并在其内容改变时发声。
package com.j2medeveloper.techtips;
import javax.microedition.lcdui.*;
public class BeforeSizeOptimization extends
                                         BasicMIDlet {
    public static final Command exitCommand =
                         new Command( "Exit",
                                    Command.EXIT, 1 );
    public BeforeSizeOptimization(){
    }
    protected void initMIDlet(){
        getDisplay().setCurrent( new MainForm() );
    }
    public class MainForm extends Form {
        public MainForm(){
            super( "MainForm" );
            addCommand( exitCommand );
            append( textf );
            setCommandListener( new CommandListener(){
                public void commandAction( Command c,
                                       Displayable d ){
                    if( c == exitCommand ){
                        exitMIDlet();
                    }
                }
              }
            );
            setItemStateListener(
                              new ItemStateListener() {
                public void itemStateChanged(
                                           Item item ){
                    if( item == textf ){
                        AlertType.INFO.playSound(
                                        getDisplay() );
                    }
                }
              }
            );
        }
        private TextField textf =
                  new TextField( "Type anything", null,
                                 20, 0 );
    }
}
虽然这个MIDlet在此仅作为一个例子,但使用的尺寸优化技巧可以适用于任一J2ME的profile上。
注意,上面的MIDlet类需要下面的辅助类:
package com.j2medeveloper.techtips;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public abstract class BasicMIDlet extends MIDlet {
    private Display display;
    public BasicMIDlet(){
    }
    protected void destroyApp( boolean unconditional )
                    throws MIDletStateChangeException {
        exitMIDlet();
    }
    public void exitMIDlet(){
        notifyDestroyed();
    }
    public Display getDisplay(){ return display; }
    protected abstract void initMIDlet();
    protected void pauseApp(){
    }
    protected void startApp()
                    throws MIDletStateChangeException {
        if( display == null ){
            display = Display.getDisplay( this );
            initMIDlet();
        }
    }
}
用J2ME WTK打包时,本例子MIDlet占用4K空间。
减小尺寸的首要步骤就是通过修正程序的功能实现来去掉多余的类。程序的所有功能确实必须都实现吗?用户可以不需要这些“附属功能”吗?要设计尽可能小的程序,这里的MIDlet例子已经相当小了。
第二步就是深入考察程序定义的内部类,特别是匿名类。记住,每个类文件都有一定量的与之相关的系统开销。即便最普通的类也有系统开销。
    public class foo {
        // nothing here
    }
编译上边的类,生成的类文件大约200byte大小。比如实现一个事件监听器,就是对匿名类的常见使用。在例子MIDlet中就定义了两个此类的监听器。接下来进行的最简单的优化就是,让主MIDlet类实现CommandListener和ItemStateListener接口,并把监听器代码移至此处。记住,多个对象可以使用同样的监听器。必要时,可以使用传递至commandAction和itemStateChanged方法的参变量来区分它们。
内部类也可使代码过大,因为编译器必须生成特殊的变量和方法,以便内部类可以访问包含它们的类的私有内容。请参考内部类的规范以获取更多信息。
第三步,尽量使用现有的类。例如,基于CLDC的profile没有构造集合类,所以我们可以用内建的Hashtable和Vector类来实现之。构造MIDP程序时也可采用此法。例子MIDlet中定义了一个Form字类来生成主表,可以容易的如下直接生成:
    mainForm = new Form( "MainForm" );
    mainForm.addCommand( okCommand );
    mainForm.setCommandListener( listener );
这里没有正确或者错误的答案,只是要推敲。
第四步就是破坏程序的继承关系。你也许把相关的代码放到一个或多个抽象类中,这是OOD中为提高程序间代码重用的推荐做法。虽然破坏继承关系与你所学知识相违背,但简化的继承关系更有意义。特别的,当你的的抽象类――可能来自其他项目――仅仅被继承一次时,破坏继承关系的结果不言而喻。例如,例子MIDlet继承了BasicMIDlet类,但两者合并为一个类。
第五步就是要缩短名字长度,如包名、类名、方法名和数据元素名。看起来有些蠢,但一个类文件确实包含太多的符号信息。缩短各量的名字可以缩小生成的类文件尺寸。这种节省不会特别明显,但多个类中进行总加的结果还是可观的。包名对减小尺寸来讲特别合适。MIDP程序是完全自我包容的,完全可以不使用包名,因为在手持设备上包名根本不可能与其他类名冲突。例子MIDlet中,可以把com.j2medeveloper.tchtips包名去掉。
注意,一般来讲,缩短名字不需要手工去做,要用一个“混淆器”去做。“混淆器”的主要功能是“隐藏”程序代码,使之不能通过反编译读出。它的副作用是减小了程序的尺寸。因为隐藏过程主要通过更改方法和数据成员的名字来完成。有一个开源的混淆器称为RetroGuard,可以免费从http://www.retrologic.com得到。也有一些商业包可用。(当为基于CLDC的profile混淆时,记得在预校验之前混淆,否则混淆器将使类文件中的预校验数据失效。)
最后,深入数组的初始化。(例子MIDlet没有做数组初始化,但对程序来说初始化是重要的一步) 在编译时,一个数组初始化声明如下所示:
    int arr[] = { 0, 1, 2, 3 };
而实际生成代码的过程如下所示:
    arr[0] = 0;
    arr[1] = 1;
    arr[2] = 2;
    arr[3] = 3;
这个过程可以通过使用Java 2 SDK中附带的javap工具把二进制代码反编译成类文件去看(使用-c选项)。也许你会诧异于看到的内容,特别当你希望看到的是一排排二进制常数时。有两种方法可以让你看不到反编译的程序代码,(1)把数据编码为字符串,运行时解码之,或者(2)把数据存为二进制文件并与程序打包,用类装载器的getResourceAsStream方法在运行时存取之。
以上只是一些指导性的方法,对每个J2ME程序而言,这里没有具体到步骤。但是多数方法可以应用的本例。优化后的MIDlet如下所示:
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class ASO extends MIDlet
                 implements CommandListener,
                            ItemStateListener {
    private Display   display;
    private Form      mainForm;
    private TextField mainFormTF =
                  new TextField( "Type anything", null,
                                 20, 0 );
    public static final Command exitCommand =
                         new Command( "Exit",
                                     Command.EXIT, 1 );
    public ASO(){
    }
    public void commandAction( Command c,
                               Displayable d ){
        if( c == exitCommand ){
            exitMIDlet();
        }
    }
    protected void destroyApp( boolean unconditional )
                    throws MIDletStateChangeException {
        exitMIDlet();
    }
    public void exitMIDlet(){
        notifyDestroyed();
    }
    public Display getDisplay(){ return display; }
    protected void initMIDlet(){
        mainForm = new Form( "MainForm" );
        mainForm.addCommand( exitCommand );
        mainForm.setCommandListener( this );
        mainForm.setItemStateListener( this );
        mainForm.append( mainFormTF );
        getDisplay().setCurrent( mainForm );
    }
    public void itemStateChanged( Item item ){
        if( item == mainFormTF ){
            AlertType.INFO.playSound( getDisplay() );
        }
    }
    protected void pauseApp(){
    }
    protected void startApp()
                    throws MIDletStateChangeException {
        if( display == null ){
            display = Display.getDisplay( this );
            initMIDlet();
        }
    }
}

关于作者:Eric Giguere是来自Sybase下属iAnywhere Solutions的软件开发人员。他致力于手持设备和无线计算领域的Java技术。他是滑铁卢大学的数学学士和数学硕士,写了很多有关计算的文章。

第24楼 2002-12-19 23:58 rocks 写道:

不错不错,我公司也在朝阳,回去请你吃饭:D
另发个新贴吧,我帮你转到精华论坛去。

第25楼 2002-12-24 21:38 Luther 写道:

調用png圖片最好事先寫在程序里.

第26楼 2002-12-30 19:08 yuanaoe 写道:

我刚学j2me没多久,以下几点是根据我对java语言特性的一些浅见来谈的,大侠们多指教
A:对于处理器速度慢的问题:
尽量使用数组,少用Vectors等对象,即使要用也要按其真实预期大小指定初始空间,其实手机上的程序都不大,通常我们完全可以把一些细节考虑通透,预先做好设想
B:对于内存少的问题:
1.有时候要牺牲一些面向对象的特征,用尽量少的类来实现程序
2.用尽量少的方法实现功能,那样做应该会花费很多空间在堆栈上
3.留点神,使用合适的数据类型,不要象在台式机上那样大大咧咧的,既然穷就要勤 俭持家啊,好习惯是最重要的,而且要尽可能少用对象,多用基本类型
4.该放手时就放手,丢个null给对象,不用倚赖GC(你以为养个GC不用钱啊?),不要让GC太忙啊
5.……等我想好了再……

第27楼 2002-12-31 19:30 horsethief 写道:

同意1,
不同意2,其实函数堆栈并不浪费时间。功能独立是最重要的,方法少可能会带来更多的代码浪费。
同意3,每个空类有200字节的空间。
不同意4,你给null了只是消除了它的连接,对象并不释放,还是要等GC,但是如果调用GC,无论它是不是null,只要它不再使用,就会释放掉。

第28楼 2002-12-31 22:31 yuanaoe 写道:

赋予null,跟不赋予null收集起来的效率是一样的吗?而且cldc中实现的gc跟j2se中的gc比较,无论是效率还是安全性都大打折扣

第29楼 2003-01-08 11:33 Sean 写道:

这文章不是我翻译过了么?还马上发到cnjm来。。。

第30楼 2003-01-08 23:10 bobyyuan 写道:

不要用混淆器,它有可能导致程序不能正确运行。提速是最关键的,而尺寸不是大问题,因为存储器的大小的发展速度很快。

第31楼 2003-01-15 21:37 threejiaomao 写道:

最近在做一个文本阅读器程序。
支持中文文件系统(含有目录),发短信。
可是由于排版算法的效率低下,程序运行速度不太快。
看来要好好优化了:(
争取在翻页速度上赶上MicroReader:)
继续努力!

第32楼 2003-01-16 00:50 rocks 写道:

to threejiaomao:
for 6688i的吗?

第33楼 2003-01-17 12:44 threejiaomao 写道:

是的.因为我用的是6688i.现在我自己经常上网吧,下载文章放到手机上看,也下载了很多短信,可以直接发出去不用再给网站钱了
以前也问过一些中文编码问题,现在大部分解决了,在此感谢大家的帮助!特别是BigBye的作者他实现了中文文件名的操作也感谢MicroReader的作者,他实现了中文写入技术而我只是反编译了一下,集中两个功能再加目录操作,才做出来了.
我学java和j2me也只有一个月,很多都不会要向大家学习啊!
程序做了一半,功能基本实现,可是现在放假了,身边没电脑只有等到下学期开学再做了.如有朋友对我的电子书有兴趣可以给我发封信,我可以给你发一个.
代码也没有混,直接反编译就出来了
我的信箱为:threejiaomao@263.net

第34楼 2003-02-19 23:08 duster 写道:

个人觉得如果确定方法不会被继承,就把它final了吧.常量也一样.速度会快一点

第35楼 2003-02-20 18:38 lostfalcon 写道:

还可以先用 WTK 自带的监视工具分析一下自己的MIDlet的瓶颈在哪里,再加以改善。

第36楼 2003-02-23 21:15 bakkhos 写道:

6 对确定不必被继承的方法使用final修饰符
这点是没用的,赫赫,就像c中的register修饰符一样

第37楼 2003-02-25 15:04 quxiancj 写道:

真没意思,看了题目满兴奋的,进来一看,全是初学者的东东。

第38楼 2003-03-05 13:44 jialete 写道:

做类似浮点运算的时候应多采用移位的方法来进行乘除运算。

第39楼 2003-03-26 16:54 whtchy 写道:

我是做dsp的,谈一下我的一些看法
1。定点运算要比浮点运算来的块,但是程序复杂
2。尽量用简单的数据结构,简单的数据类型,以避免
   不必要的类型转换
3。dsp有很多底层的函数,直接与硬件相关,
   不知在midp中能否调用底层一些的函数,虽然这与
   java的思想有些背道而驰
由于dsp本身的特点,上面的看法在midp中可能根本没用,还望大家多多指教

第40楼 2003-03-28 15:00 yinxingshu 写道:

[这个贴子最后由yinxingshu在 2003/03/28 01:02pm 第 1 次编辑]

内存管理是java与其他语言如c,c++之类的主要差别,大家总是在讨论垃圾收集器的问题,但是我们应该可以从另外一个方面来着手解决问题,那就是尽量减少内存的频繁分配与释放,让垃圾收集器少工作一点。如果是操作一个很大的文件,可以在内存中固定开辟一个大的区域,把文件中的对应部分读取进来,进行操作,不要一小块一小块地分配内存、读取文件、操作,这样肯定会加快程序的运行速度。

第41楼 2003-04-01 14:24 snowman828 写道:

推荐一本好书《高效MIDP编程中文版》

第42楼 2003-04-17 17:02 picasso 写道:

除非必要不考虑程序的继承性等因素
不使用类似造型结构
变量命名要短
减少使用innerClass
字符处理操作时注意使用 StringBuffer的优点,和其他相关操作如indexOf等
充分利用源包中已有类

第43楼 2003-04-30 12:50 xiaolong 写道:

针对特定手机,用其api,则能取得特定手机上的最佳性能!!

第44楼 2003-04-30 19:40 bevin 写道:

混淆器,是一个软件吗?哪里有下??

第45楼 2003-05-06 00:26 rocks 写道:

本站有比较常用的retroguard,可以放到WTK直接用,非常方便。如果用JB的话就更方便了,里面自带。

第46楼 2003-05-09 06:55 fantasy0212 写道:

多谢rocks大哥了,真的受益匪浅啊,呵呵

第47楼 2003-05-13 21:03 huapingchen 写道:

原文:http://wireless.java.sun.com/midp/ttips/appsize/
*******************************************************************
[glow=255,lightseagreen,2]优化J2ME程序大小[/glow]
*******************************************************************
by Eric Giguere,translated by jacksun
February 27, 2002
    要把J2ME程序与J2SE程序区分开来,其依据就是J2ME运行所处的受限环境。多数J2ME系统的主要受限条件就是可以存储和运行程序所需内存的大小。例如,许多MIDP设备限制应用程序的尺寸不大于50K,这远远不及Server端J2SE运行环境下那些成兆的程序。实际应用中,程序会很容易超出这些限制条件。通过本篇您将学到一些减小程序尺寸大小的技巧,并在下面的例子中实践这些技术。这个例子MIDlet仅仅显示一个文本框并在其内容改变时发声。
package com.j2medeveloper.techtips;
import javax.microedition.lcdui.*;
public class BeforeSizeOptimization extends
                                      BasicMIDlet {
public static final Command exitCommand =
                      new Command( "Exit",
                                 Command.EXIT, 1 );
public BeforeSizeOptimization(){
}
protected void initMIDlet(){
     getDisplay().setCurrent( new Mainform() );
}
public class Mainform extends form {
     public Mainform(){
         super( "Mainform" );
         addCommand( exitCommand );
         append( textf );
         setCommandListener( new CommandListener(){
             public void commandAction( Command c,
                                    Displayable d ){
                 if( c == exitCommand ){
                     exitMIDlet();
                 }
             }
           }
         );
         setItemStateListener(
                           new ItemStateListener() {
             public void itemStateChanged(
                                        Item item ){
                 if( item == textf ){
                     AlertType.INFO.playSound(
                                     getDisplay() );
                 }
             }
           }
         );
     }
     private TextField textf =
               new TextField( "Type anything", null,
                              20, 0 );
}
}
    虽然这个MIDlet在此仅作为一个例子,但使用的尺寸优化技巧可以适用于任一J2ME的profile上。
注意,上面的MIDlet类需要下面的辅助类:
package com.j2medeveloper.techtips;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public abstract class BasicMIDlet extends MIDlet {
private Display display;
public BasicMIDlet(){
}
protected void destroyApp( boolean unconditional )
                 throws MIDletStateChangeException {
     exitMIDlet();
}
public void exitMIDlet(){
     notifyDestroyed();
}
public Display getDisplay(){ return display; }
protected abstract void initMIDlet();
protected void pauseApp(){
}
protected void startApp()
                 throws MIDletStateChangeException {
     if( display == null ){
         display = Display.getDisplay( this );
         initMIDlet();
     }
}
}
    用J2ME WTK打包时,本例子MIDlet占用4K空间。
    减小尺寸的首要步骤就是通过修正程序的功能实现来去掉多余的类。程序的所有功能确实必须都实现吗?用户可以不需要这些“附属功能”吗?要设计尽可能小的程序,这里的MIDlet例子已经相当小了。

    第二步就是深入考察程序定义的内部类,特别是匿名类。记住,每个类文件都有一定量的与之相关的系统开销。即便最普通的类也有系统开销。
public class foo {
     // nothing here
}
    编译上边的类,生成的类文件大约200byte大小。比如实现一个事件监听器,就是对匿名类的常见使用。在例子MIDlet中就定义了两个此类的监听器。接下来进行的最简单的优化就是,让主MIDlet类实现CommandListener和ItemStateListener接口,并把监听器代码移至此处。记住,多个对象可以使用同样的监听器。必要时,可以使用传递至commandAction和itemStateChanged方法的参变量来区分它们。
内部类也可使代码过大,因为编译器必须生成特殊的变量和方法,以便内部类可以访问包含它们的类的私有内容。请参考内部类的规范以获取更多信息。

    第三步,尽量使用现有的类。例如,基于CLDC的profile没有构造集合类,所以我们可以用内建的Hashtable和Vector类来实现之。构造MIDP程序时也可采用此法。例子MIDlet中定义了一个form字类来生成主表,可以容易的如下直接生成:
mainform = new form( "Mainform" );
mainform.addCommand( okCommand );
mainform.setCommandListener( listener );
    这里没有正确或者错误的答案,只是要推敲。

    第四步就是破坏程序的继承关系。你也许把相关的代码放到一个或多个抽象类中,这是OOD中为提高程序间代码重用的推荐做法。虽然破坏继承关系与你所学知识相违背,但简化的继承关系更有意义。特别的,当你的的抽象类――可能来自其他项目――仅仅被继承一次时,破坏继承关系的结果不言而喻。例如,例子MIDlet继承了BasicMIDlet类,但两者合并为一个类。

    第五步就是要缩短名字长度,如包名、类名、方法名和数据元素名。看起来有些蠢,但一个类文件确实包含太多的符号信息。缩短各量的名字可以缩小生成的类文件尺寸。这种节省不会特别明显,但多个类中进行总加的结果还是可观的。包名对减小尺寸来讲特别合适。MIDP程序是完全自我包容的,完全可以不使用包名,因为在手持设备上包名根本不可能与其他类名冲突。例子MIDlet中,可以把com.j2medeveloper.tchtips包名去掉。
    注意,一般来讲,缩短名字不需要手工去做,要用一个“混淆器”去做。“混淆器”的主要功能是“隐藏”程序代码,使之不能通过反编译读出。它的副作用是减小了程序的尺寸。因为隐藏过程主要通过更改方法和数据成员的名字来完成。有一个开源的混淆器称为RetroGuard,可以免费从http://www.retrologic.com得到。也有一些商业包可用。(当为基于CLDC的profile混淆时,记得在预校验之前混淆,否则混淆器将使类文件中的预校验数据失效。)

    最后,深入数组的初始化。(例子MIDlet没有做数组初始化,但对程序来说初始化是重要的一步) 在编译时,一个数组初始化声明如下所示:
int arr[] = { 0, 1, 2, 3 };
而实际生成代码的过程如下所示:
arr[0] = 0;
arr[1] = 1;
arr[2] = 2;
arr[3] = 3;
    这个过程可以通过使用Java 2 SDK中附带的javap工具把二进制代码反编译成类文件去看(使用-c选项)。也许你会诧异于看到的内容,特别当你希望看到的是一排排二进制常数时。有两种方法可以让你看不到反编译的程序代码,(1)把数据编码为字符串,运行时解码之,或者(2)把数据存为二进制文件并与程序打包,用类装载器的getResourceAsStream方法在运行时存取之。
    以上只是一些指导性的方法,对每个J2ME程序而言,这里没有具体到步骤。但是多数方法可以应用的本例。优化后的MIDlet如下所示:
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class ASO extends MIDlet
              implements CommandListener,
                         ItemStateListener {
private Display   display;
private form      mainform;
private TextField mainformTF =
               new TextField( "Type anything", null,
                              20, 0 );
public static final Command exitCommand =
                      new Command( "Exit",
                                  Command.EXIT, 1 );
public ASO(){
}
public void commandAction( Command c,
                            Displayable d ){
     if( c == exitCommand ){
         exitMIDlet();
     }
}
protected void destroyApp( boolean unconditional )
                 throws MIDletStateChangeException {
     exitMIDlet();
}
public void exitMIDlet(){
     notifyDestroyed();
}
public Display getDisplay(){ return display; }
protected void initMIDlet(){
     mainform = new form( "Mainform" );
     mainform.addCommand( exitCommand );
     mainform.setCommandListener( this );
     mainform.setItemStateListener( this );
     mainform.append( mainformTF );
     getDisplay().setCurrent( mainform );
}
public void itemStateChanged( Item item ){
     if( item == mainformTF ){
         AlertType.INFO.playSound( getDisplay() );
     }
}
protected void pauseApp(){
}
protected void startApp()
                 throws MIDletStateChangeException {
     if( display == null ){
         display = Display.getDisplay( this );
         initMIDlet();
     }
}
}
    关于作者:Eric Giguere 是来自Sybase 下属iAnywhere Solutions 的软件开发人员。他致力于手持设备和无线计算领域的Java技术。他是滑铁卢大学的数学学士和数学硕士,写了很多有关计算的文章。
这是我在IBM 中国开发网上找到的,给大家看看!
是否有用呀?!

第48楼 2003-05-23 14:15 morebest 写道:

第三和第四是不是有矛盾
到底应该多用class还是少用呢

第49楼 2003-06-05 13:02 andyplay 写道:

问一个具体的问题!
我正在进行手机游戏开发,目前针对MOTO T720。当我做一个类似与坦克大战的游戏时发生了速度上的问题:游戏荡到手机上出现明显的按键粘滞,响应过慢。随后我修改代码,在进程休眠时间上做了优化,发现模拟器上的速度有明显的提升。但手机上的速度依旧缓慢。
请高手指教

第50楼 2003-06-09 19:16 tony 写道:

我的感觉,当线程多于4个,且涉及到刷屏操作,反应速度会下降。

第51楼 2003-06-19 13:42 a-b-c 写道:

TONY的文章写得好,再加一条,请尽量不要调用带参的函数.

第52楼 2003-06-23 17:47 sdh5724 写道:



QUOTE:
下面引用由horsethief2002/12/31 05:30pm 发表的内容:
同意1,
不同意2,其实函数堆栈并不浪费时间。功能独立是最重要的,方法少可能会带来更多的代码浪费。
同意3,每个空类有200字节的空间。
不同意4,你给null了只是消除了它的连接,对象并不释放,还是要等GC,但 ...

在多线程竞争资源时候, 我发现有时候, 会引起static size冲突...

第53楼 2003-06-27 12:43 rocks 写道:

一点经验,显式调用GC并令其马上执行:
...
myObjectRefrence = null; //把资源引用标记为空,使得GC可以收集掉它
System.gc();  //通知进行垃圾收集
Thread.yield();  //本线程暂停一下,使得GC可以马上获得机会运行
通过实践,我发现这个方法在很多手机上的收效非常好,能够显著提高性能,因此特别向大家推荐。

第54楼 2003-07-06 02:19 ben9657 写道:

支持rocks的观点.
System.gc();  
Thread.yield();  
这两条语句真是绝配!!

第55楼 2003-07-07 14:28 jiaboy20 写道:

System.gc();
Thread.yield();
一定要放到一起用嘛?如果我是
System.gc();
Thread.sleep(150);
可以嘛?系统会不会利用我的线程休眠的时间进行垃圾回收啊。

第56楼 2003-07-07 16:15 ben9657 写道:

哎,不过说实在的.
api上说:gc方法返回,就表示系统已经完成了回收.不用Thread.yield和sleep了

第57楼 2003-07-09 18:23 lhjiang 写道:

我现在用motoj2sdk来开发,我做页面都是用了继承componentscreen,基本上是一个页面一个类(extends componentscreen),编译以后的确会生成innerclass,都说这种方法是比较耗费内存的,但是我想出什么好的方法,要不就是不要用componentscreen?请大家介绍一下界面是怎么做的?

第58楼 2003-07-12 20:45 ben9657 写道:

继承是不会采用内部类的!
只有当你使用:
add...Listener(new ...Listener() {
public ... () {
}
});
这种形式的代码时,才会产生内部类

第59楼 2003-07-14 18:21 nosoil 写道:



QUOTE:
下面引用由yuanaoe2002/12/30 05:08pm 发表的内容:
我刚学j2me没多久,以下几点是根据我对java语言特性的一些浅见来谈的,大侠们多指教
A:对于处理器速度慢的问题:
尽量使用数组,少用Vectors等对象,即使要用也要按其真实预期大小指定初始空间,其实手机上的程 ...


第60楼 2003-07-16 12:47 rocks 写道:



QUOTE:
下面引用由ben96572003/07/12 05:45pm 发表的内容:
继承是不会采用内部类的!
只有当你使用:
add...Listener(new ...Listener() {
public ... () {
...

这样产生的是匿名内部类,编译后产生形如MyClass$1.class,还有一种内部类是在class里面再定义新的class,这种内部类是有名字的,编译后产生形如MyClass$InnerClass.class
to lhjiang:
是否注意到Form, List, TextBox等类所有的方法都是public的?这就是说,不需要继承就可以使用他们的所有功能,比如:
Form frmA = new Form("Test");
frmA.append("Input:");
frmA.append(new TextField(null, "", 20, TextField.ANY));
frmA.addCommand(new Command("Back", Command.BACK, 1));
frmA.setCommandListener(this);
....
比如要得到frmA上TextField的值就可以用:
((TextField)frmA.get(1)).getText();

第61楼 2003-08-01 16:59 evzhy 写道:

优化是错误之源,所以不是迫不得已,不要优化

第62楼 2003-08-11 16:57 evzhy 写道:

直接写bytecode不可以提速吗?

第63楼 2003-08-15 17:17 mlm102030 写道:

学习中

第64楼 2003-09-23 20:14 lxczyllxc 写道:

当要显示的png图片比较多时,能用哪些方法提高显示速度呢?
当大部分图片为整屏显示,如何提速?
当大部分图为小块显示时,如何提速?

第65楼 2003-10-06 16:56 sasinop 写道:



QUOTE:
下面引用由evzhy2003/08/11 01:57pm 发表的内容:
直接写bytecode不可以提速吗?


第66楼 2003-10-06 17:00 sasinop 写道:



QUOTE:
下面引用由evzhy2003/08/01 01:59pm 发表的内容:
优化是错误之源,所以不是迫不得已,不要优化

对说的好啊   
1尽量不要用 字符串   用数组
  2适当的 用  显示  gc()
   
3  能在 循环 外完成的 不要在循环里做
   比如 算直 生成 新的对象等  等

第67楼 2003-10-23 23:50 luoyt 写道:

还有以下几点:
1.想办法减少数组的使用,java的安全性使组数的调用速度比C慢
2.多使用static和final修饰,少使用synchronized声明

第68楼 2003-11-01 19:01 midamia 写道:

我很谦虚的看了所有的发言,不过这些小技巧都很普通,真的。
合理的设计程序框架,及时地释放不用的资源才是重点

第69楼 2003-11-02 21:52 rainysky 写道:

/admire midamia  

第70楼 2003-12-08 00:24 threejiaomao 写道:

在nokia论谈上找到的,有些价值:
I had about 140Kb of jar size and I compressed it to 58 Kb.
What I used and I recommend to everyone:
1) put all resource files into one data file - the major optimization.
2) optimize palette for your graphics files. It would be better if it will be the same and 256 colors.
3) combine small graphics files onto one big file.
4) obfuscate the class files.
5) reduce amount of methods in your classes.
6) reduce amount of classes.
Small tips: do not use set/get functions for variables. It takes pretty much space and you actually won't make your code much better. If you have some variable in the class that is used by other classes, make it static.

第71楼 2003-12-08 15:52 rocks 写道:

不错不错!
都是最实用的方法

第72楼 2004-01-02 12:36 安哥拉 写道:

好啊!提速

第73楼 2004-01-20 13:48 Sunwing 写道:

6600上的大转变,System.gc()变得超慢,请慎用。
详情参阅NOKIA官方文档

第74楼 2004-02-25 00:20 Nimrod 写道:

    是否可以教下怎样解决记忆内存不足的问题?

第75楼 2004-04-20 18:19 天行健 写道:

1、总体设计很重要。
2、小图合成大图要适度。

第76楼 2004-04-28 17:52 linuxjava 写道:

收益非浅,多谢各位了.!~~~~

第77楼 2004-07-21 16:04 jinnee 写道:

大家在测试执行时可以监视一下模拟器的内存状况
1,首先,线程是内存的主要杀手,因此,尽量少的使用线程十分重要
另外,千万不要在运行时多次创建线程,否则内存会很快耗尽
对于有可能重用的线程,需要确保仅被创建一次
2,内存的节约并不意味着执行效率的提升,还要考虑CPU的运算速度
在执行过程中,影响效率的往往并不是游戏逻辑部分,而是绘制部分
当屏幕内需要绘制的元件增多时,效率会显著下降
因此,尽可能的减少屏幕内的需要频繁绘制的区域,
例如,如果屏幕上方有128*10的区域用来显示得分,
那么这个区域只有在得分变化时才需要重绘
另外,可以使用setClip和repaint(int,int,int,int)设置剪辑区
3,王森的书上有关于控制线程时间同步的方法
比较有效,大家可以参考一下

第78楼 2004-09-18 20:49 zerker 写道:

J2ME程序优化方法二十条
--by zerker 2004.9
j2me程序由于其特殊的运行环境限制,所以优化就显得比较重要,以下是我在学习j2me编程所收集的一些技巧和自己的心得。
本文主要是说明j2me平台上的特殊优化方法,与j2se重复的一些技巧就不再赘述了。
1.显示图象时确定好你的fps,最好先做几次小实验,这样能让你在显示效果和运行速度上有比较好的平衡。
2.GamaCanvas.getGraphics()每次都会产生一个全新的对象,但是对这些对象的操作都是对同一个graphics,所以还是只取一次供后面使用。
3.让多个对象使用同样的监听器,比如让主MIDlet类实现CommandListener和ItemStateListener接口。
4.考虑使用手机开发商提供的一些sdk,没人会比他们更了解他们手机,所以有些时候能显著提高速度,特别是图片,视频使用方面。
5.使用监视工具分析MIDlet的瓶颈,wtk和各个公司提供的开发包里都会有,可以找到程序的弱点。如果是在手机上,用timer测试你认为有可以的地方。
6.使用System.gc(),在无线程阻塞的情况下可以有效的缓解内存压力,但是有些公司不是太推荐使用(如nokia).sun的说法也是越低端的机子执行的越慢,总之,慎用吧。
7.用固定的数组代替使用Vector。
8.图片的优化。考虑使用设备的规格,可能高分辨率的图片不一定显示的出来。
9.不用的对象赋值为null,为更快的回收
10.用混淆器处理你的类文件,防止反编译,还有一个好的副作用就是它减小class文件的大小,因为混淆器往往用较短的字符串代替原来的变
量或方法名。
11.若数据太大,可以将数据编码为字符串,运行时解码,或把数据存为二进制文件并与程序打包,用类装载器的getResourceAsStream方法在运行时存取。
12.使用现有的类,比如你使用了GameCanvas,就不用自己生成off-screen,另外像CLDC的profile没有构造集合类,所以我们可以用内建的Hashtable和Vector类来实现。
13.用优化软件jPresto(http://www.s5systems.com/jPresto.htm)---没用过,不过暂且写上吧。

如果对文件大小,内存限制非常严格,这时候就只能用一些非常规的方法了,可能这些方法背离了OO思想,但是多数情况下,它是起到了非常积极的作用的(但是也可能),假如你更在意于程序的维护和扩展方面,我建议你还是跳过吧 -_-||
14.把所有资源文件做成一个数据文件。
15.把所有的小图片文件做成一个文件,在运行时再“切割”开。
16.使用有限的面向对象,因为纯粹的OO往往意味着更多的虚方法,更多的层次关系,更多的class
17.生成尽可能少的class,class都有一定的系统开销。
18.class中生成尽可能少的方法。速度比较:同步方法《接口方法《实例方法《final方法《静态方法。
19.用final static限定方法可以获得小幅的速度提高。
20.对数据成员用public限定,来代替get和set方法,不过要注意安全性。

J2ME优化可能使你的程序在不同的模拟器,不同的设备下有不同的运行效果,所以优化一定要建立在开发设备的规格上。
以上所列举的方法不一定在所有midp设备上都起作用,也不一定都适合每一个程序,总之,应该根据自身的情况,在存储空间,内存使用,安全性能上找到最佳的平衡点。
学习J2ME时间不长,如果有错误,务必指出,也希望大家和我讨论有关问题,谢谢!
参考文章:
http://wireless.java.sun.com/midp/ttips/appsize/

第79楼 2004-09-19 03:41 wang1957 写道:



QUOTE:
下面引用由sdujerome2002/10/11 07:23pm 发表的内容:
以上的建议都挺好的,我再加一条:
是不是可以在适当的时候显式的调用gc

调用System.gc() 要看具体机器而言,
有些机器如7210可以加快速度
但有些机器反而最慢了,我在写MOTO的一些机器的游戏时候就遇到了这种情况

第80楼 2004-09-25 11:22 rosezhang 写道:

Use as less boolean operation as you can, it will save you both jar size and speed your MIDLet up.
Believe me or not, change boolean to int and use c-style b == 1 as true and b == 0 as false would help. Another thing, don';t use short or byte, just use int unless it is an array. This is because Java default uses int, which is the fastest. If you use others, JVM will treat them as int anyway. And also type conversion takes memory and time too.
If you don';t believe me, test by yourself!!

第81楼 2004-09-30 18:42 strongsnow 写道:

是不是用STATIC方法也能减少点内存的

第82楼 2004-10-15 12:20 strongsnow 写道:

最好也能显式的把不用的对象置为NULL,有时候也包括在方法里面的临时变量!
这样,可以减轻JVM的负担

第83楼 2005-07-13 20:51 acrobatchen 写道:

Java程序运行的大部分时间都用在运行类库文件上,只有很小的一部分是运行所编写的程序,所以应注意选择正确的库文件以及效率高的函数

发表新主题   回复此主题