posts - 23,  comments - 3,  trackbacks - 0
 
http://blog.csdn.net/watchnight/archive/2010/01/26/5258532.aspx

没有一个平台独立的方法能够在所有的JVM上实现。一个最简单、最接近取得PID的办法是使用:

ManagementFactory.getRuntimeMXBean().getName() 。

取得到的字符窜的格式为[PROCESS_ID]@[MACHINE_NAME],通过解析这个字符串就可以得到java进程的PID。

在以下平台上测试通过:

1、Windows、Linux上的Sun JDK1.5、JDK6

2、HP-UX上的JDK1.5、JDK6

3、Linux上的JRockit  R27.6



posted @ 2010-07-01 16:06 temper 阅读(1003) | 评论 (0)编辑 收藏
将jvm.dll拷贝到JavaService.exe所在目录(也可以通过设置path实现)
参照:http://forge.ow2.org/forum/forum.php?thread_id=2330&forum_id=625

ps:推荐通过设置path来实现,毕竟这样对用户和空间需求改动最小。
参照:http://www.tmro.net/2008/05/jboss-service-on-windows-server-2003/
posted @ 2010-06-25 14:28 temper 阅读(369) | 评论 (0)编辑 收藏

原文:http://roylone.blog.163.com/blog/static/378674132008816104325127/


一、相关概念


基本回收算法

  1. 引用计数(Reference Counting)
    比较古老的回收算法。原理是此对象有一个引用,即 增加一个计数,删除一个引用则减少一个计数。垃圾回收时,只用收集计数为0的对象。此算法最致命的是无法处理循环引用的问题。
  2. 标记-清除(Mark-Sweep)
    此算法执行分两阶段。第一阶段从引用根节点开始标记所 有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除。此算法需要暂停整个应用,同时,会产生内存碎片。
  3. 复制(Copying)
    此算法把内存空间划为两个相等的区域,每次只使用其中一个区域。垃 圾回收时,遍历当前使用区域,把正在使用中的对象复制到另外一个区域中。次算法每次只处理正在使用中的对象,因此复制成本比较小,同时复制过去以后还能进 行相应的内存整理,不过出现“碎片”问题。当然,此算法的缺点也是很明显的,就是需要两倍内存空间。
  4. 标记-整理(Mark-Compact)
    此算法结合了“标记-清除”和“复制”两个算法的 优点。也是分两阶段,第一阶段从根节点开始标记所有被引用对象,第二阶段遍历整个堆,把清除未标记对象并且把存活对象“压缩”到堆的其中一块,按顺序排 放。此算法避免了“标记-清除”的碎片问题,同时也避免了“复制”算法的空间问题。
  5. 增量收集(Incremental Collecting)
    实施垃圾回收算法,即:在应用 进行的同时进行垃圾回收。不知道什么原因JDK5.0中的收集器没有使用这种算法的。
  6. 分代(Generational Collecting)
    基于对对象生命周期分析后得出的 垃圾回收算法。把对象分为年青代、年老代、持久代,对不同生命周期的对象使用不同的算法(上述方式中的一个)进行回收。现在的垃圾回收器(从 J2SE1.2开始)都是使用此算法的。

分代垃圾回收详述


如上图所示,为Java堆中的各代分布。

  1. Young(年轻代)
    年轻代分三个区。一个Eden区,两个Survivor区。大部分对象在 Eden区中生成。当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当这个Survivor区满时,此区的存活对象将被复 制到另外一个Survivor区,当这个Survivor去也满了的时候,从第一个Survivor区复制过来的并且此时还存活的对象,将被复制“年老区 (Tenured)”。需要注意,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden复制过来 对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从第一个Survivor去过来的对象。而且,Survivor区总有一个是空 的。
  2. Tenured(年老代)
    年老代存放从年轻代存活的对象。一般来说年老代存放的都是生命期 较长的对象。
  3. Perm(持久代)
    用于存放静态文件,如今Java类、方法等。持久代对垃圾回收没有显著 影响,但是有些应用可能动态生成或者调用一些class,例如Hibernate等,在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增 的类。持久代大小通过-XX:MaxPermSize=<N>进行设置。

