前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >聊聊springboot的HeapDumpWebEndpoint

聊聊springboot的HeapDumpWebEndpoint

作者头像
code4it
发布2018-09-17 16:31:38
8640
发布2018-09-17 16:31:38
举报
文章被收录于专栏:码匠的流水账码匠的流水账

本文主要研究下springboot的HeapDumpWebEndpoint

HeapDumpWebEndpointAutoConfiguration

spring-boot-actuator-autoconfigure-2.0.1.RELEASE-sources.jar!/org/springframework/boot/actuate/autoconfigure/management/HeapDumpWebEndpointAutoConfiguration.java

代码语言:javascript
复制
@Configuration
public class HeapDumpWebEndpointAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnEnabledEndpoint
    public HeapDumpWebEndpoint heapDumpWebEndpoint() {
        return new HeapDumpWebEndpoint();
    }

}

HeapDumpWebEndpoint

spring-boot-actuator-2.0.1.RELEASE-sources.jar!/org/springframework/boot/actuate/management/HeapDumpWebEndpoint.java

代码语言:javascript
复制
@WebEndpoint(id = "heapdump")
public class HeapDumpWebEndpoint {

    private final long timeout;

    private final Lock lock = new ReentrantLock();

    private HeapDumper heapDumper;

    public HeapDumpWebEndpoint() {
        this(TimeUnit.SECONDS.toMillis(10));
    }

    protected HeapDumpWebEndpoint(long timeout) {
        this.timeout = timeout;
    }

    @ReadOperation
    public WebEndpointResponse<Resource> heapDump(@Nullable Boolean live) {
        try {
            if (this.lock.tryLock(this.timeout, TimeUnit.MILLISECONDS)) {
                try {
                    return new WebEndpointResponse<>(
                            dumpHeap(live == null ? true : live));
                }
                finally {
                    this.lock.unlock();
                }
            }
        }
        catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
        }
        catch (IOException ex) {
            return new WebEndpointResponse<>(
                    WebEndpointResponse.STATUS_INTERNAL_SERVER_ERROR);
        }
        catch (HeapDumperUnavailableException ex) {
            return new WebEndpointResponse<>(
                    WebEndpointResponse.STATUS_SERVICE_UNAVAILABLE);
        }
        return new WebEndpointResponse<>(WebEndpointResponse.STATUS_TOO_MANY_REQUESTS);
    }

    private Resource dumpHeap(boolean live) throws IOException, InterruptedException {
        if (this.heapDumper == null) {
            this.heapDumper = createHeapDumper();
        }
        File file = createTempFile(live);
        this.heapDumper.dumpHeap(file, live);
        return new TemporaryFileSystemResource(file);
    }

    private File createTempFile(boolean live) throws IOException {
        String date = new SimpleDateFormat("yyyy-MM-dd-HH-mm").format(new Date());
        File file = File.createTempFile("heapdump" + date + (live ? "-live" : ""),
                ".hprof");
        file.delete();
        return file;
    }

    /**
     * Factory method used to create the {@link HeapDumper}.
     * @return the heap dumper to use
     * @throws HeapDumperUnavailableException if the heap dumper cannot be created
     */
    protected HeapDumper createHeapDumper() throws HeapDumperUnavailableException {
        return new HotSpotDiagnosticMXBeanHeapDumper();
    }
}

这里调用的是dumpHeap方法,委托给heapDumper来执行

heapDumper

