精华内容
下载资源
问答
  • 之前讲了那么多关于netty的文章,都是讲netty的底层原理和实现,各位小伙伴一定都在想了,看了这么多篇文章,netty到底能干啥呢?今天让我们来使用netty简简单单搭一个支持中文的服务器,展示一下netty的威力。

    简介

    之前讲了那么多关于netty的文章,都是讲netty的底层原理和实现,各位小伙伴一定都在想了,看了这么多篇文章,netty到底能干啥呢?今天让我们来使用netty简简单单搭一个支持中文的服务器,展示一下netty的威力。

    netty的HTTP支持

    今天我们搭的服务器是支持HTTP1.1的服务器。在netty中搭建服务器就像是拼房子,找到合适的工具就可以事半功倍。那么要搭建HTTP的房子,netty提供了什么样的工具呢?

    在讲解netty对HTTP的支持之前,我们先看一下HTTP的版本发展情况。

    HTTP的全称是Hypertext Transfer Protocol,是在1989年World Wide Web发展起来之后出现的标准协议,用来在WWW上传输数据。HTTP/1.1是1997年在原始的HTTP协议基础上进行的补充和优化。

    到了2015年,为了适应快速发送的web应用和现代浏览器的需求,发展出了新的HTTP/2协议,主要在手机浏览器、延时处理、图像处理和视频处理方面进行了优化。

    基本上所有的现代浏览器都支持HTTP/2协议了,但是还有很多应用程序使用的是老的HTTP/1.1协议。netty为HTTP2和HTTP1提供了不同的支持包,对于HTTP1的支持包叫做netty-codec-http,对HTTP2支持的包叫做netty-codec-http2。

    本文会讲解netty对HTTP1的支持,将会在后续的文章中继续HTTP2的介绍。

    netty-codec-http提供了对HTTP的非常有用的一些封装。

    首先是代表HTTP中传输对象的类HttpObject,这个类代表着传输中的所有对象。继承这个类的对象有两个非常重要的对象,分别是HttpMessage和HttpContent。

    HttpMessage可能跟我想象的不太一样,它实际上只包含了两部分内容,分别是HttpVersion和HttpHeaders,但是并不包含任何内容。

    public interface HttpMessage extends HttpObject {
    
        HttpVersion protocolVersion();
    
        HttpMessage setProtocolVersion(HttpVersion version);
    
        HttpHeaders headers();
    }
    
    

    这里HttpVersion只支持HTTP/1.0和HTTP/1.1协议。而HttpHeaders就是对HTTP请求中头对象的封装。

    HttpMessage的子类是HttpRequest和HttpResponse,所以这两个类本身是不带请求内容的。

    而具体请求的内容是在HttpContent中,HttpContent继承自ByteBufHolder,表示它中间可以带有ByteBuf的内容信息。

    而HttpContent真正的实现类就是DefaultFullHttpRequest和DefaultFullHttpResponse,这两个内包含了HTTP头和HTTP请求响应内容信息。

    那么问题来了,为什么要把HTTP头和HTTP内容分开呢?

    这就涉及到HTTP1.1中消息传输中的压缩机制了。为了提升传输的效率,一般来说在传输的的过程中都会对象消息进行压缩,但是对于HTTP1.1来说,头部的内容是没办法压缩的,只能压缩content部分,所以需要区别对待。

    netty中使用HTTP的原理

    我们知道netty底层是客户端和服务器端构建通道,通过通道来传输ByteBuf消息。那么netty是怎么支持HTTP请求呢?

    当客户端向服务器端发送HTTP请求之后,服务器端需要把接收到的数据使用解码器解码成为可以被应用程序使用的各种HttpObject对象,从而能够在应用程序中对其解析。

    netty提供了HttpResponseEncoder和HttpRequestDecoder类,来对HTTP的消息进行编码和解码。

    如果不想分别使用两个类来进行编码和解码,netty还提供了HttpServerCodec类来进行编码和解码工作。

    这个类包含了HttpRequestDecoder和HttpResponseEncoder两部分的工作,可以同时用来进行编码和解码。

    100 (Continue) Status

    在HTTP中有一个独特的功能叫做,100 (Continue) Status,就是说client在不确定server端是否会接收请求的时候,可以先发送一个请求头,并在这个头上加一个"100-continue"字段,但是暂时还不发送请求body。直到接收到服务器端的响应之后再发送请求body。

    为了处理这种请求,netty提供了一个HttpServerExpectContinueHandler对象,用来处理100 Status的情况。

    当然,如果你的客户端没有这种请求,那么可以直接使用HttpObjectAggregator来将HttpMessage和HttpContent和合并成为FullHttpRequest或者FullHttpResponse。

    为netty搭建HTTP服务器

    有了上面的工作,我们就可以使用netty搭建http服务器了。最关键的一点就是在HttpRequestServerInitializer添加对应的codec和自定义handler。

        public void initChannel(SocketChannel ch) {
            ChannelPipeline p = ch.pipeline();
            p.addLast(new HttpServerCodec());
            p.addLast(new HttpServerExpectContinueHandler());
            p.addLast(new HttpRequestServerHandler());
        }
    

    在自定义的handler中,我们需要实现一个功能,就是当收到客户端的请求时候,需要返回给客户端一段欢迎语。

    首先将获得的HttpObject转换成为HttpRequest对象,然后根据请求对象构建一个DefaultFullHttpResponse对象,然后设置该response对象的头,最后将该对象写到channel中。

    对应的关键代码如下:

     private static final byte[] CONTENT = "欢迎来到www.flydean.com!".getBytes(StandardCharsets.UTF_8);
    
        public void channelRead0(ChannelHandlerContext ctx, HttpObject msg) {
            if (msg instanceof HttpRequest) {
                HttpRequest req = (HttpRequest) msg;
    
                boolean keepAlive = HttpUtil.isKeepAlive(req);
                FullHttpResponse response = new DefaultFullHttpResponse(req.protocolVersion(), OK,
                                                                        Unpooled.wrappedBuffer(CONTENT));
                response.headers()
    //                    .set(CONTENT_TYPE, TEXT_PLAIN)
                        .set(CONTENT_TYPE, "text/plain;charset=utf-8")
                        .setInt(CONTENT_LENGTH, response.content().readableBytes());
    
                if (keepAlive) {
                    if (!req.protocolVersion().isKeepAliveDefault()) {
                        //设置header connection=keep-alive
                        response.headers().set(CONNECTION, KEEP_ALIVE);
                    }
                } else {
                    // 如果keepAlive是false,则设置header connection=close
                    response.headers().set(CONNECTION, CLOSE);
                }
                ChannelFuture f = ctx.write(response);
                if (!keepAlive) {
                    f.addListener(ChannelFutureListener.CLOSE);
                }
            }
        }
    

    上面的关键代码中CONTENT包含了中文字符串,我们使用getBytes将其转换成了UTF-8编码的byte数组。那么如果要想客户端能够正确识别UTF-8编码,需要在response的header中设置内容类型文件为:“text/plain;charset=utf-8”。

    最后,使用下面的代码启动server:

     // server配置
            EventLoopGroup bossGroup = new NioEventLoopGroup(1);
            EventLoopGroup workerGroup = new NioEventLoopGroup();
            try {
                ServerBootstrap b = new ServerBootstrap();
                b.option(ChannelOption.SO_BACKLOG, 1024);
                b.group(bossGroup, workerGroup)
                 .channel(NioServerSocketChannel.class)
                 .handler(new LoggingHandler(LogLevel.INFO))
                 .childHandler(new HttpRequestServerInitializer());
    
                Channel ch = b.bind(PORT).sync().channel();
                log.info("请打开你的浏览器,访问 http://127.0.0.1:8000/");
                ch.closeFuture().sync();
            } finally {
                bossGroup.shutdownGracefully();
                workerGroup.shutdownGracefully();
            }
    

    总结

    现在,使用你的浏览器访问你搭建的服务器地址,你就可以得到"欢迎来到www.flydean.com!"。 到此一个简单的netty服务器就完成了。

    本文的例子可以参考:learn-netty4

    本文已收录于 http://www.flydean.com/19-netty-http-client-request/

    最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

    欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

    展开全文
  • 通过此书,你将学习: 希望你的网络应用超越平庸进入Web 2.0时代...《深入浅出Rails》用最新的认知科学和学习理论打造多感官的学习体验,运用适合大脑工作方式的直观的格式编排,而不是令人昏昏欲睡的密密麻麻的文字。
  • 计算机科学与技术专业:主要学什么? 本文主要包括如下内容: 程序员职位要求 CS 专业课程列表 怎样寻找资源学习? 程序员高薪排行榜 程序员职位要求 看课程之前,我们先来看看 BAT 的招聘岗位 JD: 新...

    计算机科学与技术专业:主要学什么?

    本文主要包括如下内容:

    • 程序员职位要求
    • CS 专业课程列表
    • 怎样寻找资源学习?
    • 程序员高薪排行榜

    程序员职位要求

    看课程之前,我们先来看看 BAT 的招聘岗位 JD:

    新零售技术事业群-java开发-淘系技术部 

    https://job.alibaba.com/zhaopin/position_detail.htm?positionId=71138

    岗位要求:

    1. JAVA基础扎实,理解IO、多线程、集合等基础框架,对JVM原理有充分的理解,有大型应用JVM参数调优经验优先。
    2. 5年以上使用JAVA开发的经验,对于用过的开源框架,能了解到它的原理和机制, 有开源作品且或参与开源社区贡献者优先;具备三年以上大型分布式系统开发和架构经验; 在后台技术上有长期积累和专长, 熟悉分布式系统的设计和应用,熟悉分布式、缓存、消息和存储等机制;能对分布式常用技术进行合理应用和技术方案落地。
    3. 有2B产品架构的经验,制造业IT架构经验, 熟悉微服务架构,Serverless等方面者优先。
    4. 热爱技术研发,具有快速学习能力;注重代码质量,有良好的软件工程知识和编码规范意识。
    5. 具有高度的抽象设计能力, 思路清晰, 善于思考, 能够独立分析和解决问题, 责任心强; 具备良好的团队合作精神和风险预判能力, 对系统的压力和瓶颈针对性的优化和解决方案落地。

     

    高级Java开发工程师/技术专家-研发中台

    https://job.alibaba.com/zhaopin/PositionDetail.htm?positionId=69877

    岗位要求:

    1、具有三年以上互联网/软件行业工作经验;
    2、对各种开源的框架如 Spring、Mybatis、tomcat、netty、dubbo 等有深入的了解,对框架本身有过开发或重构者可优先考虑;
    3、具备系统调试、性能调优等技能,对疑难技术问题具备较强的排查能力。有强烈的责任心和使命感;
    4、有大规模、高吞吐量的系统开发实践经验优先;有流程引擎开发经验或serverless化平台开发经验或业务平台建设经验的优先;
    5、对技术富有热情,能关注Java或互联网行业技术发展趋势,勇于创新开拓;

     

    Java开发技术专家

    https://job.alibaba.com/zhaopin/PositionDetail.htm?positionId=66575

    岗位要求:

    1. Java基础扎实,对集合、IO、反射、多线程、NIO等高级特性有深入的掌握,对JVM原理、GC机制有较好的理解。
    2. 5年以上的JAVA系统开发经验,精通面向对象设计,对项目中接触过的开源框架、技术产品、算法等有针对性的进行过深入学习,了解其底层机制和原理。
    3. 有实际中大型系统设计经验,能有效利用技术手段解决实际业务需求。
    4. 对技术富有热情,能关注JAVA或互联网行业技术发展趋势,勇于尝试、敢于推动。
    5. 良好的沟通能力,勇于担当,能和团队形成合力。
    具备以下能力或经验者优先:
      分布式环境下高可用程序设计和实现(如银行、证券等高可用系统)。
      信息距离理论基础,智能问答系统、爬虫系统设计和实现。
      统一数据接口层或类似平台的架构经验(如开放接口平台、GraphQL等)。

    25928-后台开发高级工程师(深圳)

    IEG | 深圳 | 技术 | 2019年09月09日

    工作职责

    • 负责游戏AI在线服务,包括但不限于在线预测模块,任务调度模块以及运营监控模块;
      负责相关系统模块的设计、开发与维护,确保相关系统稳定运行。

    工作要求

    • 本科或以上学历,2年以上相关开发经验;
      精通至少一门服务器端编程语言(PHP/Python/NodeJS/C++)
      责任感强、有较强的逻辑思维能力、沟通能力和抗压能力;
      具备后台开发的能力及系统运维的能力者优先。

    https://careers.tencent.com/jobdesc.html?postId=1123176064093261824

     

    30360-用户增长大数据后台高级工程师

    PCG | 深圳 | 技术 | 2019年09月09日

    工作职责

    • 负责推荐平台架构,AI平台,增长/数据画像DMP后台建设,并优化实时/离线大数据处理流程;
      负责QQ海量用户数据模型开发管理,etl处理,画像建设;
      结合QQ平台业务,优化大数据融合流程架构,提升画像挖掘算法性能。

    工作要求

    • 精通spark/flink/hadoop/hbase等分布式计算技术,熟悉其运行机制和体系结构
      精通python/scala/java任意一门编程语言,熟悉c++/golang;
      熟悉业界主流大数据解决方案整体架构,两年以上数据仓库架构/应用经验;
      具备一定的机器学习背景,有算法相关项目开发经验;
      善于发现问题解决问题,良好的编程习惯,优化意识;
      优秀的团队合作沟通能力,较强的学习能力和进取心;

      计算机相关专业,2年以上工作经验;
      熟悉网络编程.数据库等后台开发知识尤佳。

    https://careers.tencent.com/jobdesc.html?postId=1125300900185772032

     

    CS 专业课程列表

    Computer Science is the study of computers and computational systems. Unlike electrical and computer engineers, computer scientists deal mostly with software and software systems; this includes their theory, design, development, and application.

    Principal areas of study within Computer Science include :

    artificial intelligence, computer systems and networks, security, database systems, human computer interaction, vision and graphics, numerical analysis, programming languages, software engineering, bioinformatics and theory of computing.

    Although knowing how to program is essential to the study of computer science, it is only one element of the field. Computer scientists design and analyze algorithms to solve programs and study the performance of computer hardware and software. The problems that computer scientists encounter range from the abstract-- determining what problems can be solved with computers and the complexity of the algorithms that solve them – to the tangible – designing applications that perform well on handheld devices, that are easy to use, and that uphold security measures.


    1.计算机导论:


    计算机科学的基础课程之一,其教学目的是概要性地对专业课程作介绍,是典型的面向专业新生的课程(即CS0型课程)。认真学习该课程有助于今后的学习,然而这门课程往往容易被新生们忽略……

    涵盖了计算机专业的主要内容:计算机硬件和软件的基本概念,包括数据存储、数据处理、数据输入和输出、操作系统、算法、高级程序设计语言、数据结构。计算机网络和Intemet。微机组成。
    (推荐教材:可使用学校配发的教材,但建议使用外版翻译教材。)


    2.高级语言程序设计:
    计算机科学的基础课程之一,教学目的是让本专业同学实际掌握一门程序设计语言并且习得一些程序设计的基本技能,目前的教学语言是C语言。个人认为课程名称可改为“高级程序设计语言”,因为课程对语言的强调远胜于对程序设计本质的讲解。建议在学习这门课程时配以《程序设计实践》一书,效果甚佳。
    (推荐教材:
    ①《从问题到程序——程序设计与C语言引论》 机械工业出版社
    ②《程序设计实践》 机械工业出版社
    ③《程序设计语言——实践之路》 电子工业出版社 )


    3.离散数学:
    计算机科学基础课程之一,被誉为计算机科学的数学基础。其内容博大精深,从中派生出的图论(图算法)、数理逻辑、组合数学以及泛代数等多门专业课程是现代计算机科学和应用数学的主要研究领域。能否学好离散数学对进一步学习以后的专业课程有着非同一般的影响。
    (推荐教材及参考书:
    ①《离散数学》(第四版) 清华大学出版社
    ②《离散数学导学》机械工业出版社
    ③《现代应用数学手册:离散数学卷》清华大学出版社 )


    4.电路与电子技术:
    电子产业有“朝阳产业”的美誉,被认为是信息时代的工业。这门电子与电路技术可谓是对电子学领域学习的敲门砖。虽然课程本身对计算机科学专业今后的学习影响不大,但掌握这项技能对于学生本身专业素养地提高是大有裨益的。同时,学习这门课程也能为今后学习数字逻辑和微机原理等系统底层方面的课程打好基础。
    (推荐教材:《电子学基础:电路和元器件》(第四版)清华大学出版社)


    5.面向对象程序设计:
    如果说上世纪软件开发领域最伟大的突破是什么,面向对象程序设计(OOP)必为其中之一。目前主流的程序设计语言,如C++、Java、Python和Delphi等,几乎清一色支持面向对象。可以说,掌握的面向对象的精髓,便是掌握了我们这个行业的入门钥匙。我校此课程的教学语言采用的是C++,而就国内C++教学的糟糕现状来看,若想完整掌握面向对象思想,学生自己不努力是不行的。
    (推荐教材及参考书:
    ①《C++ Primer中文版》(第四版) 人民邮电出版社
    ②《Essential C++ 中文版》华中科技大学出版社
    ③《Effective C++ 中文版》(第三版)电子工业出版社
    ④《Accelerated C++(影印版)》机械工业出版社
    ⑤《C++语言的设计与演化》机械工业出版社 )


    6.数字逻辑:
    计算机科学核心课程之一。计算机科学中有一个研究领域即系统设计领域,而本门课程即为这一领域研究的基础。正确认识与掌握数字逻辑及其设计,可以使那些有志于系统底层开发的学生获益匪浅。
    (推荐教材:
    ①《数字基础(第八版)》清华大学出版社
    ②《逻辑与计算机设计基础》 中国电力出版社 )


    7.数据结构与算法:
    计算机科学核心课程之一。对数据地有效组织是程序的主要任务之一,算法的主要操作对象亦为数据结构。从简单的数组和链表,到各色高级的抽象数据类型(ADT),数据结构在程序设计中的地位不言而喻。学好数据结构,是进一步学习专业课的基本前提。可以这么说,一个不懂得如何组织和操控数据的学生,根本就不配当我们计算机科学专业的学生,更不配当一名程序员!!!
    (推荐教材:
    ①《C算法 第一卷(第三版)》人民邮电出版社
    ②《程序设计抽象思想——C语言描述》清华大学出版社
    ③《数据抽象与问题求解——C++语言描述(第四版)》清华大学出版社
    ④《数据结构与算法——Java语言描述》机械工业出版社 )


    8.计算方法:线性代数、微积分、微分方程等的计算机算法


    9.计算机原理与汇编:
    系统底层课程之一,亦为计算机科学核心课程。重点讲述计算机(微机)构造以及低级语言——汇编语言的基础知识。学习这门课程,对进一步学习编译原理等专业高级课程有很大帮助。
    (推荐教材:
    ①《深入理解计算机系统》中国电力出版社
    ②《Intel汇编语言程序设计(影印版)》清华大学出版社
    ③《Windows环境下32位汇编语言程序设计(第二版)》电子工业出版社
    ④《汇编语言编程艺术》清华大学出版社 )


    10.操作系统:
    计算机科学的核心课程之一。课程全面讲述了操作系统的原理与构造,各类上机实验更能让学生对操作系统有深刻地理解。
    (推荐教材:
    ①《操作系统(第三版)》机械工业出版社
    ②《现代操作系统(第二版)》机械工业出版社
    ③《Linux内核设计与实现(影印版)》机械工业出版社
    ④《UNIX系统编程》机械工业出版社
    ⑤《UNIX环境高级编程(第二版)》人民邮电出版社 )


    11.软件工程:
    计算机科学的核心课程之一。近年来,随着软件开发革命地进一步深化,批判软件工程及过程方法改进的著作日益丰富,我们也得以从不良的软件开放中解放。建议在学习本课程时,联系自己的实战,并阅读批判软件工程和改良软件工程的著作。
    (推荐教材及参考书:
    ①《软件工程:实践者的研究方法(第五版)》机械工业出版社
    ②《程序设计心理学(银年纪念版)》清华大学出版社
    ③《人月神话(银年纪念版)》清华大学出版社
    ④《人件》清华大学出版社 )


    12.数据库原理及应用:
    计算机科学与信息学科的好像课程之一。课程讲述了数据库原理以及设计等方面的内容。对于那些注重实效的学生而言,学好这门课程,可以使今后的工作更为轻松。
    (推荐教材:《数据库系统概念(第四版)》机械工业出版社)


    13.运筹学及其算法:线性规划、动态规划、排队论、决策分析等
    此课程课作为计算机科学的辅助课程,向学生介绍了运筹学方面的算法,此类算法属于现代算法范畴,本人暂时还未涉猎,故恕难对此课程解析之…… (推荐教材:待定)

    14.计算机网络:
    计算机科学的核心课程之一。课程详细地介绍了计算机网络的发展、组成和协议方面的内容。对于自我要求较高的同学而言,学好这门课程义不容辞!
    (推荐教材:
    ①《计算机网络(第四版)》清华大学出版社
    ②《TCP/IP协议族》清华大学出版社 )
    15.软件开发管理:
    应该是软件工程课的附属课程吧,不详。 (推荐教材:待定)
    对于工程,管理重于技术

    16.数学建模:
     

    17.J2EE体系结构:
    J2EE是目前我们产业的两大工业平台之一,学习这门课程,可以为今后涉足企业级开发领域打下基础。但请注意,J2EE和Java语言本身都是在不断演进的,因而如果不能在课程结束后持续学习相关技术,恐怕还不等你出大学校门,这门课的内容就已经过时了…… (推荐教材:最新的国外相关教材。)


    18.计算机图形学:
    计算机科学的核心课程之一。有关计算机图形学在各个领域的应用不必在下一一说明了吧。无论是游戏开发,还是航空航天等前沿领域,到处都有计算机图形学的技术被应用。目前该课程主要用C语言和OpenGL图形库进行教学,效果应该还算不错。
    (推荐教材及参考书:
    ①《计算机图形学原理与实践-C语言描述(第二版)》机械工业出版社
    ②《交互式计算机图形学——基于OpenGL的自顶向下的方法(第四版)》清华大学出版社
    ③《OpenGL超级宝典(第三版)》 人民邮电出版社 )


    19.微型计算机技术:
    计算机专业的核心课程之一。课程详细地分析了微型计算机(主要是单片机)技术,由于这方面资料奇缺,这门课程可不太受在下欢迎…… (推荐教材:待定)

    20.编译原理:
    计算机科学核心课程之一。如果想要写出好的程序,编译原理的相关知识必不可少,因而这门课程是十分重点的一门课程。课程教材“龙书”、“虎书”和“鲸书”更是我们专业的经典著作。
    (推荐教材:
    ①《编译原理》机械工业出版社
    ②《现代编译原理——C语言描述》人民邮电出版社
    ③《高级编译器设计与实现》机械工业出版社 )


    21.Web系统开发:
    目前主流的web开发主要集中在ASP.NET和JSP开发领域 ,当然,还有近来火爆异常的Ajax,以前的CGI和ASP已经不那么流行了。与J2EE一样,这是一门必须持续学习的课程,否则,你必将被其所抛弃! (推荐教材:最新国外相关书籍。)


    22.嵌入式软件开发:
    这个领域可谓是软件开发的前沿领域,也是未来软件业霸主的孕育地之一(另两个领域为Web开发和企业级开发)。目前的软件开发领域正蕴含着“泛嵌入式”的潜规则(《程序员》2006年7月刊)。认真并持续学习这门课程,对将来的工作会有莫大的帮助。 (推荐教材:《嵌入式系统开放大全》人民邮电出版社)


    23.算法设计与分析:
    计算机科学的核心课程之一。“程序是衣,算法为魂”(《程序员》2006年3月刊),这门课程是本专业学生所亟需掌握的,如果学不好这门课,那么,你就不是一名优秀的程序员!
    (推荐教材:
    ①《数据结构与算法分析-C语言描述》机械工业出版社
    ②《C算法 第一卷 (第三版)》人民邮电出版社 )


    24.情报检索与利用

     

    怎样去寻找资源学习?

     

    我搜集了一些资源,放到这个组下面了:

    https://github.com/ComputerSchool2019

     

    全球最大的程序员社区:Github

    https://github.com/search?q=%E8%AE%A1%E7%AE%97%E6%9C%BA

     

     

    Stack Overflow:2019全球编程语言高薪排行榜

     

    近日,Stack Overflow 发布了 2019 年的最新调查结果,总结了不同编程语言在行业中可能获得的薪水。当然,在这个过程中也需要关注一些其他因素,比如:语言对使用者是否友好,这有助于更快地学习语言;是否与现在的科技趋势相关。(注:该数据根据 Stack Oveflow2019 年关于编程语言薪酬排行开发者调查报告得出。)

    全球十大收入最高的编程语言

    如上图是全球前十大收入最高的编程语言排名,但根据调查,收入与地域之间也是有区别的,比如在美国,Scala 的收入最高,可以达到 143k 美元,其次是 Clojure(139k 美元)、Go(136k 美元)、Erlang(135k 美元)、Objective-C(132k 美元);在印度,Clojure 和 Rust 收入最高。

    工作经验与薪水

    工作经验与薪酬肯定是相关的,但根据调查,有些编程语言无论工作经验多少,薪资都比较高好,而有些编程语言无论多少年工作经验都很一般。

    如上图,红圈的大小不同代表着受访者人数的范围不同,横轴代表着工作经验(年数),纵轴代表着薪资中位数。

    不难看出,使用 Clojure、F#、Scala、Go、Rust 和 R 语言的开发人员,虽然工作经验并不见得非常多,尤其是 Rust、R、Ruby 和 Go,也会获得不少的薪水。然而,PHP、Java、C、C++,即使有多年开发经验,薪水也很难有比较高的提升。

    职位与薪水

    当然,薪酬高低也与所从事的职业有非常大的关系。根据对全球四大 IT 市场的调查,DevOps 专家全部高居榜首,可见市场对这一技术的需求量有多大。除此之外,数据科学家、全栈工程师、嵌入式开发工程师、桌面开发人员的市场受欢迎度均较高。

    如果按照职位来划分,薪水又会出现一些不同。管理岗位的薪水肯定会略高一些,其余基本与市场需求相对应,DevOps 专家的薪水可以达到 71k 美元,数据或者机器学习专家的薪水可以达到 61k 美元,全栈开发者的薪资为 57k 美元,后端开发者略低一些为 56k 美元。

    中国热门编程语言收入情况

    国内整体的薪资水平要略低于全球,需求量较大的依旧是 Java、Python 这类语言。如果与全球薪资较高的编程语言比的话,如果对国内主流招聘网站进行统计,以“Go 语言”为关键字在全国范围搜索,热门地区(北上广深等需求量较大的城市)月薪基本集中在 15-30k 人民币之间,一线互联网大厂的薪酬确实更具竞争力,比如 BAT、高德、奇虎 360、滴滴等,不仅给出的月薪更高(25-60k 之间浮动),不少还明确标出可以给 14 至 16 个月的薪水,而所要求的工作经验基本都在 3 到 5 年。

    至于 Scala 语言,整体薪水确实比 Go 语言略高一些,在没有筛选的情况下,首页出现的大部分薪资集中在 20-50k 之间,这一结果倒是与全球的调查报告相匹配。

    此外,在国内几个招聘网站进行搜索,都没有找到太多有关 Clojure 的招聘需求,样本数量太少,很难判断这一岗位的薪资情况,但可以看出国内对此的需求极低,而 Clojure 在全球市场却可以占到薪资排行榜的第一名,这一结果倒还蛮出乎意料。

    国内对于 Rust 的招聘需求并不旺盛,可搜寻到的岗位不到 Go 语言的十分之一,只比 Clojure 好一些,基本是规模较大的企业对此才有招聘需求,比如今日头条、滴滴等,给出的薪资倒是还算优厚,月薪基本集中在 25k 人民币以上。

    至于 DevOps,虽然国内可搜寻到的岗位不少,但薪资并没有太高,基本与 Go 语言的区间水平相当,要求具备 3 到 5 年工作经验的依旧是最普遍的。

    如果回看 2018 年某招聘网站发布的统计数据,算法研究员和机器学习工程师在过去一年的平均月薪偏高,分别为 28435 元和 26798 元,架构师薪资最高为 29600 元。编程语言中,Go 语言的平均月薪最高为 22961 元,其次是 C++、Python、Java。

    编程语言适用场景

    虽然薪水高低会成为影响开发人员是否选择的重要因素,但并不是唯一因素,不同编程语言的适用场景也是需要开发人员认真考虑的。

    Go

    Go 语言由谷歌开发,并于 2009 年 11 月发布。它是开源的,由于这个原因使得它在公司内部的不同项目中得到了积极应用,一些很有名的服务也使用 Go 语言开发,如 SoundCloud、Netflix 和 Dropbox。

    近年来 Go 语言受欢迎程度大大提高,还得益于 Go 语言下面的优势:

    • 支持多线程任务
    • 支持并行处理
    • 快速的启动时间
    • 高效的内存管理

    很多人都认为它将成为未来的服务器语言,Go 有一些很不错的特性:

    • 它非常简洁、简单和安全
    • 编译非常快
    • 它支持带有嵌入式类型的接口
    • 它不需要任何外部依赖关系来生成静态链接的本机二进制文件

    Kotlin

    Kotlin 编程语言是由 JetBrains IT 公司开发的,它已经成为 Android 的官方开发语言。这是在 2017 年谷歌开发者大会上宣布的。

    它有很多优点,如:

    • 易于理解的语法
    • 与 Java 兼容
    • 谷歌的支持
    • 快速增长的社区

    很有可能不久之后的 Android 应用程序完全使用 Kotlin 编写,所以如果想面向移动应用程序编程,应该考虑将 Kotlin 作为一个选择。

    Ruby(特别是 Rails)

    作为开发 web 应用程序的工具,Ruby 获得了广泛欢迎,并被用于开发全球很多流行产品的服务端部分。Ruby 语言的主要目的是创建强大的、易于理解的程序,其中最重要的不是程序运行的速度,而是开发时间。此外,代码的清晰性和简单性使 Ruby 非常受欢迎。

    Ruby 一些不错的特性有:

    • 一切都是对象
    • 模块——这些模块允许在运行时动态添加类层次结构的新元素
    • 代码开发
    • 动态类型
    • 鸭子类型
    • 代码质量

    Objective – C

    Objective-C 语言用于开发苹果生态系统中的应用程序,纯粹用于开发 Mac OS X 和 iOS。尽管出现了一种新的编程语言 Swift,,但 Objective-C 仍然是开发人员社区中非常流行的选择。此外,因为它与苹果的关系使其拥有一个非常高的需求市场。只要苹果“依赖”Objective-C,开发人员就会一直有市场,并可以获得丰厚的报酬。

    Objective-C 一些很好的特性有:

    • 类即对象——每个类都是一个元类的实例
    • 动态类型
    • 可选的静态类型
    • 动态运行时
    • 内省 introspection

    C #

    C# 是由一群微软工程师开发的,目的是在.NET 平台上开发应用程序。假如希望在微软平台开发本地应用程序并获得相关经验,那么 C# 是理想的语言。

    从本质上讲,C# 是一种简单、现代和通用的面向对象的编程语言。C# 的一大优点是相对简单,并且能够更多地关注算法而不是实现细节。目前,C# 被用于开发许多应用程序,从小型桌面程序到大型门户网站和人们日常使用的 web 服务。

    C# 主要用于:

    • Windows services——没有 UI 的长时间运行的程序
    • Web 应用程序——客户端 / 服务端应用程序
    • 窗口应用程序——运行在桌面上的应用程序
    • Web 服务——通过 HTTP 提供服务的应用程序
    • 游戏——用 Unity 完成
    • 控制台应用程序——没有 UI 的应用程序

    Python

    大量的框架工具、培训材料、友好的社区支持、编码的简单性使其在 2019 年的高薪编程语言榜单上占有一席之地。Python 是目前使用最强大的编程语言之一。它用于:

    • 数学计算
    • 数据分析
    • Web 开发
    • 机器学习
    • 任务自动化

    事实上 Youtube、Dropbox、Reddit 和 Google 等应用程序都是用 Python 开发的。

    Java

    很长一段时间以来,Java 编程语言一直是开发人员社区中需求最旺盛的语言之一。Java 主要用于开发银行和自动化测试中的产品。它的跨平台特性非常受欢迎,这是因为 JVM 的缘故。

    Java 是一种很有前途的编程语言。它被广泛地用于创建服务器和移动应用程序,还被用作开发 Android 本地应用程序。

    Java 可用于开发:

    • 移动应用程序
    • 网络应用程序
    • 桌面应用程序
    • 游戏
    • 数据库连接

    Swift

    Swift 是用于开发苹果平台应用程序的主要语言,主要应用于: 

    • MacOS
    • iOS
    • watchOS
    • tvOS

    这是一种非常通用的编程语言,主要用于开发苹果产品。值得一提的是,它是在 5 年前(2014 年)刚发布。其主要和最突出的优点是速度:无论是运行还是启动应用程序。正是这种优势赋予了它这个名字,它的创造者说其吸收了其他语言的所有优势。

    总  结

    市场上总是缺少有才华的程序员,未来几年,这仍然将是市场上的一个紧迫问题。对上述语言的了解和足够的相关工作经验可以为开发人员打开许多大门。此外,开发者没必要限制自己只使用一种语言。无论是理论还是实践,都可以尝试用另一种编程语言学习新的知识,所需要的只是激情和努力!

     

     


    Kotlin 开发者社区

    国内第一Kotlin 开发者社区公众号,主要分享、交流 Kotlin 编程语言、Spring Boot、Android、React.js/Node.js、函数式编程、编程思想等相关主题。

    展开全文
  • 我有一个大学校友,他是去年 8 月份才开始正式学习 Java 的,之前在一家私企工作了 5 年,工资一个月只有不到 6000 块,日子过得很苦逼,毕竟郑州的房贷压力也不小,公司就那么大,除非领导离职,否则根本看不到晋升...

    我有一个大学校友,他是去年 8 月份才开始正式学习 Java 的,之前在一家私企工作了 5 年,工资一个月只有不到 6000 块,日子过得很苦逼,毕竟郑州的房贷压力也不小,公司就那么大,除非领导离职,否则根本看不到晋升的希望。他刚 26 岁,正值青春年华,我就劝他不如改学 Java,他之前学 PHP 的,虽然做起来项目很快,但发展前景确实不怎么乐观。我身边的很多朋友在北京做 Java 开发,差不多能拿到 2 到 3 万的月薪,师弟听了非常羡慕,感觉超出了他的认知范围,就下定决心开始学习 Java,一共学了大概 6 个月的时间,今年跑去杭州找到了一份 Java 开发的工作,月薪 15K,因为是自学,能拿到这个薪水我觉得很不错了。

    这期间,我给了他很大帮助,帮他梳理了一条非常清晰的自学路线,他自己也很下劲,遇见什么问题就来问我,我有时候回复不及时,过一会他就说,不用了,自己找到了答案,这股劲真的让我感觉非常佩服。

    自学的过程并不容易,我认为有两个因素非常重要。

    第一,就是一定要自律。很多人看到 Java 很吃香,就跑过来学,很草率,学了一段时间后,感觉很痛苦,就放弃了。我师弟的情况特殊一点,他本身感觉到生存的压力比较大,就抱着很强烈的学习愿望,再一听别人拿那么多钱,就更下劲了。加上自己学习又非常自律,每天上班的时候偷偷学一点,然后下班后又一直学到晚上一点多真的超级自律。

    第二,就是有人带。如果全程靠自己去摸索,超级难受,一是没有目标,不知道该学什么,东学一块,西学一块,成不了知识体系;二是遇到问题的时候没人交流,这个是非常难受的,信心就会受到很大的打击,慢慢学习的劲头就下去了。师弟来找我,我基本上看到就回复他了,我还认识很多技术很厉害的大佬,基本上没有解决不了的问题。

    所以,总结一下就是,自身一定要主动去学习,然后要有人带你,然后就是时间,水到渠成的事。这两点少了一点,就很难成功。

    自学 Java 必须要注意的一些问题。

    1)遇到不会的点,不要死磕

    很多问题,可能是自己当时累了,然后如果钻牛角尖的话,很容易出不来,耽误了学习时间不说,还很有挫败感。可能休息一下,或者问一下大佬,或者去学一下其他的知识点,很快可能就找到了解决方案。

    2)一定要高效

    学习就是这样,如果短时间内看不到效果,会很沮丧,会怀疑自己,然后就越来越没劲去学习了。动手动脑,不要一直眼睛盯着去看,无论是视频,还是书,要学会去调解自己,累了就休息会,千万不要学头悬梁锥刺股的那种学习方式。

    3)及时沟通

    可以去问搜索引擎,一定不要用度娘,最起码也得用必应去搜索吧,最次跑到知乎直接问问题,这也是一种沟通,俗称“人机交互”,哈哈。另外一个就是问大佬,跑技术交流群去提问,不要怕没人回答你,自己总结的过程中可能就会自己得到答案。

    接下来,说一下 Java 主要学的内容。

    第一部分,Java 基础

    学 Java 基础的话,我推荐两本,一本《Java 核心技术卷》,一本《Head First Java》。

    《Java 核心技术卷》分为上下两册,上册的难度较低,可以在最短时间内刷完,尤其是有了 C语言的编程基础后,再刷这本书可以说是手到擒来。下册涉及到的内容有流与文件(☆)、XML、网络(☆)、数据库编程、国际化、Swing、AWT、JavaBean、安全(☆)、脚本编译和注解处理、分布式对象、本地方法(☆),没有标星的内容我认为可以略过。

    《Head First Java》更有趣一些,里面有很多小游戏,很活泼的一本书。

    两本书之间的风格差别比较大,之前就有读者给我反馈说,《Head First Java》有点驾驭不了,那就挑《Java 核心技术卷》。

    刷完任意一本书后,可以看一看《Java 编程思想》,看自己是否能驾驭得了。因为思想的东西嘛,只有经过一些实践后才能有所感悟,否则就像王阳明一开始对着竹子格物一样,屁也格不出来,有了后面领军作战的经验,以及到地方上体验艰苦生活的感受后就开创了心学。

    如果 Java 编程思想看起来确实比较痛苦的话,可以看一看《On Java 8》,GitHub 上有开源的中文翻译版,作者是同一个人。

    上面提到的这 4 本书里面都还保留了图形程序设计的内容(AWT 和 Swing),我认为是完全可以跳过的,希望后面出版社再版的时候能把这些内容全部删除,定价估计就降了,但他们不一定会这么干。

    Java 是一门面向对象的编程语言,所以三大特性:封装、继承、多态是必须要掌握的,然后是异常处理、IO、集合和并发编程。只要这些内容掌握了,可以说 Java 的基础知识就全部掌握了。

    这其中的难点是并发编程,我前面提到过,显然这部分内容学起来并不容易,但却最能考验一名 Java 后端工程师的功底了。怎么才能学好并发编程这块呢?我推荐一本非常牛逼的开源电子书《深入浅出 Java 多线程》,几位阿里朋友写的,质量非常高,我在很早之前推荐过,可以点击下面的链接下载离线版。

    几位阿里朋友重写的Java并发编程,牛逼了

    第二部分,Java Web

    大部分 Java 程序员都要从事 JavaWeb 的相关开发工作,要开发 JavaWeb,自然就离不开 Spring 的系列框架。甚至可以这么说,没有 Spring 的 Java 项目是不存在的。

    要学习 Spring,能读的书不多,我能想到的只有《Spring实战》,坦白地说,这本书很一般,但市面上比它好的书,我还不知道。学完 Spring,就要学 SpringMVC,推荐大家看松哥的视频,在 B 站上虽然播放量不是特别大,但我觉得内容特别棒。

    然后是 MyBatis,不用找书看了,直接看官方文档就行,讲得特别好。本身 MyBatis 也没有特别难的东西,就是一些 XML 配置和动态 SQL。

    Spring+SpringMVC+MyBatis 这三个学完,可以说你就具备了开发企业级应用的能力了。

    然后是 Spring Boot,我推荐看大哥纯洁的微笑的博客,访问量在千万级别以上,影响了无数的初学者,我个人强烈推荐。链接就不用我贴了,直接搜“Spring Boot”关键字就行了。

    如果说你已经掌握了 Spring、SpringMVC、MyBatis、Spring Boot 等内容,就有能力进行一些真正有用的应用项目开发了,比如说学生管理系统、商城系统、博客系统、秒杀系统等等。

    如果你觉得这些系统无从下手的话,其实可以到 GitHub 或者码云上去找,很快就能找到一大堆。为了节省大家的时间,我直接给大家推荐两个。一个微人事,一个 mall,可以直接到 GitHub 上搜。

    第三部分,数据库

    学习一门编程语言,如果不去操作下数据,就感觉这门编程语言空有皮囊却没有灵魂,对吧?要想学好数据库,首先要学习一下 SQL(《SQL 必知必会》这本小册子就足够用了),然后是 MySQL(最流行的关系型数据库,当推《高性能 MySQL》),然后是 Redis(缓存,老钱的《Redis 深度历险:核心原理与应用实践》非常经典)和 MongoDB(非关系型数据库,《MongoDB权威指南》就可以吃透)。

    第四部分,工具

    工欲善其事必先利其器,掌握了下面这些工具,学习起来其他的内容也会更加顺手,不用瞎折腾。

    Intellij IDEA,编写 Java 程序的最佳 IDE,必须得掌握。GitHub 上有一本开源的书库值得推荐。

    接下来是 Maven,可以帮助我们解决 jar 包的烦恼。看《Maven 实战》就可以了。

    然后是 Git,工作中是必须掌握的,看《Git 权威指南》就好了。

    这些内容学完后,就可以准备找工作了,但在找工作之前,一定还要做两件事。这两件事对找到一份心满意足的工作至关重要,缺一不可。拼命学习了这么长时间,就剩下这最后两个关键节点了,怎么能不锦上添花。

    1)first blood

    一定要刷面试题,做到有备而战。就像打战一样,如果只是招募到兵员,却不训练,上了场,根本就不经打,只有训练有素的士兵,在场上作战的时候才能做好攻守平衡,应付自如。

    我推荐这份在 GitHub 上星标 100k 的面试攻略,离线版已经更新到第四版,内容更加详实。新增了校招/社招面试指南、程序员简历之道这些大多数程序员在面试前比较关心的内容。可通过下面的方式下载离线版。

    V4.0 《JavaGuide 面试突击版》来啦!GitHub 上标星 100k,帮你成功上岸!

    2)double kill

    一定要准备一份让面试官耳目一新的简历,很多初学者容易忽略的一个点就是,随随便便整一份简历,然后就开始投递,结果就像石沉大海一般,没有回响。作为简历的撰写者,你必须要搞清楚一点,简历的本质是什么,它就是为了来销售你的价值主张的。往深处说,简历就是一块敲门砖,它通过白纸黑字的方式告诉招聘方,我是谁,我想来贵公司担任什么职位,我能够完成什么样的工作,我能够为公司带来什么价值,我期望的薪资是多少。

    入职阿里后,才知道原来简历这么写

    OK,这两件事准备充足了,就大胆地往前冲吧,相信我,就像我的师弟一样,你也一定能找到一份满意的工作。有任何关于 Java 相关的疑问,也欢迎随时私信我。

    传统美德不能丢,来个一键三连吧,笔芯芯~

    展开全文
  • 原文地址:http://android.xsoftlab.net/training/articles/perf-jni.htmlJNI的全称为Java Native Interface,中文意思是Java本地接口。它定义了Java代码与C/C++代码之间的交互方式。它是两者的桥梁,支持从动态共享...

    原文地址:http://android.xsoftlab.net/training/articles/perf-jni.html

    JNI的全称为Java Native Interface,中文意思是Java本地接口。它定义了Java代码与C/C++代码之间的交互方式。它是两者的桥梁,支持从动态共享库中加载代码。虽然有些复杂,但是它的执行效率还是蛮高的。

    如果你对JNI还不太熟悉,那么可以通过Java Native Interface Specification来了解一下JNI的大致工作流程以及JNI的特性。

    JavaVM与JNIEnv

    JNI定义了两个关键的数据结构:”JavaVM”与”JNIEnv”。这两个函数本质上都为指向函数指针的指针表。JavaVM提供了”接口调用”功能,该功能允许创建、销毁JavaVM。理论上每个进程可以拥有多个虚拟机,但是在Android中只允许出现一个。

    JNIEnv提供了大部分的JNI功能。任何本地方法都以JNIEnv为第一回调参数。

    JNIEnv用于线程局部存储。正出于这个原因,所以不能在线程间共享JNIEnv。如果不能够通过其它方式获取其对应的JNIEnv对象,那么应该先共享JavaVM,然后通过GetEnv函数获取该线程对应的JNIEnv(假设该线程拥有一个JNIEnv,具体请往下看)。

    C与C++对JNIEnv和JavaVM的声明方式并不相同。头文件”jni.h”针对C或者C++提供了不同的类型定义。正因为这个原因,在头文件中包含JNIEnv参数并不是个明智的主意。

    线程

    Android中所有的线程都是Linux线程,都由内核执行。通常由受控代码启动(比如Thread.start),但是也可以由别的地方创建,然后再附加到JavaVM上启动。举个例子,线程可以由pthread_create函数创建,然后通过AttachCurrentThread或AttachCurrentThreadAsDaemon将其附加到JavaVM上执行。

    Android并不会挂起正在执行本地代码的线程。如果垃圾收集正在进行,或者调试器发起了挂起请求,那么Android会在下次JNI调用时暂停线程。

    通过JNI所附加的线程在退出前必须调用DetachCurrentThread函数

    jclass, jmethodID, 及jfieldID

    如果需要在本地代码中访问对象的属性,那么需要执行以下操作:

    • 通过FindClass获取类对象的引用
    • 通过GetFieldID获得属性的ID
    • 通过对应的方法获取对象的内容,比如GetIntField

    相应的,如果要调用一个方法,首先获取类对象的引用,其次获取该方法的ID。ID通常只是指向了一个内部的运行时数据结构。查找这些方法通常需要进行若干次字符串比对,但是一旦找到,那么后期的获取属性或者方法调用都会非常的迅速。

    如果性能对你很重要,那么在找到这些属性或者方法之后,应该将其缓存起来。因为Android中只允许每个进程有一个JavaVM的存在,所以将这些数据缓存在一个静态本地结构中是合理的。

    类的引用、属性的ID、方法的ID在这个类被卸载之前都可以保证它们有效。一个类只有在这种情况下才会被卸载:该类所关联的ClassLoader也能被回收。虽然这几率很低,但是在Android中不是没有可能的。

    如果想在类加载的时候将这些ID缓存下来,并在类被卸载之后再重新加载时还能重新缓存,最正确的方法是添加这样一段代码:

        /*
         * We use a class initializer to allow the native code to cache some
         * field offsets. This native function looks up and caches interesting
         * class/field/method IDs. Throws on failure.
         */
        private static native void nativeInit();
        static {
            nativeInit();
        }

    在C/C++代码中创建一个名为nativeClassInit的方法,用于ID的查找与缓存。该方法会在类初始化的时候执行一次。就算是类被卸载后又重新加载,那么这个方法还是会被执行一次。

    局部引用,全局引用

    每个被回调到本地方法的参数,以及几乎所有的通过JNI方法返回的对象都是局部变量。这意味着当前线程中该方法内的所有局部变量都是合法的。在本地方法返回之后,虽然对象仍然存活,但是引用却是无效的。

    这适用于jobject所有的子类:jclass, jstring, 以及jarray。

    获取非局部变量的唯一方式就是通过NewGlobalRef及NewWeakGlobalRef函数获得。

    如果需要长时间持有一段引用,那么必须使用全局引用。NewGlobalRef函数会将一个局部引用转换为一个全局引用。在调用DeleteGlobalRef方法之前,该全局引用一直有效。

    这种模式通常用于缓存一个由FindClass返回的一个jclass对象:

    jclass localClass = env->FindClass("MyClass");
    jclass globalClass = reinterpret_cast<jclass>(env->NewGlobalRef(localClass));

    所有的JNI方法都可以以这两种引用为参数。不过引用相同的值可能有不同的结果。举个例子,以同一个引用为参数连续调用两次NewGlobalRef可能会得到不同的值。如果要查看两个引用是否指向了同一个对象,必须使用IsSameObject函数。绝不要在本地代码中使用”==”比较两个引用。

    绝不要认为在本地代码中的对象引用是个常量或者是唯一的。一个32位的值所代表的对象的方法调用可能与下次调用就有所不同,这可能是因为两个不同的对象拥有相同的32位值。不要将jobject的值当做键使用。

    程序员经常被要求不要过度的申请局部变量。这意味着如果你创建了大量的局部变量,那么应当通过DeleteLocalRef函数手动的释放它们,而不是让JNI为你做这些事情。

    要注意jfieldIDs、jmethodID并不是对象引用,所以不能够将它们传给NewGlobalRef函数使用。GetStringUTFChars函数与GetByteArrayElements函数所返回的原始数据指针也同样不是对象。

    一个不寻常的情况需要单独说明一下:如果通过AttachCurrentThread函数attach到了一个本地线程上,那么在该线程被detache之前,代码中所有的局部变量都不会被自动释放。任何创建的局部变量都需要手动删除。

    UTF-8与UTF-16字符串

    Java语言使用的是UTF-16字符串。为了方便起见,JNI所提供的方法工作在Modified UTF-8字符串下。修正后的编码对于C语言代码很有用,因为它将\u0000编码为了0xc0 0x80。

    不要忘记释放你所获得的字符串。字符串函数会返回jchar* 或 jbyte*,它们是指向原始数据的指针,而不是本地引用。它们在被释放之前一直有效,这意味着在本地方法返回后,它们并没有被释放。

    传给NewStringUTF函数的数据必须是Modified UTF-8格式。一个常见的错误就是从文件流或者网络流中读取字符串数据,然后没有过滤就直接交给了NewStringUTF函数进行处理。除非你知道这些数据是7位的ASCII,否则你需要剔除高位的ASCII字符串或者将它们转换为正确的Modified UTF-8格式。如果你不这么做,那么转换的结果可能不是你想看到的。额外的JNI检查会扫描字符串并会警告你这是无效的数据,但是它们不会捕获任何事情。

    原始数组

    JNI提供了用于访问对象数组的功能。然而,同一时间只能对一个元素进行访问,可以直接对数组今夕读写操作,就好像直接在C中声明的一样。

    为了使JNI接口尽可能的高效,也不受虚拟机实现的限制,调用GetArrayElements的相关函数可以返回一个指向实际值的指针,或者可以申请一些内存以完成复制。无论哪种方法,所返回的指针都可以保证是有效的,直到相应的释放方法被触发。必须释放你所取得的每个数组。如果Get方法调取失败,也需要保证不要去释放一个空的指针对象。

    你可以通过isCopy参数来检测一个数组是否是由指针所拷贝过来的,这一点很有用。

    Release方法需要一个mode参数,这个参数有三种值。运行时执行的操作取决于它返回指向实际数据的指针或者指针的副本:

    • 0
      • 实际指针:非final修饰的数组对象
      • 指针副本:拷贝后的数组数据,拷贝的缓冲区会被释放
    • JNI_COMMIT
      • 实际指针:不做任何事情
      • 指针副本:拷贝后的数组数据,拷贝的缓冲区不会被释放
    • JNI_ABORT
      • 实际指针:非final修饰的数组对象。早些写入不会被中止。
      • 指针副本:所拷贝的缓冲区被释放;缓冲区内的任何变更都会丢失。

    检查isCopy标志的其中一个原因是需要知道在对数组作出变更之后是否需要调用JNI_COMMIT的相关释放方法,如果要更改一个正在作出变更以及读取数组内容的操作,那么可以根据该标志跳过这次操作。另一个可能的原因就是用于有效的处理JNI_ABORT。举个例子,你可能想要得到一个数组,然后对其修改之后将其传给一个函数。如果你知道JNI会为你做一个副本的话,那么就不需要创建另外的可编辑副本了。如果JNI传回的是原始数据,那么你自己需要创建一个副本。

    一个常见的错误就是如果*isCopy是false,那么可以不调用相关释放方法。但是事实并非如此,如果没有申请拷贝缓冲区,那么原始数据内存必定会被一直占用,也不会被垃圾收集器回收。

    还要注意的是,JNI_COMMIT并不会释放数组,你需要在另外的标志执行后再执行一次释放。

    方法调用

    JNI在方法使用上有两种方式,一种如下所示:

        jbyte* data = env->GetByteArrayElements(array, NULL);
        if (data != NULL) {
            memcpy(buffer, data, len);
            env->ReleaseByteArrayElements(array, data, JNI_ABORT);
        }

    上面这段代码首先得到了一个数组,然后拷贝出len个字节的元素,最后将这个数组释放。根据实现的不同,Get调用会返回原始数据或者数据副本。在这个案例中,JNI_ABORT可以确保不出现第三个副本。

    另一种实现则要更简单一些:

        env->GetByteArrayRegion(array, 0, len, buffer);

    对于此有若干建议:
    - 减少JNI调用可以节省开销。
    - 不要原始数据或者额外的数据拷贝。
    - 降低程序员出错的风险–他们会在某些操作失败后忘记调用相关的释放方法。

    类似的,你可以使用SetArrayRegion函数将数据拷贝到一个数组中,GetStringRegion函数或GetStringUTFRegion可以从String拷贝任意长度的字符。

    异常

    当异常出现时,请不要继续向下执行。代码应当注意到这些异常并返回,或者处理这些异常。

    当异常发生时,只有以下JNI方法允许调用:

    • DeleteGlobalRef
    • DeleteGlobalRef
    • DeleteLocalRef
    • DeleteWeakGlobalRef
    • ExceptionCheck
    • ExceptionClear
    • ExceptionDescribe
    • ExceptionOccurred
    • MonitorExit
    • PopLocalFrame
    • PushLocalFrame
    • ReleaseArrayElements
    • ReleasePrimitiveArrayCritical
    • ReleaseStringChars
    • ReleaseStringCritical
    • ReleaseStringUTFChars

    很多JNI函数都会抛出异常,不过只提供了一种很简单的检查方法。比如,如果NewString函数返回了一个非空的值,那么就不需要检查异常。然而,如果你调用一个方法,比如CallObjectMethod,那么就需要每次都检查一下异常,因为如果异常被抛出后,返回值是无效的。

    主要注意的是,由中断所抛出的异常不会释放本地栈帧,Android目前也不支持C++异常。JNI的Throw与ThrowNew结构也只是在当前的线程设置了一个异常指针。当异常发生时也只是返回到代码调用处,异常也不会被正确的注意与处理。

    本地代码可以通过ExceptionCheck函数或ExceptionOccurred函数捕获异常,并可以通过ExceptionClear函数清理这些异常。通常情况下,不处理这些异常会导致一些问题的出现。

    JNI中并没有与Throwable相对应的映射函数,所以,如果你想获得异常字符串,那么就需要先找到Throwable类,然后查找相关的getMessage “()Ljava/lang/String;”方法ID,然后调用这些方法,如果返回的值是非空的话,再调用GetStringUTFChars函数来获得你想得到的异常字符串,最后将这些异常打印出来。

    本地库

    你可以通过标准的System.loadLibrary函数加载共享库中的本地代码。推荐获取本地代码的方法有:

    • System.loadLibrary(),该方法唯一的参数是一个简要的库名,所以如果要加载”libfubar.so”,你只需要传”fubar”即可。
    • 本地方法:jint JNI_OnLoad(JavaVM* vm, void* reserved);
    • 在JNI_OnLoad方法内部,注册所有的本地方法。如果将方法声明为”static”的话,那么方法名将不会占用符号表的空间。

    如果JNI_OnLoad函数是由C++实现的话,那么它看起来应该是这个样子:

    jint JNI_OnLoad(JavaVM* vm, void* reserved)
    {
        JNIEnv* env;
        if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
            return -1;
        }
        // Get jclass with env->FindClass.
        // Register methods with env->RegisterNatives.
        return JNI_VERSION_1_6;
    }

    你也可以通过System.load函数外加库的全限定名来加载本地库。

    使用JNI_OnLoad另一个需要注意的是:任何FindClass调用都会发生在类加载器的上下文环境中,该类加载器用于加载共享库。通常情况下,FindClass所用到的加载器位于解释栈的顶端,如果还没有加载器,那么它会使用系统的加载器。

    64位的注意事项

    Android目前运行于32位的平台上。虽然理论上可以为64位的平台构建系统,但是目前它不是主要的目标。大多数情况下,这不是你需要担心的事情,但是如果要将指针存储于本地结构中的一个对象的Int属性上,那么这就很值得关注了。为了支持64位指针结构,你需要将本地指针存储于一个Long属性中

    不支持特性与向后兼容

    支持所有的JNI1.6特性,以及以下异常:
    - DefineClass 还没有实现。Android并没有使用Java的字节码以及类文件,所以传入二进制的类数据是不会被执行的。

    如果需要兼容Android老的版本,那么应该检查以下部分:

    • 动态查询本地函数
      • 在Android 2.0之前,字符’$’在查找方法时不会被正确的转换为”_00024”。所以使用有关方法需要明确注册或者将内部类方法移出。
    • 分离线程
      • 在Android 2.0之前,无法使用pthread_key_create析构函数来避免”在退出之前必须分离线程”这项检查。
    • 弱的全局引用
      • 在Android 2.2之前,弱的全局引用还没有实现。之前的版本会拒绝使用它们。你可以使用Android平台版本来检测是否支持。
      • 在Android 4.0之前,弱的全局引用只能被传入NewLocalRef, NewGlobalRef, 以及 DeleteWeakGlobalRef这几个函数。
      • 从Android 4.0开始,弱的全局引用可以像其它JNI引用一样使用。
    • 本地引用
      • 在Android 4.0之前,本地引用实际上就是指针。在Android 4.0之后添加了必要的中间角色,以便更好的支持垃圾回收器的工作,不过这意味着有很多JNI的bug在老版本上无法察觉。查看JNI Local Reference Changes in ICS获取更多信息。
    • 通过GetObjectRefType检查引用类型
      • 在Android 4.0之前,由于直接指针的使用,无法正确的实现GetObjectRefType。我们通过弱的全局表、参数、本地表以及全局表进行查找。首先它会找到你的直接指针,并返回它所检查的引用类型。这意味着,如果你在全局的jclass上作用GetObjectRefType,而这个jclass以一个隐性参数传给了一个静态本地方法,那么你将会获得JNILocalRefType而不是JNIGlobalRefType。
    展开全文
  • Android资源编译器为了使使用obtainStyledAttributes()方法更加简便了大量的工作。在资源目录中的每一个资源都会在R.java中定义相应的属性id。你可以使用这预定义的常量去 TypedArray 中读取属性。下面是PieChart...
  • eeglab中文教程系列(1)-加载、显示数据

    万次阅读 多人点赞 2019-10-14 18:11:03
    目录准备工作1.安装eeglab2.准备测试数据具体操作1.加载数据2.观察事件值(event values)3.查看数据信息4.浏览EEG通道数据(并可视化)5.电压刻度调整6.调整滚动时间窗口的宽度7.通道数编辑8.数据窗口放大与缩小9.绘制...
  • Envoy 中文指南系列:Envoy 介绍

    万次阅读 2020-06-07 10:57:30
    在 HTTP 层的话,你将会从传输线路上读取整个 HTTP 请求的数据,对它解析,查看 HTTP 头部和 URL,并决定接下来要做什么。随后,你将从后端读取整个响应的数据,并将其发送给客户端。但这种做法的缺点就是非常复杂...
  • 从零开始nodejs系列文章-nodejs到底能干什么

    万次阅读 多人点赞 2016-01-08 14:04:24
     从零开始nodejs系列文章, 将介绍如何利Javascript为服务端脚本,通过Nodejs框架web开发。Nodejs框架是基于V8的引擎,是目前速度最快的 Javascript引擎。chrome浏览器就基于V8,同时打开20-30个网页都很流畅。...
  • 当加载一张图片到内存时,最好是将该图片适配到当前屏幕分辨率大小之后再内存缓存,如果原图本身分辨率很高的话,最好将其缩小到适合屏幕分辨率大小。要注意,随着位图分辨率的增加,所占的相应内存也一并增加。 ...
  • 不过与之前微软面试100题系列,红黑树系列,及十三个经典算法研究系列相比,编程艺术系列的某些篇文章的作者除了我本人自己,或多或少还得到了不少朋友的支持,我把这些朋友组织起来,成立了一个工作室,它的名字...
  • 7系列PCIe IP核用户手册(中文

    千次阅读 多人点赞 2018-11-15 12:25:34
    7系列PCIe IP核用户手册(中文)前言前言文档的目录如下下载链接参考文献 前言 你好! 这是本人阅读和使用Xilinx PCIe IP核时,参照英文版的用户手册所的笔记,内容很全,并加入了自己的理解。 前言 你好! 这是...
  • nodejs可以用来做什么

    万次阅读 多人点赞 2019-03-07 09:52:09
    Node.JS&nbsp;学习路线图 ... 从零开始nodejs系列文章, 将介绍如何利Javascript为服务端脚本,通过Nodejs框架web开发。Nodejs框架是基于V8的引擎,是目前速度最快的 Javascript引擎。chrome浏...
  • 比特币基本原理系列

    万次阅读 2019-05-13 18:41:17
    表象之下,PoW 中的挖矿实际上在的事情就是将动能(电力)转化为一个账本区块。一台矿机重复地运行哈希计算,直到它解决一个密码学难题。所有的哈希运算都会被丢弃,除了那个能够解决问题的哈希值。 这个渺小的...
  • 中文分词版本:5.6.6(需要与elasticsearch版本匹配) maven版本:3.5.5 安装 step1 官网下载合适的版本 下载页面地址:https://github.com/medcl/elasticsearch-analysis-ik 选择合适的版本,并下载: ...
  • 前面两篇文章详细讲解了哈工大Pyltp工具,包括中文分词、词性标注、实体识别、依存句法分析和语义角色标注等。但是其中文分词效果不是很理想,如“贵州财经大学”总是切分成“贵州”、“财经”和“大学”,这是因为...
  • ReID(一):什么是ReID?如何ReID?ReID数据集?ReID评测指标?        小白入门系列是我和朋友准备一起的一块内容,分模块分专题·,比如计算机视觉中的目标检测,ReID,OCR,语义分割以及...
  • 摘录自:CIPS2016 中文信息处理报告《第一章 词法和句法分析研究进展、现状及趋势》P4 CIPS2016 中文信息处理报告下载链接:http://cips-upload.bj.bcebos.com/cips2016.pdf 之前写过一篇中文分词总结,那么在...
  • 现在这个实现就适合用到类似 ListView 和 GridView 这种会回收它们子View的组件上了,简单的调用loadBitmap()就可以正常给ImageView设置图片了。比如,在一个 GridView 的实现中,这个方法就可以在相应适配器的...
  • 在windows下vim的中文字体显示并不好, 所以我们需要调整字体显示编码为utf-8, 只有这样才能使用美观的中文.这时候可能出现很多中文乱码. 如 : 文件显示乱码、菜单乱码、右键菜单乱码、conlse输出乱码、文件关联右键...
  • 在日本科研工作是怎样的体验?

    千次阅读 2016-06-16 09:48:59
    似乎目前中国的科研人员大多选择欧美或回国,平时没怎么听说过选择在日本去postdoc, faculty一类的人。(国内有零星的日本人来任教的情况,我见过的...1、日语需要达到什么水平才可以去日本比较好的大学或研究所工作
  • 什么是域什么工作

    千次阅读 2018-05-10 10:18:10
    原址:https://blog.csdn.net/ericsone/article/details/1432677 为什么要组建局域网呢?...那么究竟什么是域,什么工作组呢?它们的区别又是什么呢? “自由”的工作组 工作组(Work Group)就是将...
  • YC 创业第12课:来开发企业级产品吧 YC 创业第13课,创业者的条件 YC 创业第14课:像个编辑一样去管理 YC 创业第15课:换位思考 YC 创业第16课:如何用户调研 YC 创业第17课:Jawbone 不是硬件公司 YC 创业第18课...
  • stm32f103c8t6中文手册

    2018-03-01 10:22:53
    stm32f103c8t6中文手册,有需要的童鞋可以看一下。 STM32F103C8T6是一款基于ARM Cortex-M 内核STM32系列的32位的微控制器,程序存储器容量是64KB,需要电压2V~3.6V,工作温度为-40°C ~ 85°C。
  • 1月19日,在极客公园创新者大会IF2018的现场,Google Brain首席工程师陈智峰发表题为:《找答案从定义问题开始 ——TensorFlow 可以用来做什么?》的演讲,分享了Google Brain最近一年到两年时间里面的研究方向,...
  • 你设置共享了嘛,共享的PC要在同一个工作组内,另外 IP要在同一个网关内 才可以相互访问1、WIN+R键,打开“来运行”,输入cmd,按回车键,打开“命令提示符”。2、在“命令提示符”中输入net localgroup按回车键,...
  • 什么是火星坐标(GCJ-02)

    千次阅读 2017-09-19 17:32:51
    什么是火星坐标? 关于什么是火星坐标,我们先来看看百度百科的解释。 保密插件,也叫做加密插件或者加偏或者SM模组,是对真实地图或者导航坐标系统进行人为的加偏处理,按照一定的加偏...
  • 借助TensorFlow框架,到底能做什么

    万次阅读 2018-08-12 17:50:00
    谷歌在七月份正式推出了深度学习框架TensorFlow 1.9 版本,那么TensorFlow框架到底是什么?TensorFlow™ 是一个采用数据流图(data flo...
  • 我的大学四年到毕业工作5年的学习路线资源汇总

    千次阅读 多人点赞 2020-03-31 13:37:10
    软件 序号 软件 描述 1 word 文本编辑工具,无论是你以后毕业论文还是平时整理材料,以及将来工作中都会用到 2 excel 电子表格软件,基本统计个表、汇总个成绩,以及很多内容上都会用到 3 ppt 这个就是神器了,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 109,911
精华内容 43,964
关键字:

中文系适合做什么工作