/
EyePointerExplorer.class.st
119 lines (97 loc) · 3.54 KB
/
EyePointerExplorer.class.st
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
"
A variant on the TreeInspector that works ""backwards"".
By default it shows both weak and strong references (#openOn:) but I can be configured to omit weak refs with #openStrongOn:
Like the TreeInspector, it shows a tree of objects, but expanding a node won't show the objects which that node references, but rather the objects that reference that node. Its main use is to track down memory leaks: if you want to know why a particular object is still alive, open a PointerExplorer on it and drill down until you find the root object that's referencing it. For example, find all the references to the symbol #zot with:
EyePointerExplorer openOn: #zot
For the ""name"" of the object, the PointerExplorer shows each object's identityHash, to allow the user to identify when two similar objects are identical and notice cycles.
"
Class {
#name : #EyePointerExplorer,
#superclass : #EyeTreeInspector,
#instVars : [
'onlyStrong'
],
#category : #'Spec2-Inspector-Base'
}
{ #category : #accessing }
EyePointerExplorer class >> label [
^ 'Pointer Explorer'
]
{ #category : #'instance creation' }
EyePointerExplorer class >> openOn: anObject [
^(self new inspect: anObject) openWithSpec
]
{ #category : #'instance creation' }
EyePointerExplorer class >> openStrongOn: anObject [
"only show strong references"
^(self new
onlyStrong;
inspect: anObject) openWithSpec
]
{ #category : #'as yet unclassified' }
EyePointerExplorer class >> registerToolsOn: registry [
"Add ourselves to registry. See [Smalltalk tools class]
self registerToolsOn: Smalltalk tools
"
registry register: self as: #pointerExplorer
]
{ #category : #api }
EyePointerExplorer >> childrenForObject: anObject [
| objects |
objects := anObject wrappedObject pointersToExcept: { self. anObject}.
"filter out all wrappers and (otionally) all those who pointing only weakly to subject"
objects := objects reject: [ :each | each class = EyePointerWrapper].
onlyStrong ifTrue: [objects := objects reject: [ :each | each pointsOnlyWeaklyTo: anObject wrappedObject]].
^ objects collect: [ :each |
(PointerEyeElement
host: anObject wrappedObject
value: each)]
]
{ #category : #initialization }
EyePointerExplorer >> initialize [
super initialize.
onlyStrong := false.
]
{ #category : #accessing }
EyePointerExplorer >> object: anObject [
Smalltalk garbageCollect.
super object: (EyePointerWrapper wrap: anObject)
]
{ #category : #'event-handling' }
EyePointerExplorer >> objectChanged [
self text doItReceiver: self object.
self text ifNotNil: [ :w | w behavior: self object class ].
self tree roots: self roots
]
{ #category : #api }
EyePointerExplorer >> onlyStrong [
onlyStrong := true
]
{ #category : #accessing }
EyePointerExplorer >> roots [
^ self childrenForObject: self object
]
{ #category : #accessing }
EyePointerExplorer >> selectedObjectDo: aBlock [
self selectedElement ifNotNil: [ :element |
aBlock value: element value wrappedObject ]
]
{ #category : #accessing }
EyePointerExplorer >> title [
^ 'Pointers to: ', self object printString
]
{ #category : #accessing }
EyePointerExplorer >> tree [
^ tree ifNil: [
tree := self newTreeTable
addColumn: (SpStringTableColumn evaluated: [ :node | self labelFor: node ]);
"menu: [ :menu | self inspectionMenu: menu ];"
children: [ :node | self childrenFor: node ];
whenSelectedItemChanged: [ :item | item ifNotNil: [ self text doItReceiver: item value ] ];
whenBuiltDo: [ self initializeShortcuts ];
yourself ]
]
{ #category : #accessing }
EyePointerExplorer >> valueClass [
^ self value wrappedObject class
]