代码语言:javascript
复制
    /**
     * Factory method used to create the {@link HeapDumper}.
     * @return the heap dumper to use
     * @throws HeapDumperUnavailableException if the heap dumper cannot be created
     */
    protected HeapDumper createHeapDumper() throws HeapDumperUnavailableException {
        return new HotSpotDiagnosticMXBeanHeapDumper();
    }

    /**
     * Strategy interface used to dump the heap to a file.
     */
    @FunctionalInterface
    protected interface HeapDumper {

        /**
         * Dump the current heap to the specified file.
         * @param file the file to dump the heap to
         * @param live if only <em>live</em> objects (i.e. objects that are reachable from
         * others) should be dumped
         * @throws IOException on IO error
         * @throws InterruptedException on thread interruption
         */
        void dumpHeap(File file, boolean live) throws IOException, InterruptedException;

    }

    /**
     * {@link HeapDumper} that uses {@code com.sun.management.HotSpotDiagnosticMXBean}
     * available on Oracle and OpenJDK to dump the heap to a file.
     */
    protected static class HotSpotDiagnosticMXBeanHeapDumper implements HeapDumper {

        private Object diagnosticMXBean;

        private Method dumpHeapMethod;

        @SuppressWarnings("unchecked")
        protected HotSpotDiagnosticMXBeanHeapDumper() {
            try {
                Class<?> diagnosticMXBeanClass = ClassUtils.resolveClassName(
                        "com.sun.management.HotSpotDiagnosticMXBean", null);
                this.diagnosticMXBean = ManagementFactory.getPlatformMXBean(
                        (Class<PlatformManagedObject>) diagnosticMXBeanClass);
                this.dumpHeapMethod = ReflectionUtils.findMethod(diagnosticMXBeanClass,
                        "dumpHeap", String.class, Boolean.TYPE);
            }
            catch (Throwable ex) {
                throw new HeapDumperUnavailableException(
                        "Unable to locate HotSpotDiagnosticMXBean", ex);
            }
        }

        @Override
        public void dumpHeap(File file, boolean live) {
            ReflectionUtils.invokeMethod(this.dumpHeapMethod, this.diagnosticMXBean,
                    file.getAbsolutePath(), live);
        }

    }

这里创建的是HotSpotDiagnosticMXBeanHeapDumper,利用反射调用HotSpotDiagnosticMXBean的dumpHeap方法

TemporaryFileSystemResource

最后通过TemporaryFileSystemResource返回 ``` private static final class TemporaryFileSystemResource extends FileSystemResource {

代码语言:javascript
复制
    private final Log logger = LogFactory.getLog(getClass());

    private TemporaryFileSystemResource(File file) {
        super(file);
    }

    @Override
    public ReadableByteChannel readableChannel() throws IOException {
        ReadableByteChannel readableChannel = super.readableChannel();
        return new ReadableByteChannel() {

            @Override
            public boolean isOpen() {
                return readableChannel.isOpen();
            }

            @Override
            public void close() throws IOException {
                closeThenDeleteFile(readableChannel);
            }

            @Override
            public int read(ByteBuffer dst) throws IOException {
                return readableChannel.read(dst);
            }

        };
    }

    @Override
    public InputStream getInputStream() throws IOException {
        return new FilterInputStream(super.getInputStream()) {

            @Override
            public void close() throws IOException {
                closeThenDeleteFile(this.in);
            }

        };
    }

    private void closeThenDeleteFile(Closeable closeable) throws IOException {
        try {
            closeable.close();
        }
        finally {
            deleteFile();
        }
    }

    private void deleteFile() {
        try {
            Files.delete(getFile().toPath());
        }
        catch (IOException ex) {
            TemporaryFileSystemResource.this.logger.warn(
                    "Failed to delete temporary heap dump file '" + getFile() + "'",
                    ex);
        }
    }

    @Override
    public boolean isFile() {
        // Prevent zero-copy so we can delete the file on close
        return false;
    }

}

```

小结

heapDump的实现是依赖HotSpotDiagnosticMXBean来,如果不存在则报HeapDumperUnavailableException,然后状态码返回STATUS_SERVICE_UNAVAILABLE。如果存在则默认dump存活的对象。

doc

  • Spring Boot Reference Guide
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-04-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码匠的流水账 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • HeapDumpWebEndpointAutoConfiguration
  • HeapDumpWebEndpoint
  • heapDumper
  • TemporaryFileSystemResource
  • 小结
  • doc
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档