Discussion:
Cast/boxing/unboxing of numbers Java 9
Paulo Oliveira
2018-03-26 21:27:35 UTC
Permalink
Hello,

Testing some nashorn scripts on java 9 I got some unexpected behavior.
The code:

import java.util.Arrays;
import java.util.List;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

public class Main {

public static void main(String[] args) throws Exception{
ScriptEngine scriptEngine = new
ScriptEngineManager().getEngineByName("Nashorn");
scriptEngine.eval("var imports = new JavaImporter(java.lang.Integer, " +
"java.lang.Long);" +
"var fun1 = function(longs, ints, id) {" +
"with(imports) {" +
"print(id.getId().class);" +
"print(longs.contains(id.getId()));" +
"print(ints.contains(id.getId()));" +
"return Long.valueOf(1);" +
"}" +
"};");
Invocable invocable = (Invocable) scriptEngine;

List<Long> longs = Arrays.asList(1L, 2L);
List<Integer> ints = Arrays.asList(1, 2);
Teste teste = new Teste(1L);
Object result = invocable.invokeFunction("fun1", longs, ints, teste);
System.out.println(result.getClass());
}
}

public class Teste {


private Long id;

public Teste(Long id) {
this.id =id;
}

public Long getId() {
return id;
}
}


Executing the code
It produces:

Java 8.161
class java.lang.Long
true
false
class java.lang.Long

Java 9.0.4 and 10
class java.lang.Long
false
true
class java.lang.Integer

Nashorn is changing every number that fits a Integer in Integers, even if I
explicit define as Long.
This causes a problem on List.contains, because it receives a Object, if I
try to verify if a long exists in a list of longs, it returns false.

Is it a expected behavior ?
--
*Paulo Oliveira*
*Desenvolvedor BackEnd*

*TEL:* +55 (11) 3634-3378
www.ifood.com.br




<https://itunes.apple.com/br/app/ifood-delivery-e-entrega-comida/id483017239?mt=8>
<https://play.google.com/store/apps/details?id=br.com.brainweb.ifood>
<https://www.facebook.com/iFood?fref=ts> <https://twitter.com/iFood>
Hannes Wallnöfer
2018-03-27 15:51:32 UTC
Permalink
Hi Paulo,

What you are observing is a side effect of the optimistic-types feature, which was shipped with JDK 8u, but only became enabled by default with JDK 9. It is unfortunate that this affects observable behaviour in this case, but conversion between JavaScript and Java types is quite difficult and it’s hard to avoid border cases like this.

As a workaround you can disable this feature using the nashorn.args system property:

java -Dnashorn.args=-ot=false

Hannes
Post by Paulo Oliveira
Hello,
Testing some nashorn scripts on java 9 I got some unexpected behavior.
import java.util.Arrays;
import java.util.List;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
public class Main {
public static void main(String[] args) throws Exception{
ScriptEngine scriptEngine = new
ScriptEngineManager().getEngineByName("Nashorn");
scriptEngine.eval("var imports = new JavaImporter(java.lang.Integer, " +
"java.lang.Long);" +
"var fun1 = function(longs, ints, id) {" +
"with(imports) {" +
"print(id.getId().class);" +
"print(longs.contains(id.getId()));" +
"print(ints.contains(id.getId()));" +
"return Long.valueOf(1);" +
"}" +
"};");
Invocable invocable = (Invocable) scriptEngine;
List<Long> longs = Arrays.asList(1L, 2L);
List<Integer> ints = Arrays.asList(1, 2);
Teste teste = new Teste(1L);
Object result = invocable.invokeFunction("fun1", longs, ints, teste);
System.out.println(result.getClass());
}
}
public class Teste {
private Long id;
public Teste(Long id) {
this.id =id;
}
public Long getId() {
return id;
}
}
Executing the code
Java 8.161
class java.lang.Long
true
false
class java.lang.Long
Java 9.0.4 and 10
class java.lang.Long
false
true
class java.lang.Integer
Nashorn is changing every number that fits a Integer in Integers, even if I
explicit define as Long.
This causes a problem on List.contains, because it receives a Object, if I
try to verify if a long exists in a list of longs, it returns false.
Is it a expected behavior ?
--
*Paulo Oliveira*
*Desenvolvedor BackEnd*
*TEL:* +55 (11) 3634-3378
www.ifood.com.br
<https://itunes.apple.com/br/app/ifood-delivery-e-entrega-comida/id483017239?mt=8>
<https://play.google.com/store/apps/details?id=br.com.brainweb.ifood>
<https://www.facebook.com/iFood?fref=ts> <https://twitter.com/iFood>
Paulo Oliveira
2018-03-27 17:56:22 UTC
Permalink
Hello,

Firstly, thanks for the quick answer.
I tried some parameters however did not work, I suppose I miss typed
something.
Disabling optimistic-types will work just like JDK 8 or may have some other
side effect ?


