{"action":"closed","issue":{"url":"https://api.github.com/repos/glowroot/glowroot/issues/91","repository_url":"https://api.github.com/repos/glowroot/glowroot","labels_url":"https://api.github.com/repos/glowroot/glowroot/issues/91/labels{/name}","comments_url":"https://api.github.com/repos/glowroot/glowroot/issues/91/comments","events_url":"https://api.github.com/repos/glowroot/glowroot/issues/91/events","html_url":"https://github.com/glowroot/glowroot/issues/91","id":142536626,"number":91,"title":"Overridden generic methods not being instrumented","user":{"login":"trask","id":218610,"avatar_url":"https://avatars.githubusercontent.com/u/218610?v=3","gravatar_id":"","url":"https://api.github.com/users/trask","html_url":"https://github.com/trask","followers_url":"https://api.github.com/users/trask/followers","following_url":"https://api.github.com/users/trask/following{/other_user}","gists_url":"https://api.github.com/users/trask/gists{/gist_id}","starred_url":"https://api.github.com/users/trask/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/trask/subscriptions","organizations_url":"https://api.github.com/users/trask/orgs","repos_url":"https://api.github.com/users/trask/repos","events_url":"https://api.github.com/users/trask/events{/privacy}","received_events_url":"https://api.github.com/users/trask/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/glowroot/glowroot/labels/bug","name":"bug","color":"fc2929"}],"state":"closed","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/glowroot/glowroot/milestones/7","html_url":"https://github.com/glowroot/glowroot/milestones/v0.9","labels_url":"https://api.github.com/repos/glowroot/glowroot/milestones/7/labels","id":1403575,"number":7,"title":"v0.9","description":"","creator":{"login":"trask","id":218610,"avatar_url":"https://avatars.githubusercontent.com/u/218610?v=3","gravatar_id":"","url":"https://api.github.com/users/trask","html_url":"https://github.com/trask","followers_url":"https://api.github.com/users/trask/followers","following_url":"https://api.github.com/users/trask/following{/other_user}","gists_url":"https://api.github.com/users/trask/gists{/gist_id}","starred_url":"https://api.github.com/users/trask/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/trask/subscriptions","organizations_url":"https://api.github.com/users/trask/orgs","repos_url":"https://api.github.com/users/trask/repos","events_url":"https://api.github.com/users/trask/events{/privacy}","received_events_url":"https://api.github.com/users/trask/received_events","type":"User","site_admin":false},"open_issues":0,"closed_issues":38,"state":"open","created_at":"2015-11-10T02:46:21Z","updated_at":"2016-03-22T08:26:53Z","due_on":null,"closed_at":null},"comments":0,"created_at":"2016-03-22T03:29:18Z","updated_at":"2016-03-22T08:26:53Z","closed_at":"2016-03-22T08:26:53Z","body":"E.g. instrumentation applied to `A.m(T)` is not being applied to `B.m(String)`:\r\n\r\n```\r\ninterface A<T> {\r\n    void m(T);\r\n}\r\n\r\nclass B implements A<String> {\r\n    void m(String) {}\r\n}\r\n```\r\n\r\nThis is a bit tricky since `B.m(String)` only overrides `A.m(T)` according to Java Language Specification, and not according to JVM (bytecode) Specification.\r\n\r\nAnd it seems that other JVM-based languages could choose other override definitions.\r\n\r\nSo it seems best to look for bridge methods, look at the bytecode to see what method they are forwarding to, and propagate instrumentation from the bridge method to the forwarded method.\r\n\r\nIn the case above, there is bridge method `B.m(Object)` which overrides (in the JVM bytecode sense) `A.m(T)`, and then we can look at the bytecode of `B.m(Object)` to see that it forwards to `B.m(String)` and apply the instrumentation to `B.m(String)` (and then any method that further extends `B.m(String)`).\r\n\r\nI believe this approach should work with any JVM-based language.\r\n"}}