In general, the semantics of the Scala Native language are the same as Scala on the JVM. However, a few differences exist, which we mention here.
Annotations and types defined
scala.scalanative.unsafe may modify semantics
of the language for sake of interoperability with C libraries, read more about
those in Native code interoperability section.
Scala Native supports parallel multi-threaded programming and assumes multi-threaded execution by default. Upon the absence of system threads in the linked program, Scala Native can automatically switch to single-threaded mode, allowing to get rid of redundant synchronization, as the state is never shared between threads.
Scala Native tries to follow the Java Memory Model, but by default uses more relaxed semantics in some areas. Due to the majority of immutable shared states in most Scala programs, Scala Native does not follow Java final fields semantics. Safe publication of final fields (val`s in Scala) can be enabled by annotating fields or the whole class with `@scala.scalanative.annotation.safePublish, this behaviour can be also enabled on whole project scope by providing a Scala compiler plugin options -Pscalanative:forceStrictFinalFields. Semantics of final fields can be also overriden at linktime using NativeConfig.semanticsConfig - it can be configured to override default relaxed memory model, allowing to replace it with strict JMM semantics or disable synchronization entierely.
Scala Native ensures that all class field operations would be executed atomically, but does not impose any synchronization or happens-before guarantee.
Finalize method from
java.lang.Object is never called in Scala Native.
Generally, Scala Native follows most of the special error conditions similarly to JVM:
IndexOutOfBoundsExceptionon out-of-bounds access.
ClassCastExceptionon incorrect casts.
Accessing a field or method on
Integer division by zero throws
There are a few exceptions:
Stack overflows are undefined behavior and would typically segfault on supported architectures instead of throwing
Exhausting a heap space results in crash with a stack trace instead of throwing
Continue to Native code interoperability.