parseJavaLocations parses the location information in a java profile and populates the Locations in a profile. It uses the location addresses from the profile as both the ID of each location.
(b []byte, locs map[uint64]*Location, p *Profile)
| 237 | // location addresses from the profile as both the ID of each |
| 238 | // location. |
| 239 | func parseJavaLocations(b []byte, locs map[uint64]*Location, p *Profile) error { |
| 240 | r := bytes.NewBuffer(b) |
| 241 | fns := make(map[string]*Function) |
| 242 | for { |
| 243 | line, err := r.ReadString('\n') |
| 244 | if err != nil { |
| 245 | if err != io.EOF { |
| 246 | return err |
| 247 | } |
| 248 | if line == "" { |
| 249 | break |
| 250 | } |
| 251 | } |
| 252 | |
| 253 | if line = strings.TrimSpace(line); line == "" { |
| 254 | continue |
| 255 | } |
| 256 | |
| 257 | jloc := javaLocationRx.FindStringSubmatch(line) |
| 258 | if len(jloc) != 3 { |
| 259 | continue |
| 260 | } |
| 261 | addr, err := strconv.ParseUint(jloc[1], 16, 64) |
| 262 | if err != nil { |
| 263 | return fmt.Errorf("parsing sample %s: %v", line, err) |
| 264 | } |
| 265 | loc := locs[addr] |
| 266 | if loc == nil { |
| 267 | // Unused/unseen |
| 268 | continue |
| 269 | } |
| 270 | var lineFunc, lineFile string |
| 271 | var lineNo int64 |
| 272 | |
| 273 | if fileLine := javaLocationFileLineRx.FindStringSubmatch(jloc[2]); len(fileLine) == 4 { |
| 274 | // Found a line of the form: "function (file:line)" |
| 275 | lineFunc, lineFile = fileLine[1], fileLine[2] |
| 276 | if n, err := strconv.ParseInt(fileLine[3], 10, 64); err == nil && n > 0 { |
| 277 | lineNo = n |
| 278 | } |
| 279 | } else if filePath := javaLocationPathRx.FindStringSubmatch(jloc[2]); len(filePath) == 3 { |
| 280 | // If there's not a file:line, it's a shared library path. |
| 281 | // The path isn't interesting, so just give the .so. |
| 282 | lineFunc, lineFile = filePath[1], filepath.Base(filePath[2]) |
| 283 | } else if strings.Contains(jloc[2], "generated stub/JIT") { |
| 284 | lineFunc = "STUB" |
| 285 | } else { |
| 286 | // Treat whole line as the function name. This is used by the |
| 287 | // java agent for internal states such as "GC" or "VM". |
| 288 | lineFunc = jloc[2] |
| 289 | } |
| 290 | fn := fns[lineFunc] |
| 291 | |
| 292 | if fn == nil { |
| 293 | fn = &Function{ |
| 294 | Name: lineFunc, |
| 295 | SystemName: lineFunc, |
| 296 | Filename: lineFile, |
no test coverage detected
searching dependent graphs…