javacommons/jvms/j9utils/threaddump/src/j9threaddumper.cpp
branchRCL_3
changeset 14 04becd199f91
equal deleted inserted replaced
13:f5050f1da672 14:04becd199f91
       
     1 /*
       
     2 * Copyright (c) 2009 - 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Thread dump server of J9 VM in S60,
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <string> // Needed for strcmp
       
    20 
       
    21 #include "logger.h"
       
    22 #include "fileutilities.h"
       
    23 #include "exceptionbase.h"
       
    24 #include "javacommonutils.h"
       
    25 #include "javasymbianoslayer.h"
       
    26 
       
    27 #include "j9threaddumper.h"
       
    28 
       
    29 using namespace java::util;
       
    30 
       
    31 // ======== STATIC VARIABLES ========
       
    32 
       
    33 OS_NONSHARABLE_CLASS(ThreadDumperGlobals)
       
    34 {
       
    35 public:
       
    36     ThreadDumperGlobals() : mDumper(0)
       
    37     {
       
    38     }
       
    39 
       
    40 public:
       
    41     J9ThreadDumper*  mDumper;
       
    42 };
       
    43 
       
    44 
       
    45 #if defined(__WINSCW__)
       
    46 
       
    47 #include <pls.h>
       
    48 ThreadDumperGlobals* getThreadDumperGlobals()
       
    49 {
       
    50     // Access the PLS of this process
       
    51     ThreadDumperGlobals* globals  =
       
    52         Pls<ThreadDumperGlobals>(TUid::Uid(0x20022E77));
       
    53     return globals;
       
    54 }
       
    55 
       
    56 #else
       
    57 
       
    58 static ThreadDumperGlobals* sGlobals = 0;
       
    59 
       
    60 ThreadDumperGlobals* getThreadDumperGlobals()
       
    61 {
       
    62     if (sGlobals == 0)
       
    63     {
       
    64         sGlobals = new ThreadDumperGlobals();
       
    65     }
       
    66     return sGlobals;
       
    67 }
       
    68 #endif
       
    69 
       
    70 
       
    71 // Function prototypes
       
    72 void JNICALL agentThread(void* args);
       
    73 jint JNICALL JVM_OnLoad(JavaVM* vm, char* options, void* reserved);
       
    74 
       
    75 
       
    76 
       
    77 J9ThreadDumper::J9ThreadDumper(JavaVM* vm, DgRasInterface* jvmri) :
       
    78         mJavaVM(vm), mJNIEnv(0), mJvmriInterface(jvmri),
       
    79         mTask(NO_TASK), mState(CREATED)
       
    80 {
       
    81     JELOG2(EJavaRuntime);
       
    82 }
       
    83 
       
    84 J9ThreadDumper::~J9ThreadDumper()
       
    85 {
       
    86     JELOG2(EJavaRuntime);
       
    87 }
       
    88 
       
    89 
       
    90 void JNICALL agentThread(void* /*args*/)
       
    91 {
       
    92 #ifdef __SYMBIAN32__
       
    93     RThread().SetPriority(EPriorityMore);
       
    94 #endif // __SYMBIAN32__
       
    95     JELOG2(EJavaRuntime);
       
    96     getThreadDumperGlobals()->mDumper->doRun();
       
    97     delete getThreadDumperGlobals()->mDumper;
       
    98     getThreadDumperGlobals()->mDumper = 0;
       
    99 #ifndef __WINSCW__
       
   100     delete sGlobals;
       
   101     sGlobals = 0;
       
   102 #endif
       
   103 
       
   104 }
       
   105 
       
   106 void J9ThreadDumper::doDump()
       
   107 {
       
   108     JELOG2(EJavaRuntime);
       
   109     mTask = DO_DUMP;
       
   110     wakeUp();
       
   111 }
       
   112 
       
   113 void J9ThreadDumper::close()
       
   114 {
       
   115     JELOG2(EJavaRuntime);
       
   116     mTask = CLOSE;
       
   117     wakeUp();
       
   118     mState = CLOSED;
       
   119 }
       
   120 
       
   121 
       
   122 
       
   123 void J9ThreadDumper::moveGeneratedDumpFile()
       
   124 {
       
   125 #ifdef __SYMBIAN32__
       
   126     JELOG2(EJavaRuntime);
       
   127     const wchar_t* const midpPrivateDataCage = L"c:\\private\\102033E6";
       
   128     const wchar_t* const destRoot = L"c:\\logs\\java\\";
       
   129 
       
   130 
       
   131     // Ensure that the target dir exists.
       
   132     std::wstring dest(destRoot);
       
   133     std::replace(dest.begin(), dest.end(), '\\', '/');
       
   134     java::fileutils::FileUtilities::makeDirAll(dest);
       
   135 
       
   136     // Get all the files of the private data cage.
       
   137     std::list<std::wstring> dirList = java::fileutils::FileUtilities::getDirContentsList(midpPrivateDataCage);
       
   138 
       
   139     // Loop all existing files and try to find generated core dumps.
       
   140     std::list<std::wstring>::const_iterator it;
       
   141     for (it = dirList.begin(); it != dirList.end(); it++)
       
   142     {
       
   143         if (it->find(L"javacore.") == 0)
       
   144         {
       
   145             std::wstring oldName(midpPrivateDataCage);
       
   146             oldName += L"\\";
       
   147             oldName += *it;
       
   148             std::wstring newName(destRoot);
       
   149             newName += *it;
       
   150 
       
   151             char* oldUtf8Name = JavaCommonUtils::wstringToUtf8(oldName);
       
   152             char* newUtf8Name = JavaCommonUtils::wstringToUtf8(newName);
       
   153 
       
   154             int error = rename(oldUtf8Name, newUtf8Name);
       
   155             delete[] oldUtf8Name;
       
   156             delete[] newUtf8Name;
       
   157         }
       
   158     }
       
   159 #endif // __SYMBIAN32__
       
   160 }
       
   161 
       
   162 void J9ThreadDumper::wakeUp()
       
   163 {
       
   164     JELOG2(EJavaRuntime);
       
   165     if (mState == ACTIVE)
       
   166     {
       
   167         mMonitor->notify();
       
   168     }
       
   169 }
       
   170 
       
   171 void J9ThreadDumper::doRun()
       
   172 {
       
   173     JELOG2(EJavaRuntime);
       
   174     if (mState != CREATED)
       
   175     {
       
   176         return;
       
   177     }
       
   178 
       
   179     int status = mJavaVM->AttachCurrentThreadAsDaemon((void**)&mJNIEnv, 0);
       
   180     if (status == 0)
       
   181     {
       
   182         mMonitor.reset(Monitor::createMonitor());
       
   183         mState = ACTIVE;
       
   184         while (mState == ACTIVE)
       
   185         {
       
   186             mMonitor->wait();
       
   187             switch (mTask)
       
   188             {
       
   189             case DO_DUMP:
       
   190                 mJvmriInterface->GenerateJavacore(mJNIEnv);
       
   191                 moveGeneratedDumpFile();
       
   192                 break;
       
   193             case CLOSE:
       
   194                 mState = CLOSED;
       
   195                 break;
       
   196             }
       
   197             mTask = NO_TASK;
       
   198         }
       
   199         mJavaVM->DetachCurrentThread();
       
   200     }
       
   201     else
       
   202     {
       
   203         ELOG1(EUtils, "Thread dumper failed to attach to VM: %d", status);
       
   204     }
       
   205 }
       
   206 
       
   207 JNIEXPORT jint JNICALL JVM_OnLoad(JavaVM* vm, char* options, void* /*reserved*/)
       
   208 {
       
   209     JELOG2(EJavaRuntime);
       
   210     int     rc = -1;
       
   211     JNIEnv* env;
       
   212 
       
   213     try
       
   214     {
       
   215         // Get the JNIEnv for the current thread
       
   216         rc = vm->GetEnv((void **)&env, JNI_VERSION_1_2);
       
   217         if (rc != JNI_OK)
       
   218         {
       
   219             // No JNIEnv; fail
       
   220             return JNI_ERR;
       
   221         }
       
   222 
       
   223         // Get the RAS Interface
       
   224         DgRasInterface* jvmriInterface;
       
   225         rc = vm->GetEnv((void **)&jvmriInterface, JVMRAS_VERSION_1_3);
       
   226         if (rc != JNI_OK)
       
   227         {
       
   228             // No RAS Interface available; fail
       
   229             return JNI_ERR;
       
   230         }
       
   231 
       
   232         getThreadDumperGlobals()->mDumper = new J9ThreadDumper(vm, jvmriInterface);
       
   233 
       
   234         if (options != 0)
       
   235         {
       
   236             LOG1(EUtils, EInfo, "Dump options = %s", options);
       
   237         }
       
   238         // Request creation of the agent thread
       
   239         rc = jvmriInterface->CreateThread(env, agentThread,0 , 0);
       
   240     }
       
   241 
       
   242     catch (ExceptionBase& ex)
       
   243     {
       
   244         ELOG1(EJavaRuntime,"ERROR in Thread Dump. ExceptionBase: %s",ex.toString().c_str());
       
   245     }
       
   246     catch (std::exception& e)
       
   247     {
       
   248 
       
   249         ELOG1(EJavaRuntime,"ERROR in Thread Dump. std::exception: %s",e.what());
       
   250     }
       
   251     catch (...)
       
   252     {
       
   253         ELOG(EJavaRuntime,"ERROR in Thread Dump. Unexpected exception was caught");
       
   254     }
       
   255     return rc;
       
   256 }
       
   257 
       
   258 // Keep this in sync with typedef in threaddumper.h file
       
   259 void doThreadDump()
       
   260 {
       
   261     JELOG2(EJavaRuntime);
       
   262     J9ThreadDumper* instance = getThreadDumperGlobals()->mDumper;
       
   263     if (instance)
       
   264     {
       
   265         instance->doDump();
       
   266     }
       
   267 #ifndef __WINSCW__
       
   268     else
       
   269     {
       
   270         delete sGlobals;
       
   271         sGlobals = 0;
       
   272     }
       
   273 #endif
       
   274 }
       
   275 
       
   276 // Keep this in sync with typedef in threaddumper.h file
       
   277 void closeThreadDump()
       
   278 {
       
   279     JELOG2(EJavaRuntime);
       
   280     J9ThreadDumper* instance = getThreadDumperGlobals()->mDumper;
       
   281     if (instance)
       
   282     {
       
   283         instance->close();
       
   284     }
       
   285 #ifndef __WINSCW__
       
   286     else
       
   287     {
       
   288         delete sGlobals;
       
   289         sGlobals = 0;
       
   290     }
       
   291 #endif
       
   292 }
       
   293 
       
   294 
       
   295 #ifdef __SYMBIAN32__
       
   296 EXPORT_C FuncPtr JNICALL jni_lookup(const char* aName)
       
   297 {
       
   298     JELOG2(EJavaRuntime);
       
   299     if (!strcmp(aName, "JVM_OnLoad"))
       
   300     {
       
   301         return (FuncPtr)JVM_OnLoad;
       
   302     }
       
   303 
       
   304     else if (!strcmp(aName, "doThreadDump"))
       
   305     {
       
   306         return (FuncPtr)doThreadDump;
       
   307     }
       
   308 
       
   309     else if (!strcmp(aName, "closeThreadDump"))
       
   310     {
       
   311         return (FuncPtr)closeThreadDump;
       
   312     }
       
   313 
       
   314     return 0;
       
   315 }
       
   316 #endif // __SYMBIAN32__