📄 wrappermanager.java
字号:
// Start a thread which looks for control events sent to the
// process. The thread is also used to keep track of whether
// the VM has been getting CPU to avoid invalid timeouts and
// to maintain the number of ticks since the JVM was launched.
m_eventRunnerTicks = getTicks();
m_eventRunner = new Thread( "Wrapper-Control-Event-Monitor" )
{
public void run()
{
if ( m_debug )
{
m_out.println( "Control event monitor thread started." );
}
try
{
WrapperTickEventImpl tickEvent = new WrapperTickEventImpl();
int lastTickOffset = 0;
boolean first = true;
while ( !m_shuttingDown )
{
int offsetDiff;
if ( !m_useSystemTime )
{
// Get the tick count based on the system time.
int sysTicks = getSystemTicks();
// Increment the tick counter by 1. This loop takes just slightly
// more than the length of a "tick" but it is a good enough
// approximation for our purposes. The accuracy of the tick length
// falls sharply when the system is under heavly load, but this
// has the desired effect as the Wrapper is also much less likely
// to encounter false timeouts due to the heavy load.
// The ticks field is volatile and a single integer, so it is not
// necessary to synchronize this.
// When the ticks count reaches the upper limit of the int range,
// it is ok to just let it overflow and wrap.
m_ticks++;
// Calculate the offset between the two tick counts.
// This will always work due to overflow.
int tickOffset = sysTicks - m_ticks;
// The number we really want is the difference between this tickOffset
// and the previous one.
offsetDiff = tickOffset - lastTickOffset;
if ( first )
{
first = false;
}
else
{
if ( offsetDiff > m_timerSlowThreshold )
{
m_out.println( "The timer fell behind the system clock by "
+ ( offsetDiff * TICK_MS ) + "ms." );
}
else if ( offsetDiff < - m_timerFastThreshold )
{
m_out.println( "The system clock fell behind the timer by "
+ ( -1 * offsetDiff * TICK_MS ) + "ms." );
}
}
// Store this tick offset for the net time through the loop.
lastTickOffset = tickOffset;
}
else
{
offsetDiff = 0;
}
//m_out.println( " UNIX Time: " + Long.toHexString( System.currentTimeMillis() )
// + ", ticks=" + Integer.toHexString( getTicks() ) + ", sysTicks="
// + Integer.toHexString( getSystemTicks() ) );
// Attempt to detect whether or not we are being starved of CPU.
// This will only have any effect if the m_useSystemTime flag is
// set.
int nowTicks = getTicks();
long age = getTickAge( m_eventRunnerTicks, nowTicks );
if ( ( m_cpuTimeout > 0 ) && ( age > m_cpuTimeout ) )
{
m_out.println( "JVM Process has not received any CPU time for "
+ ( age / 1000 ) + " seconds. Extending timeouts." );
// Make sure that we don't get any ping timeouts in this event
m_lastPingTicks = nowTicks;
}
m_eventRunnerTicks = nowTicks;
// If there are any listeners interrested in core events then fire
// off a tick event.
if ( m_produceCoreEvents )
{
tickEvent.m_ticks = nowTicks;
tickEvent.m_tickOffset = offsetDiff;
fireWrapperEvent( tickEvent );
}
if ( m_libraryOK )
{
// Look for a control event in the wrapper library
int event = WrapperManager.nativeGetControlEvent();
if ( event != 0 )
{
WrapperManager.controlEvent( event );
}
}
// Wait before checking for another control event.
try
{
Thread.sleep( TICK_MS );
}
catch ( InterruptedException e )
{
}
}
}
finally
{
if ( m_debug )
{
m_out.println( "Control event monitor thread stopped." );
}
}
}
};
m_eventRunner.setDaemon( true );
m_eventRunner.start();
// Resolve the system thread count based on the Java Version
String fullVersion = System.getProperty( "java.fullversion" );
String vendor = System.getProperty( "java.vm.vendor", "" );
String os = System.getProperty( "os.name", "" ).toLowerCase();
if ( fullVersion == null )
{
fullVersion = System.getProperty( "java.runtime.version" ) + " "
+ System.getProperty( "java.vm.name" );
}
if ( m_debug )
{
// Display more JVM infor right after the call initialization of the library.
m_out.println( "Java Version : " + fullVersion );
m_out.println( "Java VM Vendor : " + vendor );
m_out.println();
}
// This thread will most likely be thread which launches the JVM.
// Once this method returns however, the main thread will likely
// quit. There will be a slight delay before the Wrapper binary
// has a change to send a command to start the application.
// During this lag, the JVM may not have any non-daemon threads
// running and would exit. To keep it from doing so, start a
// simple non-daemon thread which will run until the
// WrapperListener.start() method returns or the Wrapper's
// shutdown thread has started.
m_startupRunner = new Thread( "Wrapper-Startup-Runner" )
{
public void run()
{
if ( m_debug )
{
m_out.println( "Startup runner thread started." );
}
try
{
while ( m_startupRunner != null )
{
try
{
Thread.sleep( 100 );
}
catch ( InterruptedException e )
{
// Ignore.
}
}
}
finally
{
if ( m_debug )
{
m_out.println( "Startup runner thread stopped." );
}
}
}
};
// This thread must not be a daemon thread.
m_startupRunner.setDaemon( false );
m_startupRunner.start();
// Create the singleton
m_instance = new WrapperManager();
}
/*---------------------------------------------------------------
* Native Methods
*-------------------------------------------------------------*/
private static native void nativeInit( boolean debug );
private static native String nativeGetLibraryVersion();
private static native int nativeGetJavaPID();
private static native int nativeGetControlEvent();
private static native void nativeRequestThreadDump();
private static native void accessViolationInner();
private static native void nativeSetConsoleTitle( byte[] titleBytes );
private static native WrapperUser nativeGetUser( boolean groups );
private static native WrapperUser nativeGetInteractiveUser( boolean groups );
private static native WrapperWin32Service[] nativeListServices();
private static native WrapperWin32Service nativeSendServiceControlCode( byte[] serviceName, int controlCode );
/*---------------------------------------------------------------
* Methods
*-------------------------------------------------------------*/
/**
* Returns a tick count calculated from the system clock.
*/
private static int getSystemTicks()
{
// Calculate a tick count using the current system time. The
// conversion from a long in ms, to an int in TICK_MS increments
// will result in data loss, but the loss of bits and resulting
// overflow is expected and Ok.
return (int)( System.currentTimeMillis() / TICK_MS );
}
/**
* Returns the number of ticks since the JVM was launched. This
* count is not good enough to be used where accuracy is required but
* it allows us to implement timeouts in environments where the system
* time is modified while the JVM is running.
* <p>
* An int is used rather than a long so the counter can be implemented
* without requiring any synchronization. At the tick resolution, the
* tick counter will overflow and wrap (every 6.8 years for 100ms ticks).
* This behavior is expected. The getTickAge method should be used
* in cases where the difference between two ticks is required.
*
* Returns the tick count.
*/
private static int getTicks()
{
if ( m_useSystemTime )
{
return getSystemTicks();
}
else
{
return m_ticks;
}
}
/**
* Returns the number of milliseconds that have elapsed between the
* start and end counters. This method assumes that both tick counts
* were obtained by calling getTicks(). This method will correctly
* handle cases where the tick counter has overflowed and reset.
*
* @param start A base tick count.
* @param end An end tick count.
*
* @return The number of milliseconds that are represented by the
* difference between the two specified tick counts.
*/
private static long getTickAge( int start, int end )
{
// Important to cast the first value so that negative values are correctly
// cast to negative long values.
return (long)( end - start ) * TICK_MS;
}
/**
* Attempts to load the a native library file.
*
* @param name Name of the library to load.
* @param file Name of the actual library file.
*
* @return null if the library was successfully loaded, an error message
* otherwise.
*/
private static String loadNativeLibrary( String name, String file )
{
try
{
System.loadLibrary( name );
if ( m_debug )
{
m_out.println( "Loaded native library: " + file );
}
return null;
}
catch ( UnsatisfiedLinkError e )
{
if ( m_debug )
{
m_out.println( "Loading native library failed: " + file + " Cause: " + e );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -