0

So I'm wondering how is a value returned in Java. If I call function B from function A then we would allocate B's stackframe onto the callstack. Lets say in B we create a variable called Var and we want to return Var to A. If B's stackframe is popped off the stack during the return, and Var is a part of B's stackframe, does'nt Var cease to exist? So how do we return a variable from method B to A?

dan1881W
  • 3
  • 2
  • 4
    A picture is worth a thousand words. Show us a code example. I'm pretty sure I'm not alone in not being able to hold all of these `A`s, `B`s and `Var`s in my head while I also try to figure out what you're asking – Michael Jul 11 '19 at 16:31
  • `String B() { return "A"; } void A() { System.out.println(B()); }` Seems that it continues to exist. – BeUndead Jul 11 '19 at 16:32
  • You don't return a variable, you return a value. It may be so that the value you return happens to be the value that a specific variable happened to have at the return expression, but that changes nothing. As for how do you return a value, Java leaves the JVM actually free to do that as it sees fit. But the typical approach is, when you call a method that can return something, you add an empty space in the stack where the called method can store its returned result. That's more a part of the caller's stack than of the callee's stack. – kumesana Jul 11 '19 at 16:51
  • An object's reference value can exist in different stacks simultaneously. – Compass Jul 11 '19 at 17:07
  • There are two layers to this. First, the java compiler generates byte codes based on the program source. Byte code generation is specified for providing method parameters and handling return values. Second (typically, but not necessarily), the byte codes are processed by the JIT (just-in-time compiler), which is free to process the generated bytes codes however the JIT sees fit. For example, method invocations can be entirely omitted by being inlined. The question as given is answerable at the byte code level, and hard to answer at the JIT layer. – Thomas Bitonti Jul 11 '19 at 17:09

2 Answers2

0

To get the point how the value returning works, probably it would be better to move down to low level programming, mainly for better understanding. Let's say we executed a method for certain reasons and the result of that method was something that would be returned. The result would be saved in a special register in memory which is responsible only for saving the values that returned from the methods. In low level programming languages(like Assembly) it is noted $v0. I do think that there are two returning registers $v0, $v1. SO lets consider the following example: We have 3 methods. A(), B() and C(). A() needs a value from the B() method and B() needs a value from the C() method. In the compilation process the C() method will be executed first and a special register called Return Address($ra) will remember where the method C() was called(lets say it was called at position 0x100). Also let's suppose that the position of C() in memory is 0x200. Once C() finishes executing the register $v0 will contain the value that C() returned. Now in order to go back and continue executing method B() we have to jump at the address that we saved in $ra. That is made with a function called jr(jump register) - jr $ra. In order to use the returned value from C() now we can access the $v0 register which contains the needed information. Once it is accessed, the value of the $v0 register is not safe anymore, so it might change in any moment, but we have the job done. Same works for B() in which the return value will be overridden in the $v0 and will be used by A(). Actually this job is done by JVM, and the steps followed might not be exactly the same, but in general that is the way how it works.

Shpend Palushi
  • 597
  • 8
  • 21
0

Fully answering this will require understanding of java byte codes, which I'm leaving as an exercise. Java byte codes are detailed here:

https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html

For example 'lreturn' has this description:

Return long from method

The current method must have return type long. The value must be of type long. If the current method is a synchronized method, the monitor entered or reentered on invocation of the method is updated and possibly exited as if by execution of a monitorexit instruction (§monitorexit) in the current thread. If no exception is thrown, value is popped from the operand stack of the current frame (§2.6) and pushed onto the operand stack of the frame of the invoker. Any other values on the operand stack of the current method are discarded.

The interpreter then returns control to the invoker of the method, reinstating the frame of the invoker.

The starting point is the java utility "javap", which would be invoked with "-v to produce a verbose display of a target class:

javap -v Tester.class

For example, for the code:

    private final long longV;

    public long getLong(long adj) {
        return longV + adj;
    }

These byte codes are generated:

  public long getLong(long);
    descriptor: (J)J
    flags: ACC_PUBLIC
    Code:
      stack=4, locals=3, args_size=2
         0: aload_0
         1: getfield      #135                // Field longV:J
         4: lload_1
         5: ladd
         6: lreturn
      LineNumberTable:
        line 77: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       7     0  this   Lmy/tests/Tester;
            0       7     1   adj   J
Thomas Bitonti
  • 1,179
  • 7
  • 14