ソースを参照

Feature #TASK_QT-18250 extend jvm version

Carl 2 ヶ月 前
コミット
ae27dac7fa
3 ファイル変更76 行追加5 行削除
  1. 6 1
      containers/apm_stack_dispatch.go
  2. 24 3
      containers/container.go
  3. 46 1
      ebpftracer/getjdkversion.go

+ 6 - 1
containers/apm_stack_dispatch.go

@@ -131,7 +131,12 @@ func (c *Container) jvmStackTrace(tracer *ebpftracer.Tracer, pid uint32) error {
 		klog.WithError(err).Errorf("[jvmStackTrace] Failed get so path")
 		klog.WithError(err).Errorf("[jvmStackTrace] Failed get so path")
 		return err
 		return err
 	}
 	}
-	v, err := ebpftracer.GetJvmVersion(libjavaso)
+	libjvmso, err := utils.GetSoPath(pid, "libjvm.so", c.getRootfs())
+	if err != nil {
+		klog.WithError(err).Errorf("[jvmStackTrace] Failed get so path")
+		return err
+	}
+	v, err := ebpftracer.GetJvmVersion(libjavaso, libjvmso)
 	if err != nil {
 	if err != nil {
 		p.versionFailed = true
 		p.versionFailed = true
 		klog.WithError(err).Errorf("[jvmStackTrace] Failed get Java version")
 		klog.WithError(err).Errorf("[jvmStackTrace] Failed get Java version")

+ 24 - 3
containers/container.go

@@ -1527,7 +1527,12 @@ func (c *Container) attachJVMUprobes(tracer *ebpftracer.Tracer, pid uint32) erro
 				klog.WithError(err).Errorf("[attach] Failed get so path")
 				klog.WithError(err).Errorf("[attach] Failed get so path")
 				return err
 				return err
 			}
 			}
