Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3534508
  • 博文数量: 864
  • 博客积分: 14125
  • 博客等级: 上将
  • 技术积分: 10634
  • 用 户 组: 普通用户
  • 注册时间: 2007-07-27 16:53
个人简介

https://github.com/zytc2009/BigTeam_learning

文章分类

全部博文(864)

文章存档

2023年(1)

2021年(1)

2019年(3)

2018年(1)

2017年(10)

2015年(3)

2014年(8)

2013年(3)

2012年(69)

2011年(103)

2010年(357)

2009年(283)

2008年(22)

分类: Java

2011-08-02 11:22:54

  • 1. 尽可能不要创建global reference和global weak reference. 创建这两类引用的JNI接口NewGlobalReference和NewGlobalWeakReference内部实现
    有 一个锁。这个锁使得在多处理器上的可扩展性非常差,因为各个线程都在等待这个锁。所以尽量不要在native保存java 对象的引用,情愿在每次JNI call时都带点参数。当然,在native保持java对象的local reference是非常危险的,绝对不能那样干。

    2. 尽量不要使用GetPrimitiveArrayCritical/ReleasePrimitiveArrayCritical来pin住Java内 存。JVM本身没有提供任何只pin住一块Java内存而不影响GC的操作,所以这个操作是会阻止GC进行的。作为补 偿,ReleasePrimitiveArrayCritical会产生一次隐式的GC调用。这样就可能出现在需要GC的时候无法GC,而在不需要GC时 进行无意义GC的情况。另外,这两个操作的实现中在某些情况下也可能触发锁。
    解决方法:如果是小块内存的话,情愿使用GetArrayRegion和SetArrayRegion来在native和Java之间复制内存。

    3. 在Java appliation中尽量不要创建phantom reference或者soft reference。这些reference会极大的影响GC。
    我 们先来谈谈JVM的GC。GC分为minor GC和full GC。Java内存分为young和old两代。在young memory中,每个线程都有自己的内存分配块(不和其它线程共享),而old memory是由所有线程共享的。minor GC只对young memory作GC,而full GC对所有内存都做GC。minor GC是可以多线程并行进行的,而full GC默认只能单线程执行。所以,一次full GC需要的时间可以是minor GC是10倍以上(可以用-verbose:gc观察)。所以在一般应用中,minor GC的次数应该是full GC的10倍左右是比较理想的。minor GC会将无法收集的对象移动到old memory中去。
    minor GC不会对phantom reference和soft reference进行收集,只有full GC才会。这样的问题就是大量的这类对象积聚起来,产生许多的内存复制。这样每次minor GC可能就基本上没有释放多少内存,使得full GC就会被频繁触发。可能出现minor GC和full GC次数1:1的情况,甚至全是full GC。这样,无论是性能还是可扩展性都是非常差的。
    weak reference的影响好像小一些,但也应该尽量避免。
    在 JNI开发中,使用这3种reference的主要目的是保证native资源的释放。因为java对象的finalize方法是不保证被调用的,所以必 须用这些reference来帮助实现native资源释放。为了避免上述的问题,一种可行的方法是将native资源serialize成一块内存,然 后放到java对象中保存,从而避免使用这些reference。

    4. NIO是不错的Java和native之间share memory的方法。但要注意它的性能。首先一定要设置对big endian还是little endian,防止JVM做额外的endian转换动作。其次是在启动JVM时一定要加上-server选项,否则nio性能会非常差。在-server mode下,nio性能大概比java数组慢30%~50%.在-client mode下,性能差1倍以上。

    5. 尽量不要在JNI去new Java String对象。这个比在java层new慢很多。

    6. 对java大对象(比方说数组),一定要仔细的tune他的大小。一般来说,小对象对GC比较友好。因为对象分配时先看每个线程自己的young memory
    ,如果找的到足够大的内存的话,就分配。否则在old memory中分配。因为old memory是shared,所以可能有锁开销。而且old memory中的对象只有
    full GC才能释放它。所以对象比较小是比较好的。JVM的内存分配算法是为小对象优化过的,大量小对象的分配是很高效的,所以不用怕把大对象拆小。
    在某些情况下,如果知道对象会活的很久的话,就让它大一点,增加它直接分配在old memory中的概率。这样可以节约young GC拷贝这个对象到old memory中的开销。

  • 阅读(1068) | 评论(0) | 转发(0) |
    给主人留下些什么吧!~~