Ho appena scoperto un comportamento piuttosto strano dell'oscilloscopio Scala quando il codice bytecode generato dal codice Scala viene utilizzato dal codice Java. Si consideri il seguente frammento di codice usando Spark (Spark 1.4, Hadoop 2.6):Scope pacchetto-privato in Scala visibile da Java
import java.util.Arrays;
import java.util.List;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.broadcast.Broadcast;
public class Test {
public static void main(String[] args) {
JavaSparkContext sc =
new JavaSparkContext(new SparkConf()
.setMaster("local[*]")
.setAppName("test"));
Broadcast<List<Integer>> broadcast = sc.broadcast(Arrays.asList(1, 2, 3));
broadcast.destroy(true);
// fails with java.io.IOException: org.apache.spark.SparkException:
// Attempted to use Broadcast(0) after it was destroyed
sc.parallelize(Arrays.asList("task1", "task2"), 2)
.foreach(x -> System.out.println(broadcast.getValue()));
}
}
Questo codice non funziona, che si prevede come io distruggo volontariamente un Broadcast
prima di usarlo, ma la cosa è che nel mio modello mentale non dovrebbe anche compilare, figuriamoci correre bene.
Infatti, Broadcast.destroy(Boolean)
è dichiarato come private[spark]
quindi non dovrebbe essere visibile dal mio codice. Proverò a guardare il bytecode di Broadcast
ma non è la mia specialità, è per questo che preferisco postare questa domanda. Inoltre, scusate, ero troppo pigro per creare un esempio che non dipendesse da Spark, ma almeno avete avuto l'idea. Nota che posso usare vari metodi di Spark per i pacchetti privati, non si tratta solo di Broadcast
.
Qualche idea di cosa sta succedendo?
Grazie per la risposta. Non pensi che questo sia un po 'pericoloso per gli scrittori API? Funzionalità che non volevano mai essere esposte finiscono chiaramente visibili da Java. Mi chiedo se potrebbero usare qualche trucco di annotazione per generare avvertimenti sull'utente quando provano a usare un membro che doveva essere privato – Dici
@Dici Se hai intenzione di interop con Java, allora sì, penso che sia qualcosa che devi prendere in esame, soprattutto se questo espone gli interni che non si desidera che i client invochino. Anche se in questo caso particolare, potresti anche chiamare il pubblico 'Broadcast.metodo destory', sparandosi al piede in modo equivalente. –
Sì, quello che intendevo è che ora che conosco tutti gli interni di Spark dichiarati come package-private come esposti tramite l'API Java, penso che probabilmente ci dovrebbero essere più wrapper Java per nascondere funzionalità che non erano destinate a essere pubbliche. Il mio esempio è stato solo per mostrare che il metodo è stato effettivamente chiamato. – Dici