2013-12-27 23:59:59 +01:00
|
|
|
package appeng.services;
|
|
|
|
|
|
|
|
import java.io.BufferedReader;
|
|
|
|
import java.io.DataOutputStream;
|
|
|
|
import java.io.File;
|
|
|
|
import java.io.FileOutputStream;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.io.InputStreamReader;
|
|
|
|
import java.lang.management.ManagementFactory;
|
|
|
|
import java.lang.management.ThreadInfo;
|
|
|
|
import java.lang.management.ThreadMXBean;
|
|
|
|
import java.lang.reflect.Constructor;
|
|
|
|
import java.lang.reflect.Method;
|
|
|
|
import java.net.URL;
|
|
|
|
import java.net.URLClassLoader;
|
|
|
|
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
|
|
|
|
|
import appeng.core.AELog;
|
|
|
|
|
|
|
|
public class Profiler implements Runnable
|
|
|
|
{
|
|
|
|
|
|
|
|
public static Profiler instance = null;
|
|
|
|
public boolean profile = false;
|
|
|
|
public boolean isRunning = true;
|
|
|
|
public final Object lock = new Object();
|
|
|
|
|
|
|
|
public static String getCommandOutput(String command)
|
|
|
|
{
|
|
|
|
String output = null; // the string to return
|
|
|
|
|
|
|
|
Process process = null;
|
|
|
|
BufferedReader reader = null;
|
|
|
|
InputStreamReader streamReader = null;
|
|
|
|
InputStream stream = null;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
process = Runtime.getRuntime().exec( command );
|
|
|
|
|
|
|
|
stream = process.getInputStream();
|
|
|
|
streamReader = new InputStreamReader( stream );
|
|
|
|
reader = new BufferedReader( streamReader );
|
|
|
|
|
|
|
|
String currentLine = null;
|
|
|
|
StringBuilder commandOutput = new StringBuilder();
|
|
|
|
while ((currentLine = reader.readLine()) != null)
|
|
|
|
{
|
|
|
|
commandOutput.append( currentLine );
|
|
|
|
}
|
|
|
|
|
|
|
|
int returnCode = process.waitFor();
|
|
|
|
if ( returnCode == 0 )
|
|
|
|
{
|
|
|
|
output = commandOutput.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
catch (IOException e)
|
|
|
|
{
|
|
|
|
output = null;
|
|
|
|
}
|
|
|
|
catch (InterruptedException e)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
finally
|
|
|
|
{
|
|
|
|
|
|
|
|
if ( stream != null )
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
stream.close();
|
|
|
|
}
|
|
|
|
catch (IOException e)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( streamReader != null )
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
streamReader.close();
|
|
|
|
}
|
|
|
|
catch (IOException e)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( reader != null )
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
streamReader.close();
|
|
|
|
}
|
|
|
|
catch (IOException e)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
|
|
|
private String findJDK()
|
|
|
|
{
|
|
|
|
if ( System.getProperty( "os.name" ).contains( "win" ) || System.getProperty( "os.name" ).contains( "Win" ) )
|
|
|
|
{
|
|
|
|
String path = getCommandOutput( "where javac" );
|
|
|
|
if ( path == null || path.isEmpty() )
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
File javacFile = new File( path );
|
|
|
|
File jdkInstallationDir = javacFile.getParentFile().getParentFile();
|
|
|
|
return jdkInstallationDir.getPath();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
String response = getCommandOutput( "whereis javac" );
|
|
|
|
if ( response == null )
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int pathStartIndex = response.indexOf( '/' );
|
|
|
|
if ( pathStartIndex == -1 )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
String path = response.substring( pathStartIndex, response.length() );
|
|
|
|
File javacFile = new File( path );
|
|
|
|
File jdkInstallationDir = javacFile.getParentFile().getParentFile();
|
|
|
|
return jdkInstallationDir.getPath();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
Class ProfilingSettingsPresets;
|
|
|
|
Class CPUResultsSnapshot;
|
|
|
|
Class StackTraceSnapshotBuilder;
|
|
|
|
Class LoadedSnapshot;
|
|
|
|
Class Lookup;
|
|
|
|
Class LookupProvider;
|
|
|
|
Class ResultsSnapshot;
|
|
|
|
Class ProfilingSettings;
|
|
|
|
|
|
|
|
Method addStacktrace;
|
|
|
|
Method createSnapshot;
|
|
|
|
Method createCPUPreset;
|
|
|
|
Method save;
|
|
|
|
Constructor LoadedSnapshot_Constructor;
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void run()
|
|
|
|
{
|
|
|
|
instance = this;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
String JDKpath = findJDK();
|
|
|
|
|
|
|
|
String root = StringUtils.join( new String[] { JDKpath, "lib", "visualvm" }, File.separator );
|
|
|
|
String Base = StringUtils.join( new String[] { root, "profiler", "modules", "" }, File.separator );
|
|
|
|
String BaseB = StringUtils.join( new String[] { root, "platform", "lib", "" }, File.separator );
|
|
|
|
|
|
|
|
File a = new File( Base + "org-netbeans-lib-profiler.jar" );
|
|
|
|
File b = new File( Base + "org-netbeans-lib-profiler-common.jar" );
|
|
|
|
File c = new File( Base + "org-netbeans-modules-profiler.jar" );
|
|
|
|
File d = new File( BaseB + "org-openide-util.jar" );
|
|
|
|
File e = new File( BaseB + "org-openide-util-lookup.jar" );
|
|
|
|
|
2014-02-07 21:37:22 +01:00
|
|
|
ClassLoader cl = URLClassLoader.newInstance( new URL[] { a.toURI().toURL(), b.toURI().toURL(), c.toURI().toURL(), d.toURI().toURL(), e.toURI().toURL() } );
|
2013-12-27 23:59:59 +01:00
|
|
|
|
|
|
|
ProfilingSettingsPresets = cl.loadClass( "org.netbeans.lib.profiler.common.ProfilingSettingsPresets" );
|
|
|
|
ProfilingSettings = cl.loadClass( "org.netbeans.lib.profiler.common.ProfilingSettings" );
|
|
|
|
CPUResultsSnapshot = cl.loadClass( "org.netbeans.lib.profiler.results.cpu.CPUResultsSnapshot" );
|
|
|
|
ResultsSnapshot = cl.loadClass( "org.netbeans.lib.profiler.results.ResultsSnapshot" );
|
|
|
|
StackTraceSnapshotBuilder = cl.loadClass( "org.netbeans.lib.profiler.results.cpu.StackTraceSnapshotBuilder" );
|
|
|
|
LoadedSnapshot = cl.loadClass( "org.netbeans.modules.profiler.LoadedSnapshot" );
|
|
|
|
Lookup = cl.loadClass( "org.openide.util.Lookup" );
|
|
|
|
|
|
|
|
for (Class dc : Lookup.getDeclaredClasses())
|
|
|
|
{
|
|
|
|
if ( dc.getSimpleName().equals( "Provider" ) )
|
|
|
|
LookupProvider = dc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( LookupProvider == null )
|
|
|
|
throw new ClassNotFoundException( "Lookup.Provider" );
|
|
|
|
|
|
|
|
addStacktrace = StackTraceSnapshotBuilder.getMethod( "addStacktrace", ThreadInfo[].class, long.class );
|
|
|
|
createSnapshot = StackTraceSnapshotBuilder.getMethod( "createSnapshot", long.class );
|
|
|
|
createCPUPreset = ProfilingSettingsPresets.getMethod( "createCPUPreset" );
|
|
|
|
save = LoadedSnapshot.getMethod( "save", DataOutputStream.class );
|
|
|
|
LoadedSnapshot_Constructor = LoadedSnapshot.getConstructor( ResultsSnapshot, ProfilingSettings, File.class, LookupProvider );
|
|
|
|
}
|
|
|
|
catch (Throwable t)
|
|
|
|
{
|
|
|
|
isRunning = false;
|
|
|
|
AELog.info( "Unable to find/load JDK, profiling disabled." );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int limit = 0;
|
|
|
|
while (isRunning)
|
|
|
|
{
|
|
|
|
if ( profile )
|
|
|
|
{
|
|
|
|
limit = 9000;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
Object StackTraceSnapshotBuilder_Instance = StackTraceSnapshotBuilder.newInstance();
|
|
|
|
ThreadMXBean mxBean = ManagementFactory.getThreadMXBean();
|
|
|
|
|
|
|
|
while (profile)
|
|
|
|
{
|
|
|
|
if ( limit-- < 0 )
|
|
|
|
profile = false;
|
|
|
|
|
|
|
|
for (long th : mxBean.getAllThreadIds())
|
|
|
|
{
|
|
|
|
ThreadInfo ti = mxBean.getThreadInfo( th, Integer.MAX_VALUE );
|
|
|
|
addStacktrace.invoke( StackTraceSnapshotBuilder_Instance, new ThreadInfo[] { ti }, System.nanoTime() );
|
|
|
|
}
|
|
|
|
|
|
|
|
Thread.sleep( 20 );
|
|
|
|
}
|
|
|
|
|
|
|
|
Object CPUResultsSnapshot_Instance = createSnapshot.invoke( StackTraceSnapshotBuilder_Instance, System.currentTimeMillis() );
|
|
|
|
|
2014-02-07 21:37:22 +01:00
|
|
|
Object LoadedSnapshot_Instance = LoadedSnapshot_Constructor.newInstance( CPUResultsSnapshot_Instance, createCPUPreset.invoke( ProfilingSettingsPresets ), null,
|
|
|
|
null );
|
2013-12-27 23:59:59 +01:00
|
|
|
|
|
|
|
FileOutputStream bout = new FileOutputStream( new File( "ae-latest-profile.nps" ) );
|
|
|
|
DataOutputStream out = new DataOutputStream( bout );
|
|
|
|
save.invoke( LoadedSnapshot_Instance, out );
|
|
|
|
out.flush();
|
|
|
|
bout.close();
|
|
|
|
}
|
|
|
|
catch (Throwable t)
|
|
|
|
{
|
|
|
|
AELog.severe( "Error while profiling" );
|
2014-02-07 21:37:22 +01:00
|
|
|
AELog.error( t );
|
2013-12-27 23:59:59 +01:00
|
|
|
profile = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
synchronized (lock)
|
|
|
|
{
|
|
|
|
lock.wait();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (InterruptedException e)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|