Ошибка компиляции старой библиотеки одновременно с Java 8

Кольт математической библиотеки (версия 1.2) зависит от библиотеки EDU.oswego.cs.dl.util.concurrent (gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro. HTML). Компиляция параллельная (версия 1.3.4) работала на Java версии 7 или предыдущих выпусках. Однако компиляция не удается на Java 8 (версия 1.8 Javac). Опции компилятора -source 1.4 -target 1.4 не решить проблему.

Причина в том, что Java 8 ввел новый метод "удалить" в интерфейсе java.util.Map: default boolean remove(Object key, Object value), Этот новый метод конфликтует с методом "remove" в классе библиотеки ConcurrentHashMap.java, который реализует java.util.Map: protected Object remove(Object key, Object value),

Как только причина проблемы была определена, я мог решить проблему, переименовав метод в классе библиотеки ConcurrentHashMap.java. Это было приемлемо, потому что библиотечный метод был защищен только (и не общедоступен).

Существуют ли другие возможности для обеспечения совместимости с Java 8?

  • параметры компилятора?
  • аннотации ("@ForceOverride")?

3 ответа

Решение

Нет ни параметров компилятора, ни аннотаций, которые будут игнорировать конфликтующие сигнатуры методов.

Если вы (или, в данном случае, новичок) не используете новый remove метод, просто скомпилируйте его под Java 7. Компиляция под Java 8 не даст вам никаких преимуществ.

Но на самом деле мне больше нравится ваше решение в этом случае.

Переносить кольт из EDU.oswego.cs.dl.util.concurrent в java.util.concurrent классы. Как указано в ответе Хольгера, автор параллельной библиотеки рекомендует сделать это.

Gentoo предоставляет патч для исходного кода colt 1.2.0:

--- src/cern/colt/matrix/linalg/SmpBlas.java.orig   2015-10-07 22:23:44.969486000 +0000
+++ src/cern/colt/matrix/linalg/SmpBlas.java    2015-10-07 22:29:15.475486000 +0000
@@ -10,7 +10,8 @@

 import cern.colt.matrix.DoubleMatrix1D;
 import cern.colt.matrix.DoubleMatrix2D;
-import EDU.oswego.cs.dl.util.concurrent.FJTask;
+
+import java.util.concurrent.ForkJoinTask;
 /**
 Parallel implementation of the Basic Linear Algebra System for symmetric multi processing boxes.
 Currently only a few algorithms are parallelised; the others are fully functional, but run in sequential mode.
@@ -198,7 +199,7 @@

    // set up concurrent tasks
    int span = width/noOfTasks;
-   final FJTask[] subTasks = new FJTask[noOfTasks];
+   final ForkJoinTask[] subTasks = new ForkJoinTask[noOfTasks];
    for (int i=0; i<noOfTasks; i++) {
        final int offset = i*span;
        if (i==noOfTasks-1) span = width - span*i; // last span may be a bit larger
@@ -217,24 +218,30 @@
            CC = C.viewPart(offset,0,span,p);
        }

-       subTasks[i] = new FJTask() { 
+       subTasks[i] = new ForkJoinTask() { 
            public void run() { 
                seqBlas.dgemm(transposeA,transposeB,alpha,AA,BB,beta,CC); 
                //System.out.println("Hello "+offset); 
            }
+
+      public boolean exec() { return true; }
+      public void setRawResult(Object o) {}
+      public Object getRawResult() {return null;}
        };
    }

    // run tasks and wait for completion
-   try { 
-       this.smp.taskGroup.invoke(
-           new FJTask() {
-               public void run() { 
-                   coInvoke(subTasks); 
-               }
-           }
-       );
-   } catch (InterruptedException exc) {}
+  this.smp.taskGroup.invoke(
+          new ForkJoinTask() {
+              public void run() {  
+                  invokeAll(subTasks); 
+              }
+
+              public boolean exec() { return true; }
+              public void setRawResult(Object o) {}
+              public Object getRawResult() {return null;}
+          }
+          );
 }
 public void dgemv(final boolean transposeA, final double alpha, DoubleMatrix2D A, final DoubleMatrix1D x, final double beta, DoubleMatrix1D y) {
    /*
@@ -271,7 +278,7 @@

    // set up concurrent tasks
    int span = width/noOfTasks;
-   final FJTask[] subTasks = new FJTask[noOfTasks];
+   final ForkJoinTask[] subTasks = new ForkJoinTask[noOfTasks];
    for (int i=0; i<noOfTasks; i++) {
        final int offset = i*span;
        if (i==noOfTasks-1) span = width - span*i; // last span may be a bit larger
@@ -280,24 +287,30 @@
        final DoubleMatrix2D AA = A.viewPart(offset,0,span,n);
        final DoubleMatrix1D yy = y.viewPart(offset,span);

-       subTasks[i] = new FJTask() { 
+       subTasks[i] = new ForkJoinTask() { 
            public void run() { 
                seqBlas.dgemv(transposeA,alpha,AA,x,beta,yy); 
                //System.out.println("Hello "+offset); 
            }
+
+      public boolean exec() { return true; }
+      public void setRawResult(Object o) {}
+      public Object getRawResult() {return null;}
        };
    }

    // run tasks and wait for completion
-   try { 
-       this.smp.taskGroup.invoke(
-           new FJTask() {
-               public void run() { 
-                   coInvoke(subTasks); 
-               }
-           }
-       );
-   } catch (InterruptedException exc) {}
+  this.smp.taskGroup.invoke(
+          new ForkJoinTask() {
+              public void run() {  
+                  invokeAll(subTasks); 
+              }
+
+              public boolean exec() { return true; }
+              public void setRawResult(Object o) {}
+              public Object getRawResult() {return null;}
+          }
+          );
 }
 public void dger(double alpha, DoubleMatrix1D x, DoubleMatrix1D y, DoubleMatrix2D A) {
    seqBlas.dger(alpha,x,y,A);
@@ -369,9 +382,6 @@
 /**
  * Prints various snapshot statistics to System.out; Simply delegates to {@link EDU.oswego.cs.dl.util.concurrent.FJTaskRunnerGroup#stats}.
  */
-public void stats() {
-   if (this.smp!=null) this.smp.stats();
-}
 private double xsum(DoubleMatrix2D A) {
    double[] sums = run(A,true,
        new Matrix2DMatrix2DFunction() {
--- src/cern/colt/matrix/linalg/Smp.java.orig   2015-10-07 21:08:19.443486000 +0000
+++ src/cern/colt/matrix/linalg/Smp.java    2015-10-07 22:28:24.722486000 +0000
@@ -9,12 +9,13 @@
 package cern.colt.matrix.linalg;

 import cern.colt.matrix.DoubleMatrix2D;
-import EDU.oswego.cs.dl.util.concurrent.FJTask;
-import EDU.oswego.cs.dl.util.concurrent.FJTaskRunnerGroup;
+import java.util.concurrent.ForkJoinTask;
+import java.util.concurrent.ForkJoinPool;
+
 /*
 */
 class Smp {
-   protected FJTaskRunnerGroup taskGroup; // a very efficient and light weight thread pool
+   protected ForkJoinPool taskGroup; // a very efficient and light weight thread pool

    protected int maxThreads;   
 /**
@@ -24,41 +25,39 @@
    maxThreads = Math.max(1,maxThreads);
    this.maxThreads = maxThreads;
    if (maxThreads>1) {
-       this.taskGroup = new FJTaskRunnerGroup(maxThreads);
+       this.taskGroup = new ForkJoinPool(maxThreads);
    }
    else { // avoid parallel overhead
        this.taskGroup = null;
    }
 }
-/**
- * Clean up deamon threads, if necessary.
- */
-public void finalize() {
-   if (this.taskGroup!=null) this.taskGroup.interruptAll();
-}
 protected void run(final DoubleMatrix2D[] blocksA, final DoubleMatrix2D[] blocksB, final double[] results, final Matrix2DMatrix2DFunction function) {
-   final FJTask[] subTasks = new FJTask[blocksA.length];
+   final ForkJoinTask[] subTasks = new ForkJoinTask[blocksA.length];
    for (int i=0; i<blocksA.length; i++) {
        final int k = i;
-       subTasks[i] = new FJTask() { 
+       subTasks[i] = new ForkJoinTask() { 
            public void run() {
                double result = function.apply(blocksA[k],blocksB != null ? blocksB[k] : null);
                if (results!=null) results[k] = result; 
                //System.out.print("."); 
            }
+      public boolean exec() { return true; }
+      public void setRawResult(Object o) {}
+      public Object getRawResult() {return null;}
        };
    }

    // run tasks and wait for completion
-   try { 
-       this.taskGroup.invoke(
-           new FJTask() {
-               public void run() { 
-                   coInvoke(subTasks); 
-               }
-           }
-       );
-   } catch (InterruptedException exc) {}
+  this.taskGroup.invoke(
+          new ForkJoinTask() {
+              public void run() {  
+                  invokeAll(subTasks); 
+              }
+              public boolean exec() { return true; }
+              public void setRawResult(Object o) {}
+              public Object getRawResult() {return null;}
+          }
+          );
 }
 protected DoubleMatrix2D[] splitBlockedNN(DoubleMatrix2D A, int threshold, long flops) {
    /*
@@ -186,10 +185,4 @@
    }
    return blocks;
 }
-/**
- * Prints various snapshot statistics to System.out; Simply delegates to {@link EDU.oswego.cs.dl.util.concurrent.FJTaskRunnerGroup#stats}.
- */
-public void stats() {
-   if (this.taskGroup!=null) this.taskGroup.stats();
-}
 }

Учитывая, что этот класс является основой класса JRE, также известного как ConcurrentHashMapздесь нет конфликта имен, так как этот метод имеет именно ту семантику. Происходит конфликт, потому что метод protectedрешение, которое уже пересмотрено давно. Т.е. когда вы посмотрите на версию класса Java 5, вы увидите, что он уже имеет методremove(Object, Object) И его public, Это также требуется ConcurrentMap интерфейс и, следовательно, должен быть public,

Поэтому самое простое решение - не переименовать его, а изменить его на public и адаптировать тип возврата.


Но вы правы в своем комментарии, в долгосрочной перспективе, лучшее решение - перейти на версию JRE этого класса, как рекомендует сам автор:

Примечание. После выпуска J2SE 5.0 этот пакет входит в режим обслуживания: будут выпущены только необходимые исправления. Пакет J2SE5 java.util.concurrent включает улучшенные, более эффективные, стандартизированные версии основных компонентов этого пакета. Пожалуйста, планируйте конвертировать ваши приложения, чтобы использовать их.

И это было более десяти лет назад...

Другие вопросы по тегам