GC类型
GC有两种类型:Scavenge GC和Full GC
  1. Scavenge GC
    一般情况下,当新对象生成,并且在Eden申请空间失败时,就好触发Scavenge GC,堆Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区。然后整理Survivor的两个区。
  2. Full GC
    对整个堆进行整理,包括Young、Tenured和Perm。Full GC比Scavenge GC要慢,因此应该尽可能减少Full GC。有如下原因可能导致Full GC:
    • Tenured被写满
    • Perm域被写满
    • System.gc()被显示调用
    • 上一次GC之后Heap的各域分配策略动态变化


分代垃圾回收过程演示




二、垃圾回收器


目前的收集器主要有三种:串行 收集器、并行收集器、并发收集器

  1. 串行收集器

    使用单线程处理所有垃圾回收工作,因为无需多线程交互,所以效率比较高。但是,也 无法使用多处理器的优势,所以此收集器适合单处理器机器。当然,此收集器也可以用在小数据量(100M左右)情况下的 多处理器机器上。可以使用-XX:+UseSerialGC打开。
  2. 并行收集器
     
    1. 对年轻代进行并行垃圾回收,因此可以减少垃圾回收时间。一般在多线程多处理器机器上使用。使用-XX:+UseParallelGC. 打开。并行收集器在J2SE5.0第六6更新上引入,在Java SE6.0中进行了增强--可以堆年老代进行并行收集。如果年老代不使 用并发收集的话,是使用单线程进行垃圾回收,因此会制约扩展能力。使用-XX:+UseParallelOldGC打 开。
    2. 使用-XX:ParallelGCThreads=<N>设置并行垃圾回收的线程数。此 值可以设置与机器处理器数量相等
    3. 此收集器可以进行如下配置:
      • 最大垃圾回收暂停:指定垃圾回收时的最长暂停时间,通过-XX:MaxGCPauseMillis=<N>指 定。<N>为毫秒.如果指定了此值的话,堆大小和垃圾回收相关参数会进行调整以达到指定值。设定此值可能 会减少应用的吞吐量。
      • 吞吐量:吞吐量为垃圾回收时间与非垃圾回收时间的比值,通过-XX:GCTimeRatio=<N>来 设定,公式为1/(1+N)。例如,-XX:GCTimeRatio=19时,表示5%的时间用于垃圾回收。默认情况 为99,即1%的时间用于垃圾回收。
  3. 并发收集器
    可以保证大部分工作都并发进行(应用不停止),垃圾回收只暂停很少的时间,此收 集器适合对响应时间要求比较高的中、大规模应用。使用-XX:+UseConcMarkSweepGC打开。
     
    1. 并发收集器主要减少年老代的暂停时间,他在应用不停止的情况下使用独立的垃圾回收线程,跟踪可达对象。在每个年老代垃圾回收周期中,在收集初期并 发收集器会对整个应用进行简短的暂停,在收集中还会再暂停一次。第二次暂停会比第一次稍长,在此过程中多个线程同时进行垃圾回收工作。
    2. 并发收集器使用处理器换来短暂的停顿时间。在一个N个处理器的系统上,并发收集部分使用K/N个 可用处理器进行回收,一般情况下1<=K<=N/4
    3. 在只有一个处理器的主机上使用并发收集器,设置为incremental mode模式也可获得较短的停顿时间。
    4. 浮动垃圾:由于在应用运行的同时进行垃圾回收,所以有些垃圾可能在垃圾回收进行完成时产生,这样就 造成了“Floating Garbage”,这些垃圾需要在下次垃圾回收周期时才能回收掉。所以,并发收集器一般需要20%的 预留空间用于这些浮动垃圾。
    5. Concurrent Mode Failure:并发收集器在应用运行时进行收集,所以需要保证 堆在垃圾回收的这段时间有足够的空间供程序使用,否则,垃圾回收还未完成,堆空间先满了。这种情况下将会发生“并发模式失败”,此时整个应用将会暂停,进 行垃圾回收。
    6. 启动并发收集器:因为并发收集在应用运行时进行收集,所以必须保证收集完成之前有足够的内存空间供 程序使用,否则会出现“Concurrent Mode Failure”。通过设置-XX:CMSInitiatingOccupancyFraction=<N>指 定还有多少剩余堆时开始执行并发收集
  4. 小结
    • 串行处理器:
       --适用情况:数据量比较小(100M左右);单处理器下并且对响应时间无要求的应 用。
       --缺点:只能用于小型应用
    • 并行处理器:
       --适用情况:“对吞吐量有高要求”,多CPU、对应用响应时间无要求的 中、大型应用。举例:后台处理、科学计算。
       --缺点:应用响应时间可能较长
    • 并发处理器:
       --适用情况:“对响应时间有高要求”,多CPU、对应用响应时间有较高要 求的中、大型应用。举例:Web服务器/应用服务器、电信交换、集成开发环境。

三、常见配置举例
  1. 堆大小设置
    JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制;系统的可用虚拟内存限制;系统的可用物理内存限制。32位系统 下,一般限制在1.5G~2G;64为操作系统对内存无限制。我在Windows Server 2003 系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m。
    典型设置:
    • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k
      -Xmx3550m: 设置JVM最大可用内存为3550M。
      -Xms3550m: 设置JVM促使内存为3550m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。
      -Xmn2g:设置年轻代大小为2G。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为 64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
      -Xss128k: 设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内 存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。
    • java -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0
      -XX:NewRatio=4: 设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的 1/5
      -XX:SurvivorRatio=4:设置年轻代中 Eden区与Survivor区的大小比值。设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的 1/6
      -XX:MaxPermSize=16m:设置持久代大小为16m。
      -XX:MaxTenuringThreshold=0: 设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年 老代。对于年老代比较多的应用,可以提高效率。如果将此 值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年 轻代即被回收的概论。
  2. 回收器选择
    JVM给了三种选择:串行收集器、并行收集器、并发收集器, 但是串行收集器只适用于小数据量的情况,所以这里的选择主要针对并行收集器和并发收集器。默认情况下,JDK5.0以前都是使用串行收集器,如果想使用其 他收集器需要在启动时加入相应参数。JDK5.0以后,JVM会根据当前系统配置进行判断。
    1. 吞吐量优先的并行收集器
      如上文所述,并行收集器主要以到达一定的吞吐量为目标,适用于科学技术和后台 处理等。
      典型配置
      • java -Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20
        -XX:+UseParallelGC: 选择垃圾收集器为并行收集器。此配置仅对年轻代有效。即上述配置下,年轻代使用并发收集, 而年老代仍旧使用串行收集。
        -XX:ParallelGCThreads=20: 配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等。
      • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParallelOldGC
        -XX:+UseParallelOldGC: 配置年老代垃圾收集方式为并行收集。JDK6.0支持对年老代并行收集。
      • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC  -XX:MaxGCPauseMillis=100
        -XX:MaxGCPauseMillis=100:设 置每次年轻代垃圾回收的最长时间,如果无法满足此时间,JVM会自动调整年轻代大小,以满足此值。
      • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC  -XX:MaxGCPauseMillis=100 -XX:+UseAdaptiveSizePolicy
        -XX:+UseAdaptiveSizePolicy
        : 设置此选项后,并行收集器会自动选择年轻代区大小和相应的Survivor区比例,以达到目标系统规定的最低相应时间或者收集频率等,此值建议使用并行收 集器时,一直打开。
    2. 响应时间优先的并发收集器
      如上文所述,并发收集器主要是保证系统的响应时间,减少垃圾收集 时的停顿时间。适用于应用服务器、电信领域等。
      典型配置
      • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:ParallelGCThreads=20 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC
        -XX:+UseConcMarkSweepGC: 设置年老代为并发收集。测试中配置这个以后,-XX:NewRatio=4的配置失效了,原因不明。所以,此时年轻代大小最好 用-Xmn设置。
        -XX:+UseParNewGC:设 置年轻代为并行收集。可与CMS收集同时使用。JDK5.0以上,JVM会根据系统配置自行设置,所以无需再设置此值。
      • java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseConcMarkSweepGC -XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection
        -XX:CMSFullGCsBeforeCompaction: 由于并发收集器不对内存空间进行压缩、整理,所以运行一段时间以后会产生“碎片”,使得运行效率降低。此值设置运行多少次GC以后对内存空间进行压缩、整 理。
        -XX:+UseCMSCompactAtFullCollection:打开对年 老代的压缩。可能会影响性能,但是可以消除碎片
  3. 辅助信息
    JVM提供了大量命令行参数,打印信息,供调试使用。主要有以下一些:
    • -XX:+PrintGC
      输出形式:[GC 118250K->113543K(130112K), 0.0094143 secs]

                      [Full GC 121376K->10414K(130112K), 0.0650971 secs]

    • -XX:+PrintGCDetails
      输出形式:[GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs]

                      [GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured: 112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs]

    • -XX:+PrintGCTimeStamps -XX:+PrintGC:PrintGCTimeStamps可与上面两个混合使用
      输出形式:11.851: [GC 98328K->93620K(130112K), 0.0082960 secs]
    • -XX:+PrintGCApplicationConcurrentTime:打印每次垃圾回收 前,程序未中断的执行时间。可与上面混合使用
      输出形式:Application time: 0.5291524 seconds
    • -XX:+PrintGCApplicationStoppedTime:打印垃圾回收期间程序暂 停的时间。可与上面混合使用
      输出形式:Total time for which application threads were stopped: 0.0468229 seconds
    • -XX:PrintHeapAtGC:打印GC前后的详细堆栈信息
      输出形式:
      34.702: [GC {Heap before gc invocations=7:
       def new generation   total 55296K, used 52568K [0x1ebd0000, 0x227d0000, 0x227d0000)
      eden space 49152K,  99% used [0x1ebd0000, 0x21bce430, 0x21bd0000)
      from space 6144K,  55% used [0x221d0000, 0x22527e10, 0x227d0000)
        to   space 6144K,   0% used [0x21bd0000, 0x21bd0000, 0x221d0000)
       tenured generation   total 69632K, used 2696K [0x227d0000, 0x26bd0000, 0x26bd0000)
      the space 69632K,   3% used [0x227d0000, 0x22a720f8, 0x22a72200, 0x26bd0000)
       compacting perm gen  total 8192K, used 2898K [0x26bd0000, 0x273d0000, 0x2abd0000)
         the space 8192K,  35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00, 0x273d0000)
          ro space 8192K,  66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00, 0x2b3d0000)
          rw space 12288K,  46% used [0x2b3d0000, 0x2b972060, 0x2b972200, 0x2bfd0000)
      34.735: [DefNew: 52568K->3433K(55296K), 0.0072126 secs] 55264K->6615K(124928K)Heap after gc invocations=8:
       def new generation   total 55296K, used 3433K [0x1ebd0000, 0x227d0000, 0x227d0000)
      eden space 49152K,   0% used [0x1ebd0000, 0x1ebd0000, 0x21bd0000)
        from space 6144K,  55% used [0x21bd0000, 0x21f2a5e8, 0x221d0000)
        to   space 6144K,   0% used [0x221d0000, 0x221d0000, 0x227d0000)
       tenured generation   total 69632K, used 3182K [0x227d0000, 0x26bd0000, 0x26bd0000)
      the space 69632K,   4% used [0x227d0000, 0x22aeb958, 0x22aeba00, 0x26bd0000)
       compacting perm gen  total 8192K, used 2898K [0x26bd0000, 0x273d0000, 0x2abd0000)
         the space 8192K,  35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00, 0x273d0000)
          ro space 8192K,  66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00, 0x2b3d0000)
          rw space 12288K,  46% used [0x2b3d0000, 0x2b972060, 0x2b972200, 0x2bfd0000)
      }
      , 0.0757599 secs]
    • -Xloggc:filename:与上面几个配合使用,把相关日志信息记录到文件以便分析。
  4. 常见配置汇总
    1. 堆设置
      • -Xms:初始堆大小
      • -Xmx:最大堆大小
      • -XX:NewSize=n:设置年轻代大小
      • -XX:NewRatio=n:设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为 1:3,年轻代占整个年轻代年老代和的1/4
      • -XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。注 意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5
      • -XX:MaxPermSize=n:设置持久代大小
    2. 收集器设置
      • -XX:+UseSerialGC:设置串行收集器
      • -XX:+UseParallelGC:设置并行收集器
      • -XX:+UseParalledlOldGC:设置并行年老代收集器
      • -XX:+UseConcMarkSweepGC:设置并发收集器
    3. 垃圾回收统计信息
      • -XX:+PrintGC
      • -XX:+PrintGCDetails
      • -XX:+PrintGCTimeStamps
      • -Xloggc:filename
    4. 并行收集器设置
      • -XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数。并行收集线程数。
      • -XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间
      • -XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为 1/(1+n)
    5. 并发收集器设置
      • -XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况。
      • -XX:ParallelGCThreads=n:设置并发收集器年轻代收集方式为并行收集时,使 用的CPU数。并行收集线程数。

