Skip to content
This repository was archived by the owner on Jul 6, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions tools/logcat-parse/Grefs.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,7 +13,7 @@ public class Grefs {
const string ThreadAndStack = @"(thread (?<thread>'[^']+'\([^)]+\)))?(?<stack>.*)$";
const string AddGrefFormat = Prefix + @"\+g\+ grefc (?<gcount>\d+) gwrefc (?<wgcount>\d+) obj-handle (?<handle>0x[0-9A-Fa-f]+)/(?<handle_type>.) -> new-handle (?<ghandle>0x[0-9A-Fa-f]+)/(?<ghandle_type>.) from " + ThreadAndStack;
const string AddWgrefFormat = Prefix + @"\+w\+ grefc (?<gcount>\d+) gwrefc (?<wgcount>\d+) obj-handle (?<handle>0x[0-9A-Fa-f]+)/(?<handle_type>.) -> new-handle (?<whandle>0x[0-9A-Fa-f]+)/(?<whandle_type>.) from " + ThreadAndStack;
const string AtFormat = Prefix + @"(?<stack>at.*$)";
const string AtFormat = Prefix + @"(?<stack>\s+at.*$)";
const string DisposingFormat = Prefix + @"Disposing handle (?<handle>0x[0-9A-Fa-f]+)$";
const string FinalizingFormat = Prefix + @"Finalizing (?<type>[^ ]+) handle (?<handle>0x[0-9A-Fa-f]+)$";
const string HandleFormat = Prefix + @"handle (?<handle>0x[0-9A-Fa-f]+); key_handle (?<key_handle>0x[0-9A-Fa-f]+): Java Type: `(?<jtype>[^`]+)`; MCW type: `(?<mtype>.*)`$";
Expand DownExpand Up@@ -53,11 +53,12 @@ public static Grefs Parse (TextReader reader, int? pid = null, GrefParseOptions
HashSet<JniHandleInfo> WeakRefs = new HashSet<JniHandleInfo>();

List<PeerInfo> allocated = new List<PeerInfo> ();
List<PeerInfo> alive = new List<PeerInfo> ();

public GrefParseOptions ParseOptions {get; private set;}
public IList<PeerInfo> AllocatedPeers {get; private set;}
public IEnumerable<PeerInfo> AlivePeers {
get {return allocated.Where (p => !p.Collected && !p.Disposed && !p.Finalized);}
get {return alive;}
}

public int GrefCount {
Expand DownExpand Up@@ -145,6 +146,7 @@ Dictionary<Regex, Action<Match, int>> CreateHandlers (int? pid)
if (!WeakRefs.Any (w => p.Handles.Contains (w))) {
p.Collected = true;
p.DestroyedOnThread = m.Groups ["thread"].Value;
alive.Remove (p);
}
CheckCounts (m, l);

Expand All@@ -158,6 +160,7 @@ Dictionary<Regex, Action<Match, int>> CreateHandlers (int? pid)
if (!GlobalRefs.Any (g => p.Handles.Contains (g))) {
p.Collected = true;
p.DestroyedOnThread = m.Groups ["thread"].Value;
alive.Remove (p);
}
CheckCounts (m, l);

Expand DownExpand Up@@ -208,9 +211,9 @@ void CheckCounts (Match m, int lineNumber)
PeerInfo GetPeerInfo (Match m)
{
var h = GetHandle (m, "handle");
var i = allocated.FindLastIndex (p => p.Handles.Contains (h));
var i = alive.FindLastIndex (p => p.Handles.Contains (h));
if (i >= 0)
return allocated [i];
return alive [i];
var pid = m.Groups ["pid"].Value;
var peer = new PeerInfo (pid) {
CreatedOnThread = m.Groups ["thread"].Value,
Expand All@@ -219,6 +222,7 @@ PeerInfo GetPeerInfo (Match m)
},
};
allocated.Add (peer);
alive.Add (peer);
return peer;
}
}
Expand Down
4 changes: 4 additions & 0 deletions tools/logcat-parse/PeerInfo.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -146,6 +146,10 @@ public bool Finalized {
set {state |= PeerInfoState.Finalized;}
}

public bool Alive {
get {return state == PeerInfoState.Alive;}
}

public string JniType {get; internal set;}
public string McwType {get; internal set;}

Expand Down
50 changes: 50 additions & 0 deletions tools/logcat-parse/Tests/GrefsTest.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -398,6 +398,56 @@ public void TrackThreadInformation ()
peer.GetStackTraceForHandle ("0x100492/G"));
}
}

