Wednesday 26 February 2014

Misconceptions about Object.finalize()

I have been studying Java for about 6 years now and all along I have dissected something interesting about it at various levels. To be more general, I think the beauty of OOP lies in its inherent simplicity to hide relevant complexities and one does not unlock these complexities till the time he explicitly starts working on them.

I had always learnt that the Object.finalize() method is used to clean up resources before an object is garbage collected by the JVM. My professor simplified it all the more for me and my then innocent friends who were led to believe that in simple terms, "Object.finalize() is just the same thing as Destructors in C++". Woah, now, that's one of those instances of reckless simplification founded upon specious reasoning.

I will just explain what it really is and nothing more. Object.finalize() is a function or a method that may be overriden by any Java object (provided its class implementation provides the necessary overriding definition, that is) and this method is called by the JVM when it notes that no more references exist to this object and that it may be safely garbage collected. 

The finalize() method definition itself may include code  to cleanup resources that are not going to be used, say, file.close() method, for example. If the method has been overriden, then the JVM invokes the finalize() before the object itself will be deallocated, that is, the finalize() is in effect, the last operation that will be performed by an object along its lifecycle from birth to termination.

Now there is an essential caveat here that needs special attention. For one thing, never rely on finalize() to do anything that you believe is critical from the system functioning perspective. Well, that is because Object.finalize() is called by a JVM GC (Garbage Collector) thread while the JVM itself provides no real guarantees in regard to whether the finalize() will ever be called. 

Now, what does this really mean? It does sound fairly paradoxical in that on the one hand, you hear it will be called by the JVM before the object will be deallocated and on the other, you note that the JVM cannot guarantee that it will be called ever. Well, here is where a little extra information can help. Well, we must recollect that we can never ascertain when exactly the JVM does its garbage collection or to be more clear, one can never guess when the JVM GC thread itself will be scheduled and eventually dispatched. So, it is safe to assume that at times, the application or the program itself will run from start to completion and the JVM GC thead has not managed to run during the application program life cycle. In such cases, those objects used in the program will only be deallocated after the program itself has terminated and when the JVM GC thread will on its part, reclaim the space used by those concerned objects. So, it's now evident here that the finalize() has not been executed for the program has terminated prior to its invocation by the JVM.

So when do we really use finalize()? Well, the general idea is that do not use it to accomplish tasks or execute operations that determine the fate of the application itself. It is safe to use it to accomplish less critical functions, for say, logging information that could later be used for debugging. Here, the key idea is to never really rely on it to do anything, for that may not necessarily serve the purpose.

Now, with regard to some drawing parallels with the the C++ destructor, I must add that the destructor is guaranteed to be called during the lifetime of the program. So yes, you may use to perform some last minute work that will need to be done prior to destruction of the object itself. It's the presence of this guarantee in the case of destructors and the absence of it in the case of finalize() that makes all the difference. 

Monday 24 February 2014

Insight into Web Services for beginners

There have been a lot of questions I have been asking myself ever since I started studying computers in my undergrad. I got answers to some of them pretty early while some lingered on in my mind. Fortunately, over the last two years, I have slowly started uncovering answers to more of them.

What is a web service?
This is a pretty interesting question, actually. Now, looking at the two words in isolation, "web" and "service"; one would most likely understand that as a service offered over the web. Well! Yes, but not quite complete and convincing! This is with due consideration to the buzz around the terms when you naively start reading tech posts and keep wondering all along as to what justified the writer's extreme excitement and optimism while talking about something that sounds as trivial as a "web service".

That surely made me understand that there was a void in my understanding of "web service" and it surely is something much more than a service offered over the web. Back then, about 4 years back, I happened to ask my professor about the same thing and I could see that even this was not really helping me look at the thing from a wider perspective and attain that big picture I was looking for.

This morning, I happened to stumble upon this fine post, http://www.dummies.com/how-to/content/getting-a-look-at-web-services.html.

As it suggests, a service offered over the web that may be freely used by another application is called a web service. Sometimes, you may want to use a particular service exported by another service in a specific component of your application. Imagine, you would like to provide a search facility in your website and would like to incorporate the Google Search toolbox for the same reason. How the Google search engine works is of no concern to you and all you care about is that the Google Search toolbox accomplishes its job. Now, the search service provided by Google is an example of web service that is freely exported by Google and may be imported by anybody for use in his/her application.

