Android平台GB28181设备接入模块实现后台service按需回传摄像头数据到国标平台侧

技术背景

我们在做Android平台GB28181设备对接模块的时候,遇到这样的技术需求,开发者希望能以后台服务的形式运行程序,国标平台侧没有视频回传请求的时候,仅保持信令链接,有发起视频回传请求或语音广播时,打开摄像头,并实时回传音视频数据或接收处理国标平台侧发过来的语音广播数据。

技术实现

实际上,在做GB28181设备接入模块前几年,我们已经有后台采集摄像头推送RTMP的模块,这次只是把国标相关的代码加进去即可,废话不多说,上代码。

界面很简单,进入后,可以选择视频分辨率、前后摄像头,软硬编码类型,然后启动GB28181即可。

    @Overridepublic int onStartCommand(Intent intent, int flags, int startId) {onStartPusher(intent, startId);return super.onStartCommand(intent, flags, startId);}private void onStartPusher(Intent intent, int startId){Log.i(TAG, "onStartPusher...");video_width_ = intent.getExtras().getInt("CAMERAWIDTH");video_height_ = intent.getExtras().getInt("CAMERAHEIGHT");boolean isCameraFaceFront = intent.getExtras().getBoolean("SWITCHCAMERA");Log.i(TAG, "videoWidth: " + video_width_ + "videoHeight: " + video_height_ + " isCameraFaceFront: " + isCameraFaceFront);mCameraId = isCameraFaceFront?CAMERA_ID_FRONT:CAMERA_ID_BACK;is_hardware_encoder = intent.getExtras().getBoolean("HWENCODER");mWindowManager = (WindowManager) getSystemService(Service.WINDOW_SERVICE);intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK| Intent.FLAG_ACTIVITY_SINGLE_TOP);PendingIntent contentIntent = PendingIntent.getActivity(this,0, intent, 0);bgSurfaceView = new SurfaceView(this);WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(1, 1, WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,PixelFormat.TRANSLUCENT);layoutParams.gravity = Gravity.LEFT | Gravity.TOP;mWindowManager.addView(bgSurfaceView, layoutParams);bgSurfaceView.getHolder().addCallback(this);if (null == gb28181_agent_ ) {if(!initGB28181Agent() )return;}if (!gb28181_agent_.isRunning()) {if ( gb28181_agent_.start() ) {}}}

onStartPusher()里面,我们调用initGB28181Agent()完成国标设备侧到平台侧的register、catalog和keepalive交互,如果平台侧需要订阅位置,国标设备端可以按照平台侧的订阅要求,实时上报位置信息。