Em ter, 27 de mar de 2018 às 12:51, Hannes Wallnöfer <
Post by Hannes Wallnöfer
Hi Paulo,
What you are observing is a side effect of the optimistic-types feature,
which was shipped with JDK 8u, but only became enabled by default with JDK
9. It is unfortunate that this affects observable behaviour in this case,
but conversion between JavaScript and Java types is quite difficult and
it’s hard to avoid border cases like this.
java -Dnashorn.args=-ot=false
Hannes
Am 26.03.2018 um 23:27 schrieb Paulo Oliveira <
Hello,
Testing some nashorn scripts on java 9 I got some unexpected behavior.
import java.util.Arrays;
import java.util.List;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
public class Main {
public static void main(String[] args) throws Exception{
ScriptEngine scriptEngine = new
ScriptEngineManager().getEngineByName("Nashorn");
scriptEngine.eval("var imports = new
JavaImporter(java.lang.Integer, " +
"java.lang.Long);" +
"var fun1 = function(longs, ints, id) {" +
"with(imports) {" +
"print(id.getId().class);" +
"print(longs.contains(id.getId()));" +
"print(ints.contains(id.getId()));" +
"return Long.valueOf(1);" +
"}" +
"};");
Invocable invocable = (Invocable) scriptEngine;
List<Long> longs = Arrays.asList(1L, 2L);
List<Integer> ints = Arrays.asList(1, 2);
Teste teste = new Teste(1L);
Object result = invocable.invokeFunction("fun1", longs, ints,
teste);
System.out.println(result.getClass());
}
}
public class Teste {
private Long id;
public Teste(Long id) {
this.id =id;
}
public Long getId() {
return id;
}
}
Executing the code
Java 8.161
class java.lang.Long
true
false
class java.lang.Long
Java 9.0.4 and 10
class java.lang.Long
false
true
class java.lang.Integer
Nashorn is changing every number that fits a Integer in Integers, even
if I
explicit define as Long.
This causes a problem on List.contains, because it receives a Object, if
I
try to verify if a long exists in a list of longs, it returns false.
Is it a expected behavior ?
--
*Paulo Oliveira*
*Desenvolvedor BackEnd*
*TEL:* +55 (11) 3634-3378 <+55%2011%203634-3378>
www.ifood.com.br
<
https://itunes.apple.com/br/app/ifood-delivery-e-entrega-comida/id483017239?mt=8
<https://play.google.com/store/apps/details?id=br.com.brainweb.ifood>
<https://www.facebook.com/iFood?fref=ts> <https://twitter.com/iFood>
--
*Paulo Oliveira*
*Desenvolvedor BackEnd*

*TEL:* +55 (11) 3634-3378
www.ifood.com.br




<https://itunes.apple.com/br/app/ifood-delivery-e-entrega-comida/id483017239?mt=8>
<https://play.google.com/store/apps/details?id=br.com.brainweb.ifood>
<https://www.facebook.com/iFood?fref=ts> <https://twitter.com/iFood>
Hannes Wallnöfer
2018-03-27 18:18:00 UTC
Permalink
Disabling optimistic-types will make it behave like JDK 8 and shouldn’t have any side effects. In fact, you can make JDK 8 behave like JDK 9 by passing -ot=true.

Hannes
Post by Paulo Oliveira
Hello,
Firstly, thanks for the quick answer.
I tried some parameters however did not work, I suppose I miss typed something.
Disabling optimistic-types will work just like JDK 8 or may have some other side effect ?
Hi Paulo,
What you are observing is a side effect of the optimistic-types feature, which was shipped with JDK 8u, but only became enabled by default with JDK 9. It is unfortunate that this affects observable behaviour in this case, but conversion between JavaScript and Java types is quite difficult and it’s hard to avoid border cases like this.
java -Dnashorn.args=-ot=false
Hannes
Post by Paulo Oliveira
Hello,
Testing some nashorn scripts on java 9 I got some unexpected behavior.
import java.util.Arrays;
import java.util.List;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
public class Main {
public static void main(String[] args) throws Exception{
ScriptEngine scriptEngine = new
ScriptEngineManager().getEngineByName("Nashorn");
scriptEngine.eval("var imports = new JavaImporter(java.lang.Integer, " +
"java.lang.Long);" +
"var fun1 = function(longs, ints, id) {" +
"with(imports) {" +
"print(id.getId().class);" +
"print(longs.contains(id.getId()));" +
"print(ints.contains(id.getId()));" +
"return Long.valueOf(1);" +
"}" +
"};");
Invocable invocable = (Invocable) scriptEngine;
List<Long> longs = Arrays.asList(1L, 2L);
List<Integer> ints = Arrays.asList(1, 2);
Teste teste = new Teste(1L);
Object result = invocable.invokeFunction("fun1", longs, ints, teste);
System.out.println(result.getClass());
}
}
public class Teste {
private Long id;
public Teste(Long id) {
this.id =id;
}
public Long getId() {
return id;
}
}
Executing the code
Java 8.161
class java.lang.Long
true
false
class java.lang.Long
Java 9.0.4 and 10
class java.lang.Long
false
true
class java.lang.Integer
Nashorn is changing every number that fits a Integer in Integers, even if I
explicit define as Long.
This causes a problem on List.contains, because it receives a Object, if I
try to verify if a long exists in a list of longs, it returns false.
Is it a expected behavior ?
--
*Paulo Oliveira*
*Desenvolvedor BackEnd*
*TEL:* +55 (11) 3634-3378
www.ifood.com.br
<https://itunes.apple.com/br/app/ifood-delivery-e-entrega-comida/id483017239?mt=8>
<https://play.google.com/store/apps/details?id=br.com.brainweb.ifood>
<https://www.facebook.com/iFood?fref=ts> <https://twitter.com/iFood>
--
Paulo Oliveira
Desenvolvedor BackEnd
TEL: +55 (11) 3634-3378
www.ifood.com.br
Loading...