private void watch() {
        this.heapMemoryUsed = so11yCollector.heapMemoryUsage();
        this.heapMemoryMax = so11yCollector.heapMemoryMax();
        this.directMemoryUsed = so11yCollector.directMemoryUsage();

        if (log.isDebugEnabled()) {
            TerminalFriendlyTable table = new TerminalFriendlyTable("Watermark Controller Key Metrics");
            table.addRow(new TerminalFriendlyTable.Row("Heap Memory Max", String.format("%,d", heapMemoryMax)));
            table.addRow(new TerminalFriendlyTable.Row("Heap Memory Used", String.format("%,d", heapMemoryUsed)));
            table.addRow(new TerminalFriendlyTable.Row("Heap Memory Usage Percentage", heapMemoryUsagePercent() + "%"));
            table.addRow(new TerminalFriendlyTable.Row("Direct Memory Used", String.format("%,d", directMemoryUsed)));
            log.debug(table.toString());
        }

        boolean isLimitingTriggered = false;

        if (heapMemoryUsagePercent() > maxHeapMemoryUsagePercentThreshold) {
            this.notify(WatermarkEvent.Type.HEAP_MEMORY_USAGE_PERCENTAGE);
            isLimitingTriggered = true;
        }

        if (maxDirectHeapMemoryUsageThreshold > 0 && directMemoryUsed > 0) {
            if (directMemoryUsed > maxDirectHeapMemoryUsageThreshold) {
                this.notify(WatermarkEvent.Type.DIRECT_HEAP_MEMORY_USAGE);
                isLimitingTriggered = true;
            }
        }

        if (!isLimitingTriggered && isLimiting) {
            recovered();
        }
    }
Heap memory used, jvm_memory_used_bytes{area="heap"}, Use the combination of all available ids of heap memory.
oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/watermark/WatermarkWatcher.java