Friday, December 8, 2017

λ calculus

Rules of the universe

0. Permitted keywords: Everything in lambda calculus is function. All the algorithms are represents with functions. There are only 2 keywords, λ and . needed to write a function. And that's it. Everything between λ and . are function arguments, everything after "." is the function body.
Example: λx.x+1 represents a function, that takes an argument x and returns x+1. Note that, x can be replaced by any other names.
A few notes
    a. A function can be written in such a way so that it always takes only 1 argument.
    Example: λxy.(x+y) can be written as, λx.(λy.(x+y)). If this function is applied to argument 3 4 then, the following happens
    (λx.(λy.(x+y))) 3 4 => (λy.(3 + y)) 4 => (3 + 4) => 7
    Writing a function such that it always takes only 1 argument is called function Currying (named after Haskell Curry).
 
    b. functions do not have names. We can say, a function A = λx.x+1, when we say the function does not have a name, we say from inside the function body, we do not know the name of function. So we cannot write a function, A = λx.A(x) because, from the function body we don't have access to names of the caller A.
 
    c. When we say fx we mean f is applied on x, f(x). ABCDE means A, B, C, D and E are functions and is applied the following way
    ((((AB)C)D)E)
    which means A is applied to B, the resulting function is applied to C so on and so forth.

1. Application and value substitution:
Example: A = λx.x+1; A3 means the function A is applied on the value 3. All the x s in the expression x+1 will be replaced by 3. This is expressed as [3/x](x+1) = 3 + 1 = 4

2. Reduction:
By application and substitution, a complex function might be reduced to small one.
Example: (λx.(λy.y))ts = s

Building Blocks of the Universe

Boolean value construction
0. True:
As stated earlier everything in the universe will be functions. The value True is represented as the following function
T : λ xy.x . Basically the true function takes 2 arguments and return the first argument.
1. False:
False, F is represented by the following function.
F : λ xy.y . This function takes 2 arguments and returns the second argument.

Boolean Operations
And, ^:
^ : λxy.xyF
Or, v:
v : λxy.xTy
Not, ¬:
¬ : λx.xFT

Arithmatic value construction
Integers:
0, 1, 2, .. n are all represented by functions that takes two arguments.
0: λfx.x This means the function 0 takes two arguments f and x and applies f on x zero times.
1: λfx.f(x) , 1 takes two arguments, f, x and applies f once to x
2: λfx.f(fx) , 2 takes two argument f, x and applies f twice on x
3: λfx.f(f(fx)) 3 takes two argumetns f,x and applies f three times on x.
so on and so forth
Pairs:
A pair holding two integers a and b is represented by the following function
p : λx.xab
Retrieve the first element from p, pT => (λx.xab)T => Tab => a
Retreive the second element p, pF => (λx.xab)F => Fab => b

Arithmetic Operations:
Successor:
S: λxyz.y(xyz)
Example: S0 => (λxyz.y(xyz))0 => λyz.y(0yz)
            => λyz.y((λfx.x)yz) => λyz.y(z)
            => λfx.f(x) [renaming variable y with f and z with x]
            => 1 [from definition of 1 function]

(+ a b):
+ : (λab.aSb)
Example: (+ 2 3) => 2S3 => (λfx.f(f(x)))S3 => S(S(3)) => S(4) => 5

Predecessor, P:
We want to know the predecessor of 3. Basic idea,
start with the pair holding (0,0) then convert it the following order
(0,0) -> (1, 0) -> (2, 1) -> (3, 2) -> take second element of the pair, which yields 2.
we need a function Φ, that would take a pair (n, n-1) and would generate (n+1, n)
Φ: λpz.z(S(pT)(pT)) => lets say pair , p holds (3, 2). new pair will hold (S(pT), (pT)) => (S(3), 3) => (4, 3)
We can define P: (λn.nΦ(λz.z00))F which means Φ is applied to the pair (0,0) for 3 times and the second element of the pair is taken in the end.

