Documente Academic
Documente Profesional
Documente Cultură
other OOP language (like C#) you must know how things are managed internally by the Java
process and by the JVM. Of course Java syntax and Java implementations of OOP principles
are important but you will have a more clear image about the application resources,
memory, performance, argument passing, threads and garbage collection if you put
questions beyond How I do that ? or How I write that ?. The real questions should be How or
Why it is happening like this ? (of course, at some point you should stop and move forward).
In this post I will describe how the application variables are managed, regarding where they
are stored (Stack or Heap) and for how long.
Other topics that are part of this Java tutorial are accessible through Java 6 Tutorial
Contents
the stack size is fixed and it is determined in the compiler phase based on variables
declaration and other compiler options;
it is important to establish that the stack is limited and its size is fixed (one the
process has started, it cant change the stack size);
most of the time, the stack it is used to store functions/methods variables (input
arguments and local variables).
each method has its own stack (a zone in the process stack), including main, which
is also a function.
a method stack exists only during the lifetime of that method: from the calling
moment until the return moment;
Heap:
a memory space managed by the OS and used by processes to get additional space
at run-time;
this area it is a global, meaning that any process can use it (of course, processes
cant read or write in another process Heap reserved area);
the role of this memory is to provide additional memory resources to processes that
need that supplementary space at run-time (for example, you have a simple Java
application that is constructing an array with values from console);
//instance variable
String name;
//instance variable
public Student()
{
this.age = 0;
name = "Anonymous";
}
public Student(int Age, String Name)
{
this.age = Age;
setName(Name);
}
public void setName(String Name)
{
this.name = Name;
}
}
public class Main{
public static void main(String[] args) {
Student s;
//local variable - reference
s = new Student(23,"Jonh");
int noStudents = 1;
//local variable
}
}
In order to determine the minimum space (because we focus only on the important elements
and we keep things as simple as possible) lets analyze the Stack requirements. In the next
paragraph I describe each method stack separately but in the end all these are placed on
the same stack, the application stack.
We start with the main method because for a Java process everything begins and ends
with main. The main local variables, or variables stored on its Stack are:
the calling object reference, named this; (remember: each non-static class method
it is called by an object and that object reference is passed to the method as this)
For the previous example, when the constructor with arguments it is executed, the call stack
looks like this:
the Student memory area in Heap is created by calling the new operator and the
class constructor;
the String value is created during the object initialization inside the class constructor.
protected
private
constructor methods;
access functions(get and set);
processing methods;
Regarding the declarations of attributes and methods there are no rules on how they should
be defined, but code management is easier if the code and attributes are defined grouped.
3.
the Java source file containing the public class has the same name as the public class
(case sensitive); Book.java contains public class Book ;
4.
the code block of a class is defined by { and };
5.
if in a source file, .java, are defined more classes, then by compiling the source file
there are obtained bytecode files, .class, for each class.
Based on the simple syntax, we define a simple Java class that describes a book. The book is
described by its attributes price, title and author , and the behavior is defined by its
methodsgetPret() and display().
class Book{
//define attributes - instance variables
float price;
String title;
String author;
//define methods
public float getPrice(){
return price;
}
public String display(){
return "The book "+titlu+" has as author "+author;
}
}
The object variable that represents a reference (pointer) manages an address from the
Heap.Through this address we have access to the memory area reserved for the object. In
this zone we find its attributes values.
By defining a simple class variable, you get a reference with the default value equal to null.
To give a value to this reference you must built (instantiates) the object using new.
Access to object attributes and methods outside the class, as in the previous example in
which the object is used in TestBook class, can be controlled by access modifiers (public,
private, protected, that will be analyzed in detail in another post).
In this tutorial arrays are analyzed with primitive values, and after we see classes and
objects related concepts we will analyze arrays of objects.
//array definition with Java recommended syntax
int[] intValues;
//define array with vector-like sintax in C/C++
long longValues[];
//allocating space = array initialization
intValues = new int [10]; // 10 elements with value 0
longValues = new long [5];
//5 elements with value 0
Initialization of separate elements is done using operator []. ( WARNING! index used to
access the elements has values in [0, length-1])
intValues [0]
intValues [1]
intValues [2]
=
=
=
10;
20;
30;
If we consider that the array variables (pointers or references) are allocated on main
function stack, and the array elements space is reserved in HEAP, then the data memory
image is:
In this way the object becomes eligible for garbage collector because we dont have any
other reference used to reach the object.
2. Reassigning the reference we make the previous object unreachable:
public class Main{
public static void main(String[] args)
{
int[] intArray = null;
//request space in Heap
intArray = new int[10000];
//process your data
//...
//create a new object and use the same reference
//the previous array values are becoming eligible for GC
intArray = new int[99];
}
}
In this way the first object becomes eligible for garbage collector because we dont have any
other reference used to reach the object.
3. Isolating a reference it is a more hidden scenario because at a first glance you may say
that your object is still alive. If we consider the next class:
class Student{
int age;
int[] marks;
//instance variable
//instance variable
public Student()
{
this.age = 0;
marks = new int[10];
}
}
you can see that every Student object contains an array reference as an instance variable. If
we test the class like this
public class Main{
public static void main(String[] args)
{
Student s = null;
//request space in Heap
s = new Student();
//process your data
//...
//remove the reference
s = null;
}
}
it is clear that the Student object is going to be collected by the GC. But, what is going to
happen with the integers array inside the object. If we analyze the Heap, we can see that
the array object is still reachable through the marks reference.
non-access modifier define other attributed for the method like: static (the method is
defined at class level its not an object method), final (the method cant be overridden in
subclasses),abstract (the method cant be instantiated because contains abstract methods
virtual pure methods)
return_type any primitive or reference type; if the method doesnt return a value then the
return type is void; if you define a return type, then the method must end with a return
value/variablestatement, where the value/variable type is the defined return type:
public class Test {
public static void main(String[] args) {
int vb1 = 10;
int vb2 = 20;
//calling the doSum method
int sum = doSum(vb1, vb2);
System.out.println("The sum is "+sum);
}
public static int doSum(int a, int b)
{
int result = a + b;
return result;
}
}
method_name must respect the same naming convention used for variables; Java
recommends using camelCase naming convention (the first word starts with a small letter);
also, the names should be verb-noun pairs, like getName, doSum;
parameters represent the input values (primitive or references) for the method; regarding
parameters you must know this:
the method header variables are called parameters; when you call a method, the
input values are called arguments;
methods input parameters are local variables for the method;
you can define a variable number of input parameters var-arg methods;
class MyValue
{
public int value;
}
public class Main {
public static void main(String[] args) {
int vb1 = 10;
int vb2 = 20;
//calling the doSum method
int sum1 = doSum(vb1, vb2);
System.out.println("The sum is "+sum1);
MyValue ref1
MyValue ref2
ref1.value =
ref2.value =
= new MyValue();
= new MyValue();
100;
200;
Despite the doInterchange() method is implementing the correct algorithm, the output is
not the expected one because, based on the previous rule, the method is interchanging the
values of its own local variables a and b.
So we must write a better method, that will interchange the values of 2 main variables. Lets
try with references by boxing the 2 integers into their corresponding objects, like this:
public class Main {
public static void main(String[] args) {
int vb1 = 10;
int vb2 = 20;
doInterchange2(vb1, vb2); //the values are boxed by default
System.out.println("vb1 = "+vb1+", vb2 = "+vb2);
}
public static void doInterchange2(Integer ra, Integer rb)
{
int temp = ra;
//default unboxing
ra = rb;
rb = temp;
//boxing
}
}
{
void main(String[] args) {
10;
20;
because the references from main stack and from doInterchange3 stack reference the same
objects in Heap:
aValue = bValue;
bValue = temp;
}
Remember, aValue reference value is the copy of the value1 reference value.
Another solution, is to use an array as a wrapper for the primitive values, like this:
public class Main
public static
int vb1 =
int vb2 =
{
void main(String[] args) {
10;
20;
Regarding how to pass variables into methods in Java you must also read: