JAVA内存管理
set JAVA_OPTS=-server -Xms1024m -Xmx1024m -XX:PermSize=512M -XX:MaxPermSize=512m -XX:MaxNewSize=512M 虚拟机栈和本地方法栈溢出:StackOverflowError -Xoss:设置本地方法栈大小 java堆溢出:OutOfMemoryError java heap space -Xmx:设置虚拟机堆参数的最大值 -Xms:设置虚拟机堆参数的最小值 运行时常量池溢出:OutOfMemoryError PermGen space -XX:PermSize ,-XX:MaxPermSize:限制方法区的大小 1.程序计数器 当前线程所执行的字节码的行号指示器 这类内存区域为“线程私有”的内存 此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域 2.Java虚拟机栈 这类内存区域为“线程私有”的内存 它的生命周期与线程相同。虚拟机栈描述的是Java 方法执行的内存模型:每个方法被执 行的时候都会同时创建一个栈帧(Stack Frame ①)用于存储局部变量表、操作栈、动态 链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在 虚拟机栈中从入栈到出栈的过程。 3.本地方法栈 本地方法栈(NativeMethodStacks)与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务。与虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常 4.堆 垃圾回收的主要区域 是虚拟机所管理的内存中最大的一块,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存,但是随着JIT编译器的发展和逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙的变化发生,所有的对象都分配在堆上就变得不是那么绝对了。 5.方法区 方法区用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。 运行时常量池是方法区的一部分,用于存放编译器生成的各种字面量和符号引用。 标记清除算法 标记死亡和存活的类,然后清除掉。碎片化可能比较严重 复制算法 内存划分两部分,存活的移动到一边,然后另一边清除,吃内存 标记整理 存活的移动到一边,另一部分清理掉 分代回收算法 新生代用复制算法 老年代用标记清除、标记整理算法 1: /// <summary> 2: /// A program abstraction. 3: /// </summary> 4: public interface IHost : IDisposable 5: { 6: /// <summary> 7: /// The programs configured services. 8: /// </summary> 9: IServiceProvider Services { get; } 10: 11: /// <summary> 12: /// Start the program. 13: /// </summary> 14: /// <param name="cancellationToken">Used to abort program start.</param> 15: /// <returns>A <see cref="Task"/www.hongyaoyul.cn> that will be completed when the <see cref="IHost"/> starts.</returns> 16: Task StartAsync(CancellationToken cancellationToken = default); 17: 18: /// <summary> 19: /// Attempts to gracefully stop the program. 20: /// </summary> 21: /// <param name="cancellationToken">Used to indicate when stop should no longer be graceful.</param> 22: /// <returns>A <see cref="Task"/> that will be completed when the <see cref="IHost"/> stops.</returns> 23: Task StopAsync(CancellationToken cancellationToken = default); 24: } 该接口含有一个只读属性:IServiceProvider Services { get; },通过该属性,我们可以拿到所有Host初始化时所注入的对象信息。 IHostBuilder接口所承担的核心功能就是程序的初始化,通过:IHost Build()来完成,当然只需要运行一次即可。其初始化内容一般包括以下几个功能: host3 另外需要说明的是,以上功能的初始化,是通过IHostBuilder提供的接口获取用户输入的信息后,通过调用Build()方法来完成初始化。以下为IHostBuilder的部分源代码: 1: /// <summary> 2: /// Set up the configuration for the builder itself. This will be used to initialize the <see cref="IHostEnvironment"/> 3: /// for use later in the build process. This can be called multiple times and the results will be additive. 4: /// </summary> 5: /// <param name="configureDelegate">The delegate for configuring the www.hnyxysy.com<see cref="IConfigurationBuilder"/> that will be used 6: /// to construct the <see cref="IConfiguration"/> for the host.</param> 7: /// <returns>The same instance of the <www.luqintang.com see cref="IHostBuilder"/> for chaining.</returns> 8: public IHostBuilder ConfigureHostConfiguration(Action<IConfigurationBuilder> configureDelegate) 9: { 10: _configureHostConfigActions.Add(configureDelegate ?? throw new ArgumentNullException(nameof(configureDelegate))); 11: return this; 12: } 13: 14: /// <summary> 15: /// Adds services to the container. This can be called multiple times and the results will be additive. 16: /// </summary> 17: /// <param name="configureDelegate">The delegate for configuring the <see cref="IConfigurationBuilder"/> that will be used 18: /// to construct the <see cref="IConfiguration"/> for the host.</param> 19: /// <returns>The same instance of the <see cref="IHostBuilder"/> for chaining.</returns> 20: public IHostBuilder ConfigureServices(Action<HostBuilderContext,IServiceCollection> configureDelegate) 21: { 22: _configureServicesActions.Add(configureDelegate ?? throw new ArgumentNullException(nameof(configureDelegate))); 23: return this; 24: } 25: 26: /// <summary> 27: /// Overrides the factory used to create the service provider. 28: /// </summary> 29: /// <typeparam name="TContainerBuilder">The type of the builder to create.</typeparam> 30: /// <param name="factory">A factory used for creating service providers.</param> 31: /// <returns>The same instance of the www.qiaoheibpt.com<see cref="IHostBuilder"/> for chaining.</returns> 32: public IHostBuilder UseServiceProviderFactory<TContainerBuilder>(IServiceProviderFactory<TContainerBuilder> factory) 33: { 34: _serviceProviderFactory = new ServiceFactoryAdapter<TContainerBuilder>(factory ?? throw new ArgumentNullException(nameof(factory))); 35: return this; 36: } 37: 38: /// <summary> 39: /// Enables configuring the instantiated dependency container. This can be called multiple times and 40: /// the results will be additive. 41: /// </summary> 42: /// <typeparam name="TContainerBuilder">The type of the builder to create.</typeparam> 43: /// <param name="configureDelegate">The delegate for configuring the <see cref="IConfigurationBuilder"/> that will be used 44: /// to construct the <see cref="IConfiguration"/> for the host.</param> 45: /// <returns>The same instance of the <see cref="IHostBuilder"/> for chaining.</returns> 46: public IHostBuilder ConfigureContainer<TContainerBuilder>(Action<HostBuilderContext,TContainerBuilder> configureDelegate) 47: { 48: _configureContainerActions.Add(new www.sanguoyoux.cn ConfigureContainerAdapter<TContainerBuilder>(configureDelegate 49: ?? throw new ArgumentNullException(nameof(configureDelegate)))); 50: return this; 51: } IHostService 文章开头有说过自定义Host Service对象,那么我们如何自定义呢,其实很简单只需要实现IHostService,并在ConfigureServices中调用services.AddHostedService<MyServiceA>()即可,以下是IHostService的源码: 1: /// <summary> 2: /// Defines methods for objects that are managed by the host. 3: /// </summary> 4: public interface IHostedService 5: { 6: /// <summary> 7: /// Triggered when the application host is ready to start the service. 8: /// </summary> 9: /// <param name="cancellationToken">Indicates that the start process has been aborted.</param> 10: Task StartAsync(CancellationToken cancellationToken); 11: 12: /// <summary> 13: /// Triggered when the application host is performing a graceful shutdown. 14: /// </summary> 15: /// <param name="cancellationToken">Indicates that the shutdown process should no longer be graceful.</param> 16: Task StopAsync(CancellationToken cancellationToken); 17: } 根据源码我们可以知道,该接口只有两个方法,即代码程序开始与停止的方法。具体的实现可以参考如下: 1: public class MyServiceA : IHostedService,IDisposable 2: { 3: private bool _stopping; 4: private Task _backgroundTask; 5: 6: public MyServiceA(ILoggerFactory loggerFactory) 7: { 8: Logger = loggerFactory.CreateLogger<MyServiceB>(); 9: } 10: 11: public ILogger Logger { get; } 12: 13: public Task StartAsync(CancellationToken cancellationToken) 14: { 15: Logger.LogInformation("MyServiceB is starting."); 16: _backgroundTask = BackgroundTask(www.hongshengyl.cn); 17: return Task.CompletedTask; 18: } 19: 20: private async Task BackgroundTask() 21: { 22: while (!_stopping) 23: { 24: await Task.Delay(TimeSpan.FromSeconds(7)); 25: Logger.LogInformation("MyServiceB is doing background work."); 26: } 27: 28: Logger.LogInformation("MyServiceB background task is stopping."); 29: } 30: 31: public async Task StopAsync(CancellationToken cancellationToken) 32: { 33: Logger.LogInformation(www.pingguoyul.cn"MyServiceB is stopping."); 34: _stopping = true; 35: if (_backgroundTask != null) 36: { 37: // TODO: cancellation 38: await _backgroundTask; 39: } 40: } 41: 42: public void Dispose() 43: { 44: Logger.LogInformation("MyServiceB is disposing."); 45: } 46: } IHostService是我们自定义Host管理对象的入口,所有需要压入到Host托管的对象都必须要实现此接口。 Host生命周期的管理 该接口提供了一种我们可以在程序运行期间进行管理的功能,如程序的启动与停止事件的订阅,关于Host生命周期的管理,主要由IHostApplicationLifetime和IHostLifetime这两个接口来完成。 以下是IHostApplicationLifetime的源码? 1: public interface IHostApplicationLifetime 2: { 3: /// <summary> 4: /// Triggered when the application host has fully started. 5: /// </summary> 6: CancellationToken ApplicationStarted { get; } 7: 8: /// <summary> 9: /// Triggered when the application host is performing a graceful shutdown. 10: /// Shutdown will block until this event completes. 11: /// </summary> 12: CancellationToken ApplicationStopping { get; } 13: 14: /// <summary> 15: /// Triggered when the application host is performing a graceful shutdown. 16: /// Shutdown will block until this event completes. 17: /// </summary> 18: CancellationToken ApplicationStopped { get; } 19: 20: /// <summary> 21: /// Requests termination of the current application. 22: /// </summary> 23: void StopApplication(www.jintianxuesha.com); 24: } IHostLifetime源码如下: 1: public interface IHostLifetime 2: { 3: /// <summary> 4: /// Called at the start of <see cref="IHost.StartAsync(CancellationToken)"/> which will wait until it‘s complete before 5: /// continuing. This can be used to delay startup until signaled by an external event. 6: /// </summary> 7: /// <param name="cancellationToken">Used to indicate when stop should no longer be graceful.</param> 8: /// <returns>A <see cref="Task"/>.</returns> 9: Task WaitForStartAsync(CancellationToken cancellationToken); 10: 11: /// <summary>http://jintianxuesha.com/?id=8 12: /// Called from <see cref="IHost.StopAsync(CancellationToken)"/> to indicate that the host is stopping and it‘s time to shut down. 13: /// </summary> 14: /// <param name="cancellationToken">Used to indicate when stop should no longer be graceful.</param> 15: /// <returns>A <see cref="Task"/>.</returns> 16: Task StopAsync(CancellationToken cancellationToken); 17: } 具体的使用可以参考如下代码: 1: public class MyLifetime : IHostLifetime,IDisposable 2: { 3: ......... 4: 5: private IHostApplicationLifetime ApplicationLifetime { get; } 6: 7: public ConsoleLifetime(IHostApplicationLifetime applicationLifetime) 8: { 9: ApplicationLifetime = applicationLifetime ?? throw new ArgumentNullException(nameof(applicationLifetime)); 10: } 11: 12: public Task WaitForStartAsync(CancellationToken cancellationToken) 13: { 14: _applicationStartedRegistration = ApplicationLifetime.ApplicationStarted.Register(state => 15: { 16: ((ConsoleLifetime)state).OnApplicationStarted(); 17: }, 18: this); 19: _applicationStoppingRegistration = ApplicationLifetime.ApplicationStopping.Register(state => 20: { 21: ((ConsoleLifetime)state).OnApplicationStopping(); 22: }, 23: this); 24: 25: ....... 26: 27: return Task.CompletedTask; 28: } 29: 30: private void OnApplicationStarted() 31: { 32: Logger.LogInformation("Application started. Press Ctrl+C to shut down."); 33: Logger.LogInformation("Hosting environment: {envName}",Environment.EnvironmentName); 34: Logger.LogInformation("Content root path: {contentRoot}",Environment.ContentRootPath); 35: } 36: 37: private void OnApplicationStopping() 38: { 39: Logger.LogInformation("Application is shutting down..."); 40: } 41: 42: ........ 43: } 总结 至此,我们知道了创建Long Run Program所需要关注的几个点,分别是继承IHostService、订阅程序的生命周期时间以及Host的初始化过程。相对来说这段内容还是比较简单的,但是开发过程中,依然会遇到很多的问题,比如任务的定时机制、消息的接入、以及程序的性能优化等等,这些都需要我们在实践中进一步总结完善。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |