Skip to content

Commit

Permalink
More JarScan reports
Browse files Browse the repository at this point in the history
  • Loading branch information
chriswhocodes committed Jan 28, 2016
1 parent 694eed3 commit ef9ef71
Show file tree
Hide file tree
Showing 29 changed files with 1,697 additions and 164 deletions.
@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2015 Chris Newland. * Copyright (c) 2013-2016 Chris Newland.
* Licensed under https://github.com/AdoptOpenJDK/jitwatch/blob/master/LICENSE-BSD * Licensed under https://github.com/AdoptOpenJDK/jitwatch/blob/master/LICENSE-BSD
* Instructions: https://github.com/AdoptOpenJDK/jitwatch/wiki * Instructions: https://github.com/AdoptOpenJDK/jitwatch/wiki
*/ */
Expand Down Expand Up @@ -236,6 +236,7 @@ public static final Set<String> getAutoGeneratedClassPrefixes()
public static final String S_XML_DOCTYPE_START = "<!DOCTYPE"; public static final String S_XML_DOCTYPE_START = "<!DOCTYPE";
public static final String S_BYTECODE_METHOD_COMMENT = "// Method"; public static final String S_BYTECODE_METHOD_COMMENT = "// Method";
public static final String S_BYTECODE_INTERFACEMETHOD_COMMENT = "// InterfaceMethod"; public static final String S_BYTECODE_INTERFACEMETHOD_COMMENT = "// InterfaceMethod";
public static final String S_BYTECODE_INVOKEDYNAMIC_COMMENT = "// InvokeDynamic";
public static final String S_DEFAULT = "default"; public static final String S_DEFAULT = "default";
public static final String S_FILE_COLON = "file:"; public static final String S_FILE_COLON = "file:";
public static final String S_DOT_CLASS = ".class"; public static final String S_DOT_CLASS = ".class";
Expand Down
@@ -0,0 +1,61 @@
package org.adoptopenjdk.jitwatch.jarscan;

import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_COMMA;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_DOUBLE_QUOTE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_STATIC_INIT;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_NEWLINE;

import java.util.List;

import org.adoptopenjdk.jitwatch.model.MemberSignatureParts;
import org.adoptopenjdk.jitwatch.model.bytecode.BytecodeInstruction;
import org.adoptopenjdk.jitwatch.model.bytecode.MemberBytecode;

public class FreqInlineCounter implements IJarScanOperation
{
private int freqInlineSize;

private StringBuilder builder = new StringBuilder();

public FreqInlineCounter(int freqInlineSize)
{
this.freqInlineSize = freqInlineSize;
}

public String getReport()
{
return builder.toString();
}

@Override
public void processInstructions(String className, MemberBytecode memberBytecode)
{
List<BytecodeInstruction> instructions = memberBytecode.getInstructions();

if (instructions != null && instructions.size() > 0)
{
BytecodeInstruction lastInstruction = instructions.get(instructions.size() - 1);

// final instruction is a return for 1 byte
int bcSize = 1 + lastInstruction.getOffset();

MemberSignatureParts msp = memberBytecode.getMemberSignatureParts();

if (bcSize >= freqInlineSize && !S_STATIC_INIT.equals(msp.getMemberName()))
{
builder.append(C_DOUBLE_QUOTE);
builder.append(className);
builder.append(C_DOUBLE_QUOTE);
builder.append(C_COMMA);

builder.append(C_DOUBLE_QUOTE);
builder.append(msp.getMemberName());
builder.append(C_DOUBLE_QUOTE);
builder.append(C_COMMA);

builder.append(bcSize);
builder.append(S_NEWLINE);
}
}
}
}
@@ -0,0 +1,15 @@
/*
* Copyright (c) 2013-2016 Chris Newland.
* Licensed under https://github.com/AdoptOpenJDK/jitwatch/blob/master/LICENSE-BSD
* Instructions: https://github.com/AdoptOpenJDK/jitwatch/wiki
*/
package org.adoptopenjdk.jitwatch.jarscan;

import org.adoptopenjdk.jitwatch.model.bytecode.MemberBytecode;