四、 调优总结
  1. 年轻代大小选择
    • 响应时间优先的应用尽可能设大,直到接近系 统的最低响应时间限制(根据实际情况选择)。在此种情况下,年轻代收集发生的频率也是最小的。同时,减少到达年老代的对 象。
    • 吞吐量优先的应用:尽可能的设置大,可能到达Gbit的程度。因为对响应时间没有要求,垃圾收集可 以并行进行,一般适合8CPU以上的应用。
  2. 年老代大小选择
    • 响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率会 话持续时间等一些参数。如果堆设置小了,可以会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较 长的收集时间。最优化的方案,一般需要参考以下数据获得:
      • 并发垃圾收集信息
      • 持久代并发收集次数
      • 传统GC信息
      • 花在年轻代和年老代回收上的时间比例
      减少年轻代和年老代花费的时间,一般会提高应用的效率
    • 吞吐量优先的应用:一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。原因是,这样可 以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象。
  3. 较小堆引起的碎片问题
    因为年老代的并发收集器使用标记、清除算法,所以不会对堆进行压缩。 当收集器回收时,他会把相邻的空间进行合并,这样可以分配给较大的对象。但是,当堆空间较小时,运行一段时间以后,就会出现“碎片”,如果并发收集器找不 到足够的空间,那么并发收集器将会停止,然后使用传统的标记、清除方式进行回收。如果出现“碎片”,可能需要进行如下配置:
    • -XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩。
    • -XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩
posted @ 2010-06-25 14:21 temper 阅读(154) | 评论 (0)编辑 收藏
http://blog.csdn.net/ai_33/archive/2008/06/10/2529096.aspx

关于中文文件下载的问题,网上的咨询和答疑已经很多,我原来处理下载的代码如下:
    
    response.setHeader("Content-Disposition", "attachment; filename=" + java.net.URLEncoder.encode(fileName, "UTF-8"));
 下载的程序里有了这句,一般在IE6的下载提示框上将正确显示文件的名字,无论是简体中文,还是日文。不过当时确实没有仔细测试文件名很长的中文文件名。先如今经过仔细测试,发现文字只要超过17个字,就不能下载了。经过好一番google和反复测试,总算对这个问题有了系统的认识,分列如下:

    . 通过我原来的方式,也就是先用URLEncoder编码,当中文文字超过17个时,IE6 无法下载文件。这是IE的bug,参见微软的知识库文章 KB816868 。原因可能是因为ie在处理 Response Header 的时候,对header的长度限制在150字节左右。而一个汉字编码成UTF-8是9个字节,那么17个字便是153个字节,所以便会报错。微软提供了一个补丁,可以从 这里 下载。这个补丁需要先安装ie6 sp1。因为我平时勤打补丁,我的IE6版本号是 6.0.2800.1106.xpsp2_xxxxx。所以我可能已经安装过了补丁,从而可以下载,但仍然出现文件名被截断的现象。微软让我们等待IE下一个service pack的发布。我今天也上网看到了好消息,迫于firefox的压力,IE7可能在年中发布。另外,Firefox 不支持这样的方式,将把编码后的%xx%xx直接作为文件名显示。


    . 我尝试使用 javamail 的MimeUtility.encode()方法来编码文件名,也就是编码成 =?gb2312?B?xxxxxxxx?= 这样的形式,并从 RFC1522 中找到对应的标准支持。不过很遗憾,IE6并不支持这一个标准。我试了一下,Firefox是支持的。

    . 按网上很多人提供的解决方案:将文件名编码成ISO8859-1似乎是有效的解决方案,代码如下:
    
    response.setHeader( "Content-Disposition", "attachment;filename="  + new String( fileName.getBytes("gb2312"), "ISO8859-1" ) );
    
    在确保附件文件名都是简体中文字的情况下,那么这个办法确实是最有效的,不用让客户逐个的升级IE。如果台湾同胞用,把gb2312改成big5就行。但现在的系统通常都加入了国际化的支持,普遍使用UTF-8。如果文件名中又有简体中文字,又有繁体中文,还有日文。那么乱码便产生了。另外,在我的电脑上Firefox(v1.0-en)下载也是乱码。

    折中考虑,我结合了一、三的方式,代码片断如下:

        String fileName = URLEncoder.encode(atta.getFileName(), "UTF-8");
        /*
         * see http://support.microsoft.com/default.aspx?kbid=816868
         */
        if (fileName.length() > 150) {
            String guessCharset = xxxx /*根据request的locale 得出可能的编码,中文操作系统通常是gb2312*/
            fileName = new String(atta.getFileName().getBytes(guessCharset), "ISO8859-1");
        }
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
        
    暂且不考虑 Firefox 是因为它目前似乎还没有有力侵食到IE的企业用户市场。影响客户买单的常常是进度,而不是兼容度。
