diff --git a/dacapo/parser.py b/dacapo/parser.py
index ebae97dbb2bfe492dca261701c9aaff56676f1d4..63abdf4bde80737a61e2ca18e7a622218863f903 100644
--- a/dacapo/parser.py
+++ b/dacapo/parser.py
@@ -213,7 +213,8 @@ class Parser(object):
       msg: stdout from Java running static analysis.
 
     Returns:
-      a dictionary with loaded classes mapped to a jar file.
+      a dictionary with loaded classes mapped to a jar file, a list of loaded
+      classes, and a list of executed methods.
     """
 
     tokens = self._lexer(msg)
diff --git a/dacapo/report.py b/dacapo/report.py
index d8b917d2c02af99305e9363ddb9624a02b7d28b4..1d9b6e59c003912116dbc24b52df43c3f51a76d0 100644
--- a/dacapo/report.py
+++ b/dacapo/report.py
@@ -1,19 +1,26 @@
 """Records analysis data."""
 
 from dacapo.dynamic_analysis import DynamicAnalysis
-import pandas as pd
 from dacapo.static_analysis import StaticAnalysis
+import pandas as pd
 
 
 class Report(object):
   """Stores a collection of data from static and dynamic analysis."""
 
   def __init__(self, label='default'):
+    """Constructs a new Report."""
     self._static_analysis = StaticAnalysis()
     self._dyn_analysis = {}
     self._label = label
 
   def add_dyn_analysis(self, bm, dict_results):
+    """Adds a new DynamicAnalysis object as a new invocation.
+
+    Args:
+      bm: the benchmark that the results correspond to.
+      dict_results: associates metric to results.
+    """
     df = pd.DataFrame(dict_results)
     if bm not in self._dyn_analysis:
       self._dyn_analysis[bm] = DynamicAnalysis()
diff --git a/dacapo/run.py b/dacapo/run.py
index 8daf7df785485b95649971c1d93788140622a070..714a9b703154e0351c3f96fdb0f7fc41c1f9e3d3 100644
--- a/dacapo/run.py
+++ b/dacapo/run.py
@@ -18,6 +18,8 @@ class Run(object):
   """
 
   def __init__(self, n=1):
+    """Constructs a new Run."""
+
     self._cmd_builder = CommandBuilder()
     self.n = n
     self.label = 'default'