public interface IJarScanOperation
{
void processInstructions(String className, MemberBytecode memberBytecode);

String getReport();
}
146 changes: 103 additions & 43 deletions src/main/java/org/adoptopenjdk/jitwatch/jarscan/JarScan.java
@@ -1,42 +1,59 @@
/* /*
* Copyright (c) 2013-2015 Chris Newland. * Copyright (c) 2013-2016 Chris Newland.
* Licensed under https://github.com/AdoptOpenJDK/jitwatch/blob/master/LICENSE-BSD * Licensed under https://github.com/AdoptOpenJDK/jitwatch/blob/master/LICENSE-BSD
* Instructions: https://github.com/AdoptOpenJDK/jitwatch/wiki * Instructions: https://github.com/AdoptOpenJDK/jitwatch/wiki
*/ */
package org.adoptopenjdk.jitwatch.jarscan; package org.adoptopenjdk.jitwatch.jarscan;


import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_COLON;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_DOT;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_DOT_CLASS;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_NEWLINE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_SLASH;

import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.Writer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.List; import java.util.List;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;


import org.adoptopenjdk.jitwatch.jarscan.bytecodefrequency.BytecodeFrequencyTree;
import org.adoptopenjdk.jitwatch.jarscan.chains.ChainCounter;
import org.adoptopenjdk.jitwatch.jarscan.freqinline.FreqInlineCounter;
import org.adoptopenjdk.jitwatch.jarscan.invokecounter.InvokeCounter;
import org.adoptopenjdk.jitwatch.loader.BytecodeLoader; import org.adoptopenjdk.jitwatch.loader.BytecodeLoader;
import org.adoptopenjdk.jitwatch.model.MemberSignatureParts;
import org.adoptopenjdk.jitwatch.model.bytecode.BytecodeInstruction;
import org.adoptopenjdk.jitwatch.model.bytecode.ClassBC; import org.adoptopenjdk.jitwatch.model.bytecode.ClassBC;
import org.adoptopenjdk.jitwatch.model.bytecode.MemberBytecode; import org.adoptopenjdk.jitwatch.model.bytecode.MemberBytecode;


import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.*; public class JarScan

