PD: Lo siento por mi pobre English.I no puede describir el problema con claridad. :(
Cuando yo no uso el estilo de código "lambda referencia del método" en el bloque estático, como:
static{
map.keySet().parallelStream().forEach(e -> {
System.out.println(e);
});
}
a continuación, el programa que se ejecuta siempre, nunca se detiene.
Pero cuando cambio el código de
static{
map.keySet().parallelStream().forEach(System.out::println);
}
a continuación, el programa gone.The error puede terminar inmediatamente.
Basta con mirar directamente en el código por favor, Ya he intentado simplificar el código en lo que pueda.
public class BugSimulate {
static {
init();
}
private static void init() {
Map<Integer, String> map = new HashMap<>();
int i = 0;
map.put(++i, "1");
map.put(++i, "1");
map.put(++i, "1");
map.put(++i, "1");
map.put(++i, "1");
map.put(++i, "1");
map.put(++i, "1");
map.put(++i, "1");
map.put(++i, "1");
// running forever
map.keySet().parallelStream().forEach(e -> {
System.out.println(e);
});
// finish immediately
// map.keySet().parallelStream().forEach(System.out::println);
}
@Test
public void test() {
new BugSimulate();
}
}
pero cuando cambio el código lambda
e -> {System.out.println(e);}
a
System.out::println
el programa acabado inmediatamente
O cambio parallelStream () para flujo normal (), los insectos han ido.
O elimino los bloques estáticos, insectos ido demasiado.
Mi versión JDK es 1.8.0_202
Y la versión del sistema operativo MacOS es 10.14.5
Interesting Question: This question is similar with Class Loading with Static Block Competition Cause Deadlock,
but for this issue, it's caused by when use e -> {System.out.println(e);}
after compiling, it will generate an synthetic method: anonymous static private method for this, as:
// access flags 0x100A
private static synthetic lambda$init$0(Ljava/lang/Integer;)V
L0
LINENUMBER 27 L0
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ALOAD 0
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
L1
LINENUMBER 28 L1
RETURN
L2
LOCALVARIABLE e Ljava/lang/Integer; L0 L2 0
MAXSTACK = 2
MAXLOCALS = 1
this synthetic method: private static method is generated by e -> {System.out.println(e);}
compile.
also it's similar equal to:
static {
init();
}
private static void init() {
Map<Integer, String> map = new HashMap<>();
int i = 0;
map.put(++i, "1");
***
Thread foo = new Thread() {
@Override
public void run() {
print(map.keySet().iterator().next()); //try access the private method, this cause a competition with **Class Initializer** and **static block**
}
};
foo.start();
try {
foo.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//equal to e -> {System.out.println(e);}
private static void print(int t) {
System.out.println(t);
}
con el fin de Carga Clase con estático Competencia Bloque causar interbloqueo este post explicación: cuando init clase BugSimulate , se invocará static block
en primer lugar, pero ya que se trata de utilizar parallelStream y tratar de invocar el método anónimo privada generada, esto causó un concurso con el inicializador de la clase , por lo que finalmente es punto muerto.