Thursday, May 14, 2020

Kotlin vs Java continued

Kotlin vs Java continued
Sample code to print the stack trace in Kotlin
try {
     Throw RuntimeException(“printStackTrace”)
} catch (e : Exception) {
     e.printStackTrace()
     LOG.error(“Exception: “, e)
}
As an aside, StackTraces are valuable for the analysis of faults and their categorization.
For example, Software support folks in the field often encounter crash dumps at the customer's premise. They may have access to some dumps but they find situations where they do not have any access to symbols particularly when the customer's operating system is Windows. What they see in the dumps or crash log reports are stack frames with raw addresses such as 0x7ff34555 and these are not yet resolved as module!class::method. Resolving of stackframes is the first step towards recognizing and categorizing them for identifying software components that have been generating exceptions. A debugger helps with finding the raw frames but symbols are needed to resolve the stack frame.  The production support personnel can't take the symbols to the customer's machine. This results in a round-trip or call-home with the exception or the dump for putting the symbols and the frames together. This can be achieved by using the same module that the debuggers use to translate the stack trace - dbghelp.dll when the symbols are available This module exports methods such as StackWalk and StackWalk64 that gives the stack trace when pointed to the dump and it has methods SymFromAddr and SymFromAddrW that just seems to do what we want. A call to  SymInitialize is required first so that we have a handle to the process. The method takes the following parameters :
- a handle retrieved from the SymInitialize method
- an Address pertaining to a frame in the stack for which the symbol should be located.
- a displacement from the beginning of a symbol or zero and this is optional
- a buffer to receive the SYMBOL_INFO resolved from the address.
If the function succeeds, it returns true. The SYMBOL_INFO struct has a member called MaxNameLen that should be set to the size of the name in characters. The name can be requested to be undecorated for easy readability.
The code from MSDN is something like this:
 
DWORD64  dwDisplacement = 0;
DWORD64  dwAddress = SOME_ADDRESS;
 
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
 
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
pSymbol->MaxNameLen = MAX_SYM_NAME;
 
if (SymFromAddr(hProcess, dwAddress, &dwDisplacement, pSymbol))
{
    // SymFromAddr returned success
   printf("%s\n", buffer);
}
else
{
    // SymFromAddr failed
    DWORD error = GetLastError();
    printf("SymFromAddr returned error : %d\n", error);
}
 
When we give some address, it should be the relative offset from the base address. A stackhasher application involves the parsing of stacktraces, their hashing into buckets and their reporting say via bar charts based on categories.
Npw returning back to the runtime determination of the origination of objects using stack traces, we find that Kotlin runtime adds a layer over the native runtime even resulting in quite deep stack traces unlike go language. 
The Kotlin runtime is also tightly bound to the garbage collector. The GC allocation errors are frequently tied to the runtime requirements of POJO like objects. When the objects are marshaled across boundaries, they are often serialized and desersialized resulting in lots of byte range copying and small allocations depending on the type and composition of the objects 


No comments:

Post a Comment