-			v, err := ebpftracer.GetJvmVersion(libjavaso)
+			libjvmso, err := utils.GetSoPath(pid, "libjvm.so", rootfs)
+			if err != nil {
+				klog.WithError(err).Errorf("[attach] Failed get so path")
+				return err
+			}
+			v, err := ebpftracer.GetJvmVersion(libjavaso, libjvmso)
 			if err != nil {
 			if err != nil {
 				klog.WithError(err).Errorf("[attach] Failed get Java version")
 				klog.WithError(err).Errorf("[attach] Failed get Java version")
 				return err
 				return err
@@ -1535,10 +1540,14 @@ func (c *Container) attachJVMUprobes(tracer *ebpftracer.Tracer, pid uint32) erro
 			c.AppInfo.Version = v
 			c.AppInfo.Version = v
 			major, minor, patch, err := ebpftracer.ParseVersion(v)
 			major, minor, patch, err := ebpftracer.ParseVersion(v)
 			klog.Infof("[attach] version: %s (Major: %d, Minor: %d, Patch: %d)", v, major, minor, patch)
 			klog.Infof("[attach] version: %s (Major: %d, Minor: %d, Patch: %d)", v, major, minor, patch)
-			if major != 1 || minor != 8 {
+			if !isSupportedJava(major, minor, patch) {
 				klog.Errorf("[attach] Unsupported Java version.")
 				klog.Errorf("[attach] Unsupported Java version.")
-				return fmt.Errorf("[attach] Unsupported Java version")
+				return fmt.Errorf("[attach] Unsupported Java version %s", v)
 			}
 			}
+			//if major != 1 || minor != 8 {
+			//	klog.Errorf("[attach] Unsupported Java version.")
+			//	return fmt.Errorf("[attach] Unsupported Java version")
+			//}
 		}
 		}
 
 
 		/*libNioProbes, err := tracer.AttachJavaNioReadUprobes(pid, codeType, rootfs)
 		/*libNioProbes, err := tracer.AttachJavaNioReadUprobes(pid, codeType, rootfs)
@@ -1568,6 +1577,18 @@ func (c *Container) attachJVMUprobes(tracer *ebpftracer.Tracer, pid uint32) erro
 	return nil
 	return nil
 }
 }
 
 
+func isSupportedJava(major, minor, patch int) bool {
+	switch major {
+	case 1:
+		return minor == 8 // JDK 8
+	case 11: // JDK 11/17/21
+		//case 11, 17, 21:
+		return true // JDK 11/17/21
+	default:
+		return false
+	}
+}
+
 func (c *Container) attachJavaAotUprobes(tracer *ebpftracer.Tracer, pid uint32) error {
 func (c *Container) attachJavaAotUprobes(tracer *ebpftracer.Tracer, pid uint32) error {
 	if common.IsOpenFilter() && !common.IsFilterPid(pid) {
 	if common.IsOpenFilter() && !common.IsFilterPid(pid) {
 		return nil
 		return nil

+ 46 - 1
ebpftracer/getjdkversion.go

@@ -1,8 +1,10 @@
 package ebpftracer
 package ebpftracer
 
 
 import (
 import (
+	"bufio"
 	"bytes"
 	"bytes"
 	"fmt"
 	"fmt"
+	"io"
 	"os"
 	"os"
 	"os/exec"
 	"os/exec"
 	"regexp"
 	"regexp"
@@ -11,7 +13,7 @@ import (
 	"unicode"
 	"unicode"
 )
 )
 
 
-func GetJvmVersion(filePath string) (string, error) {
+func GetJvmVersion(filePath, libjvmPath string) (string, error) {
 	minLength := 4
 	minLength := 4
 	var maxFileSize int64 = 3 * 1024 * 1024 // 3MB
 	var maxFileSize int64 = 3 * 1024 * 1024 // 3MB
 	// 打开文件
 	// 打开文件
@@ -74,9 +76,52 @@ func GetJvmVersion(filePath string) (string, error) {
 		}
 		}
 	}
 	}
 
 
+	// 其他版本从jvm获取
+	f, err := os.Open(libjvmPath)
+	if err != nil {
+		return "", fmt.Errorf("failed to open file: %w", err)
+	}
+	defer f.Close()
+	// 读取整个文件(libjvm.so 一般几十 MB 内)
+	br := bufio.NewReader(f)
+	data, err := io.ReadAll(br)
+	if err != nil {
+		return "", fmt.Errorf("failed to read file: %w", err)
+	}
+	if err != nil {
+		return "", fmt.Errorf("failed to read file: %w", err)
+	}
+	text := string(stringsLike(data))
+	if m := regexp.MustCompile(`JRE \(([^)]+)\)`).FindStringSubmatch(text); len(m) == 2 {
+		return m[1], nil
+	}
+
 	return "", fmt.Errorf("failed to extract java version from %s", filePath)
 	return "", fmt.Errorf("failed to extract java version from %s", filePath)
 }
 }
 
 
+func stringsLike(b []byte) []byte {
+	var out bytes.Buffer
+	var buf []byte
+
+	flush := func() {
+		if len(buf) >= 4 {
+			out.Write(buf)
+			out.WriteByte('\n')
+		}
+		buf = buf[:0]
+	}
+
+	for _, c := range b {
+		if c >= 32 && c <= 126 { // 可打印 ASCII(不含换行)
+			buf = append(buf, c)
+		} else {
+			flush()
+		}
+	}
+	flush()
+	return out.Bytes()
+}
+
 // 解析版本号为大版本、中间版本和小版本
 // 解析版本号为大版本、中间版本和小版本
 func ParseVersion(version string) (int, int, int, error) {
 func ParseVersion(version string) (int, int, int, error) {
 	re := regexp.MustCompile(`^(\d+)\.(\d+)\.(\d+)`)
 	re := regexp.MustCompile(`^(\d+)\.(\d+)\.(\d+)`)