In case you are a web programmer, you may be familiar with REST and SOAP calls. Typically, the web service is queried by the importer application using the REST or SOAP calls and the response of the web service called service response is rendered and shown to the user. These days, a format such as JSON (JavaScript Object Notation) is used to return the service response and this is rendered by a view-level language such as JSP. For those familiar with AJAX, it is a robust framework and technique that may be used to make the web service call and wait on its response.


Revisiting the UNIX Process


A process in UNIX, or for that matter, any operating system may be defined as a program in execution. While the statement is fairly complete and clear in itself, there are some other things about processes that I will highlight today.
1. Program and Process
A program is in essence, an executable sequence of code that is run by the processor. The program or the code is not the process itself. The program containing the process code constitutes only the content of the text segment of a process. The process itself is more than the program and the following figure is an illustration lets us get a deeper picture of this idea.


Process in memory [1]

We can see from the above figure that a process in memory comprises various segments such as the stack, heap, data and text (code).

Stack segment: Holds references to local variables in the process. Generally, the stack is further split into several stack frames, one for each function or method in the process. Also recall that each thread of the process has its own copy or instance of the stack that is not visible to other threads.

Heap: Dynamic portion of the memory assigned to a process that is used to allocate memory to objects on demand during their creation. The heap memory is divided into arenas, one for each thread of the process. The arena of one thread is not visible to another thread, but it is visible to all functions and methods in the same thread.

Data: Holds global variables shared between various threads of the process. The program or code is the passive entity containing the lines of instructions governing the execution by the processor of the active entity, process that resides in memory and undergoes several transitions during its lifetime, since its creation until its death.

·        The process may also be viewed as an instance of the program in execution. This is similar to the idea of classes and objects. Different processes are different instances of the same program that share the same code segment and have their own independent heap, stack and data segments.

2. Process representation in operating system
Each process is represented using a data structure called the Process Control Block or Task Control Block (PCB). The PCB has information regarding a process such as its identifier (pid), the identifier of the parent process that created it (ppid) state (new, ready, running, blocked, terminated), reference to the next instruction to be executed for the process (IP), the list of files opened by the process, the reference to the process address space (this is OS dependent and this is typically a memory management concern), the values of the CPU flags, the remaining amount of time for executing the process (in a time slice) and other process specific information that needs to be logged. 

A typical PCB in Linux is represented using a structure, task_struct as shown below:
struct task_struct {
pid_t pid;
long state;
unsigned int time_slice;
struct files_struct *files;
struct mm_struct *mm;
}
[2]

The operating system maintains a doubly linked list of PCBs. This is typically used while doing a context switch from one process to the other. When the CPU switches from the execution of one process to another, the current state of the PCB of the process in execution is updated and saved and the PCB of the process which is going to be executed is loaded in memory. It is vital to understand the role of memory management schemes in this context. It is of particular importance if physical memory constraints prevent the maintenance of some PCBs in memory when the processes they correspond to are currently not in execution. In such cases, it is safe to assume that the operating system maintains references to PCBs (using virtual memory addressing techniques) if not the PCBs themselves. 

3. Fork, Memory Overlaying, Zombie state
A process in UNIX/Linux may create a new process using the fork system call. Upon execution of the fork call, the operating system creates a new process and loads the address space of the newly spawned child process with the current state of the address space of the parent process. This is similar to object cloning in programming.

Upon successful invocation of the fork(), a new process is created and its process identifier is returned to the parent whereas the child process itself is returned 0.
Typically, after creation, the new process is tasked with some objective as reflected from its own code segment. However, keep in mind that the code segment of the newly created process is identical to that of its parent process immediately after its creation as its address space is a mere replica of that of its parent. Now, to get the child process to execute some other instructions and accomplish a different objective, we use system calls in the exec family to which we pass reference to another sequence of code. This is shown in the following program:

