序
本文主要研究下springboot的HeapDumpWebEndpoint
HeapDumpWebEndpointAutoConfiguration
spring-boot-actuator-autoconfigure-2.0.1.RELEASE-sources.jar!/org/springframework/boot/actuate/autoconfigure/management/HeapDumpWebEndpointAutoConfiguration.java
@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
@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
/**
* 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 {
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存活的对象。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。