Skip to main content
Glama

get_memory_info

Retrieve memory usage information for Java processes by specifying a process ID to monitor JVM heap and performance metrics.

Instructions

获取内存使用情况

        Args:
            pid (str): 进程ID,使用字符串形式(如:"12345")。
                支持十进制和十六进制格式。
                空字符串将返回错误信息。

        Returns:
            Dict: 包含内存信息的字典,包含以下字段:
                - raw_output (str): 原始输出
                - timestamp (float): 时间戳
                - success (bool): 是否成功
                - error (Optional[str]): 错误信息
        

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pidNo

Implementation Reference

  • Handler and registration for get_memory_info tool. Validates the PID input, executes JmapCommand with JmapHeapFormatter to retrieve JVM heap memory information, and formats the response.
    @self.mcp.tool()
    def get_memory_info(pid: str = "") -> Dict:
        """获取内存使用情况
    
        Args:
            pid (str): 进程ID,使用字符串形式(如:"12345")。
                支持十进制和十六进制格式。
                空字符串将返回错误信息。
    
        Returns:
            Dict: 包含内存信息的字典,包含以下字段:
                - raw_output (str): 原始输出
                - timestamp (float): 时间戳
                - success (bool): 是否成功
                - error (Optional[str]): 错误信息
        """    
        try:
            validated_pid = self._validate_and_convert_id(pid if pid else None, "process ID")
            if validated_pid is None:
                return {
                    "raw_output": "",
                    "timestamp": time.time(),
                    "success": False,
                    "error": "Invalid process ID"
                }
        except ValueError as e:
            return {
                "raw_output": "",
                "timestamp": time.time(),
                "success": False,
                "error": str(e)
            }
        
        cmd = JmapCommand(self.executor, JmapHeapFormatter())
        result = cmd.execute(str(validated_pid))
        return {
            "raw_output": result.get('output', ''),
            "timestamp": time.time(),
            "success": result.get('success', False),
            "error": result.get('error')
        }
  • Formatter used by the get_memory_info handler to process the raw output from JmapCommand into a standardized dictionary format.
    class JmapHeapFormatter(OutputFormatter):
        """Jmap堆内存概要格式化器(仅文本输出)"""
    
        def format(self, result: CommandResult) -> Dict[str, Any]:
            if not result.success:
                return {
                    "success": False,
                    "error": result.error,
                    "timestamp": result.timestamp.isoformat()
                    }
            return {
                "success": True,
                "output": result.output,
                "execution_time": result.execution_time,
                "timestamp": result.timestamp.isoformat()
                }
  • JmapCommand class used in get_memory_info to execute the appropriate jmap (or jhsdb) command for heap information based on JDK version.
    class JmapCommand(BaseCommand):
        """Jmap命令实现"""
    
        def __init__(self, executor, formatter):
            super().__init__(executor, formatter)
            self.timeout = 60  # 设置默认超时时间为60秒
            self._jdk_version = None  # 缓存 JDK 版本
    
        def _get_jdk_version(self) -> int:
            """获取 JDK 主版本号"""
            if self._jdk_version is not None:
                return self._jdk_version
            
            try:
                # 检查是否为远程执行器
                from ..base import NativeCommandExecutor
                if isinstance(self.executor, NativeCommandExecutor) and self.executor.ssh_host:
                    # 远程执行 java -version
                    result = self.executor.run('java -version', timeout=10)
                    version_output = result.error if result.error else result.output
                else:
                    # 本地执行
                    result = subprocess.run(['java', '-version'], 
                                          capture_output=True, text=True, timeout=10)
                    version_output = result.stderr  # java -version 输出到 stderr
                
                # 解析版本号,支持多种格式
                # 格式1: "openjdk version "11.0.12" 2021-07-20"
                # 格式2: "java version "1.8.0_291""
                # 格式3: "openjdk version "17.0.15" 2025-04-15 LTS"
                version_patterns = [
                    r'version "1\.(\d+)',  # 匹配 "1.8.0_291",优先放前面
                    r'version "(\d+)',  # 匹配 "11.0.12" 或 "17.0.15"
                ]
                
                for pattern in version_patterns:
                    version_match = re.search(pattern, version_output)
                    if version_match:
                        version_str = version_match.group(1)
                        if pattern == r'version "1\.(\d+)':
                            # 对于 "1.8" 格式,返回 8
                            self._jdk_version = int(version_str)
                        else:
                            # 对于 "11" 或 "17" 格式,直接返回
                            self._jdk_version = int(version_str)
                        break
                else:
                    # 如果无法解析,假设是低版本
                    self._jdk_version = 8
                    
            except Exception as e:
                # 如果无法获取版本,假设是低版本
                self._jdk_version = 8
            
            return self._jdk_version
    
        def _is_modern_jdk(self) -> bool:
            """判断是否为现代 JDK (9+)"""
            return self._get_jdk_version() >= 9
    
        def _test_jhsdb_availability(self) -> bool:
            """测试 jhsdb 命令是否可用"""
            try:
                from ..base import NativeCommandExecutor
                if isinstance(self.executor, NativeCommandExecutor) and self.executor.ssh_host:
                    # 远程测试
                    result = self.executor.run('jhsdb --help', timeout=5)
                    return result.success
                else:
                    # 本地测试
                    result = subprocess.run(['jhsdb', '--help'], 
                                          capture_output=True, text=True, timeout=5)
                    return result.returncode == 0
            except Exception:
                return False
    
        def get_command(self, pid: str, operation: JmapOperation = JmapOperation.HEAP,
                        dump_file: Optional[str] = None, live_only: bool = False,
                        *args, **kwargs) -> str:
            """获取jmap命令
    
            Args:
                pid: 进程ID
                operation: 操作类型
                dump_file: 转储文件路径(仅在dump操作时需要)
                live_only: 是否只统计存活对象
    
            Returns:
                str: jmap命令字符串
            """
            # 验证 pid 参数
            if not pid or not pid.strip():
                raise ValueError("Process ID is required")
            
            try:
                int(pid)  # 验证 pid 是否为有效数字
            except ValueError:
                raise ValueError(f"Invalid process ID: {pid}")
            
            if operation == JmapOperation.HEAP:
                # 对于现代 JDK,优先尝试 jhsdb,如果不可用则回退到传统 jmap
                if self._is_modern_jdk() and self._test_jhsdb_availability():
                    return f'jhsdb jmap --heap --pid {pid}'
                else:
                    return f'jmap -heap {pid}'
            elif operation == JmapOperation.HISTO:
                live_flag = " -live" if live_only else ""
                return f'jmap -histo{live_flag} {pid}'
            elif operation == JmapOperation.DUMP:
                if not dump_file:
                    raise ValueError("dump_file is required for dump operation")
                live_flag = ":live" if live_only else ""
                return f'jmap -dump:format=b{live_flag},file={dump_file} {pid}'
            else:
                raise ValueError(f"Unsupported operation: {operation}")
  • Helper method used in get_memory_info (and other tools) to validate and convert PID from string (decimal/hex) to int.
    def _validate_and_convert_id(self, value: Union[int, str, None], param_name: str = "ID") -> Optional[int]:
        """
        验证并转换ID参数,支持int和str类型的数字参数
        
        Args:
            value: 要转换的值,可以是int、str或None
            param_name: 参数名称,用于错误信息
            
        Returns:
            转换后的整数值,如果输入为None则返回None
            
        Raises:
            ValueError: 如果无法转换为有效的整数
        """
        if value is None:
            return None
            
        if isinstance(value, int):
            return value
            
        if isinstance(value, str):
            # 去除前后空白字符
            value = value.strip()
            if not value:
                return None
                
            try:
                # 支持十六进制格式(如0x2c03)和十进制格式
                if value.lower().startswith('0x'):
                    return int(value, 16)
                else:
                    return int(value)
            except ValueError:
                raise ValueError(f"Invalid {param_name}: '{value}' cannot be converted to integer")
        
        raise ValueError(f"Invalid {param_name} type: expected int, str or None, got {type(value)}")

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/xzq-xu/jvm-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server