#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
int main() {
pid_t pid;
pid = fork();
if ( pid < 0 ) {
fprintf ( stderr , “Fork failed” );
exit (EXIT_FAILURE);        
}
else if ( pid == 0 ) { /*in child */
execlp (“/bin/ls” , “ls” , NULL);
}
else { /*parent*/
wait (NULL);
printf (“Execution of child process is complete”);
exit ( EXIT_SUCCESS );
}

This particular example uses execlp whose signature is
int execlp(const char *file, const char *arg, ...);

We can see that the first argument is pointer to a character stream, the second parameter onward are pointers to strings that serve as instruction arguments. We can see that in our example, execlp is called with the argument,
“/bin/ls” that is itself a pointer to the file containing the instruction, “ls” in the second argument.

Now, upon execution of the execlp system call, the operating system loads the code segment in the address space of the child process with the code contained in the pointer to the code stream referenced in the first argument of execlp and the heap, stack and data segments are also refreshed to reflect to the new program. This technique wherein the address space is entirely replaced without the creation of a new process identifier is called Overlay. It is important to understand here that the changes to the address space of the process are done within the context of the process itself.

Generally, before forking a process, a shared memory Pipe communication is established so as to facilitate communication between a process and its child. This detail has been ignored in the above example.
It is also important to remember that the parent process waits until the completion of the child process using the system call, pid_t wait(int* status). The wait system call is used to prevent the child process being in Zombie state for too long.

In UNIX, when a process finishes executing, the memory allocated to it is reclaimed but the entry of the process in the process table is not immediately removed. Such a process is called a Zombie process for it has terminated execution but is not actually dead. If the parent of the process does not execute wait(), the process would remain a Zombie process for long periods of time (until the death of its own parent when it will be adopted by ‘init’, pid = 1. Once it has been adopted by init, it will eventually be killed as init periodically executes the wait()). The argument to the wait is NULL in our example which means that the status of the child process completion is not stored. Generally, a pointer is passed by the parent to store the value of the status code of the completion of child process.



References
[2]. Silberschatz, Galvin and Gagne (Operating Systems Concepts, 7th edition)


Interesting relationship between Pointers and Arrays


Most of us have worked with Java and other object oriented programming languages and this has exposed us to the world of Arrays which are simply a collection of variables stored sequentially in memory.
For those familiar with C, pointers is an interesting concept. Pointers are variables that store references to other variables.

The declaration and definition, int *ptr =&a causes variable ptr to hold the address of ‘a’ or a reference to ‘a’.

All of this may seem trivial and rather unimpressive. But, the idea of pointers has some interesting ramifications in the world of programming itself and what we will explore today is the relationship between Arrays and Pointers.

Let’s make a simple array definition.
int[ ] a = {1,2,3,4,5,6};

Now, let’s have a pointer ‘p’ refer to the first item of this array;

int* p = &a[0]; ........(1)
What we have now done is stored a reference to the first item of array a in p. Let’s say the six array elements are stored from addresses, 1000 through 1005.

That will store 1000 in p. Now, it is known to us that the ith element of an array, may be accessed using the expression, array[i]. Let’s say we want to access the 0th element of the array, in this case, ‘a’. That could be done by simply saying, a[0]. Now, let’s say we want to access the element of this array at index 4. That would be possible with a[4].

While all this may seem really trivial, we will now see how similar accesses to the array elements may be done using pointers. We just created a pointer, p that references the 0th element of a. Now, we may also access the contents here using the expression *p (value at address stored in p) or *(p+0). If you want to access the content at first index of ‘a’, you can do that with *(p+1). In general, the ith element of ‘a’ may be accessed using *(p+i).

Thus, we can see that the following expressions are equivalent:
a[0] ó *p or *(p+0)
a[1] ó *(p+1)
a[2] ó *(p+2)
and in general: a[i] ó *(p+i)

Now, it is a good idea to recall that the pointer, ‘p’ is itself a variable whereas the array name ‘a’ is just a synonym or a name equivalent for the address of the first element of the array.

In fact, the reference a[i] may be alternately written as *(a+i) because each time you write a[i], C itself converts it to *(a+i). Now, the initial pointer definition in (1) could have been alternately written as int* p = &a for, a[0] is simply *(a+0).
Hold on. Does that suggest ‘a’ is itself a pointer? Well, technically, No. Remember that pointers are variables. Here, ‘a’ is actually more like value that cannot be reassigned, so operations like a++ and assignment statements like a = 3 are illegal.

All that said, *(p+i) may be alternately written as p[i] and this is same as a[i]. In general, the array name and index expression is equivalent to the pointer and offset expression. The latter is determined to be marginally faster, so, it is not a bad idea to use the pointer and offset method for any way, C has to internally convert the array name and index expression to the pointer and offset expression.