public final class JarScan
{ {
private JarScan() private List<IJarScanOperation> operations = new ArrayList<>();

private Writer writer;

public JarScan(Writer writer)
{ {
this.writer = writer;
} }


@SuppressWarnings("unchecked") public void addOperation(IJarScanOperation op)
public static void iterateJar(File jarFile, int maxMethodBytes, PrintWriter writer) throws IOException {
operations.add(op);
}

public void iterateJar(File jarFile) throws IOException
{ {
List<String> classLocations = new ArrayList<>(); List<String> classLocations = new ArrayList<>();


classLocations.add(jarFile.getPath()); classLocations.add(jarFile.getPath());


try (ZipFile zip = new ZipFile(jarFile)) try (ZipFile zip = new ZipFile(jarFile))
{ {
@SuppressWarnings("unchecked")
Enumeration<ZipEntry> list = (Enumeration<ZipEntry>) zip.entries(); Enumeration<ZipEntry> list = (Enumeration<ZipEntry>) zip.entries();


while (list.hasMoreElements()) while (list.hasMoreElements())
Expand All @@ -47,49 +64,47 @@ public static void iterateJar(File jarFile, int maxMethodBytes, PrintWriter writ


if (name.endsWith(S_DOT_CLASS)) if (name.endsWith(S_DOT_CLASS))
{ {
String fqName = name.replace(S_SLASH, S_DOT).substring(0, name.length() - 6); String fqName = name.replace(S_SLASH, S_DOT).substring(0, name.length() - S_DOT_CLASS.length());


process(classLocations, fqName, maxMethodBytes, writer); process(classLocations, fqName);
} }
} }
} }

createReport();
}

private void createReport() throws IOException
{
for (IJarScanOperation op : operations)
{
String report = op.getReport();

writer.write(report);
writer.flush();
}
} }


private static void process(List<String> classLocations, String className, int maxMethodBytes, PrintWriter writer) private void process(List<String> classLocations, String className)
{ {
ClassBC classBytecode = BytecodeLoader.fetchBytecodeForClass(classLocations, className); ClassBC classBytecode = BytecodeLoader.fetchBytecodeForClass(classLocations, className);


if (classBytecode != null) if (classBytecode != null)
{ {
for (MemberBytecode memberBytecode : classBytecode.getMemberBytecodeList()) for (MemberBytecode memberBytecode : classBytecode.getMemberBytecodeList())
{ {
List<BytecodeInstruction> instructions = memberBytecode.getInstructions(); for (IJarScanOperation op : operations)

if (instructions != null && instructions.size() > 0)
{ {
BytecodeInstruction lastInstruction = instructions.get(instructions.size() - 1); try

// final instruction is a return for 1 byte
int bcSize = 1 + lastInstruction.getOffset();

MemberSignatureParts msp = memberBytecode.getMemberSignatureParts();

if (bcSize >= maxMethodBytes && !S_STATIC_INIT.equals(msp.getMemberName()))
{ {
writer.print(C_DOUBLE_QUOTE); op.processInstructions(className, memberBytecode);
writer.print(className); }
writer.print(C_DOUBLE_QUOTE); catch (Exception e)
writer.print(C_COMMA); {

System.err.println("Could not process " + className + " " + memberBytecode.getMemberSignatureParts().getMemberName());
writer.print(C_DOUBLE_QUOTE); System.err.println(memberBytecode.toString());
writer.print(msp.getMemberName()); e.printStackTrace();
writer.print(C_DOUBLE_QUOTE); System.exit(-1);
writer.print(C_COMMA);

writer.print(bcSize);
writer.println();

writer.flush();
} }
} }
} }
Expand All @@ -101,23 +116,68 @@ private static void process(List<String> classLocations, String className, int m
} }
} }


private static void showUsage()
{
System.err.println("JarScan [options] <jar> [jar]...");
System.err.println("Options:");
System.err.println("-DmaxMethodSize=n\t\t\tFind methods with bytecode larger than n bytes");
System.err.println("-DmaxBytecodeChain=n\t\t\tCount bytecode chains of length n");
System.err.println("-DmaxFrequencyTreeChildren=n\t\t\tFind the n most frequent next bytecodes");
System.err.println("-DinvokeCount\t\t\tCount methods by invoke type");
}

public static void main(String[] args) throws IOException public static void main(String[] args) throws IOException
{ {
int maxMethodBytes = Integer.getInteger("maxMethodSize", 325); if (args.length == 0)
{
showUsage();
System.exit(-1);
}

Writer writer = new PrintWriter(System.out);

JarScan scanner = new JarScan(writer);


PrintWriter writer = new PrintWriter(System.out); if (System.getProperty("maxMethodSize") != null)
{
int maxMethodBytes = Integer.getInteger("maxMethodSize");
scanner.addOperation(new FreqInlineCounter(maxMethodBytes));
}
else if (System.getProperty("maxBytecodeChain") != null)
{
int maxBytecodeChain = Integer.getInteger("maxBytecodeChain");
scanner.addOperation(new ChainCounter(maxBytecodeChain));
}
else if (System.getProperty("maxFrequencyTreeChildren") != null)
{
int maxFrequencyTreeChildren = Integer.getInteger("maxFrequencyTreeChildren");

scanner.addOperation(new BytecodeFrequencyTree(maxFrequencyTreeChildren));
}
else if (System.getProperty("invokeCount") != null)
{
scanner.addOperation(new InvokeCounter());
}

if (scanner.operations.size() == 0)
{
// default mode is to report methods > 325 bytes
int maxMethodBytes = Integer.getInteger("maxMethodSize", 325);
scanner.addOperation(new FreqInlineCounter(maxMethodBytes));
}


for (String jar : args) for (String jar : args)
{ {
File jarFile = new File(jar); File jarFile = new File(jar);


writer.print(jarFile.getAbsolutePath()); writer.write(jarFile.getAbsolutePath());


writer.println(C_COLON); writer.write(C_COLON);
writer.write(S_NEWLINE);


iterateJar(jarFile, maxMethodBytes, writer); scanner.iterateJar(jarFile);


writer.println(); writer.write(S_NEWLINE);
} }


writer.flush(); writer.flush();
Expand Down

0 comments on commit ef9ef71

Please sign in to comment.