@@ -75,13 +77,13 @@ class Run(object):
     """
     report = Report()
 
-    if self._cmd_builder.loaded_classes:
+    if self._cmd_builder.static_analysis:
       parser = Parser()
       bms = self.get_benchmarks()
       for bm in bms:
         cmd = self._cmd_builder.construct_static_analysis_cmd(bm)
         out = util.execute_cmd(cmd)
-        results = parser.parse_probes(out)
+        results, _, _ = parser.parse_static_analysis(out)
         report.static_analysis.run_loaded(results)
     else:
       report.static_analysis.run_from_jar(self._cmd_builder.dacapo)
diff --git a/dacapo/static_analysis.py b/dacapo/static_analysis.py
index 17c31df7fb24d22c1cd95c56f9afe0a4e4364723..5a3dd681941c920dec6bcdb05fea0ce5365fabe7 100644
--- a/dacapo/static_analysis.py
+++ b/dacapo/static_analysis.py
@@ -2,8 +2,8 @@
 from collections import deque
 import tempfile
 import zipfile
-import pandas as pd
 import dacapo.util as util
+import pandas as pd
 
 
 class StaticAnalysis(object):
@@ -132,5 +132,16 @@ class StaticAnalysis(object):
 
     self._df.loc[len(self._df.index)] = parsed_result
 
+  def get_result_of_class(self, class_name):
+    """Gets static analysis result for a particular class name.
+
+    Args:
+      class_name: the name of the class that you want to get data from.
+
+    Returns:
+      static analysis results for the given class.
+    """
+    return self._df.loc[self._df['class'] == class_name]
+
   def __repr__(self):
     return repr(self._df)
diff --git a/tests/run_test.py b/tests/run_test.py
index d702168f9a775ad7ee9d8fc124de6ec84e37d340..a1cd61380e11bba3925573c17972504c8fdfdb8a 100644
--- a/tests/run_test.py
+++ b/tests/run_test.py
@@ -1,17 +1,19 @@
 """Test class for run."""
 
 import unittest
-import dacapo.run
+from dacapo.run import Run
+import mock
+from dacapo.parser import Parser
 
 
 class TestRun(unittest.TestCase):
 
   def test_default(self):
-    my_run = dacapo.run.Run()
+    my_run = Run()
     self.assertEqual(my_run.n, 1)
 
   def test_config(self):
-    my_run = dacapo.run.Run()
+    my_run = Run()
     my_run.config(w=3, n=2, interpreted=True, dacapo='dacapo.jar',
                   bms='eclipse', compiled=True, static_analysis=True,
                   events='branches', label='my run')
@@ -30,10 +32,67 @@ class TestRun(unittest.TestCase):
            'lusearch', 'pmd', 'sunflow', 'tomcat', 'tradebeans', 'tradesoap',
            'xalan'
           ]
-    my_run = dacapo.run.Run()
+    my_run = Run()
     my_run.command_builder.bms = None
     for bm in my_run.get_benchmarks():
       self.assertIn(bm, bms)
 
+  @mock.patch('dacapo.util.execute_cmd')
+  def test_run_perf(self, mock_execute_cmd):
+    dacapo_printout = '''begin is called at iteration 1
+  ===== DaCapo 9.12 fop starting =====
+  end is called at iteration 1
+  report is called at iteration 1
+  ============================ Perf Counter warmup 1 ============================
+  cycles:CPU(all):10000000000
+  instructions:CPU(all):10000000001
+  ------------------------------ Perf Counter Statistics -----------------------------
+  cleanup is called
+  ===== DaCapo 9.12 fop PASSED in 200 msec ====='''
+
+    mock_execute_cmd.return_value = dacapo_printout
+
+    my_run = Run()
+    my_run.config(bms='fop', events='cycles,instructions')
+
+    report = my_run.run_perf()
+    self.assertEqual(report.number_of_dyn_analyses, 1)
+    self.assertEqual(report.bms, ['fop'])
+
+    dyn_analysis = report.get_dyn_analysis('fop')
+    self.assertEqual(dyn_analysis.size, 1)
+
+    invocation = dyn_analysis.get_invocation(0)
+    self.assertEqual(invocation['cycles'][0], 10000000000)
+    self.assertEqual(invocation['instructions'][0], 10000000001)
+    self.assertEqual(invocation['time'][0], 200)
+
+    mock_execute_cmd.assert_called_once()
+
+  @mock.patch('dacapo.util.execute_cmd')
+  def test_run_ckjm(self, mock_execute_cmd):
+    loaded_classes = '[Loaded Bar.class from file:foo.jar]'
+    ckjm_output = '''Bar 1 2 3 4 5 6 7 8'''
+
+    mock_execute_cmd.side_effect = [loaded_classes, ckjm_output]
+
+    my_run = Run()
+    my_run.config(static_analysis=True, bms='fop')
+
+    report = my_run.run_ckjm()
+    self.assertEqual(report.number_of_static_analyses, 1)
+
+    result = report.static_analysis.get_result_of_class('Bar')
+
+    self.assertEqual(result['class'][0], 'Bar')
+    self.assertEqual(result['wmc'][0], '1')
+    self.assertEqual(result['dit'][0], '2')
+    self.assertEqual(result['noc'][0], '3')
+    self.assertEqual(result['cbo'][0], '4')
+    self.assertEqual(result['rfc'][0], '5')
+    self.assertEqual(result['lcom'][0], '6')
+    self.assertEqual(result['ca'][0], '7')
+    self.assertEqual(result['npm'][0], '8')
+
 if __name__ == '__main__':
   unittest.main()