(- a b) :
- = (λab.bPa)
Example: (- 3 2) => 2 P 3 => P(P(3)) => P(2) => 1

Conditionals:
Conditional such as a == b, a >= b or a <= b etc can be expressed by function.
(>= a b):
a >= b check can be done with the following function 
>= : (λab.Z(- b a))

(== a b):
a == b check can be done with the following function 
== : (λab.( >= b a) ^ (>= a b))

Recursion:
The λ functions don't have name, so from inside the body it is not possible to call the * function. Recursive calls are made using Y combinator.
Y : (λ f  . (λ x .  (f (x x)) (λ x . f (x x))))

R is a function that needs to be called recursively. Then, Y is applied to R
YR = Y(R) = (λ x. (R (x x)) (λx. R (x x)))
= R ((λ x. (R (x x)) (λx. R (x x)))) [value substitution]
= R (YR) ...... 
= R(R(R(R....(YR))))

We can see that YR is being computed with computing R first, one return value of R is used to compute caller's value.

Example:
we want to compute (1+2+3+...+n)
R : (λrn.Zn0(+ n r((- n 1))))
R is a function that takes 2 arguments, n and r. 
In base case, n become 0. Zn returns T then T gets two arguments 0 and (+ n r((- n 1))). We know T always returns the first argument so in this case R will return 0.
if n > 0 then Zn returns F. F would return the second argument (+ n r((- n 1))), which means it would return n + r(n-1)
Example evaluation:
YR3 = R(YR)3
= (λnr.Zn0(+ n r((- n 1)))) (YR) 3
= Z 3 0 (+ 3 YR(- 3 1))
= Z 3 0 (+ 3 YR2)
= F 0  (+ 3 R(YR)2)
= (+ 3 (λnr.Zn0(+ n r((- n 1)))) (YR) 2)
..........
= (+ 3 (+ 2 (+ 1 0) ))
= 6



References
[0] computerphile video on lamda calc: https://www.youtube.com/watch?v=eis11j_iGMs
[1] Dason's slide: https://www.slideshare.net/g33ktalk/lambda-calculus-by-dustin
[2] friendly explanation: http://www.inf.fu-berlin.de/lehre/WS03/alpi/lambda.pdf
[3] Dustin's presentation: https://www.youtube.com/watch?v=E5DwIxGOu1E

Saturday, December 2, 2017

SML syntax and functional programming concepts

Expression
All the expression from 1 and below must be used in a function.

0. Function
A function would take zero or more parameters and will always return a value.
fun foo () = 3
fun sqr (x, y, z) = x + y + z
A function always takes a parameter, either in the form of tuple or currying (discussed later).

1. let
A let expression lets extend the current environment by letting the creation of variables and functions. has to be used inside a function. example
fun foo (x) = let y = x * x in y end

2. if then else 
An if then else construct has to always return a value. the type of the value must be same from each of the branch. has to be used inside a function. example:
if x = 3 then true else false

3. pattern matching
Given a value, takes the branch that matches the data type of the value. example:
case exp of
    [] => NONE
   | Some x => do something

Environment
0. Extending environment
Any time a variable, function is declared, current environment is extended by a new binding.
| y = 3 | z = 5| x = 5  <=== current environment
val p = 3
| y = 3 | z = 5| x = 5| p =3  <=== updated environment
A new variable can be introduced from a pattern matching expression. Example:
case lst of
 x :: xs => do something (* :: is the append function which is declared as infix *)

1. Shadowing
introducing a new binding does not override a value in the environment, rather a new entry is created and from that scope new entry's value is used.
| y = 3 | z = 5| x = 5  <=== current environment
val y = 3
| y = 3 | z = 5| x = 5| y =3  <=== updated environment

2. Closure
Combination of a function and a pointer of the environment is closure.
Example:
val y =3
val z = 5
fun foo = z + 3
val z = 5
val y = 3
val closure = foo
closure has the instruction pointer of the function foo and the following pointer of the environment
| y = 3 | z = 5| z= 5| y =3  <=== updated environment
                    ^
  <======  | | to get a value of a variable, closure will start from the pointer and go left.