posted @ 2009-05-08 17:30 temper 阅读(1350) | 评论 (0)编辑 收藏
曾经在系统中使用了一个从网上弄来的可编辑select,根据需要做了一些修改,在ie6下面运行正常。昨晚突然收到领导邮件说不好用。了解完才知道是在ie8下面出问题,每次把鼠标放到那个黄色的按钮上面,都会出现一个action.do的提示。
此button对应的js是:
esHTML='<div id='+this.divname+'>'
         
+'<table id='+this.tablename+' cellpadding=0 cellspacing=0 class=select><tr><td bgcolor=#FFFFFF>'
         
+'<input type=text class=selecttext size="'+size+'" name='+name+' value="'+defaulttext+'" '+readonly+'><td><button class=selectbutton id='+this.buttonname+'>6</td></tr></table>'
         
+'</div>'
ps:俺们以前一直只支持ie6,这就是不做网站的好处。
赶紧下载一个ie8装上,确认此问题,然后满世界的找资料。说实话,也没找到。
后来一气之下试验了一下另外一种写法,居然好用了,希望牛人给点解释。
esHTML='<div id='+this.divname+'>'
         
+'<table id='+this.tablename+' cellpadding=0 cellspacing=0 class=select><tr><td bgcolor=#FFFFFF>'
         
+'<input type=text class=selecttext size="'+size+'" name='+name+' value="'+defaulttext+'" '+readonly+'><td><input type="button" class="selectbutton" id='+this.buttonname+' value="6"/></td></tr></table>'
         
+'</div>'
看来要赶紧学习了,不然ie9出来我就得去要饭了。
posted @ 2009-04-03 15:23 temper 阅读(106) | 评论 (0)编辑 收藏
Hi   TOM,  
  I   have   a   problem   with   ref   cursors.I'll   try   to   explain   it(sorry   if   my   english   is    
  not   very   good).  
  I   have   2   databases   and   i   want   to   return   values   from   one   DBto   the   other.  
  In   the   DB   that   i   want   to   recieve   the   data   i   have   the   call(with   a   procedure)   and      
  i   create   a   variable    
  wich   the   type   is   REF   CURSOR   from   the   second   DB.   In   example:  
  --the   variable    
  vResultCursor   user_DB2.pk_k1.vSqlCursorD@DB2;    
  --where   pk1   is   a   package   in   which   i   declare   the   REF   CURSOR   variable  
  ..  
  --The   call  
  user_DB2.pk_k1.P_1@DB2(vResultCursor);  
  --where   P1   is   the   procedure   in   wich   i   open   the   cursor   and    
  after   that   i   want   to   work   with   this   cursor  
   
  loop            
  --vx   is   varchar2              
                  FETCH   vResultCursor   INTO   vx;  
                        EXIT   WHEN   vResultCursor%NOTFOUND;  
                        insert   into   tbl_probe   values   (sysdate,'vx',vx);              
                      commit;                          
             
  end   loop;  
  close     vResultCursor;  
   
  In   the   first   DB   i   have   in   PK_K1   the   declaration   of   the   ref   cursor,   and   the    
  procedure   wich   open   the   dinamic  
    cursor:  
  CREATE     OR   REPLACE   PACKAGE   PK_K1   IS    
  TYPE   vSqlCursorD   IS   REF   CURSOR;  
  PROCEDURE   P_RESOLVECURSOR   (vSQLCURSOR   OUT   vSqlCursorD);  
  END   PK_K1;  
   
  CREATE   OR   REPLACE   PACKAGE   BODY   PK_K1   IS  
   
  PROCEDURE   P_RESOLVECURSOR   (vSQLCURSOR   OUT   vSqlCursorD)   IS  
  vSqlCursortxt   VARCHAR2(4096);  
  BEGIN  
  vSqlCursortxt:=   'SELECT   *   FROM   DUAL';  
  OPEN   vSQLCURSOR   FOR   vSqlCursortxt;  
  EXCEPTION  
                    WHEN   OTHERS   THEN  
                                IF   (vSQLCURSOR%ISOPEN)   THEN  
                                        CLOSE   vSQLCURSOR;  
                              END   IF;  
  END;    
  END   PK_K1;  
  The   problem   that   i   have   is,   that   if   i   make   a   procedure   in   the   package   PK_K1   and    
  i   call   the   procedure   P_RESOLVECURSOR  
  it   works,   but   when   i   call   from   the   other   DB   it   doesnt   work.   The   error   is   ERROR    
  ORA-01001   when   whe   make   the   FETCH  
  I   gave   the   EXECUTE   grant   from   one   DB   to   the   OTHER  
  GRANT   EXECUTE   ON   PK_K1   TO   USERDB1;  
  could   u   help   me?  
  Thanks    
     
   
   
  Followup:  
   
  ref   cursors   cannot   be   used   over   a   dblink   like   that.  
   
   
  http://download-east.oracle.com/docs/cd/B19306_01/appdev.102/b14261/sqloperations.htm#sthref1448  
   
  ....  
  Note:  
   
          *     Using   a   REF   CURSOR   variable   in   a   server-to-server   RPC   results   in   an    
  error.   However,   a   REF   CURSOR   variable   is   permitted   in   a   server-to-server   RPC   if    
  the   remote   database   is   a   non-Oracle   database   accessed   through   a   Procedural    
  Gateway.  
          *     LOB   parameters   are   not   permitted   in   a   server-to-server   RPC.  
   
  .....    
   
  Passing   a   cursor   from   one   DB   to   the   other     March   23,   2006  
  Reviewer:     Jorge     from   Spain  
   
  Thank   for   the   explanation,   we   solve   the   problem   opening   and   closing   the   cursor    
  in   one   DB   and   passig   the   data   to   the   other   server   in   an   TABLE   Object   by   means   of    
  a   function.  
  Thanks   a   lot     

  ==========================================================