[Test]
public void RepeatedThreadHandles ()
{
using (var source = new StreamReader (Assembly.GetExecutingAssembly ().GetManifestResourceStream ("stdio-repeated-handles"))) {
var info = Grefs.Parse (source, options: GrefParseOptions.ThrowOnCountMismatch);
Assert.AreEqual (2, info.AllocatedPeers.Count);
Assert.AreEqual (1, info.AlivePeers.Count ());
Assert.AreEqual (1, info.GrefCount);
Assert.AreEqual (0, info.WeakGrefCount);

var peer = info.AllocatedPeers [0];
Assert.IsTrue (peer.Collected);
Assert.IsTrue (peer.Disposed);
Assert.IsFalse (peer.Finalized);
Assert.AreEqual ("java/lang/String", peer.JniType);
Assert.AreEqual ("Java.Lang.String", peer.McwType);

Assert.AreEqual ("'(null)'(3)", peer.CreatedOnThread);
Assert.AreEqual ("'(null)'(3)", peer.DestroyedOnThread);

Assert.AreEqual ("0x41e29778", peer.KeyHandle);
Assert.AreEqual (2, peer.Handles.Count);
Assert.IsTrue (peer.Handles.Contains ("0x4a00009/L"));
Assert.IsTrue (peer.Handles.Contains ("0x19004aa/G"));

Assert.AreEqual (
" at Doesn't Matter",
peer.GetStackTraceForHandle ("0x19004aa/G"));

peer = info.AllocatedPeers [1];
Assert.IsFalse (peer.Collected);
Assert.IsFalse (peer.Disposed);
Assert.IsFalse (peer.Finalized);
Assert.AreEqual ("java/lang/String", peer.JniType);
Assert.AreEqual ("Java.Lang.String", peer.McwType);

Assert.AreEqual ("'(null)'(3)", peer.CreatedOnThread);
Assert.AreEqual (null, peer.DestroyedOnThread);

Assert.AreEqual ("0x41e29778", peer.KeyHandle);
Assert.AreEqual (2, peer.Handles.Count);
Assert.IsTrue (peer.Handles.Contains ("0x4a00009/L"));
Assert.IsTrue (peer.Handles.Contains ("0x19004aa/G"));

Assert.AreEqual (
" at Doesn't Matter",
peer.GetStackTraceForHandle ("0x19004aa/G"));
}
}
}
}

3 changes: 3 additions & 0 deletions tools/logcat-parse/Tests/LogcatParse-Tests.csproj
Original file line numberDiff line numberDiff line change
Expand Up@@ -84,5 +84,8 @@
<EmbeddedResource Include="Resources\stdio-Finalized-threads.txt">
<LogicalName>stdio-Finalized-threads</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Resources\stdio-repeated-handles.txt">
<LogicalName>stdio-repeated-handles</LogicalName>
</EmbeddedResource>
</ItemGroup>
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
+g+ grefc 1 gwrefc 0 obj-handle 0x4a00009/L -> new-handle 0x19004aa/G from thread '(null)'(3)
at Doesn't Matter
handle 0x19004aa; key_handle 0x41e29778: Java Type: `java/lang/String`; MCW type: `Java.Lang.String`
Disposing handle 0x19004aa
-g- grefc 0 gwrefc 0 handle 0x19004aa/G from thread '(null)'(3)
at Doesn't Matter
+g+ grefc 1 gwrefc 0 obj-handle 0x4a00009/L -> new-handle 0x19004aa/G from thread '(null)'(3)
at Doesn't Matter
handle 0x19004aa; key_handle 0x41e29778: Java Type: `java/lang/String`; MCW type: `Java.Lang.String`