blob: f82e66782aa9bc821c9e169364982a5ee2af582a [file] [log] [blame]
/**********************************************************************
// @@@ START COPYRIGHT @@@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// @@@ END COPYRIGHT @@@
**********************************************************************/
/* -*-C++-*-
******************************************************************************
*
* File: LmJavaHooks.cpp
* Description: A class containing static functions that we register
* as callback functions when we create a JVM
*
* Created: June 2003
* Language: C++
*
*
******************************************************************************
*/
#include "LmJavaHooks.h"
#include "LmDebug.h"
#include "LmExtFunc.h"
#include "ComSafePrinter.h"
#include "BaseTypes.h"
#include "str.h"
char LmJavaHooks::textBuf_[LMJ_HOOK_TEXT_BUF_SIZE] = {'\0'};
// Exclude the following methods for coverage as they are called when JVM aborts
void JNICALL LmJavaHooks::abortHookJVM()
{
LM_DEBUG0("[HOOK] Invoking JVM abort hook");
fprintf(stdout, "The JVM is about to abort\n");
fflush(stderr);
lmMakeTFDSCall("The Java virtual machine aborted", "", 0);
// should not reach here
abort();
}
void JNICALL LmJavaHooks::exitHookJVM(jint code)
{
LM_DEBUG1("[HOOK] Invoking JVM exit hook. Exit code is %d", (Int32) code);
fprintf(stdout, "The JVM is about to exit with code %d\n", (Int32) code);
fflush(stderr);
char buf[200];
sprintf(buf, "The Java virtual machine exited with code %d", (Int32) code);
lmMakeTFDSCall(buf, "", 0);
// should not reach here
exit(code);
}
jint JNICALL LmJavaHooks::vfprintfHookJVM(FILE *stream, const char *fmt,
va_list printArgs)
{
if (!fmt || !stream)
{
return 0;
}
LM_DEBUG0("[BEGIN vfprintf hook]");
char tmpBuf[LMJ_HOOK_TEXT_BUF_SIZE] = "";
// 1. First make a temporary copy of the output message
ComSafePrinter safePrinter;
safePrinter.vsnPrintf(tmpBuf, LMJ_HOOK_TEXT_BUF_SIZE, fmt, printArgs);
// 2. Send the message to its intended FILE stream
// Do not know why but inside this hook, writing to the FILE pointer
// that was passed in seems to cause problems on Windows. Depending
// on how the FILE pointer is used we have seen crashes inside JVM
// code after hook returns, and inside fprintf. The JVM bug database
// says a few things about the JVM being compiled with a version of
// certain stdio structures such as va_list that may not be
// compatible with all IDEs. Have not tried to verify that
// though. For now on Windows we just write our temporary string to
// stderr. And our observation has been that all JVM messages go to
// stderr anyway, so this seems to serve the same purpose.
//
// For example the following line does not work
//
// vfprintf(stream, fmt, printArgs)
//
// And neither does this
//
// fprintf(stream, tmpBuf)
//
fprintf(stderr, tmpBuf);
// Write as much as possible into our textBuf_ area
Int32 currentLength = str_len(textBuf_);
Int32 tmpLen = str_len(tmpBuf);
if ((currentLength + 1) < LMJ_HOOK_TEXT_BUF_SIZE)
{
Int32 bytesToCopy =
MINOF(tmpLen + 1, LMJ_HOOK_TEXT_BUF_SIZE - currentLength);
str_cpy_all(&textBuf_[currentLength], tmpBuf, bytesToCopy);
textBuf_[LMJ_HOOK_TEXT_BUF_SIZE - 1] = 0;
}
else
{
LM_DEBUG0("*** WARNING: textBuf_ buffer is full");
}
LM_DEBUG0("[END vfprintf hook]");
return 0;
}
void LmJavaHooks::init_vfprintfHook()
{
textBuf_[0] = '\0';
}