Datatype and Accessing data
0. Record, Tuple
Records are created dynamically. They can have any number of fields in them.
Example: {first="isaac", middle="buddha", last="christ"}
A type can be given a name. Example
type set = { insert : int -> set, member : int -> bool, size : unit -> int }

1. List
Lists are immutable. An insertion or deletion would always cause a new list to be created with desired elements.
Example:
[] is empty list
"a" :: [] (* insert an element at the head *)
["1, 2, 3, 4] @ [5, 6, 7, 8] (* append operator *)

2. Custom data type
datatype myType = StudentInfo of string * string | Grade of int

val myInfo = StudentInfo ("isaac", "christ").
Datatypes can be pattern matched.

Modular Programming
It can be think of like a Java package. Gives client visibility of enough information so that they can import the library in their code and use it. Best practice is to provide just enough information so that a client executes the given program with minimum risk.
Example:
signature MATHLIB =
sig
    val fact : int -> int
    val half_pi : real
    val doubler : int -> int
end

structure MyMathLib :> MATHLIB =struct
     fun fact x = if x=0 then 1 else x * fact (x - 1)
     val half_pi = Math.pi / 2.0
     fun doubler y = y + y
end

Mutability
Variables can be mutated through reference.
val x = ref 7 (* the memory location x points to holds the value 7 *)
val y = x (* y points to same memory location as x does *)
val z = ref 7 (* the memory location z points to holds 7 *)
val _ = x := 20 (* := operator is for assigning value, := operator returns unit *)
val p = !x (* retrieve content of x, p get 20*)
val q = !y (* q has 20 *)
val r = !z (* r has 7 *)

Misc

0. Higher order function
functions that can take another function and return a function as a return value.

1. Anonymous function
functions that does not have names.
fun foo bar x = bar x
val v = foo (fn (x) => x+1) 1

2. Currying
Curried functions always takes 1 argument and returns either a value or another function. Curried functions use closure to access variables it uses. Curried functions can be called with less arguments.

3. Tail recursion
A recursive call where the caller just returns the value the callee returns without applying any application on the callee's returned value. more can be seen [1].

4. Syntactic sugar
Certain language features that lets a programmer do a certain task with less amount of typing.
Example:
fun f = fn (x) => (fn (y) => (fn (z) => x + y + z))
f can be written using syntactic sugar fun x y z = x + y + z

5. map, filter, fold
these functions are applied on a list.
map => converts each item of the list to something else (* convert degree list to celcius list *)
filter => returns a list where every item meets a certain criteria (* get students who passed *)
fold => returns value that depicts certain attribute of a list (* get sum of the values of a list *)

6. value restriction
Because of mutability, it might be possible to assign value with wrong type on a variable. The value would not be shadowed rather overwritten. Initially, if we say we are able to say we would be storing a polymorphic data in a certain memory location, then later we might try to assign wrong type values in that memory location.
Example:
val r = ref NONE (* system does not which type will go where r is pointing to *)
(* type of r is given ?.X1 option ref type *)
r := SOME "abc" (* trying to assign string *)
r := SOME 1        (* trying to assign int *)
To prevent this, the variable declaration must have a concrete type, otherwise system will give r a type to make r not usable anymore.
That's why we cannot do the following
val funhandle =  map (fn (x) => (x, 1))

The following works, as it have concrete type
val r : int option ref = ref NONE;

Value restriction is introduced only for mutability or ref type. This restriction is generalized because many times the compiler cannot tell about a type. One case being types introduced through modular programs.

Reference:
[0] https://www.coursera.org/learn/programming-languages
[1] http://www.saifulabu.me/2017/11/tail-recursion.html

Wednesday, November 29, 2017

Tail Recursion

We want to compute sum from 1 + 2 + .. + n

In an imperative programming language, we would write something like

sum = 0
for(int i = 1; i < n; i++){
    sum = sum + i;
}

In a functional programming language, we don't have looping mechanism. We will have to use recursion to get the task done

Version: 1
sum(n){
    if n = 0
    then 0
    else 0 + sum(n-1)
}

The second program will be slower, as there will be n activation record will be created for n function calls. For large value of n, it might cause No Memory Exception.

This problem can be solved by writing the above program differently,

Version: 2
sum(n, res){
   if n = 0
   then res
   else sum(n-1, res+n)
}

Initial call to the function will be, sum(n, 0).

If compared with the first version of the function, the second version of the function does not do anything after it receives the return value of calling function. The later version is called tail recursive function, caller does not do anything after the callee returns, it merely return the value returned by the callee. If a functional programming execution engine detects a tail recursive function, it does not create new activation records for callee functions, callee functions just reuses activation records of the caller.

Source
[0] https://www.coursera.org/learn/programming-languages/lecture/YZic1/tail-recursion


Thursday, November 2, 2017

Do What I want

Imagine, I am letting a friend use my apartment. I can tell them how, I want them to clean the apartment -

How I want x to clean my apartment [2]

1. Take a picture of the place.
2. Focus on rooms you will actually use.
3. Pick up dirty clothes and towels.
4. Deposit empty glasses or dirty dishes into the sink.
5. Caddy your cleaning supplies.
6. Give the toilet, sink, and bathroom mirror a quick clean.
7. But just keep the shower curtain closed.
8. Tidy up the surfaces.
9. Toss stuff in baskets.
11. Take out the trash.
13. Take care of pet hair.
14. And vacuum
15. Fluff the couch pillows.
16. Spray a scent or light a candle.

Or I can tell them What I Want


Leave the apartment as it was before


Quicksort in C++. Code snippet taken from [0]

//Quick Sort Functions for Descending Order
// (2 Functions)

void QuickSort(apvector <int> &num, int top, int bottom)
{
      // top = subscript of beginning of array
      // bottom = subscript of end of array
      

     
int middle;
     if (top < bottom)
    {
          middle = partition(num, top, bottom);
          quicksort(num, top, middle);   // sort first section
          quicksort(num, middle+1, bottom);    // sort second section
     }
     return;
}

//Function to determine the partitions
// partitions the array and returns the middle subscript

int partition(apvector <int> &array, int top, int bottom)
{
     int x = array[top];
     int i = top - 1;
     int j = bottom + 1;
     int temp;
     do
     {
           do  
           {
                  j - -;
           }while (x >array[j]);

          do
         {
                 i++;
          } while (x <array[i]);

          if (i < j)
         {
                 temp = array[i];    
                 array[i] = array[j];
                 array[j] = temp;
         }
     }while (i < j);     
     return j;           // returns middle subscript  }

Quicksort in Haskell. Code snippet taken from [1]


  1. quicksort :: (Ord a) => [a] -> [a]  
  2. quicksort [] = []  
  3. quicksort (x:xs) =   
  4.     let smallerSorted = quicksort [a | a <- xs, a <= x]  
  5.         biggerSorted = quicksort [a | a <- xs, a > x]  
  6.     in  smallerSorted ++ [x] ++ biggerSorted

>> What I want not How I want!


[0] https://mathbits.com/MathBits/CompSci/Arrays/Quick.htm
[1] http://learnyouahaskell.com/recursion
[2] https://makespace.com/blog/posts/how-to-clean-your-apartment-fast/

Sunday, October 15, 2017

[JVM-1] Byte code file structure

Java byte code has a structure so that the virtual machine knows where to look for which information. Usually, an assembly program has the following structure.
Data segment:
  //goes constant
  //array initialization and declaration
  //global variables
Code segment:
  //several sub routines that act on top of the data segment.

Byte Code File Structure:
Byte code has similar structure. It's Data segment follows a very specific format.
  Class_File_Format {
     u4 magic_number;

     u2 minor_version; 
     u2 major_version;

     u2 constant_pool_count; 
   
     cp_info constant_pool[constant_pool_count - 1];

     u2 access_flags;

     u2 this_class;
     u2 super_class;

     u2 interfaces_count; 
   
     u2 interfaces[interfaces_count];

     u2 fields_count; 
     field_info fields[fields_count];

     u2 methods_count;
     method_info methods[methods_count];

     u2 attributes_count; 
     attribute_info attributes[attributes_count];
  }

constant pool is one of the main parts of the bytecode file. It hold's the constants, variable names, method names, interfaces this class implements etc.

One interesting this is the magic number at the beginning for any java byte code file is always OxCAFEBABE. JVM won't read this file if this magic number is not found at the begin.

Constructors:
In byte code files, constructors are treated differently. All the constructors are replaced by a bytecode method <init> (parameters).

// In source packet in file init/ex8/CoffeeCup.java
class CoffeeCup {
    public CoffeeCup() {
        //...
    }
    public CoffeeCup(int amount) {
        //...
    }
    // ...
}
the compiler would generate the following two instance initialization methods in the class file for class CoffeeCup, one for each constructor in the source file:

// In binary form in file init/ex8/CoffeeCup.class:
public void <init>(CoffeeCup this) {...}
public void <init>(CoffeeCup this, int amount) {...}

Reading byte code
java Test.java  ==> produces Test.class
xxd Test.class  ==> reads byte codes of the class
javap -verbose Test.class ==> view the constant pool area
javap -c Test.class  ==> only shows the instructions

Example:
  class Test{
    public static void main(String args[]){
      int i = 0;
      int j = 1;
      for(i = 0; i < 10; i++){
        j = j + 1;
      }
    }
  }

  javap -verbose Test.class output is following
    Classfile /Users/sa050870/Desktop/blog/javacompile/Test.class
    Last modified Oct 3, 2017; size 325 bytes
    MD5 checksum e48f946daadcae98c0ce5bcc07ac8094
    Compiled from "Test.java"
  class Test
    minor version: 0
    major version: 52
    flags: ACC_SUPER
  Constant pool:
     #1 = Methodref          #3.#13         // java/lang/Object."<init>":()V
     #2 = Class              #14            // Test
     #3 = Class              #15            // java/lang/Object
     #4 = Utf8               <init>
     #5 = Utf8               ()V
     #6 = Utf8               Code
     #7 = Utf8               LineNumberTable
     #8 = Utf8               main
     #9 = Utf8               ([Ljava/lang/String;)V
    #10 = Utf8               StackMapTable
    #11 = Utf8               SourceFile
    #12 = Utf8               Test.java
    #13 = NameAndType        #4:#5          // "<init>":()V
    #14 = Utf8               Test
    #15 = Utf8               java/lang/Object
  {
    Test();
      descriptor: ()V
      flags:
      Code:
        stack=1, locals=1, args_size=1
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return
        LineNumberTable:
          line 1: 0

    public static void main(java.lang.String[]);
      descriptor: ([Ljava/lang/String;)V
      flags: ACC_PUBLIC, ACC_STATIC
      Code:
        stack=2, locals=3, args_size=1
           0: iconst_0
           1: istore_1
           2: iconst_1
           3: istore_2
           4: iconst_0
           5: istore_1
           6: iload_1
           7: bipush        10
           9: if_icmpge     22
          12: iload_2
          13: iconst_1
          14: iadd
          15: istore_2
          16: iinc          1, 1
          19: goto          6
          22: return
        LineNumberTable:
          line 3: 0
          line 4: 2
          line 5: 4
          line 6: 12
          line 5: 16
          line 8: 22
        StackMapTable: number_of_entries = 2
          frame_type = 253 /* append */
            offset_delta = 6
            locals = [ int, int ]
          frame_type = 15 /* same */
  }
  SourceFile: "Test.java"
 

Reference
[0] object initialization in java. https://www.javaworld.com/article/2076614/core-java/object-initialization-in-java.html
[1] hacking java byte code. https://www.acloudtree.com/hacking-java-bytecode-for-programmers-part3-yes-disassemble-with-javap-all-over-the-place/
[2] Inside the Java 2 virtual machine. Bill Venners. http://www.artima.com/insidejvm/ed2/
[3] Java class file architecture, wikipedia. https://en.wikipedia.org/wiki/Java_class_file
[4] JVM specification. https://docs.oracle.com/javase/specs/jvms/se7/html/index.html

start from here https://www.javaworld.com/article/2076614/core-java/object-initialization-in-java.html?page=2

Thursday, October 12, 2017

[Philosophy] In search of the true family

Today while walking through dense fog of Missouri, Kansas City a thought suddenly struck my mind. Why I keep running? I recalled my past. God knows, I worked as hard as hell to stand where I am standing today. Even when I was a young kid, I would wake up when it is still one or two hours for sun rise. I would wash my face with icy-cold water, I would pray to Almighty to show me path, to take me where I should go, then I would start my work. I would study and I stop only when it was time to go to school. If I wanted to do something, I never looked for a shortcut. I would always learn every material diligently, tried to think about them, understand them, never looked for memorizing something. I always wanted to go deep. Years after, even today I woke up at 5:30 in the morning, started looking at a MIT course material name "Hacking a Google code interview". During my undergrad days, I lost myself. I had a wrong thought that talent is all about something God-gifted. At this point of life, after realizing earnest and mindful work always beats a talent, I started educating myself again. I choose the topics that I felt I should be good at. So everyday, I would wake up at 5 am, educate myself on the knowledge I want to know. I would go to work, work for 9 hours, I would come back home take 2 hour of rest and from 7:30 pm I would start educating myself again. I have been doing this for days after days, months after months. I asked myself Why am I doing this?

Suddenly today my heart spoke. I have been living in several places. As I live in a place, I have to leave some of my parts there. With the help of that place, I transform some part of myself and become a modified person. I have to shed incompatible part of me that would not go with that place and let new parts grow in myself. May be, all I am looking for is a family. A family where members live under the shed of joy and respect. Their discussions are not trivial, their work is synergistic and solid. They don't take life for only merry-making. They work, think, reflect, invent, create necessity, fullfill the necessities and thus earn honest living. I believe, the members of true family do not grow up under the same roof. One member of the true family may be from Bangladesh, another may be from Africa, another may be from China, USA or Brazil. I have met many many people at many different parts of the world. I keep talking with them, I keep asking them what makes them happy. May be I do this because, someday, somewhere, some person will say something that will change my world forever. May be all these self modifications are taking me closer and closer to my family, to the people I truly belong. 

Wednesday, October 4, 2017

[JVM-0] Architecture of JVM

Java and Java Platform

Java has 4 core parts
  0. Language: a programmer uses it to write programs
  1. Class file format: java compiler translates it to byte codes to be executed by jvm
  2. JVM: an application that executes bytecode
  3. API: to interact with host machine

Java platform has 2 parts
  0. API
  1. JVM

A Java program runs on a Java platform.

Java program execution

Here are the steps to run a java program on a Java platform.

0. programmer writes java code

  class Test{
    public static void main(String args[]){
      int i = 0;
      int j = 1;
      for(i = 0; i < 10; i++){
        j = j + 1;
      }
    }
  }

1. Compile and produce byte code
              javac Test.java
bytecode has instruction that is targeted for a virtual architecture, java virtual machine.

javap -c Test.class produces the following output

class Test {
  Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_0
       1: istore_1
       2: iconst_1
       3: istore_2
       4: iconst_0
       5: istore_1
       6: iload_1
       7: bipush        10
       9: if_icmpge     22
      12: iload_2
      13: iconst_1
      14: iadd
      15: istore_2
      16: iinc          1, 1
      19: goto          6
      22: return
}

2. user starts jvm by the command,
                java Test
Note: a jvm only runs a single application. jvm takes a class file as an agrument. the class file must have the main method with proper signature.

3. jvm loads, interprets the byte code and runs on host system.


Parts of JVM

0. Class loader: locates and imports byte code to jvm's memory.
    a. checks correctness of a type.
    a. on method area, loads byte code, initializes class variables. on heap creates Class object.
    b. links bytecode of method area with Class on heap.

there are two types of class loader
    a. bootstrap class loader: loads java api from installation location. this is part of jvm and written in c++ probably.
    b. user defined class loader: java classes created by user. these are objects in heap.

1. Method area: class loader loads byte code instructions to this place. For each class following information are stored
    a. fully qualified name of the type
    b. super class
    c. is it class or interface?
    d. modifier (public, abstract, final)
    e. constant pool: constants used by this type
        - string, int, float,
        - other classes used by this class (initially it holds only a symbolic link(fully qualified name), later when those classes are loaded to method area and in heap, those symbolic links are replaced by reference to class)
    f. field information (field name, type, modifier)
    g. method information
      0. name
      1. return type
      2. argument info
      3. modifier
      4. bytecode
      5. number of local variables
      6. size of operand stack
      7. exception table
    h.  class variable: all class's get a copy of static-final variable. static non-final are stored method area.
    i. class loader reference: reference to the loader that loaded this class.
    j. method table: instruction memory address for each method's start.

2. Java stack: each thread has separate java stack. only push and pop operations are allowed. contains stack frames for methods. each stack frame holds following information of a method
  a. parameters
  b. local variables
  c. operand stack
  d. return val
  e. return address
  f. exception table


      if an exception occurs and not catch clause found for that instruction, jvm causes the method return abruptly and re-throws the exception to the callers context.
one thread cannot access another thread's java stack.

3. Program counter: each thread gets one entry in the program counter (pc). pc remembers the next instruction to be run for a thread.

4. Heap: objects gets created in this area.

5. Execution engine: Fetches instructions from method area, translates and executes them. instructions acts on the data on java stack and heap. each thread is an execution engine. Interpreted byte code is cached and accessed if necessary.
2 popular techniques
  a. just in time compile: One by one, takes byte code, translates to native code, executes.
  b. adaptive: acts just like jit except as soon as it finds a code that is being used a lot of time(hot spot) it forks a thread. the thread heavily optimizes the code in hotspot and jvm in later time executes those optimized instructions.


6. Native method stack: holds frames for native methods. native methods works on the frame data and data in heap of JVM.

The following picture shows architecture of JVM


The following picture depicts Program counter and Java stack



** Object representation on JVM


** Thread Synchronization
Thread needs object locking and wait-notify mechanism to work.
calling the following methods on an object
  a. lock: a thread can access lock to an object. another thread has to wait to acquire the lock until the first thread unlocks the object.
  b. wait: a thread calls wait on an object. jvm puts the thread to the wait list of the object and makes it sleep. the thread sleeps until another thread calls notify or notify all
  c. notify and notify all: a thread calls this method on an object to notify the threads waiting on the object's wait list.

** Type of java threads
0. non-daemon thread: used by jvm. inital thread that starts a program, garbage collector.
1. daemon thread: created by running program.
As long as a non-daemon thread keeps running, the jvm would not stop unless exit method has not been called.

Atomic operations such as int, char operations makes sure a variable gets a value assigned either by one of the racing threads. if thread_1 tries to assign 0100 and thread_0 tries to assign 1011 to a variable x, it is guaranteed that x will have either 0100 or 1011 not any other values.

** Data types of jvm
a. reference type: holds object reference
b. primitive type: holds int, float. boolean false is stored as 0, any non-zero is stored as true. primitive types has same size and properties in all jvms. they don't depend on the host architecture.

As the jvm starts working, it's class loader loads byte codes to jvm's method area.