java – JIT优化和弱引用

前端之家收集整理的这篇文章主要介绍了java – JIT优化和弱引用前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有以下代码
  1. private final List<WeakReference<T>> slaves;
  2.  
  3. public void updateOrdering() {
  4. // removes void weak references
  5. // and ensures that weak references are not voided
  6. // during subsequent sort
  7. List<T> unwrapped = unwrap();
  8. assert unwrapped.size() == this.slaves.size();
  9. // **** could be reimplemented without using unwrap() ****
  10. Collections.sort(this.slaves,CMP_IDX_SLV);
  11. unwrapped = null;// without this,....
  12. }

方法unwrap()只是创建一个由Slaves中的弱引用引用的T列表
并且作为副作用消除了在从属中引用null的弱引用.
然后是依赖于每个奴隶成员引用一些T的排序;
否则代码会产生NullPointerException.

由于unwrapped在slave中的每个T上都有一个引用,因此在排序过程中没有GC消除T.最后,unwrapped = null消除了unwrapped上的引用
然后再次发布GC.似乎工作得很好.

现在我的问题:

如果我删除unwrapped = null;在某些负载下运行许多测试时,这会导致NullPointerExceptions.我怀疑JIT消除了List< T> unwrapped = unwrap();
因此GC在分拣过程中适用于奴隶中的T.

你有其他解释吗?如果您同意我的意见,这是JIT中的错误吗?

我个人认为unwrapped = null不是必需的,因为一旦updateOrdering()返回,就会从帧中删除unwrapped.是否存在可以优化和不优化的规范?

或者我是以错误的方式做事了?我有想法修改比较器,它允许对null的弱引用.你觉得怎么样?

谢谢你的建议.

加入(1)

现在我想添加一些缺失的信息:
首先是Java版本:
java版“1.7.0_45”
OpenJDK运行时环境(IcedTea 2.4.3)(suse-8.28.3-x86_64)
OpenJDK 64位服务器VM(内置24.45-b08,混合模式)

然后有人想看方法展开

  1. private synchronized List<T> unwrap() {
  2. List<T> res = new ArrayList<T>();
  3. T cand;
  4. WeakReference<T> slvRef;
  5. Iterator<WeakReference<T>> iter = this.slaves.iterator();
  6. while (iter.hasNext()) {
  7. slvRef = iter.next();
  8. cand = slvRef.get();
  9. if (cand == null) {
  10. iter.remove();
  11. continue;
  12. }
  13. assert cand != null;
  14. res.add(cand);
  15. } // while (iter.hasNext())
  16.  
  17. return res;
  18. }

请注意,在迭代时,将删除void引用.
事实上我用这个方法取代了

  1. private synchronized List<T> unwrap() {
  2. List<T> res = new ArrayList<T>();
  3. for (T cand : this) {
  4. assert cand != null;
  5. res.add(cand);
  6. }
  7.  
  8. return res;
  9. }

使用我自己的迭代器,但在功能上这应该是相同的.

然后有人在堆栈跟踪中徘徊.这是一块.

  1. java.lang.NullPointerException: null
  2. at WeakSlaveCollection$IdxComparator.compare(WeakSlaveCollection.java:44)
  3. at WeakSlaveCollection$IdxComparator.compare(WeakSlaveCollection.java:40)
  4. at java.util.TimSort.countRunAndMakeAscending(TimSort.java:324)
  5. at java.util.TimSort.sort(TimSort.java:189)
  6. at java.util.TimSort.sort(TimSort.java:173)
  7. at java.util.Arrays.sort(Arrays.java:659)
  8. at java.util.Collections.sort(Collections.java:217)
  9. at WeakSlaveCollection.updateOrdering(WeakSlaveCollection.java:183)

它指向比较器,返回线.

  1. static class IdxComparator
  2. implements Comparator<WeakReference<? extends XSlaveNumber>> {
  3. public int compare(WeakReference<? extends XSlaveNumber> slv1,WeakReference<? extends XSlaveNumber> slv2) {
  4. return slv2.get().index()-slv1.get().index();
  5. }
  6. } // class IdxComparator

最后,

  1. private final static IdxComparator CMP_IDX_SLV = new IdxComparator();

是一个重要的常数.

加入(2)

现在观察到即使在updateOrdering()中存在’unwrapped = null’,NPE也会发生.

java运行时可能会删除弱引用
如果jit优化后没有严格的引用.
代码似乎并不重要.

我通过以下方式解决了问题:

  1. public void updateOrdering() {
  2. Collections.sort(this.slaves,CMP_IDX_SLV);
  3. }

没有插入任何装饰,以防止奴隶被垃圾收集
并启用CMP_IDX_SLV中的比较器来处理对null的弱引用:

  1. public int compare(WeakReference<? extends XSlaveNumber> slv1,WeakReference<? extends XSlaveNumber> slv2) {
  2. XSlaveNumber sSlv1 = slv1.get();
  3. XSlaveNumber sSlv2 = slv2.get();
  4. if (sSlv1 == null) {
  5. return sSlv2 == null ? 0 : -1;
  6. }
  7. if (sSlv2 == null) {
  8. return +1;
  9. }
  10. assert sSlv1 != null && sSlv2 != null;
  11.  
  12. return sSlv2.index()-sSlv1.index();
  13. }

作为副作用,订购基础列表List>奴隶;
将void弱引用放在列表的末尾,以后可以在其中收集.

解决方法

我检查你的源代码,当JIT编译我的方法对应你的方法“updateOrdering”并且GC在排序期间发生时,我得到了NullPointerException.

但是当Collections.sort无论是否有unwrapped = null时,我都得到了NullPointerException.
这可能发生在我的示例源代码和您的示例源代码之间的差异,或Java版本差异.我会检查你是否告诉Java版本.

我使用java下面的版本.

  1. java version "1.7.0_40"
  2. Java(TM) SE Runtime Environment (build 1.7.0_40-b43)
  3. Java HotSpot(TM) 64-Bit Server VM (build 24.0-b56,mixed mode)

如果你想欺骗JIT编译,下面的代码插入你的源代码而不是unwrapped = null(例如).然后,JIT编译不会消除未包装的代码.

  1. long value = unwrapped.size() * unwrapped.size();
  2. if(value * value % 3 == 1) {
  3. //Because value * value % 3 always is 1 or 0,this code can't reach.
  4. //Insert into this the source code that use unwrapped array,for example,show unwrapped array.
  5. }

我的考试成绩如下.

>如果JIT没有优化我对应于updateOrdering的方法,则不会发生NullPointerException.
>如果JIT优化了我的方法,那么在某些时候会发生NullPointerException.

>如果JIT优化我的方法插入上面的代码欺骗JIT编译器,那么就不会发生NullPointerException.

所以,我(和你)建议JIT optimze消除未包装的代码,然后发生NullPointerException.

顺便说一下,如果要显示JIT编译器优化,可以使用-XX:PrintCompilation调用java.
如果要显示GC,请使用-verbose:gc.

仅供参考,我的示例源代码如下.

  1. public class WeakSampleMain {
  2. private static List<WeakReference<Integer>> weakList = new LinkedList<>();
  3. private static long sum = 0;
  4. public static void main(String[] args) {
  5. System.out.println("start");
  6. int size = 1_000_000;
  7. for(int i = 0; i < size; i++) {
  8. Integer value = Integer.valueOf(i);
  9. weakList.add(new WeakReference<Integer>(value));
  10. }
  11. for(int i = 0; i < 10; i++) {
  12. jitSort();
  13. }
  14. GcTask gcTask = new GcTask();
  15. Thread thread = new Thread(gcTask);
  16. thread.start();
  17. for(int i = 0; i < 100000; i++) {
  18. jitSort();
  19. }
  20. thread.interrupt();
  21. System.out.println(sum);
  22. }
  23.  
  24. public static void jitSort() {
  25. List<Integer> unwrappedList = unwrapped();
  26. removeNull();
  27. Collections.sort(weakList,new Comparator<WeakReference<Integer>>() {
  28.  
  29. @Override
  30. public int compare(WeakReference<Integer> o1,WeakReference<Integer> o2) {
  31. return Integer.compare(o1.get(),o2.get());
  32. }
  33. }
  34. );
  35. for(int i = 0; i < Math.min(weakList.size(),1000); i++) {
  36. sum += weakList.get(i).get();
  37. }
  38. unwrappedList = null;
  39. // long value = (sum + unwrappedList.size());
  40. // if((value * value) % 3 == 2) {
  41. // for(int i = 0; i < unwrappedList.size(); i++) {
  42. // System.out.println(unwrappedList.get(i));
  43. // }
  44. // }
  45. }
  46.  
  47. public static List<Integer> unwrapped() {
  48. ArrayList<Integer> list = new ArrayList<Integer>();
  49. for(WeakReference<Integer> ref : weakList) {
  50. Integer i = ref.get();
  51. if(i != null) {
  52. list.add(i);
  53. }
  54. }
  55. return list;
  56. }
  57.  
  58. public static void removeNull() {
  59. Iterator<WeakReference<Integer>> itr = weakList.iterator();
  60. while(itr.hasNext()) {
  61. WeakReference<Integer> ref = itr.next();
  62. if(ref.get() == null) {
  63. itr.remove();
  64. }
  65. }
  66. }
  67.  
  68. public static class GcTask implements Runnable {
  69. private volatile int result = 0;
  70. private List<Integer> stockList = new ArrayList<Integer>();
  71. public void run() {
  72. while(true) {
  73. if(Thread.interrupted()) {
  74. break;
  75. }
  76. int size = 1000000;
  77. stockList = new ArrayList<Integer>(size);
  78. for(int i = 0; i < size; i++) {
  79. stockList.add(new Integer(i));
  80. }
  81. if(System.currentTimeMillis() % 1000 == 0) {
  82. System.out.println("size : " + stockList.size());
  83. }
  84. }
  85. }
  86.  
  87. public int getResult() {
  88. return result;
  89. }
  90. }
  91. }

猜你在找的Java相关文章