看来这几天的努力白费了,气愤啊
posted @ 2009-03-30 16:58 temper 阅读(139) | 评论 (0)编辑 收藏
创建另一个数据库的连接
CREATE [PUBLIC] DATABASE LINK dblink
    [CONNECT TO user IDENTIFIED BY password]
    [USING 'connect_string']



部署新版本
java.util.zip.ZipException: invalid entry CRC (expected 0x0 but got 0xab633fa2)
 at java.util.zip.ZipInputStream.read(ZipInputStream.java:164)
 at java.util.jar.JarInputStream.read(JarInputStream.java:171)
 at java.io.BufferedInputStream.read1(BufferedInputStream.java:254)
 at java.io.BufferedInputStream.read(BufferedInputStream.java:313)
 at java.util.jar.JarInputStream.getBytes(JarInputStream.java:88)
 at java.util.jar.JarInputStream.<init>(JarInputStream.java:65)
 at java.util.jar.JarInputStream.<init>(JarInputStream.java:43)
原因:jdk版本不对
posted @ 2009-03-27 13:22 temper 阅读(172) | 评论 (0)编辑 收藏

怎样查看oracle当前的连接数呢?只需要用下面的SQL语句查询一下就可以了。
select * from v$session where username is not null

select username,count(username) from v$session where username is not null group by username #查看不同用户的连接数

select count(*) from v$session   #连接数

Select count(*) from v$session where status='ACTIVE' #并发连接数

show parameter processes   #最大连接

alter system set processes = value scope = spfile;重启数据库   #修改连接

/home/oracle9i/app/oracle9i/dbs/init.ora

/home/oracle9i/app/oracle9i/dbs/spfilexxx.ora ## open_cursor

posted @ 2009-03-24 11:10 temper 阅读(14930) | 评论 (0)编辑 收藏
具体参见:http://wrapper.tanukisoftware.org
网上的介绍基本上是自己写个测试类,然后用warpper做成系统进程的。但是我们目前是一个比较大的java项目,经过一个多小时摸索,终于试验成功。
大概需要注意的地方如下:
系统的配置文件放入bin目录,系统打成包,放入lib,系统需要的其它第三方包也放入lib,配置wrapper.conf文件,将这些包都配入wrapper.java.classpath.[n].在wrapper.app.parameter.1中配入main方法所在的类。运行一下App.bat,看看是否成功。:)
ps:详细的配置请自己去网络搜索,这只是对其中没有提及的进行了补充。另外这次配置的项目不是web项目。
posted @ 2008-12-11 14:08 temper 阅读(344) | 评论 (0)编辑 收藏

 

db2获得刚插入的自增字段的值:
values(identity_val_local())


Select Top在不同数据库中的使用用法:


1. Oracle数据库

<CENTER><CCID_NOBR> SELECT * FROM TABLE1 WHERE ROWNUM<=N



2. Infomix数据库


SELECT FIRST N * FROM TABLE1


3. DB2数据库


SELECT * ROW_NUMBER() OVER(ORDER BY COL1 DESC) AS ROWNUM WHERE ROWNUM<=N


或者


SELECT COLUMN FROM TABLE FETCH FIRST N ROWS ONLY



4. SQL Server数据库


SELECT TOP N * FROM TABLE1


5. Sybase数据库


SET ROWCOUNT N
GO
SELECT * FROM TABLE1



6. MySQL数据库


SELECT * FROM TABLE1 LIMIT N



7. FoxPro数据库


SELECT * TOP N FROM TABLE ORDER BY COLUMN

转载自http://tech.techweb.com.cn/archiver/tid-243262.html
posted @ 2008-11-03 10:32 temper 阅读(141) | 评论 (0)编辑 收藏
仅列出标题
共3页: 上一页 1 2 3 下一页