Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are Scala's `AnyVal`s stack allocated?

Tags:

scala

Are Scala AnyVal and its subclasses [can be] stack allocated [like C# structs or Java primitives]? And can we make a customized stack allocated variable like C#'s structs on Scala?

like image 495
Ebrahim Byagowi Avatar asked Jul 12 '12 07:07

Ebrahim Byagowi


4 Answers

A.scala:

class A {
  val a: AnyVal = 1
  val b: Int = 1
}

scalac A.scala

javap -c A

public class A extends java.lang.Object implements scala.ScalaObject{
 public java.lang.Object a();
  Code:
   0:   aload_0
   1:   getfield        #13; //Field a:Ljava/lang/Object;
   4:   areturn

 public int b();
  Code:
   0:   aload_0
   1:   getfield        #16; //Field b:I
   4:   ireturn

 public A();
  Code:
   0:   aload_0
   1:   invokespecial   #22; //Method java/lang/Object."<init>":()V
   4:   aload_0
   5:   iconst_1
   6:   invokestatic    #28; //Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
   9:   putfield        #13; //Field a:Ljava/lang/Object;
   12:  aload_0
   13:  iconst_1
   14:  putfield        #16; //Field b:I
   17:  return
}

So explicit AnyVal usage leads to boxed primitive on the heap, as expected.

like image 186
ron Avatar answered Nov 10 '22 21:11

ron


AnyVal subclasses are stack allocated, where possible. The exception happens with newer user-created classes that extend AnyVal on 2.10.0, if the object escapes the scope.

Any and AnyVal will be stored on the heap... unless you @specialized.

like image 42
Daniel C. Sobral Avatar answered Nov 10 '22 23:11

Daniel C. Sobral


I'm also new to Scala, but AFAIK, a Scala variable can not contain an actual object. It can at most contain a reference to an object. (You get a reference from new and there's no dereference operator to follow that reference to an object (such as * in C++ for instance).)

In other words, all non-primitive values live on the heap. (Just as in Java.)

like image 3
aioobe Avatar answered Nov 10 '22 21:11

aioobe


The JVM does not support reification of generics and provides no means of having a primitive super type for all primitive types. Thus a field or parameter of type AnyVal will always be of type java.lang.Object in the byte code and boxing/unboxing will be performed.

This does not necessarily mean that the value is stored on the heap though as the JVM may perform certain optimizations. You have to still expect a runtime penalty though.

like image 3
Moritz Avatar answered Nov 10 '22 21:11

Moritz