GB28181信令交互处理如下:

    // BackgroudService.java// Author: daniusdk.com@Overridepublic void ntsRegisterOK(String dateString) {Log.i(TAG, "ntsRegisterOK Date: " + (dateString!= null? dateString : ""));}@Overridepublic void ntsRegisterTimeout() {Log.e(TAG, "ntsRegisterTimeout");}@Overridepublic void ntsRegisterTransportError(String errorInfo) {Log.e(TAG, "ntsRegisterTransportError error:" + (errorInfo != null?errorInfo :""));}@Overridepublic void ntsOnHeartBeatException(int exceptionCount,  String lastExceptionInfo) {Log.e(TAG, "ntsOnHeartBeatException heart beat timeout count reached, count:" + exceptionCount+", exception info:" + (lastExceptionInfo!=null?lastExceptionInfo:""));// 停止信令, 然后重启handler_.postDelayed(new Runnable() {@Overridepublic void run() {Log.i(TAG, "gb28281_heart_beart_timeout");record_executor_.cancel_tasks();stopGB28181Stream();destoryRTPSender();if (gb28181_agent_ != null) {gb28181_agent_.terminateAllPlays(true);Log.i(TAG, "gb28281_heart_beart_timeout sip stop");gb28181_agent_.stop();String local_ip_addr = IPAddrUtils.getIpAddress(context_);if (local_ip_addr != null && !local_ip_addr.isEmpty() ) {Log.i(TAG, "gb28281_heart_beart_timeout get local ip addr: " + local_ip_addr);gb28181_agent_.setLocalAddress(local_ip_addr);}record_executor_.cancel_tasks();Log.i(TAG, "gb28281_heart_beart_timeout sip start");gb28181_agent_.start();}}},0);}@Overridepublic void ntsOnInvitePlay(String deviceId, SessionDescription session_des) {handler_.postDelayed(new Runnable() {@Overridepublic void run() {// 先振铃响应下gb28181_agent_.respondPlayInvite(180, device_id_);MediaSessionDescription video_des = null;SDPRtpMapAttribute ps_rtpmap_attr = null;// 28181 视频使用PS打包Vector<MediaSessionDescription> video_des_list = session_des_.getVideoPSDescriptions();if (video_des_list != null && !video_des_list.isEmpty()) {for(MediaSessionDescription m : video_des_list) {if (m != null && m.isValidAddressType() && m.isHasAddress() ) {video_des = m;ps_rtpmap_attr = video_des.getPSRtpMapAttribute();break;}}}if (null == video_des) {gb28181_agent_.respondPlayInvite(488, device_id_);Log.i(TAG, "ntsOnInvitePlay get video description is null, response 488, device_id:" + device_id_);return;}if (null == ps_rtpmap_attr) {gb28181_agent_.respondPlayInvite(488, device_id_);Log.i(TAG, "ntsOnInvitePlay get ps rtp map attribute is null, response 488, device_id:" + device_id_);return;}Log.i(TAG,"ntsOnInvitePlay, device_id:" +device_id_+", is_tcp:" + video_des.isRTPOverTCP()+ " rtp_port:" + video_des.getPort() + " ssrc:" + video_des.getSSRC()+ " address_type:" + video_des.getAddressType() + " address:" + video_des.getAddress());long rtp_sender_handle = lib_publisher_.CreateRTPSender(0);if ( rtp_sender_handle == 0 ) {gb28181_agent_.respondPlayInvite(488, device_id_);Log.i(TAG, "ntsOnInvitePlay CreateRTPSender failed, response 488, device_id:" + device_id_);return;}gb28181_rtp_payload_type_  = ps_rtpmap_attr.getPayloadType();gb28181_rtp_encoding_name_ =  ps_rtpmap_attr.getEncodingName();lib_publisher_.SetRTPSenderTransportProtocol(rtp_sender_handle, video_des.isRTPOverUDP()?0:1);lib_publisher_.SetRTPSenderIPAddressType(rtp_sender_handle, video_des.isIPv4()?0:1);lib_publisher_.SetRTPSenderLocalPort(rtp_sender_handle, 0);lib_publisher_.SetRTPSenderSSRC(rtp_sender_handle, video_des.getSSRC());lib_publisher_.SetRTPSenderSocketSendBuffer(rtp_sender_handle, 2*1024*1024); // 设置到2Mlib_publisher_.SetRTPSenderClockRate(rtp_sender_handle, ps_rtpmap_attr.getClockRate());lib_publisher_.SetRTPSenderDestination(rtp_sender_handle, video_des.getAddress(), video_des.getPort());if ( lib_publisher_.InitRTPSender(rtp_sender_handle) != 0 ) {gb28181_agent_.respondPlayInvite(488, device_id_);lib_publisher_.DestoryRTPSender(rtp_sender_handle);return;}int local_port = lib_publisher_.GetRTPSenderLocalPort(rtp_sender_handle);if (local_port == 0) {gb28181_agent_.respondPlayInvite(488, device_id_);lib_publisher_.DestoryRTPSender(rtp_sender_handle);return;}Log.i(TAG,"get local_port:" + local_port);String local_ip_addr = IPAddrUtils.getIpAddress(context_);MediaSessionDescription local_video_des = new MediaSessionDescription(video_des.getType());local_video_des.addFormat(String.valueOf(ps_rtpmap_attr.getPayloadType()));local_video_des.addRtpMapAttribute(ps_rtpmap_attr);local_video_des.setAddressType(video_des.getAddressType());local_video_des.setAddress(local_ip_addr);local_video_des.setPort(local_port);local_video_des.setTransportProtocol(video_des.getTransportProtocol());local_video_des.setSSRC(video_des.getSSRC());if (!gb28181_agent_.respondPlayInviteOK(device_id_,local_video_des) ) {lib_publisher_.DestoryRTPSender(rtp_sender_handle);Log.e(TAG, "ntsOnInvitePlay call respondPlayInviteOK failed.");return;}gb28181_rtp_sender_handle_ = rtp_sender_handle;}private String device_id_;private SessionDescription session_des_;public Runnable set(String device_id, SessionDescription session_des) {this.device_id_ = device_id;this.session_des_ = session_des;return this;}}.set(deviceId, session_des),0);}@Overridepublic void ntsOnCancelPlay(String deviceId) {// 这里取消Play会话handler_.postDelayed(new Runnable() {@Overridepublic void run() {Log.i(TAG, "ntsOnCancelPlay, deviceId=" + device_id_);destoryRTPSender();}private String device_id_;public Runnable set(String device_id) {this.device_id_ = device_id;return this;}}.set(deviceId),0);}@Overridepublic void ntsOnAckPlay(String deviceId) {handler_.postDelayed(new Runnable() {@Overridepublic void run() {Log.i(TAG,"ntsOnACKPlay, device_id:" +device_id_);InitAndSetConfig();stream_publisher_.SetGB28181RTPSender(gb28181_rtp_sender_handle_, gb28181_rtp_payload_type_, gb28181_rtp_encoding_name_);//libPublisher.SetGBTCPConnectTimeout(publisherHandle, 10*60*1000);//libPublisher.SetGBInitialTCPReconnectInterval(publisherHandle, 1000);//libPublisher.SetGBInitialTCPMaxReconnectAttempts(publisherHandle, 3);boolean start_ret  = stream_publisher_.StartGB28181MediaStream();if (!start_ret) {stream_publisher_.try_release();destoryRTPSender();Log.e(TAG, "Failed to start GB28181 service..");return;}startAudioRecorder();startLayerPostThread();}private String device_id_;public Runnable set(String device_id) {this.device_id_ = device_id;return this;}}.set(deviceId),0);}@Overridepublic void ntsOnPlayInviteResponseException(String deviceId, int statusCode, String errorInfo) {// 这里要释放掉响应的资源Log.i(TAG, "ntsOnPlayInviteResponseException, deviceId=" + deviceId + " statusCode=" +statusCode+ " errorInfo:" + errorInfo);handler_.postDelayed(new Runnable() {@Overridepublic void run() {Log.i(TAG, "ntsOnPlayInviteResponseException, deviceId=" + device_id_);destoryRTPSender();}private String device_id_;public Runnable set(String device_id) {this.device_id_ = device_id;return this;}}.set(deviceId),0);}@Overridepublic void ntsOnByePlay(String deviceId) {handler_.postDelayed(new Runnable() {@Overridepublic void run() {Log.i(TAG, "ntsOnByePlay, stop GB28181 media stream, deviceId=" + device_id_);stopGB28181Stream();destoryRTPSender();}private String device_id_;public Runnable set(String device_id) {this.device_id_ = device_id;return this;}}.set(deviceId),0);}@Overridepublic void ntsOnTerminatePlay(String deviceId) {handler_.postDelayed(new Runnable() {@Overridepublic void run() {Log.i(TAG, "ntsOnTerminatePlay, stop GB28181 media stream, deviceId=" + device_id_);stopGB28181Stream();destoryRTPSender();}private String device_id_;public Runnable set(String device_id) {this.device_id_ = device_id;return this;}}.set(deviceId),0);}@Overridepublic void ntsOnPlayDialogTerminated(String deviceId) {/*Play会话对应的对话终止, 一般不会出发这个回调,目前只有在响应了200K, 但在64*T1时间后还没收到ACK,才可能会出发收到这个请做相关清理处理*/handler_.postDelayed(new Runnable() {@Overridepublic void run() {Log.i(TAG, "ntsOnPlayDialogTerminated, deviceId=" + device_id_);stopGB28181Stream();destoryRTPSender();}private String device_id_;public Runnable set(String device_id) {this.device_id_ = device_id;return this;}}.set(deviceId),0);}@Overridepublic void ntsOnDevicePositionRequest(String deviceId, int interval) {}

