发布新日志

  • windows 配置 ant环境

    2012-04-28 10:06:46

    以下设置WinXP及以上用户,右键点击我的电脑->属性->高级->环境变量,设置即可。设置完成后需重新启动命令提示符才能生效。具体如下:

      JAVA环境变量设置

      Windows下JAVA用到的环境变量主要有3个,JAVA_HOME、CLASSPATH、PATH。

      JAVA_HOME指向的是JDK的安装路径,如D:\Program Files\IBM\Java50,在这路径下你应该能够找到bin、lib等目录。

      设置方法:

      JAVA_HOME = D:\Program Files\IBM\JAVA50

      PATH环境变量原来Windows里面就有,只要保留原来的PATH的内容,并在其中加上%JAVA_HOME%\bin (%JAVA_HOME%就是是引用上一步设定好的环境变量JAVA_HOME) 。

      设置方法:

      PATH = %JAVA_HOME%\bin;%PATH%

      同样,%PATH%是引用以前你设置的PATH环境变量,你照抄以前的值就行了。

      注意的是最前面的".\;",这个是告诉JDK,搜索CLASS时先查找当前目录的CLASS文件,至于CLASSPATH后面指定tools.jar这个具体文件,是由java语言的import机制和jar机制决定的。

      设置方法:

      CLASSPATH = .\;%JAVA_HOME%\lib\tools.jar;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\jre\lib\rt.jar

      ANT环境变量设置

      Windows下ANT用到的环境变量主要有2个,ANT_HOME 、PATH。

      设置ANT_HOME指向ant的安装目录。

      设置方法:

      ANT_HOME = D:\apache_ant_1.7.0

      将%ANT_HOME%\bin; %ANT_HOME%\lib添加到环境变量的path中。

      设置方法:

      PATH = %ANT_HOME%\bin; %ANT_HOME%\lib

  • 转:Code Review

    2012-04-23 10:28:10

    Code Review应该是软件工程最最有价值的一个活动,之前,本站发表过《简单实用的Code Review工具》,那些工具主要是用来帮助更有效地进行这个活动,这里的这篇文章,我们主要想和大家分享一下Code Review代码审查的一些心得。

    首先,我们先来看看Code Reivew的用处:

    Code reviews 中,可以通过大家的建议增进代码的质量。
    Code reviews 是一个传递知识的手段,可以让其它并不熟悉代码的人知道作者的意图和想法,从而可以在以后轻松维护代码。
    Code reviews 也鼓励程序员们相互学习对方的长处和优点。
    Code reviews 也可以被用来确认自己的设计和实现是一个清楚和简单的。
    你也许注意到了在上面的Code Reivew中的诸多用处中,我们没有提到可以帮助找到程序的bug和保证代码风格和编码标准。这是因为我们认为:


    Code reviews 不应该承担发现代码错误的职责。Code Review主要是审核代码的质量,如可读性,可维护性,以及程序的逻辑和对需求和设计的实现。代码中的bug和错误应该由单元测试,功能测试,性能测 试,回归测试来保证的(其中主要是单元测试,因为那是最接近Bug,也是Bug没有扩散的地方)
    Code reviews 不应该成为保证代码风格和编码标准的手段。编码风格和代码规范都属于死的东西,每个程序员在把自己的代码提交团队Review的时候,代码就应该是符合规 范的,这是默认值,属于每个人自己的事情,不应该交由团队来完成,否则只会浪费大家本来就不够的时间。我个人认为“meeting”是奢侈的,因为那需要 大家在同一时刻都挤出时间,所以应该用在最需要的地方。代码规范比起程序的逻辑和对需求设计的实现来说,太不值得让大家都来了。
    10年前,上面这两件事会是理所当然的(10年前的中国的软件开发还没有Code Reivew呢),今天,在中国的很多公司上面这两件事依然被认为是Code Reivew最重要的事,所以,我能够看到很多开发Team抱怨Code Review就是一个形式,费时费力不说,发现的问题还不如测试,而评审者们除了在代码风格上有些见术,别的也就没什么用了,长而久之,大家都会开始厌烦 这个事了。

    所以,在今天,请不要把上面的那两件事分散了Code Review的注意力,取而代之的是,对于Bug,程序的作者要在Review前提交自己的单元测试报告(如:XUnit的测试结果),对于代码规范,这 是程序作者自己需要保证的,而且,有一些工具是可以帮你来检查代码规范的。

    当然,上述这些言论并不是说,你不能在Code Review中报告一个程序的bug或是一个代码规范的问题。我只是说,那并不是Code Review的意图。

    下面是我们认为的几个小提示可以让你更好进行Code Review这项最有价值的活动。

    1.- 经常进行Code Review
    以前经历过几个相当痛苦的Code Review,那几次Code Review都是在程序完成的时候进行的,当你面对那近万行的代码,以前N多掺和在一起的功能,你会发现,整个Code Review变得非常地艰难,用不了一会儿,你就会发现大家都在拼命地打着哈欠,但还是要坚持,有时候,这样的Review会持续3个小时以上,相当的夸 张。而且,会议上会出现相当多的问题和争论,因为,这就好像,人家都把整个房子盖好了,大家Review时这挑一点那挑一点,有时候触动地基或是承重墙 体,需要大动手术,让人返工,这当然会让盖房的人一下就跳起来极力地维护自己的代码,最后还伤了团队成员的感情。

    所以,千万不要等大厦都盖好了再去Reivew,而且当有了地基,有了框架,有了房顶,有了门窗,有了装修,的各个时候循序渐进地进行Review,这样反而会更有效率,也更有帮助。

    下面是一些观点,千万要铭记:

    要Review的代码越多,那么要重构,重写的代码就会越多。而越不被程序作者接受的建议也会越多,唾沫口水战也会越多。

    程序员代码写得时候越长,程序员就会在代码中加入越来越多的个人的东西。 程序员最大的问题就是“自负”,无论什么时候,什么情况下,有太多的机会会让这种“自负”澎涨开来,并开始影响团队影响整个项目,以至于听不见别人的建 议,从而让Code Review变成了口水战。
    越接近软件发布的最终期限,代码也就不能改得太多。
    我个人的习惯,并且也是对团队成员的要求是——先Review设计实现思路,然后Review设计模式,接着Review成形的骨干代码,最后 Review完成的代码,如果程序复杂的话,需要拆成几个单元或模块分别Review。当然,最佳的practice是,每次Review的代码应该在 1000行以内,时间不能超过一部电影的时间——1.5小时(因为据说那个一个正常人的膀胱可以容纳尿液的最长限度)

    当然,在敏捷开发中,他们不需要Code Reivew,其实,敏捷开发中使用更为极端的“结对编程”(Pair-Programming)的方法 —— 一种时时刻刻都在进行Code Review的方法,个人感觉在实际过程中,这种方法有点过了。另外,大家可以看看本站的另一篇文章《结对编程的利与弊》来了解一下这种方法的问题。

    2.- Code Review不要太正式,而且要短
    忘了那个代码评审的Checklist吧,走到你的同事座位跟前,像请师父一样请他坐到你的电脑面前,然后,花5分钟给他讲讲你的代码,给他另外 一个5分钟让他给你的代码提提意见,这比什么都好。而如果你用了一个Checklist,让这个事情表现得很正式的话,下面两件事中必有一件事会发生:

    只有在Checklist上存在的东西才会被Review。
    Code Reviews 变成了一种礼节性的东西,你的同事会装做很关心你的代码,但其实他心里想着尽快地离开你。
    只有不正式的Code Review才会让你和评审者放轻松,人只有放松了,才会表现得很真实,很真诚。记住Review只不过是一种形式,而只有在相互信任中通过相互的讨论得 到了有意义和有建设性的建议和意见,那才是最实在的。不然,作者和评审者的关系就会变成小偷和警察的关系。

    3.- 尽可能的让不同的人Reivew你的代码
    这是一个好主意,如果可能的话,不要总是只找一个人来Review你的代码,不同的人有不同的思考方式,有不同的见解,所以,不同的人可以全面的 从各个方面评论你的代码,有的从实现的角度,有的从需求的角度,有的从用户使用的角度,有的从算法的角度,有的从性能效率的角度,有的从易读的角度,有的 从扩展性的角度……,啊,好多啊,还让不让人活了。不管怎么说,多找一些不同的人会对你很有好处。当然,不要太多了,人多嘴杂反而适得其反,基本上来说, 不要超过3个人,这是因为,这是一个可以围在一起讨论的最大人员尺寸。

    下面是几个优点:

    从不同的方向评审代码总是好的。
    会有更多的人帮你在日后维护你的代码。
    这也是一个增加团队凝聚力的方法。
    4.- 保持积极的正面的态度
    再说一次,程序最大的问题就是“自负”,尤其当我们Reivew别人的代码的时候,我已经见过无数的场面,程序员在Code Review的时候,开始抨击别人的代码,质疑别人的能力。太可笑了,我分析了一下,这类的程序员其实并没有什么本事,因为他们指责对方的目的是想告诉大 家自己有多么的牛,靠这种手段来表现自己的程序员,其实是就是传说中所说的“半瓶水”。

    所以,无论是代码作者,还是评审者,都需要一种积极向上的正面的态度,作者需要能够虚心接受别人的建议,因为别人的建议是为了让你做得更好;评审者也需要以一种积极的正面的态度向作者提意见,因为那是和你在一个战壕里的战友。记住,你不是一段代码,你是一个人!

    5.- 学会享受Code Reivew
    这可能是最重要的一个提示了,如果你到了一个人人都喜欢Code Reivew的团阿,那么,你会进入到一个生机勃勃的地方,在那里,每个人都能写出质量非常好的代码,在那里,你不需要经理的管理,团队会自适应一切变 化,他们相互学习,相互帮助,不仅仅是写出好的代码,而且团队和其中的每个人都会自动进化,最关键的是,这个是一个团队。
  • Ora-12516有可能是连接数过多,修改Oracle数据库processes和sessions

    2012-04-18 13:03:28

    1、 plsql连接数据库时,出现

     

    Ora-12516:TSN:监听程序找不到符合协议堆栈要求的可以处理程序

     

     

    2、查看alert_SID.log出现下面的信息

    Process q006 started up but failed with error = 20

    Process q006 started up but failed with error = 20

    Process q006 started up but failed with error = 20

    Process q006 started up but failed with error = 20

     

    3        、查看数据库的当前连接数

    Select * from v$license;

     

    2、 数据库的连接数

    Select * from v$patameter ;

    中的processessessions值接近当前的连接数

     

    如果不修改数据库的连接数,重新数据库也可以解决该问题,但毕竟不是长远之计。

    修改数据库的连接数(sys用户):

     

    SQL> alter system set processes=500 scope=spfile;

     

    System altered.

     

    SQL> show parameter processes

     

    SQL> show parameter sessions

     

    SQL>

    SQL> alter system set sessions=555 scope=spfile;

     

    System altered.

     

    SQL> shutdown abort;

    ORACLE instance shut down.

    SQL> startup

    ORACLE instance started.

     

    Total System Global Area 2625634304 bytes

    Fixed Size                  793464 bytes

    Variable Size            456385672 bytes

    Database Buffers        2164260864 bytes

    Redo Buffers               4194304 bytes

    Database mounted.

    Database opened.

    SQL>

    SQL> show parameter processes

     

    NAME                                TYPE       VALUE

    ------------------------------------ ----------- ---------------------------

    aq_tm_processes                     integer    0

    db_writer_processes                 integer    2

    gcs_server_processes                integer    0

    job_queue_processes                 integer    10

    log_archive_max_processes           integer    2

    processes                           integer    500

    SQL> show parameter sessions

     

    NAME                                TYPE       VALUE

    ------------------------------------ ----------- ---------------------------

    java_max_sessionspace_size          integer    0

    java_soft_sessionspace_limit        integer    0

    license_max_sessions                integer    0

    license_sessions_warning            integer    0

    logmnr_max_persistent_sessions      integer    1

    session_cached_cursors              integer    0

    session_max_open_files              integer    10

    sessions                            integer    555

    shared_server_sessions              integer

    SQL> create pfile from spfile;

     

    File created.
  • 【转】oracle pfile和spfile小结

    2012-04-18 13:02:25

    1、pfile 文本文件 client端参数文件;不能动态修改,可以用普通的编辑器修改,修改之后需要重启。pfile可能会导致服务器启动不一致,因为可以在客户端启动。 2、spfile 二进制文件服务器端参数文件,有了spfile,oracle可以实现动态参数在线修改,部分参数修改之后无需重启。但是,因为是二进制文件,所以不能用 普通的编辑器修改,要用alter命令从sql里面来修改。spfile保证服务器每次的启动都是一致的。只有spfile而没有pfile文件时,可以 通过: create pfile='位置+名字' from spfile; 如: create pfile='E:/ORACLE/PRODUCT/10.2.0/DB_1/DBS/spfileorcl_bak.ora' from spfile; 进行创建pfile文件。 同理,只有pfile而没有spfile时,可以通过: create spfile='位置+名字' from pfile; 进行创建spfile文件。pfile和spfile二者可以互相备份。 3、通过spfile或pfile启动数据库: (1)startup nomount启动方式,查找文件的顺序是 spfileSID.ora-〉spfile.ora-〉initSID.ora-〉init.ora(spfile优先于pfile)。 (2)startup pfile='文件目录'----通过pfile文件启动;(3)startup spfile='文件目录'----通过spfile文件启动。 以下转自: http://www.cnblogs.com/jacktu/archive/2008/02/27/1083232.html 查看系统是以pfile还是spfile启动 Select isspecified,count(*) from v$spparameter group by isspecified; 如果isspecified里有true,表明用spfile进行了指定配置 如果全为false,则表明用pfile启动 使用SPfile的好处 Spfile改正了pfile管理混乱的问题,在多结点的环境里,pfile会有多个image 启动时候需要跟踪最新的image。这是个烦琐的过程。 用spfile以后,所有参数改变都写到spfile里面(只要定义scope=spfile或both),参数配置有个权威的来源。 查看spfile location show parameter spfile 从spfile获取pfile Create pfile='d:pfileSID.ora' from spfile; Create pfile='d:pfileSID.ora' from spfile='spfile_location'; 从pfile获取spfile Create spfile from pfile='Your_pfile_location' Create spfile='spfile_location' from pfile='Your_pfile_location' 动态修改参数 alter system set parameter=Value scope=spfile|both|memory Startup nomount的时候需要读去spfile或pfile,两者共存,spfile优先 强制用pfile启动 SQL>startup pfile='Your_Pfile.ora' startup spfile='/data/oracle/product/10.2.0/db_1/dbs/dbs/spfile_mqq.ora' force 通过pfile连接到spfile启动 修改pfile文件

     

    oracle pfile spfiel 总结
    2008-08-17 11:43

       ORACLE SPFILE PFILE 总结

    OS:Linux localhost.localdomain 2.4.21-20.EL #1 Wed Aug 18 20:58:25 EDT 2004 i686 i686 i386 GNU/Linux

    ORACLE:
    SQL> select*from v$version;

    BANNER
    ----------------------------------------------------------------
    Oracle9i Release 9.2.0.4.0 - Production
    PL/SQL Release 9.2.0.4.0 - Production
    CORE    9.2.0.3.0       Production
    TNS for Linux: Version 9.2.0.4.0 - Production
    NLSRTL Version 9.2.0.4.0 - Production


    1。指定PFILE的路径:
    CREATE SPFILE FROM PFILE='初始化变量文件的全路径';

    CREATE SPFILE [= '<spfile_name>;'] FROM PFILE [= '<pfile_name>;'];

    The above will create a Server Parameter file (SPFILE) based on the existing
    Parameter File (PFILE) (INIT<ORACLE_SID>;.ORA).
    The SPFILE is by default named SPFILE<ORACLE_SID>;.ORA and placed in the default (port specific) directory.

    If existing PFILE (INIT<ORACLE_SID>;.ORA) is not in default directory and using default naming,
    the below must be specified:
    CREATE SPFILE FROM PFILE='<directory-and-filename>;' ;

    SQL> create spfile='/opt/oracle/admin/boco/pfile/spfileorcl.ora' from pfile='/opt/oracle/admin/boco/pfile/initorcl.ora.716200815553';

       File created.

       SQL> show parameter process;

       NAME                                 TYPE        VALUE
       ------------------------------------ ----------- ------------------------------
       aq_tm_processes                      integer     1
       db_writer_processes                  integer     1
       job_queue_processes                  integer     10
       log_archive_max_processes            integer     2
       processes                            integer     50
       SQL> shutdown immediate;
       Database closed.
       Database dismounted.
       ORACLE instance shut down.
       SQL> startup
       ORACLE instance started.

       Total System Global Area 236000356 bytes
       Fixed Size                   451684 bytes
       Variable Size             201326592 bytes
       Database Buffers           33554432 bytes
       Redo Buffers                 667648 bytes
       Database mounted.
       Database opened.
       SQL> show parameter process;

       NAME                                 TYPE        VALUE
       ------------------------------------ ----------- ------------------------------
       aq_tm_processes                      integer     1
       db_writer_processes                  integer     1
       job_queue_processes                  integer     10
       log_archive_max_processes            integer     2
       processes                            integer     150
       SQL> create spfile from pfile='/opt/oracle/admin/boco/pfile/initorcl.ora.716200815553'
        2 ;
       create spfile from pfile='/opt/oracle/admin/boco/pfile/initorcl.ora.716200815553'
       *
       ERROR at line 1:
       ORA-32002: cannot create SPFILE already being used by the instance


       SQL> shutdown immediate
       Database closed.
       Database dismounted.
       ORACLE instance shut down.
       SQL> startup pfile='/opt/oracle/admin/boco/pfile/initorcl.ora.716200815553';
       ORACLE instance started.

       Total System Global Area 236000356 bytes
       Fixed Size                   451684 bytes
       Variable Size             201326592 bytes
       Database Buffers           33554432 bytes
       Redo Buffers                 667648 bytes
       Database mounted.
       Database opened.
       SQL> create spfile from pfile='/opt/oracle/admin/boco/pfile/initorcl.ora.716200815553'
        2 ;

       File created.


    3.在pfile中可以指定引用spfile,
    启动时会先用pfile指定的参数,然后如果spfile中有相同的参数覆盖pfile中的参数
    你可以在pfile中指定引用spfile
    如,你可以在pfile中加入如下一行:

    spfile='/opt/oracle/dbs/spfile<sid>.ora'

    4.查看当前数据库是pfile还是spfile启动
    oracle在默认情况下以spfile启动,除非你启动时指定pfile
    如:startup pfile=/opt/oracle/admin/boco/pfile/initorcl.ora

    show parameter spfile;如果是不为空,会告诉你spfile的文件路径,说明是以spfile启动。如下面例子

    SQL> startup pfile=/opt/oracle/admin/boco/pfile/initorcl.ora.716200815553
       ORACLE instance started.

       Total System Global Area 236000356 bytes
       Fixed Size                   451684 bytes
       Variable Size             201326592 bytes
       Database Buffers           33554432 bytes
       Redo Buffers                 667648 bytes
       Database mounted.
       Database opened.
       SQL> show parameter process;

       NAME                                 TYPE        VALUE
       ------------------------------------ ----------- ------------------------------
       aq_tm_processes                      integer     1
       db_writer_processes                  integer     1
       job_queue_processes                  integer     10
       log_archive_max_processes            integer     2
       processes                            integer     50
       SQL> show parameter spfile;

       NAME                                 TYPE        VALUE
       ------------------------------------ ----------- ------------------------------
       spfile                               string
       SQL> show parameter pfile;

       NAME                                 TYPE        VALUE
       ------------------------------------ ----------- ------------------------------
       spfile                               string

  • 电脑上测试Android应用

    2012-04-18 10:14:50

    现在流行安卓系统,鉴于囊中羞涩,买不起手机和平板电脑,所以我就在网上找了个安卓模拟器,整理了一下,分享给大家,对安卓系统感兴趣的朋友不妨拿来解解馋吧。
    这 个方法目前可以模拟android1.5-3.0系统,从各种安卓系统的手机,到安卓系统的平板电脑都可以模拟,而且可以安装所有安卓程序,可以上网、登 QQ、听音乐等等。跟在手机和平板电脑上的操作和功能几乎一样。由于安装和设置比较复杂,特意为大家写个详细的安装教程,以windows XP为例。

    工具/原料

    • java JDK 1.6
    • sdk模拟器
    • 安装apk程序到手机或模拟器的工具:APK安装器
    • 光盘映像文件制作/编辑/转换工具:UltraISO软碟通

    步骤/方法

    1. 设置电脑系统的环境变量。在桌面【我的电脑】上点击鼠标右键,选择【属性】菜单,即打开了系统属性对话框。

      在【高级】选项卡中,单击【环境变量】按钮,即打卡了环境变量的对话框。
      在系统变量里面,新建一个系统变量:
      变量名:JAVA_HOME
      变量值:C:\Program Files\Java\jdk1.6.0_10
      还要新建一个系统变量:(注意符号)
      变量名:classpath
      变量值:.;%JAVA_HOME%\lib;
      另外一个环境变量Path 默认已经有了,选中它,并点击【编辑】按钮,对其进行编辑。变量值里面,在原有的的前面加入这个值C:\Program Files\Java\jdk1.6.0_10\bin;


    2. 下载并安装java JDK 1.6。可以去网上搜索下载,可以在这个地址去下载:
      http://www.java.net/download/jdk6/6u10/promoted/b28/binaries/jdk-6u10-rc-bin-b28-windows-i586-p-21_jul_2008.exe
      文件下载完了如下:
      然后安装这个它很简单,一步步安装过去就好了。
    3. 安装最新的sdk模拟器。
      我在这里下载的:
      http://dl.google.com/android/android-sdk_r05-windows.zip
      下载并解压,不需要安装,直接放到一个可用空间比较大的磁盘,因为到时候里面还要装很多东西。比如我解压后放在D盘的。
      打开这个文件夹,运行里面这个程序:SDK Setup.exe。
      运行这个程序后,会打开几个窗口,不要去管它。
      程序自动连接到google的服务器检查可用的包裹,这里需要几十秒到几分钟,请等待。
    4. 下载和安装模拟器的安卓系统版本。
      如果你看到一条关于SSL的错误信息,点击【Settings】标签(在SDK and AVD Manager窗口左边)。然后把Force https://……前面的勾去掉,点确定。
      然后重新选择左边的【installed packages】标签。
      左边列出来的这些,就是安卓的各个系统版本的模拟程序,我这里因为已经下载了很多,所以有很多。你那里没有的话那么多,或者没有你想要的版本的话,请点击【update all】按钮,来进行升级。
      我这里几乎都下载完了,所以全部是绿色的勾,如果是问号,不用管它,选中右边的【Accept All】,并单击【Install】按钮,就会自动下载并安装。
      这个过程有点长,需要几十分钟,甚至几十个小时,取决于你的网速和下载版本的多少。下载一段时间了,不想下载了,可以点【Cancel】取消下载和安装,接着点【Close】关闭下载安装窗口。
      回到【installed packages】标签,可以查看到你安装了哪些版本,比如我这里安装了1.5,1.6,2.1,2.2,2.3.1,2.3.3,3.0版本,除了3.0版本是模拟的安卓平板电脑系统之外,其他的较低的版本都是模拟的安卓手机系统。
    5. 创建设置模拟器。
      点击左侧【Virtual Devices(虚拟设备)】标签。这里来创建和设置模拟器。可以创建多个模拟器。也对可以对其编辑和删除。
      我 演示一下创建一个模拟器,先点击右侧的【NEW】按钮,表情新建一个模拟器,然后在如下设置参数。在Name里输入你模拟器的名字,最好用英文或数字。在 Target中选择安卓系统的版本,你下载了哪些版本的,这里就可以选择哪些版本。在Size里设置SD卡的大小,SD卡就相当于手机中插的内存卡,可以 把各种文件和程序放进去,它是个镜像文件,比如我这里设置的1G,即1024M。在Built-in中选择模拟器的屏幕大小,大家最好选择第一个选项,也 就是前面带有Default的默认选项。最后点击最下方的【Create AVD】按钮完成创建模拟器,因为我这里输入的Name不对,所以点击不了。
    6. 运行模拟器。以android2.2为例。
      选中你创建的模拟器,然后点击【Start】运行它。比如我这里来运行2.2版本的。
      在弹出来的窗口,直接点【Launch】就好了。
      稍等几秒钟,模拟器就弹出来了,相继出现两个等待画面,此段时间可能需要等待几分钟,特别是第一次进入模拟器的时候。
      等待一会儿,Android的home screen出现了!你可以用鼠标点进行操作,比如拖动解锁,需要注意的是你不需要双击来打开应用。左边的模拟键盘可以用鼠标点击操作,打字也可以用电脑的键盘进行操作。
    7. 设置操作界面的语言(英语特别好的可以省略)。
      由于默认是英语的操作界面,我们首先为了方便,可以改变语言设置,先拖动解锁。
      打开主菜单,进入【Settings(设置)】菜单,像手机一样操作,网上拖动屏幕,选择【Language & Keyboard(语言和键盘)】菜单:
      选择最上面的那个菜单【Select Language(选择语言)】,进行设置语言。
      同样把屏幕网上拖动,知道最后出现【中文(简体)】的选项,然后选择它,你的“手机”就变成了中文界面了,可能主菜单还没有变成中文的,下次启动就成中文的了。
      可以点击右边模拟键盘上像个房子的图标,表示回到主画面。
      以后的操作大家就很熟悉了,可以进行其他设置,可以用浏览器就行上网,下载文件和软件。可以对桌面进行各种管理等等。
      直接打开浏览器就跳到谷歌搜索(中国网站)首页,这是浏览器默认的主页,可以进行输入网址和搜索的方式进行网络访问。不需任何设置即可上网。可以去网上下载软件

      跟用安卓手机一样操作,大家可以多多试试。
      可以下载并使用QQ:同样后台可以运行程序,跟手机一样操作。
      3.0的系统跟平板电脑操作也一样:
      需要注意的是,这个版本没有单独的模拟键盘,打字的时候可以用电脑键盘。


    8. 给模拟器安装软件。
      除了可以用模拟器上网下载软件安装之外,还可以用专门的APK安装器,进行安装软件。
      这款工具可以给连接电脑的安卓系统手机安装程序,也可以给模拟器安装程序。先去下载,它是个绿色软件,直接打开即可。
      比如可以在这里下载2.3版本的:
      http://www.crsky.com/soft/16759.html
      打开之后,点击右侧【刷新设备列表】,上方就会出现一个模拟器,选中它。在点击上面【选择APK文件】按钮,选择你下载的APK程序文件,点击【开始安装】。有的安装较快,有的稍微慢点。
    9. 管理SD卡。之前设置了SD卡,这个SD卡是虚拟的,用的光盘镜像文件,大小之前设置了的,我这里设置的1024M,还记得吗。它的位置在电脑中这里:
      C:\Documents and Settings\Administrator\.android\avd\luthui.avd\sdcard.img
      Administrator是你电脑的用户名,如果不是这个用户名,请改。
      luthui.avd是你创建的模拟器的AVD名称,请改成自己的。

      找到sdcard.img文件就可随意读写文件了,需要用光盘映像文件制作/编辑/转换工具,进行文件的管理,我一般用ultraiso工具。可以到这里下载并安装:
      http://www.crsky.com/soft/1134.html
      打开这个工具之后,打开上面那个光盘镜像文件sdcard.img,然后进行管理。把电脑里的文件和程序复制进去,也可以删除、移动、建立文件和文件夹等操作。
      文档整理完之后,请保存,再关闭。而且保存的时候,需要先关闭模拟器。
      如果你无法查看SD卡或模拟器的文件,可以通过手机上网的方式,下载并安装一个文件管理器。比如我用的是双文件管理器Dual File Manager。
      你可以通过手机自带浏览器打开网页,搜索下载,也可以在电脑的浏览器上找好下载万网,然后直接在手机中输入这个网址进行下载:
      http://www.ggdown.com/view/3479.html 进去下载,然后安装这个文件。
      打开文件管理器,就可以管理你模拟器和SD卡的文件。

      我在镜像文件里面,复制了很多文件和软件进去,那么在这个文件管理器中,可以尽情的安装。
  • linux程序常见安装、卸载方法

    2011-12-21 11:58:26

    Linux常见的安装为tar,zip,gz,rpm,deb,bin等。我们可以简单的分为三类.

    熬头:打包或压缩文件tar,zip,gz等,一般解压后即可,或解压后运行sh文件;

    第二:对应的有管理东西的deb,rpm等,凡是的这类安装文件可以通过第三方的命令行或UI来简单的安装,例如Ubuntu中的apt来安装

    deb,Redhat中的yum来安装rpm;

    第三:像.bin类,其实就是把sh和zip打包为bin,或把sh和rpm打包为bin等,当在命令交运行bin安装文件时,其实就是bin里面的sh来解

    压bin中的zip或安装rpm的过程

    1. rpm安装,更新与卸载

    RPM包,这种软件包就像windows的EXE安装文件同样,各种文件已编译好,并打了包,哪个文件该放到哪个文件夹,都指定好了,

    安装很是利便,在图形界面里你只需要双击就能自己主动安装。但是有一点儿不好,就是包的依赖瓜葛,这个会烦死人的

    A. rpm安装

    1) 找到相应的软件包,比如soft.version.rpm,下载到本机某个目录;

    2) 打开1个终端,su 成root用户;

    3) cd soft.version.rpm地点的目录;

    4) 输入rpm -ivh soft.version.rpm

    B。rpm更新

    #rpm -Uvh soft.version.rpm

    C。rpm卸载

    1) 查找欲卸载的软件包 rpm -qa | grep ×XXX×

    2) 例如找到软件mysql-4.1.22-2.el4_8.4 ,执行rpm -e mysql-4.1.22-2.el4_8.4

    注重:查询软件的安装目录,用命令 rpm -ql mysql-4.1.22-2.el4_8.4

    2. 以.bin结尾的安装包

    bin类似rpm包安装,也比力简单

    bin安装

    1) 打开1个SHELL,即终端

    2) 用CD 命令进入源代码压缩包地点的目录

    3) 给文件加之可执行属性:chmod +x ******.bin(中心是字母x,小写)

    4) 执行命令:./******.bin 或 直接执行 sh ******.bin

    bin卸载

    把安装时中选择的安装目录删除就OK

    3. tar.gz(bz或bz2等)结尾的源代码包

    这种软件包里面都是源程序,没有编译过,需要编译后才气安装

    源代码安装

    1) 打开1个SHELL,即终端

    2) 用CD 命令进入源代码压缩包地点的目录

    3) 根据压缩包类型解压缩文件(*代表压缩包名称)

    tar -zxvf ****.tar.gz

    tar -jxvf ****.tar.bz(或bz2)

    4) 用CD命令进入解压缩后的目录

    5) 输入编译文件命令:./configure(有的压缩包已编译过,这一步可以省去)

    6) 然后是命令:make

    7) 再是安装文件命令:make install

    注重:我们可以通过./configure --help 来查看配置软件的功能;大多软件是提供./configure 配置软件的功能的;少数的也没有,

    如果没有的就不用./configure ;直接make;make install 就好了;./configure 比力重要的1个参数是 --prefix ,用--prefix 参

    数,我们可以指定软件安装目录

    源代码卸载

    1) 打开1个SHELL,即终端

    2) 用CD 命令进入编译后的软件目录,即安装时的目录

    3) 执行反安装命令:make uninstall

    4. yum安装

    yum是rpm的管理东西,管理1个软件库,可以很好的解决依赖瓜葛

    1) yum安装

    yum install -y 软件名

    2) yum更新

    yum update -y软件名

    3) yum卸载

    yum remove -y 软件名

    yum erase -y 软件名

    5apt-get安装

    apt-get是deb的管理东西,类似yum

    apt-get install package 安装包

    apt-get reinstall package重新安装包

    apt-get upgrade 更新已安装的包

    apt-cache rdepends package 是查看该包被哪些包依赖

    apt-cache depends package 了解使用依赖

    apt-get clean &&apt-get autoclean 清算无用的包

    apt-cache show package 获取包的相关信息,如说明、巨细、版本等

    apt-get remove package 删除包

    apt-get purge package删除包,包孕删除配置文件等

    ---end----

  • jvisualvm的使用遇到的问题

    2011-12-20 19:00:58

    在多线程调试的时候用到了java的VisualVM工具,可能会遇到以下问题:

    在windows下由于以下原因会导致 Local Applications Cannot Be Detected (Error Dialog On Startup):
    1. Java程序缺少读写Windows的临时目录的权限
    2. Windows的临时目录是放在非NTFS分区(确切地说,是不支持ACL的分区)
    所以我们必须保证以下两点
    1. 重新授权,保证对Windows的临时目录有足够的权限
    2. 运行需要监控的Java程序时加上参数-XX:+PerfBypassFileSystemCheck

    连接到远程主机
    要从远程应用程序中检索数据,需要在远程 JVM 上运行 jstatd 实用程序。有关如何启动 jstatd 的更多信息 请参见 jstatd - Virtual Machine jstat Daemon(jstatd - 虚拟机 jstat 守护进程)。无法对远程主机上运行的应用程序进行性能分析。

    1需要在被监控的服务器上面,通过jstatd来启动RMI服务。新建个文件jstatd.all.policy 文件内容如下:
    grant codebase "file:${java.home}/../lib/tools.jar" {
    permission java.security.AllPermission;
    };

    2启动jstatd
    jstatd -J-Djava.security.policy=jstatd.all.policy &

    jstatd -J-Djava.security.policy=/home/admin/jstatd.java.policy -J-Djava.rmi.server.logCalls=true
    上面启动的RMI服务的端口是1099。启动通过:netstat -an|grep 8888可以查看端口是否已经被监听

    同时需要执行一个命令看看(linux需要):

    Hostname –i

    如果显示是127.0.0.1,则需要修改/etc/hosts文件,去掉对本机名的配置,让本机名解析到它的IP地址,如10.20.131.214


    3连接远程主机
    • 右键单击“应用程序”窗口中的“远程”节点,然后选择“添加远程主机”。
    • 在“添加远程主机”对话框中,键入远程计算机的主机名或 IP 地址。
    • (可选)键入远程主机的显示名称。此名称将显示在“应用程序”窗口中。如果没有输入显示名称,则在“应用程序”窗口中使用主机名标识远程主机。
    • 单击“确定”。

  • 转:什么是JMX

    2011-12-20 14:26:29

    一、什么是JMX

    JMX(Java Management Extensions)是一个为应用程序植入管理功能的框架。JMX是一套标准的代理和服务,实际上,用户可以在任何Java应用程序中使用这些代理和服务实现管理。

    JMX的前身是JMAPI。

    JMX致力于解决分布式系统管理的问题,因此,能够适合于各种不同的环境是非常重要的。为了能够利用功能强大的Java计算环境解决这一的问题,Sun公司扩充了Java基础类库,开发了专用的管理类库。

    JMX是一种应用编程接口,可扩充对象和方法的集合体,可以用于跨越一系列不同的异构操作系统平台、系统体系结构和网络传输协议,灵活的开发无缝集成的系统、网络和服务管理应用它提供了用户界面指导、Java类和开发集成系统、网络及网络管理应用的规范。

    管 理对象是JMX应用程序的核心。JMX结构包括:支持Java的Web浏览器用户接口,管理运行模块ARM(Admin Runtime Module)和应用。这三个部件之间通过RMI(Remote Method Invocation)进行通信。这里需要说明的是,RMI是使得一个Java虚拟机(JVM)上运行的程序可以调用远程服务器上另一个JVM总的对象。

    用户接口用来发布管理操作,这些操作可以间接的通过浏览器或通过单独的应用程序来激发。管理运行模块用来给应用提供实例化的管理对象。它包括Agent对象接口,通知接口和被管数据接口。应用指的是那些被管设备单元。

    JMX是一个完整的网络管理应用程序开发环境,它同时提供了:厂商需要收集的完整的特性清单,可生成资源清单表格,图形化的用户接口;访问SNMP的网络API;主机间远程过程调用;数据库访问方法。

    JMX这一轻型的管理基础结构,价值在于对被管理资源的服务实现了抽象,提供了低层的基本类集合,开发人员在保证大多数的公共管理类的完整性和一致性的前提下,进行扩展以满足特定网络管理应用的需要。

    JMX注重于构造管理工具的软件框架,并尽量采用已成熟的技术。

    JMX体系被分成三个层次

    。表现层
    。代理层
    。分布式服务层


    JMX框架

     基本概念

      JMX涉及到以下基本概念。

    MBean:暴露用来操作和访问被管资源的管理接口的java对象
    MBean Server:管理一组MBean的java类,类似一个查找Mbean的注册表,暴露出所有注册过的Mbean的管理接口,以及提供查找Mbean和通知监听器的方法。
    MBean Agent:提供管理MBean的服务的一个Java进程,是MBean Server的容器。提供这些服务:建立MBean关系、动态加载类、简单监控服务、定时器等。
     MBean Agent可以指望有一组协议适配器(Adaptor)或连接器(Connector),使远程客户和不同客户使用agent。协议适配器和连接器通常也是MBean。
    协议适配器(Adaptor)或连接器(Connector):在MBean Agent之中的一些对象,用来将Agent暴露给管理应用和协议。
    Adaptor和Connector区别: Adaptor通常要监听进来的信息,这些信息是在某个协议如HTTP或SNMP中构造的。在这个意义上,协议适配器在任何时间都存在于Agent中并只 有一个组件。Connector由两个组件组成,一个在Agent端,一个在客户端。客户使用客户端连接器组件和服务器端连接器组件联系并和Agent通 讯。

      下图为RMI Connector的两个组件通讯情况:
     

    管理应用:连接任意数量MBean Agent的用户应用。
     JMX Agent可以通过定制开发适配器或连接器,和一个非jmx管理应用进行交互。
    通知(Notification):由MBean或MBean Server发出的,封装了事件、警告和通用信息的Java对象。MBean或Java对象可以注册为监听者来接收通知。JMX的通知模型类似于Java的事件模型。
    设备(Instrumentation):使用MBean或一组MBean暴露管理资源的进程。
    管理应用(Manager Appliction):使用MBean的管理应用程序。

    JMX的三层架构

    分布层(Distributed Layer):包含了能使管理应用和JMX Agent通讯的组件
    代理层(Agent Layer):包含了Agents和MBean Server
    装备层(Instrument Layer):包含了可以代表可管理资源的MBean

    1、分布层:jmx的最外层,负责向外界提供jmx的agent。

      有两种类型的分布式交互(interaction),即建立一个连接(Connectin):
      1) 通过Adaptor获取的交互方式:通过不同的协议如HTTP,SNMP提供到MBean的可见性(visibility)。
      2) JMX Agent有Connector组件,将agent的API暴露给其他分布式技术,如RMI。

     
      当远程客户端通过Adaptor或Connector和Agent建立连接后,就可以和agent中注册的MBean进行交互。接着就进入了代理层。

    2、代理层:

    代理层的主要组件是MBean Server,作为MBean的登记处,是代理层的核心。
    代理层提供4个代理服务来更方便地管理MBean:定时器、监控、动态MBean 加载、关系服务。
    代理层提供从管理应用到被管理资源的访问。
    Jmx代理可以运行在管理资源的机器上的JVM中,也可以位于在远程。agent不需要知道它暴露出的资源的信息,或使用MBean的管理应用。
    agent担当了一个服务的角色,用来处理MBean,允许通过暴露出的Connector或Adaptor的一系列协议来操作MBean。

    3、装备层:离被管理资源最近的一层。由注册在Agent上的MBean组成。

    每个MBean暴露一个底层资源的一块配置和功能,并通过一个Java对象来提供。如果底层资源不使用Java, 则MBean充当一个翻译器。
    MBean是一个轻量级的类,知道如何使用、获取操作其资源,并向agent和用户提供访问途径和功能。
     

    使用JMX作为应用程序架构:
     

      jmx 代理层用来构件应用很理想。MBean Server可以用作应用组件,如数据层、日志组件、事务管理器的骨架。

      使用这种架构,开发人员可以很容易地从服务器中增加、改变、删除应用服务。



    二、表现层

    表现层定义的是JMX可管理资源所在的层。

    这些已管理的资源可以编写或封装为MBean。

    MBean分为四种类型:
    标准、动态、开放、模型

    三、代理层

    定义的是MBean向应用程序施加管理的层。包括MBean服务器和代理服务的定义。还至少包括一个协议适配器或连接器。

    代理的组成:
    。一个MBean服务器
    。要管理的MBean
    。作为MBean实现的代理服务
    。至少一个协议适配器

    3.1 MBean

    在JMX中,最小的可管理单元是MBean。

    MBean不是一个真正的接口和类,而是必须准循的设计模式以确保资源是一个兼容的MBean。

    MBean的激活方法:

    invoke()方法是管理应用程序用于激活MBean的方法的手段。
    invoke()方法有三个参数,分别是方法的名称、表示属性的对象数组和描述方法签名的一个字符串数组。它与使用Java Reflection Api 激活方法的方式类似。

    Notification(通知)模型:

    MBean的通知模型类似与Java事件的监听器模型。
    MBean或管理应用程序可以作为MBean事件的监听器注册。
    通知支持由两个基本的概念组成,即广播器和监听器。

    3.2 MBean服务器

    MBean服务器用于注册可管理的MBean。

    所有对MBean的请求或查询都是通过MBean服务器实施的。

    3.3 代理服务

    代理服务是一些特殊的函数,代理把这些服务提供给MBean,这些代理服务独立于任何MBean。

    一个代理可以提供四种主要的服务:
    。动态装载:允许代理通过下载这个Bean的类动态实例化MBean,这与装载applet的方式类似。
    JMX使用m-let这个标记指定期望动态装载的MBean的位置。
    。监控:允许代理通知有关的监听器监控一个MBean的属性值的变化
    JMX允许使用三种基本类型的监控程序
    (1)CounterMonitor:该程序可以观察类型方面的变化,比如Byte类似或Integer类型
    (2)GaugeMonitor:该程序可以观察类型方面的变化,比如Byte类似或Integer类型,还可以在到达上下阀值时进行报告。
    (3)StringMonitor:该程序可以观察java.lang.String类型的变化。
    。计时器:允许预设的时间间隔发送通知,可以作为一个调度程序
    。关系:允许创建和维护MBean之间的关系

    四、分布式服务层

    包含协议适配器和连接器两种类型的组件,通过它们连接到外部的应用,如RMI管理应用、基于浏览器的管理控制等

    五、协议适配器和连接器

    协议适配器是代理与管理客户通信的手段,每个通信的协议都可能不同。

    它们都是管理客户与MBean交互的方式。

    六、JMX的好处

    。可减少对JAVA应用实施管理的投资
    。提供了一个可伸缩的管理框架
    。集成现有的管理方案:如:WBEM,SNMP,TMN
    。使用现有的标准JAVA技术
    。能使用未来的一些管理概念:如Jini连接技术、通用即插即用、服务定位协议(Service Location Protocol)
    。只定义了一些可以访问的接口

    七、 Getting Started:简单MBean

      运行本文程序需要在JDK5.x环境下,并且要到 java.sun.com网站上去下载Sun的JDMK5.1(Java Dynamic Management Kit 5.1),下载后解压,将lib目录下的jdmktk.jar文件加到项目的类路径上即可(如果找不到,可以向我索取 chengy@primeton.com )。

      1. 定义接口4. 运行
    在IE中打入http://localhost:9092/

    1. package jmxbook.ch2;
    2.  
    3. public interface HelloWorldMBean {
    4. public void setGreeting(String greeting);
    5.  
    6. public String getGreeting();
    7.  
    8. public void printGreeting();
    9. }

    2. 编写Mbean实现类

    1. package jmxbook.ch2;
    2.  
    3. public class HelloWorld implements HelloWorldMBean {
    4. private String greeting=null;
    5.  
    6. public HelloWorld() {
    7. this.greeting="I'm a standard MBean";
    8. }
    9.  
    10. public HelloWorld(String greeting) {
    11. this.greeting=greeting;
    12. }
    13.  
    14. public String getGreeting() {
    15. return greeting;
    16. }
    17.  
    18. public void printGreeting() {
    19. System.out.println(greeting);
    20. }
    21.  
    22. public void setGreeting(String greeting) {
    23. this.greeting=greeting;
    24. }
    25. }

    3. 编写Agent

    1. package jmxbook.ch2;
    2.  
    3. import javax.management.MBeanServer;
    4. import javax.management.MBeanServerFactory;
    5. import javax.management.ObjectName;
    6. import com.sun.jdmk.comm.HtmlAdaptorServer;
    7.  
    8. public class HelloAgent {
    9. private MBeanServer server = null;
    10.  
    11. public HelloAgent() {
    12. server = MBeanServerFactory.createMBeanServer("HelloAgent");
    13.  
    14. HtmlAdaptorServer adapter = new HtmlAdaptorServer();
    15.  
    16. HelloWorld hw = new HelloWorld();
    17.  
    18. ObjectName adapterName = null;
    19. ObjectName mbeanName = null;
    20.  
    21. try {
    22. mbeanName = new ObjectName("HelloAgent:name=helloWrold");
    23. server.registerMBean(hw, mbeanName);
    24.  
    25. adapterName = new ObjectName(
    26. "HelloAgent:name=htmlAdaptor,port=9092");
    27. adapter.setPort(9092);
    28. server.registerMBean(adapter, adapterName);
    29. adapter.start();
    30.  
    31. } catch (Exception e) {
    32. e.printStackTrace();
    33. }
    34.  
    35. }
    36.  
    37. public static void main(String args[]) {
    38. System.out.println("HelloAgent is running");
    39. HelloAgent agent = new HelloAgent();
    40. }
    41. }

     说明:
    1) 区分Mbean: 使用ObjcetName对象,分两部分:1) 域名 2) key-value对列表
    如 HelloAgent:name=helloWorld

    两个ObjectName的相等:
    ObjectName objName1=new ObjectName(“HelloAgent:name=helloWorld,type=typeA”);
    ObjectName objName2=new ObjectName(“HelloAgent: type=typeA,name=helloWorld”);

    则objName1.equals(objName2)返回true.

    2) ObjectName冲突: MBean Server注册两个相同ObjectName的MBean会抛出异常.

    5.使用html客户端访问jmx agent:

    1) Agent View: 显示所有注册的MBean
     
    2) MBean View: 显示一个MBean信息
     
    3) Admin View: 管理MBean,注册和取消注册MBean
     

      输入key和java className, action选择Constrctors, 可以查看类的构造函数列表(需要MBean的接口命名为  名称+MBean, 如HelloWorldMBean), 输入构造函数的参数(有的话),按create可以建立新的MBean并注册到agent.
     

    四.使用通知:

      jmx可以使用通知机制,从一个MBean发送通知给另一个MBean,如下图:

     
    使用通知的步骤如下:
    1) 建立通知发送者:
    两种方式:
    (1) 实现javax.management.NotificationBroadcaster接口
    (2) 扩展 javax.management.NotificationBroadcasterSupport类

    改造HelloWorld.java

    1. package jmxbook.ch2.notification;
    2.  
    3. import javax.management.Notification;
    4. import javax.management.NotificationBroadcasterSupport;
    5.  
    6. public class HelloWorld extends NotificationBroadcasterSupport
    7. implements HelloWorldMBean {
    8. public HelloWorld() {
    9. this.greeting = "I'm a Notification Sender";
    10. }
    11.  
    12. public HelloWorld(String greeting) {
    13. this.greeting = greeting;
    14. }
    15.  
    16. public void setGreeting(String greeting) {
    17. this.greeting = greeting;
    18. Notification notification = new Notification(
    19. "jmxbook.ch2.helloWorld.test", this, -1, System
    20. .currentTimeMillis(), greeting);
    21. sendNotification(notification);
    22. }
    23.  
    24. public String getGreeting() {
    25. return greeting;
    26. }
    27.  
    28. public void printGreeting() {
    29. System.out.println(greeting);
    30. }
    31.  
    32. private String greeting;
    33. }


     2) 建立通知接收者:
    接口: MyListenerMBean.java:

    1. package jmxbook.ch2.notification;
    2.  
    3. import javax.management.NotificationListener;
    4.  
    5. public interface MyListenerMBean extends NotificationListener {
    6. public void printInfo(String message);
    7. }


    实现类: MyListener.java

    1. package jmxbook.ch2.notification;
    2.  
    3. import javax.management.Notification;
    4.  
    5. public class MyListener implements MyListenerMBean {
    6.  
    7. public void printInfo(String message) {
    8. System.out.println(message);
    9. }
    10.  
    11. public void handleNotification(Notification notification, Object handback) {
    12. this.printInfo("My listener recieve Nofitication: " + notification.getType() + " "
    13. + notification.getMessage());
    14. }
    15. }

    3) 改造HelloAgent:

    1. package jmxbook.ch2.notification;
    2.  
    3. import javax.management.*;
    4. import com.sun.jdmk.comm.HtmlAdaptorServer;
    5.  
    6. public class HelloAgent implements NotificationListener {
    7. private MBeanServer mbs = null;
    8.  
    9. public HelloAgent() {
    10. mbs = MBeanServerFactory.createMBeanServer("HelloAgent");
    11. HtmlAdaptorServer adapter = new HtmlAdaptorServer();
    12.  
    13. HelloWorld hw = new HelloWorld();
    14. ObjectName adapterName = null;
    15. ObjectName helloWorldName = null;
    16. try {
    17. adapterName = new ObjectName(
    18. "HelloAgent:name=htmladapter,port=9092");
    19. mbs.registerMBean(adapter, adapterName);
    20. adapter.setPort(9092);
    21. adapter.start();
    22.  
    23. MyListener listener = new MyListener();
    24. mbs.registerMBean(listener, new ObjectName(
    25. "HelloAgent:name=myListener"));
    26.  
    27. helloWorldName = new ObjectName(
    28. "HelloAgent:name=helloWorld,notification=yes");
    29. mbs.registerMBean(hw, helloWorldName);
    30. hw.addNotificationListener(this, null, null);
    31. hw.addNotificationListener(listener, null, null);
    32. } catch (Exception e) {
    33. e.printStackTrace();
    34. }
    35. }// constructor
    36.  
    37. public void handleNotification(Notification notif, Object handback) {
    38. System.out.println("My listener recieve Nofitication: "
    39. + notif.getType() + " " + notif.getMessage());
    40. }
    41.  
    42. public static void main(String args[]) {
    43. HelloAgent agent = new HelloAgent();
    44. System.out.println("HelloAgent is running");
    45. }
    46. }

    4) 运行:
    调用HelloWorld的greeting(“Can I help you?”)方法, 控制台显示:
    Agent recieve Nofitication: jmxbook.ch2.helloWorld.test Can I help you?
    My listener recieve Nofitication: jmxbook.ch2.helloWorld.test Can I help you?

    五.使用RMI Connector:

    1) 改造Agent:

    1. package jmxbook.ch3;
    2.  
    3. import com.sun.jdmk.comm.*;
    4. import javax.management.*;
    5.  
    6. public class JMXBookAgent {
    7. private MBeanServer server = null;
    8.  
    9. public JMXBookAgent() {
    10. System.out.println("/n/tCREATE the MBeanServer.");
    11. server = MBeanServerFactory.createMBeanServer("JMXBookAgent");
    12. startHTMLAdapter();
    13. startRMIConnector();
    14. }
    15.  
    16. protected void startHTMLAdapter() {
    17. HtmlAdaptorServer adapter = new HtmlAdaptorServer();
    18. ObjectName adapterName = null;
    19. try {
    20. adapter.setPort(9092);
    21. adapterName = new ObjectName("JMXBookAgent:name=html,port=9092");
    22. server.registerMBean(adapter, adapterName);
    23. adapter.start();
    24. } catch (Exception e) {
    25. ExceptionUtil.printException(e);
    26. System.out.println("Error Starting HTML Adapter for Agent");
    27. }
    28. }
    29.  
    30. protected void startRMIConnector() {
    31. RmiConnectorServer connector = new RmiConnectorServer();
    32. ObjectName connectorName = null;
    33. try {
    34. connector.setPort(2099);
    35. connectorName = new ObjectName("JMXBookAgent:name=RMIConnector");
    36. server.registerMBean(connector, connectorName);
    37. connector.start();
    38. } catch (Exception e) {
    39. ExceptionUtil.printException(e);
    40. }
    41. }
    42.  
    43. public static void main(String[] args) {
    44. System.out.println("/n~~~~~~~~~~~~~~~~~~~~~~~"
    45. + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    46. System.out.println("/n>>> START of JMXBook Agent");
    47. System.out.println("/n>>> CREATE the agent...");
    48. JMXBookAgent agent = new JMXBookAgent();
    49. System.out.println("/nAgent is Ready for Service.../n");
    50. }
    51. }


    2) 添加异常显示类

    1. package jmxbook.ch3;
    2.  
    3. import javax.management.*;
    4.  
    5. public class ExceptionUtil {
    6. public static void printException(Exception e) {
    7. System.out.println("-------[ Exception ]-------");
    8. e.printStackTrace();
    9. if (e instanceof MBeanException) {
    10. boolean hasEmbeddedExceptions = true;
    11. Exception embeddedExc = e;
    12. while (hasEmbeddedExceptions) {
    13. embeddedExc = ((MBeanException) embeddedExc)
    14. .getTargetException();
    15. System.out.println("-------[ Embedded Exception ]-------");
    16. embeddedExc.printStackTrace();
    17. if (!(embeddedExc instanceof MBeanException)) {
    18. hasEmbeddedExceptions = false;
    19. }
    20. }
    21. }
    22. }
    23. }

    3) RMI 工厂

    1. package jmxbook.ch3;
    2.  
    3. import com.sun.jdmk.comm.RmiConnectorAddress;
    4. import com.sun.jdmk.comm.RmiConnectorClient;
    5.  
    6.  
    7. public class RMIClientFactory {
    8. public static RmiConnectorClient getClient() {
    9. RmiConnectorClient client = new RmiConnectorClient();
    10. RmiConnectorAddress address = new RmiConnectorAddress();
    11. address.setPort(2099);
    12. System.out.println("/t/tTYPE/t= " + address.getConnectorType());
    13. System.out.println("/t/tPORT/t= " + address.getPort());
    14. System.out.println("/t/tHOST/t= " + address.getHost());
    15. System.out.println("/t/tSERVER/t= " + address.getName());
    16. try {
    17. client.connect(address);
    18. } catch (Exception e) {
    19. ExceptionUtil.printException(e);
    20. }
    21. return client;
    22. }
    23. }

    5) 建立RMI客户端:

    1. package jmxbook.ch3;
    2.  
    3. import javax.management.*;
    4. import jmxbook.ch2.*;
    5. import com.sun.jdmk.comm.*;
    6.  
    7. public class MBeanSetup {
    8. public MBeanSetup() {
    9. try {
    10. RmiConnectorClient client = RMIClientFactory.getClient();
    11. ObjectName hwName = new ObjectName("JMXBookAgent:name=helloWorld");
    12. client.createMBean("jmxbook.ch2.HelloWorld", hwName);
    13. client.invoke(hwName, "printGreeting", null, null);
    14. } catch (Exception e) {
    15. e.printStackTrace();
    16. }
    17. }
    18.  
    19. public static void main(String args[]) {
    20. MBeanSetup setup = new MBeanSetup();
    21. }
    22. }

    6) 运行:
    运行agent:

    1. java -cp ../lib/jdmkrt.jar;. jmxbook.ch3.JMXBookAgent
    2.  
    3. >>> START of JMXBook Agent
    4.  
    5. >>> CREATE the agent...
    6.  
    7. CREATE the MBeanServer.
    8.  
    9. Agent is Ready for Service...

    运行客户端:

    1. java -cp ../lib/jdmkrt.jar;. jmxbook.ch3.MBeanSetup
    2.  
    3. TYPE = SUN RMI
    4. PORT = 2099
    5. HOST = chengy
    6. SERVER = name=RmiConnectorServer
  • 使用JConsole监控进程、线程、内存、cpu、类情况

    2011-12-20 13:51:30

    Jconsole简介:

    Jconsole是一个JMX兼容的监视工具。它使用Java虚拟机的JMX机制来提供运行在Java平台的应用程序的性能与资源耗费信息。


    监控进程使用方法如下:
    由于JConsole监控需要使用JMX代理技术,因此在启动应用程序的参数中添加以下几个参数:
    -Djava.rmi.server.hostname=192.168.1.80
    -Dcom.sun.management.jmxremote.port=8089
    -Dcom.sun.management.jmxremote.ssl=false
    -Dcom.sun.management.jmxremote.authenticate=false

    配置完以上参数后,本地启动JConsole后,选择相应的进程名称,点击连接后,就可监控了。


    关于JMX的介绍:
    http://www.51testing.com/?uid-115295-action-viewspace-itemid-804845

    其他使用:

    Jconsole界面:

    Jconsole界面由以下六个选项卡组成:

    Summary选项卡:显示JVM和被监视值的汇总信息

    Memory选项卡:显示内存使用信息。

    Threads选项卡:显示线程使用信息。

    Classes选项卡:显示类(class)加载信息。

    MBeans选项卡:显示MBeans信息

    VM选项卡:显示JVM信息。

    以下是详细介绍:

    查看汇总信息:

    Summary选项卡显示了关于线程使用、内存消耗和class加载的一些关键监视信息,以及JVM和操作系统的信息。

    clip_image008

    Summary

    UptimeJVM已运行时长。

    Total compile time花费在即时编译(JIT compilation)中的时间。

    Process CPU timeJVM花费的总CPU时间。

    Threads

    Live threads当前活动的daemon线程加non-daemon线程数量。

    Peak自JVM启动后,活动线程峰值。

    Daemon threads当前活动的Daemon线程数量。

    Total started自JVM启动后,启动的线程总量(包括daemon,non-daemon和终止了的)

    Memory

    Current heap size堆(heap)占用的内存量,以K为单位。

    Committed memory为堆分配的内存总量

    Maximum heap size堆占用的最大内存量。

    Objects pending for finalization等待析构(finalization)的对象数量。

    Garbage collector informationGC信息,摆阔垃圾回收器名称,已执行的垃圾回收次数和执行垃圾回收总耗时。

    Classes

    Current classes loaded当前被加载到内存的classes数量

    Total classes loaded自JVM启动后被加载到内存的classes总量,包括后来卸载的。

    Total classes unloaded自JVM启动后,从内存卸载的classes总量。

    Operating System:

    Total physical memory物理内存总量

    Free physical memory物理内存空闲量

    Committed virtual memory为运行中的进程分配的虚拟内存总量

    监视内存消耗:

    Memory选项卡提供了内存消耗和内存池信息。

    clip_image010

    以上图表显示了JVM的内存使用和时间的对应关系,包括heap和non-heap内存以及指定的(specific)内存池。内存池种类与具体使用的JVM有关,以HotSpot JVM为例,内存池有:

    l Eden Space(heap):大多数对象初始化时从Eden Space池分配内存,即是存在于此池中

    l Survivor Space(heap):此池包含的对象是那些原先在eden space中,但是已经经历过垃圾回收而仍然存在的对象。

    l Tenured Generation(heap):在surviver space中已经存在了一段时间之后的对象会移动到这个池中。

    l Permanent Generation(non-heap):包含虚拟机自身的所有反射数据。比如class和mothod对象。对于使用class data sharing的JVM,这一代分为只读和读写两个区域。

    Code Cache (non-heap):HotSpot JVM也包含一个“代码缓存”,是编译和存储本地代码所占用的内存。

    查看关于内存池的详细信息:Garbage Collection.

    Detail区域显示了几种当前内存度量:

    lUsed当前使用的内存总量。使用的内存总量是指所有的对象占用的内存,包括可达和不可达的对象。

    lCommittedJVM可使用的内存量。Committed内存数量可能随时间变化而变化。JAVA虚拟机可能将某些内存释放,还给操作系统,committed内存可能比启动时初始分配的内存量要少。Committed内存总是大于等于used内存。

    lMax内存管理可用的最大内存数量。此值可能改变或者为未定义。如果JVM试图增加使用内存(used memory)超出了committed内存,那么即时使用内存小于或者等于最大内存(比如系统虚拟内存较低),内存分配仍可能失败。

    右下角的图表显示了内存池在heap和non-heap消耗的内存量。当内存使用超出了内存使用阀值时,柱状图会变红。你可以通过设置MemoryMXBean的一个属性来调整内存占用阀值。

    Heap and Non-heap内存

    JVM管理两种内存:heap和non-heap内存,两种内存都是在JVM启动时建立。

    Heap memory是运行时数据区域,用于JVM为所有对象实例和队列分配的内存。Heap可能为固定植或者可变值。垃圾收集器是一个用于回收对象占用的heap内存的自动化内存管理系统。

    Non-heap memory 包含一个在所有线程共享的方法区域(method area)和内部进程或JVM优化所需的内存。它存储了每一个类的结构,比如运行常量池,字段和方法数据,构造函数和方法的代码。方法区域逻辑上是 heap的一部分,但是依赖于实现,JVM可能不进行垃圾收集或压缩。像heap一样,方法区域可能为固定或可变大小。方法区域所需要的内存没有必要是连 续的。

    除了方法区域之外,一个JVM实现的内部进程或优化所需的内存也属于non-heap内存。比如JIT编译器为了提高性能而用于存储本地机器码所需的内存。

    内存池和内存管理

    内存池(Memory pools)和内存管理器是JVM内存管理系统的关键部分

    一个内存池(memory pool)代表JVM管理的一块内存区域。JVM拥有最少一个内存池,JVM在运行中可能创建或删除内存池。一个内存池可以属于heap内存或者non-heap内存。

    内存管理器(memory manager)管理一个或多个内存池。垃圾回收其是一种负责回收被不可打对象占用的内存的内存管理器。一个JVM可以拥有一个或者多个内存管理器。JVM在运行中可能增加或删除内存管理器。一个内存池可以被多于一个内存管理器管理。

    垃圾收集:

    垃圾收集(GC)是指JVM释放那些被无引用对象占用的内存空间。它通常认为那些有活动引用的对象是“活”对象,而那些没有引用或不可达的对象为“死”对象”。垃圾收集是释放被死对象占用的内存的过程。GC的算法和参数对性能有巨大的影响。

    HotSpot VM垃圾收集器使用 分代垃圾收集(generational garbage collection)。分代GC利用了大多数程序中,从经验看有如下特点:

    很多对象有一个很短的生存期(比如迭代器iterators、本地变量)

    某些对象拥有很长的生存期(比如高层持久化对象)

    所 以,分代的GC将内存划分为代(generations)并且赋予每一个内存池。当一代用尽了分配的内存,VM会在那个内存池进行一次局部 (partial)的垃圾收集(或者叫minor collection)来收集被死对象占用的内存。局部垃圾收集比全垃圾收集(full GC)快的多。

    HotSpot VM定义了2代:young generation (有时叫做nursery)和old generation。Young generation由一个eden space和两个survivor spaces组成。最初,VM将所有的对象放入eden space,大多数对象死在那里~~~,当VM运行了一次minor GC,VM将剩余的对象从eden space移动到某个survivor space中。然后VM将那些在survivor spaces中生存了足够长时间的对象移动到位于old generation中的tenured spaces。当tenured spaces满了以后,将发生一次full GC,full GC涉及到所有存活的对象,因此比较慢。Permanent generation保存了所有的虚拟机自身的反射数据,比如class和method objects

    默认情况下代的排列类似于下图:

    clip_image012

    如同下文链接中说明的,如果垃圾收集器成为瓶颈,你可以通过自定义代大小来提高性能。使用jconsole可以发现你的性能情况对垃圾收集器参数的敏感程度。详细情况见:

    Tuning Garbage collection with the 5.0 HotSpot VM

    监视线程使用:

    线程选项卡提供了关于线程使用的信息。

    clip_image014

    左下角列出的为所有的活动线程。如果你在过滤(filter)对话框输入字符串,那么线程列表将尽显示那些包含你输入字符串的线程。在线程列表上点击线程名,可以显示在右侧显示县城信息,包括线程名,状态和调用堆栈。

    图表显示了活动线程/时间。有三行内容:

    Magenta:线程总数

    Red:峰值线程数

    Blue:活动线程数。

    关于线程、daemon线程详细信息,请查看链接:java.lang.Thread

    监视Class加载:

    Classes选项卡显示了关于class loading的信息:

    clip_image016

    图表显示了 类加载/时间

    红线是类加载总数(包括后来卸载的)

    蓝线表示当前的类加载数量。

    选项卡底部的Detail节显示了自JVM启动后类加载的总量,当前加载量和卸载量。

    监视和管理MBeans:

    MBean选项卡显示了所有在platform. MBean server上注册的MBeans的信息。

    clip_image018

    左边的树形结构显示了所有的MBean,按其对象名排序。当在树种选择了一个MBean之后,其属性、操作、通知和其他信息会在右边显示。

    如果属性值是可写的(可写会蓝色显示),你可以设置属性值。你也可以调用在操作选项卡中显示的操作。

    显示图表:

    你可以通过双击属性值的方法显示一个属性值/时间图表,比如,如果你双击java.lang.GarbageCollector.Copy Mbean的CollectionTime属性,你会得到如下图所示的显示:

    clip_image020

    查看VM信息。

    VM选项卡提供了JVM的信息。

    clip_image022

    这些信息包括:

    Uptime:JVM启动后的总时间。

    Processes CPU Time:JVM启动后消耗的总CPU时间。

    Total Compile Time:即时编译(JIT compilation)消耗的总时间。JVM的具体实现决定JIT编译何时发生。Hotspot VM使用adaptive compilation,在这种方式zhogn ,VM使用标准的解释器(interpreter)运行一个应用程序,但是会分析其代码判断性能瓶颈或者”hot spots”。

    配置tomcat使用jconsole

    修改catalina脚本

    Windows平台:修改catalina.bat,在dorun和dostart段开头增加一行(注意是一行):

    set JAVA_OPTS=%JAVA_OPTS% -Djava.rmi.server.hostname=192.168.1.101

    -Dcom.sun.management.jmxremote

    -Dcom.sun.management.jmxremote.port="9004"

    -Dcom.sun.management.jmxremote.authenticate="false" -Dcom.sun.management.jmxremote.ssl="false"

    Unix/Linux平台:修改catalina.sh,在dorun和dostart段开头增加一行(注意是一行):

    JAVA_OPTS="$JAVA_OPTS "-Dcom.sun.management.jmxremote

    -Dcom.sun.management.jmxremote.port="9004"

    -Dcom.sun.management.jmxremote.authenticate="false" -Dcom.sun.management.jmxremote.ssl="false"

    启动jconsole

    启动tomcat之后,根据上文中的jconsole简介中的命令启动jconsole,如果是在服务器本地运行jconsole,会出现如下界面:

    clip_image023

    直接进行连接即可。

    如果是远程监控,需要点击远程选项卡并输入相关信息,示例如下:

    clip_image024

    “主机名或ip”处填写需要监视的主机ip,端口为服务器上上文中添加的-Dcom.sun.management.jmxremote.port="portNumber"设定的端口,本文以9004为例。在设定为:-Dcom.sun.management.jmxremote.authenticate="false" 的情况下,用户名和口令留空即可。

     

    如果需要使用JConsole远程监控 Tomcat可以在命令行直接输入:

    JConsole 192.168.1.101:9004

    进阶安全设定

    在上文中的配置适用于在测试环境中监视tomcat,如果是在生产环境中监视tomcat则需要在安全性上有进一步要求。

    配置jmx访问密码

    1. 修改上文中的catalina脚本中的JAVA_OPT参数,将
    -Dcom.sun.management.jmxremote.authenticate="false" 修改为:
    -Dcom.sun.management.jmxremote.authenticate="true"

    2. 将$JRE/lib/management/jmxremote.password.template文件在同目录下复制一份,重命名为$JRE/lib /management/jmxremote.password,编辑jmxremote.password,添加允许访问的用户名及密码,比如添加用户 zxwh,密码为zxme,则在文件尾添加一行:
    zxwh zxme
    注意用户密码不能包含空格,tab等字符

    3. 编辑$JRE_HOME/lib/management/jmxremote.access文件,对刚才添加的用户赋予一定的权限:
    zxwh readonly (或者readwrite)

    4. 确认jmxremote.password和jmxremote.access两个文件中的用户是相同的。注意如果jmxremote.access中没有对应用户的话,配置是无效的。
    注:以上配置文件的位置都是可以更改的,具体配置方法在此不再赘述。

    5. 由于jmxremote.password中的密码都是明文保存的,所以jmxremote.password、jmxremote.access文件的权限要注意,应该设置为只有owner才可读,当然这个用户也必须是启动tomcat的用户。

    6. 启动jconsole进行连接,在用户名和口令处输入设定的用户和密码。

    7. 使用密码认证方式进行连接,不但可以提高安全性,而且可以对用户的权限进行设置。如果不使用密码认证的方式,则无法对用户的权限进行限制。

    配置使用ssl进行加密连接

    1. 在服务器上使用keytool创建密钥对
    keytool是java平台自带的一个密钥和证书管理工具,使用keytool创建密钥对:
    keytool -genkey -alias tomcat -keystore /somepath/tomcatKeyStore
    按照提示输入相关信息(包括设定密码、姓、组织名等),这些信息是可以随便输入的,但从产品角度讲应该统一设定。输入的密码在今后操作中均需要使用。

    2. 导出公钥
    keytool -export -alias tomcat -keystore /somepath/tomcatKeyStore -file /somepath/jconsole.cert

    3. 将公钥导入至需要运行jconsole的机器。
    keytool –import –alias jconsole –keystore /somepath/jconsoleKeyStore -file /somepath/jconsole.cert

    4. 修改tomcat的catalina脚本
    将-Dcom.sun.management.jmxremote.ssl="false"修改为:
    -Dcom.sun.management.jmxremote.ssl="true",并在 JAVA_OPTS变量行添加:
    -Djavax.net.ssl.keyStore=/somepath/jconsoleKeyStore
    -Djavax.net.ssl.keyStorePassword=设定的密码

    5. 使用如下参数启动jconsole :
    jconsole -J-Djavax.net.ssl.trustStore=/somepath/jconsoleKeyStore

    6. 填入主机名、用户、口令连接服务器。

    其他问题

    1. 在执行shutdown.sh或者shutdown.bat脚本关闭tomcat时出现如下错误,tomcat无法关闭:
    错误: 代理抛出异常: java.rmi.server.ExportException: Port already in use: 9004;
    nested exception is:
    java.net.BindException: Address already in use: JVM_Bind


    其他分析参考:

    http://jiajun.iteye.com/blog/810150

    http://jingyan.baidu.com/article/215817f73a4f941edb14234f.html

    推荐使用升级版 JConsole 即 jvisualvm




  • 转:JDK自带VM分析工具jps,jstat,jmap,jconsole

    2011-12-20 10:28:22

    一、概述  
        SUN 的JDK中的几个工具,非常好用。秉承着有免费,不用商用的原则。以下简单介绍一下这几种工具。(注:本文章下的所有工具都存在JDK5.0以上版本的工具集里,同javac一样,不须特意安装)  。
         
        我一共找到以下四个工具:重点看看jconsole和jmap
    1.jps                
    .:与unix上的ps类似,用来显示本地的java进程,可以查看本地运行着几个java程序,并显示他们的进程号。                    

    2.jstat                
    .:一个极强的监视VM内存工具。可以用来监视VM内存内的各种堆和非堆的大小及其内存使用量。                    
                
    3.jmap                
    .:打印出某个java进程(使用pid)内存内的,所有‘对象’的情况(如:产生那些对象,及其数量)。                    
    4.jconsole                
    .:一个java GUI监视工具,可以以图表化的形式显示各种数据。并可通过远程连接监视远程的服务器VM。    
     
    二、 使用介绍: 
         
        1、jps :我想很多人都是用过unix系统里的ps命令,这个命令主要是用来显示当前系统的进程情况,有哪些进程,及其 id。 jps 也是一样,它的作用是显示当前系统的java进程情况,及其id号。我们可以通过它来查看我们到底启动了几个java进程(因为每一个java程序都会独 占一个java虚拟机实例),和他们的进程号(为下面几个程序做准备),并可通过opt来查看这些进程的详细启动参数。 
        使用方法:在当前命令行下打 jps(需要JAVA_HOME,没有的话,到改程序的目录下打) 。
    可惜没有linux下的ps好用,名称不好用。但是在第四个工具jconsole的界面里面会有具体JAR包的名称。
    /data/jdk1.6.0_06/bin/jps    
    6360 Resin
    6322 WatchdogManager
    2466 Jps

          
        2、jstat :对VM内存使用量进行监控。 
        jstat工具特别强大,有众多的可选项,详细查看堆内各个部分的使用量,以及加载类的数量。使用时,需加上查看进程的进程id,和所选参数。以下详细介绍各个参数的意义。 
        jstat -class pid:显示加载class的数量,及所占空间等信息。 
        jstat -compiler pid:显示VM实时编译的数量等信息。 
        jstat -gc pid:可以显示gc的信息,查看gc的次数,及时间。其中最后五项,分别是young gc的次数,young gc的时间,full gc的次数,full gc的时间,gc的总时间。 
        jstat -gccapacity:可以显示,VM内存中三代(young,old,perm)对象的使用和占用大小,如:PGCMN显示的是最小perm的内存使 用量,PGCMX显示的是perm的内存最大使用量,PGC是当前新生成的perm内存占用量,PC是但前perm内存占用量。其他的可以根据这个类推, OC是old内纯的占用量。 
        jstat -gcnew pid:new对象的信息。 
        jstat -gcnewcapacity pid:new对象的信息及其占用量。 
        jstat -gcold pid:old对象的信息。 
        jstat -gcoldcapacity pid:old对象的信息及其占用量。 
        jstat -gcpermcapacity pid: perm对象的信息及其占用量。 
        jstat -util pid:统计gc信息统计。 
        jstat -printcompilation pid:当前VM执行的信息。 
        除了以上一个参数外,还可以同时加上 两个数字,如:jstat -printcompilation 3024 250 6是每250毫秒打印一次,一共打印6次,还可以加上-h3每三行显示一下标题。 
         
       3、jmap 是一个可以输出所有内存中对象的工具,甚至可以将VM 中的heap,以二进制输出成文本。使用方法 jmap -histo pid。如果连用 SHELL jmap -histo pid>a.log可以将其保存到文本中去(windows下也可以使用),在一段时间后,使用文本对比工具,可以对比出GC回收了哪些对象。jmap -dump:format=b,file=f1 3024可以将3024进程的内存heap输出出来到f1文件里。 
         
        4、jconsole 是一个用java写的GUI程序,用来监控VM,并可监控远程的VM,非常易用,而且功能非常强。由于是GUI程序,这里就不详细介绍了,不会的地方可以参考SUN的官方文档。 
        使用方法:命令行里打 jconsole,选则进程就可以了。 
         
        友好提示:windows查看进程号,由于任务管理器默认的情况下是不显示进程id号的,所以可以通过如下方法加上。ctrl+alt+del打开任务管 理器,选择‘进程’选项卡,点‘查看’->''选择列''->加上''PID'',就可以了。当然还有其他很好的选项。
     
    实例:
    jmap -histo:live $pid
    jmap -histo $pid
    jstack -l $pid
     
    三、参考资料:
        article:http://elf8848.javaeye.com/blog/442806

        jps:http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/jps.html 

        jstat:http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/jstat.html 

        jmap:http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/jmap.html 

        jconsole:http://java.sun.com/j2se/1.5.0/docs/guide/management/jconsole.html
  • CMWAP和CMNET

    2011-12-18 14:25:55

    (1) 为什么会有两个接入点?

      在网上查阅大量资料后并经过反复的尝试与探索后,我大致对中国移动提供的这两种接入方式有了初步了解。
      在国际上,通常只有一种GPRS接入方式,为什么在中国会有CMWAP和CMNET两兄弟呢?(彩信之所以单独配置接入点是因为彩信服务需要连接专用的服务器,在这里不作探讨。)
      其实,CMWAP 和 CMNET 只是中国移动人为划分的两个GPRS接入方式。前者是为手机WAP上网而设立的,后者则主要是为PC、笔记本电脑、PDA等利用GPRS上网服务。它们在实现方式上并没有任何差别,但因为定位不同,所以和CMNET相比,CMWAP便有了部分限制,资费上也存在差别。

    (2) 什么是WAP?

      WAP只是一种GPRS应用模式,它与GRPS的接入方式是无关的。WAP应用采用的实现方式是“终端+WAP网关+WAP服务器”的模式,不同于一般Internet的“终端+服务器”的工作模式。主要的目的是通过WAP网关完成WAP-WEB的协议转换以达到节省网络流量和兼容现有WEB应用的目的。
      WAP网关从技术的角度讲,只是一个提供代理服务的主机,它不一定由网络运营商提供。但据我所知,中国移动GPRS网络目前只有唯一的一个WAP网关:10.0.0.172,有中国移动提供,用于WAP浏览(HTTP)服务。有一点需要注意,WAP网关和一般意义上的局域网网关是有差别的,标准的 WAP网关仅仅实现了HTTP代理的功能,并未完成路由、NAT等局域网网关的功能。这就决定了它在应用上所受到的限制。

    (3) 中国移动对CMWAP的限制

      为了从应用中区别两者的定位,中国移动对CMWAP作了一定的限制,主要表现在CMWAP接入时只能访问GPRS网络内的IP(10.*.*.*),而无法通过路由访问Internet。(少数地区的移动网络可能不存在这一限制。)我们用CMWAP浏览Internet上的网页就是通过WAP网关协议或它提供的HTTP代理服务实现的。
      说到这里,就让我自然而然的联想到我们公司的网络,相信不少工作的朋友都有类似的体会。公司的网络在网关上不提供路由和NAT,仅仅提供一个可以访问外网的HTTP代理。这样,我们就无法直接使用QQ、MSN等非HTTP协议的应用软件了(好在它们还提供的有HTTP代理的连接方式)。CMWAP也正是

    (4) 适用范围

      适用范围才是大家最关心的问题。CMNET拥有完全的Internet访问权,这里就不多说了,主要让我们来看看CMWAP。因为有了上面提到的限制,CMWAP的适用范围就要看WAP网关所提供的支持了。目前,中国移动的WAP网关对外只提供HTTP代理协议(80和8080端口)和WAP网关协议(9201端口)。(据有的网友提到1080端口也是开放的,但无法连接。这也许是移动内部使用的一个Socks后门吧^_^)。

      因此,只有满足以下两个条件的应用才能在中国移动的CMWAP接入方式下正常工作:
      1. 应用程序的网络请求基于HTTP协议。
      2. 应用程序支持HTTP代理协议或WAP网关协议。

    如何辨别一个应用程序的网络请求是否基于HTTP协议?

      这个问题还真不好回答,要完全做到这一点需要通过拦截应用程序的通信数据包进行分析。这里提供几个简单的方法给广大菜鸟朋友:从表现上看,如果它的网络请求是网址(URL)的形式,那么通常是基于HTTP协议的,如Web浏览器;如果它连接的服务器端口是80,那么它可能是基于HTTP协议的。如果确实无法准确判断,那么请直接看下一个条件。(满足第二个条件的应用一定是基于HTTP协议的)

    如何区别一个应用程序支持HTTP代理协议还是WAP网关协议呢?

      首先看它的设置中有没有代理服务器的选项(通常在S60上未特别说明的代理都是特指HTTP代理),如果有则表示它支持HTTP代理协议。如果没有,则需要按照以下步骤测试:
      在GPRS接入点设置的高级设置里去掉代理服务器的设置项:Server Address 和 Server Port(,如果应用程序可以正常工作,那么它是基于WAP网关协议,如Java程序、S60内置的浏览器。如果在此状态下不能正常工作,而恢复GPRS 接入点高级设置中的代理服务器设置后能够正常工作,则应用程序支持HTTP代理协议(代理设置从系统中读取)。如果仍不能正常工作,那么这个应用程序一般来说是不支持HTTP代理协议或WAP网关协议的。

      这里需要特别说明的是JavaQQ,它有Socket和HTTP两种版本。现在网上流传的可用于CMWAP的JavaQQ就是基于HTTP协议的。就拿那个JavaQQ 2004来说,启动画面中就明确的写着“KJava QQ HTTP”。而SIS版的QQ和AgileMessenger(S60的MSN客户端)因为是采用的普通的Socket连接方式,因此无法用于 CMWAP。

    要连接的url假设为:www.baidu.com/test.htm
    url改成10.0.0.172/test.htm
    然后在请求的head中添加x-online-host:www.baidu.com


    from:http://www.eoeandroid.com/forum-viewthread-tid-93645-highlight-cmwap.html

  • windows下通过vnc图形界面登陆linux

    2011-12-17 13:51:18

    键入下面的命令来检查vnc客户端和服务器是否已经安装在你的系统中:

    操作命令:

    rpm -q vnc vnc-server

    显示内容

    vnc-4.0-0.beta4.3.2

    vnc-server-4.0-0.beta4.3.2

    显示如上内容就可以不用安装了,否则要安装相应的软件,一般vnc-server是默认安装的,只需要安装vncrpm包就可以了,简单的一条命令就解决了:yum -y install vnc

    要把vnc配置成一项系统服务,把你的用户名称加入到下面的配置文件中:

    操作命令:

    vi /etc/sysconfig/vncservers

    显示内容

    # The VNCSERVERS variable is a list of display:user pairs.

    #

    # Uncomment the line below to start a VNC server on display :1

    # as my 'myusername' (adjust this to your own).   You will also

    # need to set a VNC password; run 'man vncpasswd' to see how

    # to do that.

    #

    # DO NOT RUN THIS SERVICE if your local area network is

    # untrusted!   For a secure way of using VNC, see

    # URL:http://www.uk.research.att.com/vnc/sshvnc.html

                                                                                                  

    # VNCSERVERS="1:myusername"

    VNCSERVERS="1:root"

    在启动vnc服务之前,用vncpasswd这个命令来创建一个vnc的口令

    注意这将同时在你的home目录下,创建一个隐藏的目录.vnc,其中有一个文件passwd保存着你的vnc口令.

    操作命令:

    vncpasswd

    显示

    Password:

    Verify:

    继续操作

    ls -d .vnc

    .vnc

    ls .vnc

    passwd

    现在来启动vnc服务

    service vncserver start

    察看一下.vnc这个目录的内容,应该类似于下面的东西.

    CODE:

    [tchung@tchung101 tchung]$ cd .vnc

    [tchung@tchung101 .vnc]$ ls

    passwd   tchung101:1.log   tchung101:1.pid   xstartup

    [tchung@tchung101 .vnc]$

    编辑/root/.vnc/xstartup的脚本,注意到下面红色的部分的注释

    注:.vnc是隐藏文件夹

    将这两行标记成红色的内容前面的注释符号去掉,否则你将只能得到一个什么都没有的灰屏。

    #!/bin/sh                                                                                              

    # Uncomment the following two lines for normal desktop:

    unset SESSION_MANAGER

    exec /etc/X11/xinit/xinitrc

                                                                                                   

    [ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup

    [ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources

    xsetroot -solid grey

    vncconfig -iconic &

    xterm -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &

    twm &

    因为已经修改了启动脚本,现在来重新启动vncserver.

    service vncserver restart

    照下面使用客户端的vncviewer命令.就会出现图形界面了

    vncviewer localhost:1

    VNC Viewer Free Edition 4.1.2 for X - built Mar 24 2009 19:53:14

    Copyright (C) 2002-2005 RealVNC Ltd.

    See http://www.realvnc.com for information on VNC.

    X connection to localhost:11.0 broken (explicit kill or server shutdown).

    如果出现如上界面,那么Xming没有打开

    安装Xming
    需要在本地Windows上运行一个X Server。选择有很多:Cygwin下的X Server恐怕是最著名的,但是为了这么一个小小的事情去安装一个“相对巨大”的Cygwin,似乎有些夸张;除了Cygwin,还有两个著名的商业软 件可以选用,Xwin32和Xmanager,上学期IC实验用的就是Xmanager,感觉很流畅很好用,不过,虽然Xmanager可以试用,但是终 究还是商业软件;还有一个选择,就是这里要讲的,开源软件Xming。

    Xming是一个配置简单而功能强大的开源X Server,可以运行在M$的XP/2003/Vista操作系统下。
    Xming的主页http://www.straightrunning.com/XmingNotes/
    Xming的SourceForge页面http://sourceforge.net/projects/xming/

    从SourceForge下载Xming-setup.exe,在本地安装。

    注意:安装这个Xming-mesa才可以,我安装Xming最后无法实现目标。
    第一次运行时使用开始菜单里面的XLaunch来启动,产生一个初始的配置文件。对于简单的使用来说,不需要任何特殊的配置,一切使用默认即可。Xming的具体配置和使用可以参考Xming的Manual
    启动完成后,在托盘区会出现一个“X”形状的图标,这表示Xming已经在运行了,将鼠标悬停上去,能看到当前使用的“Display number”。

    使用SSH,不需要作特别设置

    使用putty需要在Connection->SSH->X11下,勾选Enable X11 forwarding,在X display location处填写:localhost:0.

    注:以上操作都是在禁止的远程控制的机器的防火墙的情况下的



    windows下通过vnc图形界面登陆linux(转)

    VNC是由AT&T试验室开发,是一款优秀的远程控制工具软件,后来以GPL授权的形式开源。经过几年的发展,现在的VNC已经不单指某个软件,而是一类软件的通称。下面介绍Linux下常用的两个VNC软件。

    VNC的原理就是不停的对窗口界面截屏,再将图像传输给客户端,同时VNC服务器端接管服务器端的键盘、鼠标控制权,客户端可以通过服务器端操纵键盘鼠标。比较类似Windows下的pcAnywhere

     

    一、Windows 端设置

    先讲Windows端是因为,下述的两个VNC可以用同一个客户端连接。

    Windows平台上,客户端我选择了RealVNCRealVNC包括了一整套的服务器端与客户端,如果只安装客户端是不需要注册码的,其客户端程序名为vncviewer.exe,这是个绿色软件,你可以从安装目录下拷贝到其他电脑中运行。

     

    二、VINO

    VINOGnome中集成的一个VNC软件,安装Gnome环境时默认安装,点击系统”-“首选项”-“远程桌面就打开了其配置窗口。



    选中允许其他人查看您的桌面VINO就会启动服务器端进程vino-server,同时它监听TCP 5900端口。如果不选中允许其他用户控制您的桌面,客户端则只能观看不能操纵。

    VINO的模式与下面介绍的XVNC有很大不同,我觉得VINO其实是“Windows下的远程协助,因为客户端显示的桌面与Linux端本地显示器中显示的桌面一样,如果你操纵客户端中的鼠标,Linux的显示器也能看到鼠标在跑。如果你在Windows下安装过VNC服务器端,效果就是这个样。

    另外,VINO的带宽占用真是变态,就算是一进桌面什么都不打开无操作的情况下,带宽也要占到4-5Mbps(桌面1280×1024,色彩24),如果有操作会占到8-12Mbps

    所以,VINO不适合做为服务器的日常远程管理,比较适合做为Linux下的远程协助和远程教学,也就是说你遇到一个问题,求助高手,而高手可以手把手的教你,你可以直接观看屏幕学习,或者做故障重现,你在本地做故障或Bug重现,而工程师可以远程观看。

     

    三、XVNC

    XVNC就是大家所熟悉的vncvncserver,是由RealVNC公司开发的开源版的VNC软件。

     

    1、安装XVNC

    安装Linux时,可以从安装包中选中。若没有安装,可以从安装盘中找到。

    服务器的组件名叫 vnc-server。请执行rpm -q vnc-server 这个指令。

    它的输出应该是package vnc-server is not installed 或类似vnc-server-4.0-11.el4

    假如服务器未被安装,请用这个指令来安装它:yum install vnc-server

     

    2、启动vncserver

    在终端中输入:

    vncserver :1 -geometry 1280x1024 –depth 24  注::11号窗口,-geometry指窗口分辨率,-depth指色彩数

    也可以简单的指定:

    vncserver :1  注:使用RealVNC的客户端,窗口分辨率与色彩数可以在客户端指定

    当你第一次启动vncserver时,会要求指定密码,该密码是VNC客户端连接时要输入。

    窗口可以从0开始指定,如果Linux本地端已经启用图形环境,则必须从1开始指定,因为窗口0X11占用。

     

    3、配置xstartup

    XVNC默认采用twm做为图形环境,如果你安装了KDEGnome也可以启动。

    vi ~/.vnc/xstartup

    显示如下内容:

    #!/bin/sh

     

    # Uncomment the following two lines for normal desktop:

    # unset SESSION_MANAGER

    # exec /etc/X11/xinit/xinitrc

     

    [ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup

    [ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources

    xsetroot -solid grey

    vncconfig -iconic &

    xterm -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &

    twm &

     

    最后一行twm &表示启动twm,修改成gnome-session &启动Gnome,修改成startkde &启动KDE

    如果Linux本地端已经启用GnomeKDE图形环境,当VNC客户端连接服务器后,可能会只显示灰屏,没有正常启用图形环境。查看~/.vnc下的日志时会提示错误:You are already running a session manager

    这时需要去掉xstartup文件中的

    # unset SESSION_MANAGER

    # exec /etc/X11/xinit/xinitrc

    这两行前的#,再重启vncserver。如果Linux本地端是init 3模式,则不需要修改这两行。

    vnc客户端连接服务器时显示的界面是英文的,主要是中文环境还没有装入,而且没有中文输入法。在# exec /etc/X11/xinit/xinitrc行后添加下面内容:

    export .UTF-8  注:启用中文环境

    scim –d  注:加载scim输入法

     

    4、关闭vncserver

    vncserver –kill :1  注:关闭窗口1,以此类推关闭窗口2就为:2

    当所有窗口都关闭vncserver服务就关闭了。

     

    5、客户端使用

    XVNC不仅支持vncview等客户端程序,还支持浏览器控制。

    浏览器直接输入地址http://IP:5800,就会启动Java客户端连接。

    窗口0占用TCP 5900端口(VNC客户端)TCP 5800端口(浏览器)

    窗口1占用TCP 5901端口(VNC客户端)TCP 5801端口(浏览器)

    窗口23以此类推。

     

    6、开机自启动vncserver

    上面的操作都是要先登录Linux端,然后手动启动vncserver服务后,才能使用VNC连接。如果你想开机自启动vncserver服务,必须这样做。

    先按上面的步骤启动一次vncserver,确保密码和xstartup文件都建立了。

    然后,vi /etc/sysconfig/vncservers,添加如下内容:

    VNCSERVERS="1:root 2:zhang 3:li"  注:123代表窗口,比如root用户用窗口1zhang用户用窗口2,这里的用户是指Linux中的正规的用户帐户

    VNCSERVERARGS[1]="-geometry 640x480 –depth 24"  注:为root用户指定分辨率和色彩数,这里的[1]指上面的“1:root”

    VNCSERVERARGS[2]="-geometry 640x480 –depth 16"  注:为zhang用户指定分辨率和色彩数

    VNCSERVERARGS[3]="-geometry 800x600"

    注:上面的这三行可以不添加,由vnc客户端自行控制分辨率和色彩。上面的rootzhangli用户必须确保密码和xstartup文件都建立了,你可以分别登录先执行一次vncserver :1

    最后,执行/sbin/chkconfig vncserver on指令。

     

    7、安全

    XVNC的数据传输都是明文的,因涉及服务器的管理,使用明文是不可接受的。

    我们可以使用SSH加密VNC数据。

    首先,开启Linux端的SSH服务。

    第二,在Windows端下载一个SSH telnet工具。推荐的有PuTTySecureCRT

    第三,启用SSH隧道。下面以SecureCRT为例,PuTTy操作类似。

    先建立一个连接到Linux端的普通SSH会话。

    在该会话选项中端口转发中,添加本地端口转发属性


    见右图中,在本地中输入一个端口,这里选择了5901,也可以选择5801或其他端口,只要不与本地的服务相冲突,这个本地端口与Linuxvncserver监听的窗口端口无关,在远程中输入5901,这个端口是Linux端的vncserver监听的端口,这里是启动窗口1,如果启动窗口2则这里要输入5902。确定。

    设置完后,在SecureCRT中启动与LinuxSSH会话,正确登录Linux后。打开vncviewer


    VNC服务器中输入:localhost:5901(这里的端口就是上面指定的本地端口,而非Linux端的端口),因为这里要连接的是本地的SecureCRT启动的SSH隧道。在VNC运行过程中SecureCRT不能关闭。

    这样,在Linux端的防火墙就可以只开放SSH端口,关闭掉有关VNC的所有端口。
  • Jboss启用http压缩

    2011-12-12 19:09:12

    HTTP 压缩可以大大提高 浏览网站的速度,它的原理是,在客户端请求网页后,从服务器端将网页文件压缩,再下载到客户端,由客户端的浏览器负责解压缩并浏览。相对于普通的浏览过程 HTML ,CSS,Javascript. , Text ,它可以节省40%左右的流量。更为重要的是,它可以对动态生成的,包括CGI、PHP , JSP , ASP , Servlet,SHTML等输出的网页也能进行压缩,压缩效率惊人。
    下面是启用压缩的配置 内容可以看出,要使用gzip压缩功能,你可以在Connector实例中加上如下属性即可
    1) compression="on" 打开压缩功能
    2) compressionMinSize="2048" 启用压缩的输出内容大小,这里面默认为2KB
    3) noCompressionUserAgents="gozilla, traviata" 对于以下的浏览器,不启用压缩 
    4) compressableMimeType="text/html,text/xml" 压缩类型
     < Connector  port ="80"  maxHttpHeaderSize ="8192" 
                     maxThreads ="150"  minSpareThreads ="25"  maxSpareThreads ="75" 
                     enableLookups ="false"  redirectPort ="8443"  acceptCount ="100" 
                     connectionTimeout ="20000"  disableUploadTimeout ="true"  URIEncoding ="utf-8" 
                        compression ="on"  
                     compressionMinSize ="2048"  
                     noCompressionUserAgents ="gozilla, traviata"  
                     compressableMimeType ="text/html,text/xml,text/javascript,text/css,text/plain"    /> 
  • java内存溢出分析工具:jmap使用实战

    2011-12-08 16:33:11

    java内存溢出分析工具:jmap使用实战
    在一次解决系统tomcat老是内存撑到头,然后崩溃的问题时,使用到了jmap。
    1 使用命令
    在环境是linux+jdk1.5以上,这个工具是自带的,路径在JDK_HOME/bin/下
    jmap -histo pid>a.log

    2 输出结果摘要
    Size    Count   Class description
    -------------------------------------------------------
    353371288       9652324 char[]
    230711112       9612963 java.lang.String
    139347160       114865  byte[]
    76128096        3172004 java.util.Hashtable$Entry
    75782280        3157595 com.test.util.IPSeeker$IPLocation
    25724272        9115    java.util.Hashtable$Entry[]
    9319968 166428  org.apache.tomcat.util.buf.MessageBytes
    8533856 32889   int[]

    发现有大量的String和自定义对象com.test.util.IPSeeker$IPLocation存在,检查程序发现此处果然存在内存溢出。修改程序上线后再次用jmap抓取内存数据:

    146881712   207163  byte[]
    98976352    354285  char[]
    42595272    53558   int[]
    11515632    479818  java.util.HashMap$Entry
    9521896 59808   java.util.HashMap$Entry[]
    8887392 370308  com.test.bean.UnionIPEntry
    8704808 155443  org.apache.tomcat.util.buf.MessageBytes
    8066880 336120  java.lang.String

    内存溢出问题消除。
    注意:这个jmap使用的时候jvm是处在假死状态的,只能在服务瘫痪的时候为了解决问题来使用,否则会造成服务中断。
  • 两个JBoss 实例在一台机器上启动的端口配置

    2011-11-17 12:23:11

    经验证主要有以下几个地方需要改动,用来避免启动时的地址已经被绑定的异常。

    环境:JBoss 4.2.2GA,JDK 1.5

    1.   $JBoss_home/server/default/deploy/ejb3.deployer/META-INF/jboss-service.xml
         修改3873端口的值;
    2.   $JBoss_home/server/default/deploy/jboss-web.deployer/server.xml
         修改8080,8009,8443端口值。
    3.   $JBoss_home/server/default/conf/jboss-service.xml
         修改8083,1098,1099,4444,4445,4446端口值
    4.   $JBoss_home/server/default/conf/jboss-minimal.xml
         修改1099端口值,与3中保持一致。
    5.   $JBoss_home/server/default/deploy/jms/uil2-service.xml
         修改8093端口值。
  • 转:美国企业家发布中国创业报告:丑网站表现更好

    2011-11-01 20:10:19

    http://tech.sina.com.cn/i/2011-11-01/10046258797.shtml

    新浪科技讯 北京时间11月1日早间消息,美国企业家盖博伟(Bowei Gai,音译)周一发布了一份名为《中国创业报告》的文档,对他所调查的中国科技创业环境进行了介绍。

      盖博伟去年将他最新创办的一家名为CardMunch的名片读取移动应用卖给了LinkedIn。他上月来到中国对创业环境进行调查,希望了解这里是否存在适合硅谷企业家和投资者的机会。

      他周一将《中国创业报告》发布到幻灯片分享网站Slideshare后,迅速成为该网站第二受欢迎的幻灯片。

      以下为《中国创业报告》内容摘要:

      - 竞争白热化。在美国,一个好创意可能会吸引几个模仿者。但在中国,却几乎达到毫无节制的地步。有传言 称,模仿Groupon的中国团购网站达到5000家,而且至少有100个不同的Android商店。为了在竞争中胜出,很多企业甚至会采用恶意策略,包 括雇人在竞争对手的网站上发布负面评论,或窃取知识产权。

      - 中国用户的体验与美国截然不同。中国部分网民从来没有看过电子邮件,因为他们的整个生活都依靠QQ。

      - 在中国创办公司是一场“噩梦”。如果你是一家外国公司,并希望通过美国基金融资,就必须要在不同国家设立一系列子公司,从而实现资金流转,并获得运营牌照。如果要为员工授予股票期权,还要建立一些信托。

      - 创业技术环境落后。像亚马逊(微博)网络服务、Heroku或谷歌Apps这样可靠的云计算基础设施在中国很少,你必须要亲自托管所有内容,而开发者的技术也落后一代。

      - 创业公司花很多钱租办公室。多数中国技术人员仍然倾向于到大公司工作,并且更加看重现金,而非股权。所以如果创业公司没有宽敞漂亮的办公室,潜在应聘者就会认为前景暗淡,不会为他们工作。家庭式办公室和板房根本不在考虑之列。

      - 丑网站表现更好。按照西方标准来看,多数中文网站都很丑,而且很拥挤。但测试显示,这些网站的广告转化率和点进率却高于干净整洁的Web 2.0网站,后者更受美国市场青睐。

      - 外部天使投资人没有机会。没有人会相信自己圈子外的人,唯一的办法就是充分融入这一文化。

      除此之外,盖博伟还表示,创业者有必要亲自到中国去了解情况,但必须要懂得或学习中文,并把重点放在北京(这里的创业公司数量是排名第二的上海的10倍),并将美国人的傲慢丢到一边。(书聿)

      附:美国企业家盖博伟《中国创业报告》全部幻灯片

    1、中国创业报告1、中国创业报告
    2、作者自我介绍,生于中国、幼时移居美国,曾在HP、AMD、甲骨文就职2、作者自我介绍,生于中国、幼时移居美国,曾在HP、AMD、甲骨文就职
    3、为什么是“中国”3、为什么是“中国”
    4、巨大的市场:13亿人,一半城市人口4、巨大的市场:13亿人,一半城市人口
    5、中美市场对比5、中美市场对比
    6、超富新星:53万百万富翁6、超富新星:53万百万富翁
    7、互联网第一梯队7、互联网第一梯队
    8、互联网文化:有一些基本法则并不适用于此地8、互联网文化:有一些基本法则并不适用于此地
    9、7成互联网用户在30岁以下;没有为实物和游戏以外的服务付费的习惯9、7成互联网用户在30岁以下;没有为实物和游戏以外的服务付费的习惯
    10、竞争格局10、竞争格局
    11、在中国创业之难11、在中国创业之难
    12、人力成本较低12、人力成本较低
    13、北京成为创业中心13、北京成为创业中心
    14、天使投资/VC:钱多,对圈子以外的人信任少14、天使投资/VC:钱多,对圈子以外的人信任少
    15、创业精神:就业者更喜欢在大公司工作,而非一起创业15、创业精神:就业者更喜欢在大公司工作,而非一起创业
    16、如同他们不到结婚不离开家,创业团队往往30-40了还在孵化;办公地点要拿得出手,不然没人就职  16、如同他们不到结婚不离开家,创业团队往往30-40了还在孵化;办公地点要拿得出手,不然没人就职
    17、你的优势:来自硅谷的人会得到更多尊敬和重视17、你的优势:来自硅谷的人会得到更多尊敬和重视
    18、你的劣势:难解当地文化,缺少社会信任18、你的劣势:难解当地文化,缺少社会信任
    19、别在中国做天投,除非准备花大把时间研究市场19、别在中国做天投,除非准备花大把时间研究市场
    20、结论:进入中国市场就像建立你的第一家公司一样,因为不知接下来会发生什么20、结论:进入中国市场就像建立你的第一家公司一样,因为不知接下来会发生什么
    21、如果依旧要去:谦卑下来,学习中国文化,和中国团队合作21、如果依旧要去:谦卑下来,学习中国文化,和中国团队合作

  • 安装与配置(4.2.1 GA)

    2011-10-20 17:51:02

    一.             下载与安装JBoss

    在本文中,我们下载的JBoss版本为:4.2.1.GA

    下载地址:

    http://sourceforge.net/project/showfiles.php?group_id=22866&package_id=16942&release_id=523619

    在如上的下载页中下载JBoss-4.2.1.GA.zip文件。

    下载完成后,将其解压缩后即可完成安装,解压缩后将其放置到一个不带空格的目录(若目录带有空格,例如:C:"Program Files,日后可能会产生一些莫名的错误)egE:"JBoss4.2.1。同时在“环境变量设置”中设置名为JBOSS_HOME的环境变量,值为JBoss的安装路径,如下图所示:

    在此,JBoss的安装工作已经结束,可通过如下方式测试安装是否成功:

    运行JBoss安装目录"bin"run.bat,如果窗口中没有出现异常,且出现:字样,则表示安装成功。

    10:16:19,765 INFO [Server] JBoss (MX MicroKernel) [4.2.1.GA (build: SVNTag=JBoss_4_2_1_GA date=200707131605)] Started in 30s:828ms

    我们可以通过访问:http://localhost:8080进入JBoss的欢迎界面,点击JBoss Management下的JMX Console可进入JBoss的控制台。

    若启动失败,可能由以下原因引起:

    1)              JBoss所用的端口(8080109910988083等)被占用。一般情况下为8080端口被占用(例如,Oracle占用了8080端口),此时需要修改JBoss的端口,方法为进入JBoss安装目录"server"default"deploy"jboss-web.deployer目录,修改其下的server.xml目录,在此文件中搜索8080,将其改成你想要的端口即可(例如8088);

    2)              JDK安装不正确;

    3)              JBoss下载不完全。

    二.             JBoss的目录结构说明

    目录

    描述

    bin

    启动和关闭JBoss 的脚本(run.batwindows系统下的启动脚本,shutdown.batwindows系统下的关闭脚本)。

    client

    客户端与JBoss 通信所需的Java 库(JARs)。

    docs

    配置的样本文件(数据库配置等)。

    docs/dtd

    JBoss 中使用的各种XML 文件的DTD

    lib

    一些JARJBoss 启动时加载,且被所有JBoss 配置共享。(不要把你的库放在这里)

    server

    各种JBoss 配置。每个配置必须放在不同的子目录。子目录的名字表示配置的名字。JBoss 包含3 个默认的配置:minimialdefault all,在你安装时可以进行选择。

    server/all

    JBoss 的完全配置,启动所有服务,包括集群和IIOP

    server/default

    JBoss 的默认配置。在没有在JBoss 命令行中指定配置名称时使用。(我们下载的4.2.1版本默认采用此配置)

    server/default/conf

    JBoss 的配置文件。

    server/default/data

    JBoss 的数据库文件。比如,嵌入的数据库,或者JBossMQ

    server/default /deploy

    JBoss 的热部署目录。放到这里的任何文件或目录会被JBoss 自动部署。EJBWAR EAR,甚至服务。

    server/default /lib

    一些JARJBoss 在启动特定配置时加载他们。(default minimial 配置也包含这个和下面两个目录。)

    server/default/log

    JBoss 的日志文件。

    server/default/tmp

    JBoss 的临时文件。

    三.             JBoss的配置

    1.       日志文件设置

    若需要修改JBoss默认的log4j设置,可修改JBoss安装目录"server"default"conf下的jboss-log4j.xml文件,在该文件中可以看到,log4j的日志输出在JBoss安装目录"server"default"log下的server.log文件中。对于log4j的设置,读者可以在网上搜索更加详细的信息。

    2.       web服务的端口号的修改

    这点在前文中有所提及,即修改JBoss安装目录"server"default"deploy"jboss-web.deployer下的server.xml文件,内容如下:

    <Connector port="8080" address="${jboss.bind.address}"    

             maxThreads="250" maxHttpHeaderSize="8192"

             emptySessionPath="true" protocol="HTTP/1.1"

             enableLookups="false" redirectPort="8443" acceptCount="100"

             connectionTimeout="20000" disableUploadTimeout="true" />

    将上面的8080端口修改为你想要的端口即可。重新启动JBoss后访问:http://localhost:新设置的端口,可看到JBoss的欢迎界面。

  • 转《人件》 精华版 为软件企业指明成功之路 为开发人员伸张权益

    2011-10-20 11:07:00

    http://blog.csdn.net/xabcdjon/article/details/6853758
  • mysql 8小时空闲后连接超时的问题

    2011-10-13 10:57:23

    近一段时间,部门同事反映在使用mysql的过程出现数据库连接问题

    应用程序和数据库建立连接,如果超过8小时应用程序不去访问数据库,数据库就断掉连接 。这时再次访问就会抛出异常,如下所示:

    java.io.EOFException
        at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:1913)
        at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2304)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2803)
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1573)
    ...

    查了一下发现应用程序和mysql数据库建立连接,如果超过8小时应用程序不去访问数据库,数据库就断掉连接 。这时再次访问就会抛出异常。

    关于mysql自动断开的问题研究结果如下,在mysql中有相关参数设定,当数据库连接空闲一定时间后,服务器就会断开等待超时的连接:
    1、相关参数,红色部分
    mysql> show variables like '%timeout%';
    +--------------------------+-------+
    | Variable_name            | Value |
    +--------------------------+-------+
    | connect_timeout          | 5     |
    | delayed_insert_timeout   | 300   |
    | innodb_lock_wait_timeout | 50    |
    | interactive_timeout      | 28800 |
    | net_read_timeout         | 30    |
    | net_write_timeout        | 60    |
    | slave_net_timeout        | 3600 |
    | wait_timeout             | 28800 |
    +--------------------------+-------+        
    同一时间,这两个参数只有一个起作用。到底是哪个参数起作用,和用户连接时指定的连接参数相关,缺省情况下是使用wait_timeout。我建议是将这两个参数都修改,以免引起不必要的麻烦。

    2、修改参数
    这两个参数的默认值是8小时(60*60*8=28800)。我测试过将这两个参数改为0,结果出人意料,系统自动将这个值设置为1。换句话说,不能将该值设置为永久。
    将这2个参数设置为24小时(60*60*24=604800)即可。
    set interactive_timeout=604800;
    set wait_timeout=604800;

    也可以修改my.cof,修改后重起mysql
    打开/etc/my.cnf,在属性组mysqld下面添加参数如下:
    [mysqld]
    interactive_timeout=28800000
    wait_timeout=28800000

    如果一段时间内没有数据库访问则mysql自身将切断连接,之后访问java访问连接池时对数据库的数据通道早就关闭了,因为dbcp连接池无法时时维护与数据库的连接关系,mysql5以后即使在dbcp配置中加入autoReconnect=true也没有效果。


    另外一种解决办法是,通过连接池在空闲时自动重新连接解决这个问题,如下是hibernate连接池的实现方法:

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- the proxool configuration can be embedded within your own application's.
    Anything outside the "proxool" tag is ignored. -->
    <something-else-entirely>
    <proxool>
    <!-- proxool别名 -->
    <alias>product</alias>
    <!-- 数据库连接Url -->
    <driver-url>jdbc:mysql://db:3306/product?useUnicode=true&amp;characterEncoding=utf8</driver-url>
    <!-- JDBC驱动名称 -->
    <driver-class>com.mysql.jdbc.Driver</driver-class>
    <!-- 数据库连接帐卿-->
    <driver-properties>
    <property name="user" value="chinawidth" />
    <property name="password" value="123456" />
    </driver-properties>
    <!-- proxool自动侦察各个连接状态的时间间隔(毫秒),侦察到空闲的连接就马上回撿超时的销歿-->
    <house-keeping-sleep-time>90000</house-keeping-sleep-time>
    <!-- 指因未有空闲连接可以分配而在队列中等候的最大请求数,超过这个请求数的用户连接就不会被接受 -->
    <maximum-new-connections>20</maximum-new-connections>
    <!-- 最少保持的空闲连接擿-->
    <prototype-count>3</prototype-count>
    <!-- 允许最大连接数,超过了这个连接,再有请求时,就排在队列中等候,最大的等待请求数由maximum-new-

    connections决定 -->
    <maximum-connection-count>20</maximum-connection-count>
    <!-- 最小连接数 -->
    <minimum-connection-count>3</minimum-connection-count>
    <!-- 在分配连接前后是否进行有效性测试,这个是解决本问题的关钿-->
    <test-before-use>true</test-before-use>
    <test-after-use>true</test-after-use>
    <!-- 用于测试的SQL语句 -->
    <house-keeping-test-sql>SELECT CURRENT_USER</house-keeping-test-sql>
    </proxool>
    </something-else-entirely>


  • Log4j具体输出信息级别配置方法

    2011-10-12 13:03:55

    1. 配置文件
    Log4J配置文件的基本格式如下:

    #配置根Logger
    log4j.rootLogger 
    =   [ level ]   ,  appenderName1 ,  appenderName2 ,
     …

    #配置日志信息输出目的地Appender
    log4j.appender.appenderName 
    =
     fully.qualified.name.of.appender.class 
      log4j.appender.appenderName.option1 
    =
     value1 
      … 
      log4j.appender.appenderName.optionN 
    =
     valueN 

    #配置日志信息的格式(布局)
    log4j.appender.appenderName.layout 
    =
     fully.qualified.name.of.layout.class 
      log4j.appender.appenderName.layout.option1 
    =
     value1 
      … 
      log4j.appender.appenderName.layout.optionN 
    =  valueN 


    其中 [level] 是日志输出级别,共有5级:


    FATAL      0  
    ERROR     
    3
     
    WARN      
    4
     
    INFO      
    6
     
    DEBUG     
    7


    Appender 为日志输出目的地,Log4j提供的appender有以下几种:


    org.apache.log4j.ConsoleAppender(控制台),
    org.apache.log4j.FileAppender(文件),
    org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
    org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),
    org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)


    Layout:日志输出格式,Log4j提供的layout有以下几种:


    org.apache.log4j.HTMLLayout(以HTML表格形式布局),
    org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
    org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
    org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)


    打印参数: Log4J采用类似C语言中的printf函数的打印格式格式化日志信息,如下:


      %m   输出代码中指定的消息
      %p   输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL 
      %r   输出自应用启动到输出该log信息耗费的毫秒数 
      %c   输出所属的类目,通常就是所在类的全名 
      %t   输出产生该日志事件的线程名 
      %n   输出一个回车换行符,Windows平台为“\r\n”,Unix平台为“\n” 
      %d   输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss
    , SSS},输出类似:2002年10月18日  22 10 28 921
     
      %l   输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:
    10


    2. 在代码中初始化Logger:
    1)在程序中调用BasicConfigurator.configure()方法:给根记录器增加一个ConsoleAppender,输出格式通过PatternLayout设为"%-4r [%t] %-5p %c %x - %m%n",还有根记录器的默认级别是Level.DEBUG.
    2)配置放在文件里,通过命令行参数传递文件名字,通过PropertyConfigurator.configure(args[x])解析并配置;
    3)配置放在文件里,通过环境变量传递文件名等信息,利用log4j默认的初始化过程解析并配置;
    4)配置放在文件里,通过应用服务器配置传递文件名等信息,利用一个特殊的servlet来完成配置。

    3. 为不同的 Appender 设置日志输出级别:
    当调试系统时,我们往往注意的只是异常级别的日志输出,但是通常所有级别的输出都是放在一个文件里的,如果日志输出的级别是BUG!?那就慢慢去找吧。
    这时我们也许会想要是能把异常信息单独输出到一个文件里该多好啊。当然可以,Log4j已经提供了这样的功能,我们只需要在配置中修改AppenderThreshold
    就能实现,比如下面的例子:

    [配置文件]


    ### set log levels ###
    log4j.rootLogger
    = debug ,  stdout ,  D ,
     E

    ### 输出到控制台 ###
    log4j.appender.stdout
    =
    org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.Target
    =
    System.out
    log4j.appender.stdout.layout
    =
    org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern
    =  %d{ABSOLUTE} %5p %c{ 1
    }:%L - %m%n

    ### 输出到日志文件 ###
    log4j.appender.D
    =
    org.apache.log4j.DailyRollingFileAppender
    log4j.appender.D.File
    =
    logs/log.log
    log4j.appender.D.Append
    =
    true
    log4j.appender.D.Threshold
    =
    DEBUG ## 输出DEBUG级别以上的日志
    log4j.appender.D.layout
    =
    org.apache.log4j.PatternLayout
    log4j.appender.D.layout.ConversionPattern
    = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]
     %m%n

    ### 保存异常信息到单独文件 ###
    log4j.appender.D
    =
    org.apache.log4j.DailyRollingFileAppender
    log4j.appender.D.File
    =
    logs/error.log ## 异常日志文件名
    log4j.appender.D.Append
    =
    true
    log4j.appender.D.Threshold
    =
    ERROR ## 只输出ERROR级别以上的日志!!!
    log4j.appender.D.layout
    =
    org.apache.log4j.PatternLayout
    log4j.appender.D.layout.ConversionPattern
    = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n


    [代码中使用]


    public   class  TestLog4j  {
        
    public   static   void  main(String[] args) 
    {
            PropertyConfigurator.configure(
    " D:/Code/conf/log4j.properties "
    );
            Logger logger 
    =  Logger.getLogger(TestLog4j. class
    );
            logger.debug(
    " debug "
    );
            logger.error(
    " error "
    );
        }

    }


    运行一下,看看异常信息是不是保存在了一个单独的文件error.log中。


    4、对不同的包设置不同输出信息级别
    eg:
    打印OppenSessionInViewFilter中debug级别信息方法:
    log4j.logger.org.springframework.orm.hibernate3.support.OpenSessionInViewFilter=debug
    打印Struts标签中warn级别信息的方法:
    log4j.logger.org.apache.struts.util=WARN


    原理:
     Suppose   we   are   no   longer   interested   in   seeing   the   output   of   any   component   belonging   to   the   com.foo   package.   The   following   configuration   file   shows   one   possible   way   of   achieving   this.    
       
      log4j.rootLogger=DEBUG,   A1  
      log4j.appender.A1=org.apache.log4j.ConsoleAppender  
      log4j.appender.A1.layout=org.apache.log4j.PatternLayout  
       
      #   Print   the   date   in   ISO   8601   format  
      log4j.appender.A1.layout.ConversionPattern=%d   [%t]   %-5p   %c   -   %m%n  
       
      #   Print   only   messages   of   level   WARN   or   above   in   the   package   com.foo.  
      log4j.logger.com.foo=WARN

251/212>
Open Toolbar