投递数据的代码如下:

    @Overridepublic void onPreviewFrame(byte[] data, Camera camera) {frameCount++;if (data == null) {Parameters params = camera.getParameters();Size size = params.getPreviewSize();int bufferSize = (((size.width | 0x1f) + 1) * size.height * ImageFormat.getBitsPerPixel(params.getPreviewFormat())) / 8;camera.addCallbackBuffer(new byte[bufferSize]);} else {if (stream_publisher_.is_gb_stream_publishing()) {if (3 == video_opt_) {int w = video_width_, h = video_height_;int y_stride = video_width_, uv_stride = video_width_;int y_offset = 0, uv_offset = video_width_ * video_height_;int is_vertical_flip = 0, is_horizontal_flip = 0;int rotation_degree = 0;// 镜像只用在前置摄像头场景下if (CAMERA_ID_FRONT.equals(mCameraId)) {// 竖屏, (垂直翻转->顺时旋转270度)等价于(顺时旋转旋转270度->水平翻转)if (PORTRAIT == currentOrigentation)is_vertical_flip = 1;elseis_horizontal_flip = 1;}if (PORTRAIT == currentOrigentation) {if (CAMERA_ID_BACK.equals(mCameraId))rotation_degree = 90;elserotation_degree = 270;} else if (LANDSCAPE_LEFT_HOME_KEY == currentOrigentation) {rotation_degree = 180;}int scale_w = 0, scale_h = 0, scale_filter_mode = 0;stream_publisher_.PostLayerImageNV21ByteArray(0, 0, 0,data, y_offset, y_stride, data, uv_offset, uv_stride, w, h,is_vertical_flip, is_horizontal_flip, scale_w, scale_h, scale_filter_mode, rotation_degree);}}camera.addCallbackBuffer(data);}}

onDestroy()处理如下:

    @Overridepublic void onDestroy() {// TODO Auto-generated method stubLog.i(TAG, "activity destory!");record_executor_.cancel_tasks();if (gb28181_agent_ != null ) {gb28181_agent_.terminateAllPlays(true);gb28181_agent_.stop();}stopAudioRecorder();stopGB28181Stream();destoryRTPSender();stream_publisher_.release();stopLayerPostThread();if (gb28181_agent_ != null ) {Log.i(TAG, " gb28181_agent_.unInitialize++");gb28181_agent_.unInitialize();gb28181_agent_.unBindLocalPort();gb28181_agent_.releaseSipStack();Log.i(TAG, " gb28181_agent_.unInitialize--");gb28181_agent_ = null;}if (!record_executor_.shutdown(60, TimeUnit.SECONDS))Log.w(TAG, "call record_executor_.shutdown failed");super.onDestroy();}

总结

以上是Android平台GB28181设备接入侧后台摄像头采集并按需回传到GB28181平台大概流程,目前,Android平台GB28181设备接入侧模块,覆盖以下功能:

  •  [视频格式]H.264/H.265(Android H.265硬编码);
  •  [音频格式]G.711 A律、AAC;
  •  [音量调节]Android平台采集端支持实时音量调节;
  •  [H.264硬编码]支持H.264特定机型硬编码;
  •  [H.265硬编码]支持H.265特定机型硬编码;
  •  [软硬编码参数配置]支持gop间隔、帧率、bit-rate设置;
  •  [软编码参数配置]支持软编码profile、软编码速度、可变码率设置;
  •  支持横屏、竖屏推流;
  •  Android平台支持后台service推送屏幕(推送屏幕需要5.0+版本);
  • 支持纯视频、音视频PS打包传输;
  • 支持RTP OVER UDP和RTP OVER TCP被动模式(TCP媒体流传输客户端);
  • 支持信令通道网络传输协议TCP/UDP设置;
  • 支持注册、注销,支持注册刷新及注册有效期设置;
  • 支持设备目录查询应答;
  • 支持心跳机制,支持心跳间隔、心跳检测次数设置;
  • 支持移动设备位置(MobilePosition)订阅和通知;
  •  适用国家标准:GB/T 28181—2016;
  • 支持语音广播;
  • 支持语音对讲;
  • 支持图像抓拍;
  • 支持历史视音频文件检索;
  • 支持历史视音频文件下载;
  • 支持历史视音频文件回放;
  • 支持云台控制和预置位查询;
  •  [实时水印]支持动态文字水印、png水印;
  •  [镜像]Android平台支持前置摄像头实时镜像功能;
  •  [实时静音]支持实时静音/取消静音;
  •  [实时快照]支持实时快照;
  •  [降噪]支持环境音、手机干扰等引起的噪音降噪处理、自动增益、VAD检测;
  •  [外部编码前视频数据对接]支持YUV数据对接;
  •  [外部编码前音频数据对接]支持PCM对接;
  •  [外部编码后视频数据对接]支持外部H.264数据对接;
  •  [外部编码后音频数据对接]外部AAC数据对接;
  •  [扩展录像功能]支持和录像SDK组合使用,录像相关功能。

后台采集摄像头回传到GB28181平台侧,主要还是启动个service,其他和前台采集流程类似,感兴趣的开发者,也可跟我单独沟通探讨。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/670265.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数字孪生网络攻防模拟与城市安全演练

在数字化浪潮的推动下&#xff0c;网络攻防模拟和城市安全演练成为维护社会稳定的不可或缺的环节。基于数字孪生技术我们能够在虚拟环境中进行高度真实的网络攻防模拟&#xff0c;为安全专业人员提供实战经验&#xff0c;从而提升应对网络威胁的能力。同时&#xff0c;在城市安…

GEE数据集——全球健康地图项目Global Healthsites Mapping Project

Global Healthsites Mapping Project Healthsites.io和全球健康网站绘图项目的使命是帮助向政府、非政府组织和私营部门提供准确的最新健康设施信息。医疗机构登记簿是一个国家内运作良好的医疗信息系统的基石。准确和最新的数据提供了基础数据&#xff0c;有助于推动服务可用…

5分钟掌握接口自动化测试,4个知识点简单易学!

一. 什么是接口测试 接口测试是一种软件测试方法&#xff0c;用于验证不同软件组件之间的通信接口是否按预期工作。在接口测试中&#xff0c;测试人员会发送请求并检查接收到的响应&#xff0c;以确保接口在不同场景下都能正常工作。 就工具而言&#xff0c;常见的测试工具有…

16-Verilog实现二线制I2C CMOS串行EEPROM的读写操作

Verilog实现二线制I2C CMOS串行EEPROM的读写操作 1&#xff0c;二线制I2C CMOS串行EEPROM的简单介绍2&#xff0c;I2C总线特征介绍3&#xff0c;二线制I2C、CMOS串行EEPROM的读写操作4&#xff0c;EEPROM的Verilog HDL程序4.1&#xff0c;EEPROM的行为模型思路如下&#xff1a;…

【Kotlin】Kotlin环境搭建

1 前言 Kotlin 是一种现代但已经成熟的编程语言&#xff0c;由 JetBrains 公司于 2011 年设计和开发&#xff0c;并在 2012 年开源&#xff0c;在 2016 年发布 v1.0 版本。在 2017 年&#xff0c;Google 宣布 Kotlin 正式成为 Android 开发语言&#xff0c;这进一步推动了 Kotl…

【Go】一、Go语言基本语法与常用方法容器

GO基础 Go语言是由Google于2006年开源的静态语言 1972&#xff1a;&#xff08;C语言&#xff09; — 1983&#xff08;C&#xff09;—1991&#xff08;python&#xff09;—1995&#xff08;java、PHP、js&#xff09;—2005&#xff08;amd双核技术 web端新技术飞速发展&…

【Python程序开发系列】聊一聊github的pull request几种合并方式

一、什么是PR 在正常的工作流程中&#xff0c;PR 用于将一个分支的更改合并到另一个分支&#xff0c;而这些更改通常以提交的形式存在。每个提交都有一个唯一的提交 ID&#xff0c;用于标识和跟踪更改的历史。因此一般情况下PR包含源分支的多个commit提交记录&#xff08;pr_co…

数据结构_找环,破环题-2.5

一. 判断单链表有无环 a. 错误的思路&#xff1a;遍历陷入死循环 1&#xff09;和相交的遍历思路一样&#xff0c;找指向相同。 错误点 一直在死循环。 思考点&#xff1a;如何破环 b. 个人思路&#xff1a;反转链表回首结点 1&#xff09;目前的经验&#xff0c;无非就…

无人机集群协同导航构型自适应选择算法

无人机集群协同导航构型自适应选择算法 Evandworld E-mail&#xff1a;evandworldfoxmail.com 摘要 针对卫星定位系统用于无人机集群时成本高、精度低等问题&#xff0c;本文提出一种基于卡尔曼滤波和概率的无人机集群构型自适应选择算法。在自适应扩展卡尔曼滤波的基础上&a…

kubernetes部署nacos2.3.0

一、nacos简介 nacos官网地址 简单易用 动态配置管理、服务发现和动态的一站式解决方案&#xff0c;20多种开箱即用的以服务为中心的架构特性&#xff0c;基本符合生产要求的轻量级易用控制台。 更适应云架构 无缝支持 Kubernetes 和 Spring Cloud&#xff0c;在主流公共云上…

Qt:QFileDialog

目录 一、介绍 二、功能 三、具体事例 1、将某个界面保存为图片&#xff0c;后缀名可选PNG、JPEG、SVG等 一、介绍 QFileDialog提供了一个对话框&#xff0c;允许用户选择文件或者目录&#xff0c;也允许用户遍历文件系统&#xff0c;用以选择一个或多个文件或者目录。 QF…

Debezium发布历史111

原文地址&#xff1a; https://debezium.io/blog/2021/10/07/incremental-snapshots/ 欢迎关注留言&#xff0c;我是收集整理小能手&#xff0c;工具翻译&#xff0c;仅供参考&#xff0c;笔芯笔芯. Incremental Snapshots in Debezium October 7, 2021 by Jiri Pechanec mys…

linux虚拟机升级g++编译器版本

原先的 更新你的软件包列表&#xff1a; sudo apt update 添加Ubuntu Toolchain PPA&#xff08;Personal Package Archive&#xff09;&#xff0c;这是一个提供较新编译器版本的第三方软件源&#xff1a; sudo add-apt-repository ppa:ubuntu-toolchain-r/test 再次更新软件包…

Tokitsukaze and Short Path (plus minus)

一、Tokitsukaze and Short Path (plus) 解析&#xff1a; 容易知道 对于 u 和 v 两点之间的距离是 2*max(a[u],a[v]),同时这也是这两个点的最短距离&#xff0c;因为如果想要绕路的话&#xff0c;就必须再至少经过一个点&#xff0c;这样的话&#xff0c;就会使得两者的距离变…

RTthread线程间通信(邮箱,消息队列,信号/软件中断)---02代码分析邮箱和消息队列

RT-Thread代码分析 这是源码分析, 实际使用看这个 信号看这个 看这一篇之前最好看一下我的RT-Thread对象管理以及线程管理, 时钟管理 邮箱 实际是实现是一个对环形缓存区的使用 struct rt_mailbox {struct rt_ipc_object parent; /**< inherit from…

python进行批量搜索匹配替换文本文字的matlab操作实例

在进行一些数据处理时&#xff0c;可能需要抓取原文中的一些内容&#xff0c;批量替换原文另外的一些内容&#xff0c;而且事先还需要一步搜索匹配的步骤。 举个例子&#xff0c;如下matlab输出的txt文件&#xff0c;原文件有几万行数据&#xff0c;这里只摘取3行对应的 文件文…

R语言:箱线图绘制(添加平均值趋势线)

箱线图绘制 1. 写在前面2.箱线图绘制2.1 相关R包导入2.2 数据导入及格式转换2.3 ggplot绘图 1. 写在前面 今天有时间把之前使用过的一些代码和大家分享&#xff0c;其中箱线图绘制我认为是非常有用的一个部分。之前我是比较喜欢使用origin进行绘图&#xff0c;但是绘制的图不太…

vite+vue3发布自己的npm组件+工具函数

记录一下个人最近一次发布npm组件的过程&#xff1a; 一、创建组件和工具函数 执行命令创建一个空项目&#xff1a; npm create vite 创建过程稍微有些慢&#xff0c;不知何故&#xff1f;其中选择vue , 个人暂时使用的JS 。在 src 目录下面创建一个文件 package 存放组件和公…

【Java八股面试系列】JVM-垃圾回收

目录 垃圾回收 堆空间的基本结构 内存分配和回收原则 分代收集机制 Minor GC 流程 空间分配担保 老年代 大对象直接进入老年代 长期存活的对象将进入老年代 GC的区域 对象存活判定算法 引用计数法 可达性分析算法 finalize() 字符串常量判活 类判活 垃圾回收算…

1、将 ChatGPT 集成到数据科学工作流程中:提示和最佳实践

将 ChatGPT 集成到数据科学工作流程中:提示和最佳实践 希望将 ChatGPT 集成到您的数据科学工作流程中吗?这是一个利用 ChatGPT 进行数据科学的提示的实践。 ChatGPT、其继任者 GPT-4 及其开源替代品非常成功。开发人员和数据科学家都希望提高工作效率,并使用 ChatGPT 来简…