Java 8中Lambda表达式的阴暗面

blog_lambada_2

这篇文章可能不会使我成为任何新朋友。 哦,好吧,无论如何我从来没有真正在学校受到欢迎。 但是,让我们说清楚。 就语言而言,Java 8的最大特色无疑是Lambda表达式。 几年来,它一直是功能语言(例如Scala和Clojure)的旗舰功能,现在Java终于加入了。

第二大功能(当然取决于您问谁)是Nashorn –新的JVM JavaScript引擎,可以使Java与其他JS引擎(例如V8和它的node.js容器)相提并论。

但是这些新功能对他们不利。

我会解释。 Java平台由两个主要组件构建而成。 JIT编译并执行字节码的JRE,JDK包含开发工具和javac源代码编译器。 这两个组件是完全(但不是完全)分离的,这使人们能够编写自己的JVM语言,而Scala在最近几年中日益受到关注。 其中存在一些问题。

JVM被构建为与语言无关,只要它可以转换为字节码,就可以执行以任何语言编写的代码。 字节码规范本身是完全面向对象的,旨在与Java语言紧密匹配。 这意味着从Java源代码编译的字节码在结构上将非常类似于它。

但是与Java的距离越远,距离就越远。 当您查看Scala是一种功能语言时,源代码与执行的字节码之间的距离就很大。 编译器添加了大量合成类,方法和变量,以使JVM执行该语言所需的语义和流控制。

当您查看完全动态的语言(例如JavaScript)时 ,这种距离变得很大。

而现在有了Java 8,它也开始渗透到Java中。

那我为什么要在乎呢?

我希望这是一个理论性的讨论,尽管有趣,但对我们的日常工作没有实际意义。 不幸的是,它确实以很大的方式做到了。 随着向Java中添加新元素的推动,代码与运行时之间的距离越来越大,这意味着您正在编写的内容和正在调试的内容将是两件事。

要了解让我们如何(重新)访问下面的示例。

Java 6和7

这是传统的方法,通过该方法我们可以遍历一串字符串以映射其长度。

// simple check against empty strings
public static int check(String s) {if (s.equals("")) {throw new IllegalArgumentException();}return s.length();
}//map names to lengthsList lengths = new ArrayList();for (String name : Arrays.asList(args)) {lengths.add(check(name));
}

如果传递一个空字符串,这将引发异常。 堆栈跟踪看起来像–

at LmbdaMain.check(LmbdaMain.java:19)
at LmbdaMain.main(LmbdaMain.java:34)

在这里,我们看到了所看到的堆栈跟踪与所编写的代码之间的1:1关系,这使得调试此调用堆栈非常简单。 这就是大多数Java开发人员所习惯的。

现在让我们看一下Scala和Java 8。

斯卡拉

让我们看看Scala中的相同代码。 在这里,我们有两个重大变化。 第一个是使用Lambda表达式映射长度,第二个是迭代是由框架执行的(即内部迭代)。

val lengths = names.map(name => check(name.length))

在这里,我们真的开始注意到您编写的代码外观与JVM(以及您)在运行时如何看到它们之间的区别。 如果抛出异常,则调用堆栈会长一个数量级 ,并且很难理解。

at Main$.check(Main.scala:6)
at Main$$anonfun$1.apply(Main.scala:12)
at Main$$anonfun$1.apply(Main.scala:12)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
at scala.collection.immutable.List.foreach(List.scala:318)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
at scala.collection.AbstractTraversable.map(Traversable.scala:105)
at Main$delayedInit$body.apply(Main.scala:12)
at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main$1.apply(App.scala:71)
at scala.App$$anonfun$main$1.apply(App.scala:71)
at scala.collection.immutable.List.foreach(List.scala:318)
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:32)
at scala.App$class.main(App.scala:71)
at Main$.main(Main.scala:1)
at Main.main(Main.scala)

*请记住,此示例非常简单。 使用现实世界中的嵌套Lambda和复杂结构,您将需要更长的综合调用堆栈,您需要从中了解发生了什么。

长期以来,Scala一直是一个问题,这也是我们构建Scala Stackifier的原因之一。

现在在Java 8中

直到现在,Java开发人员都对此免疫。 随着Lambda表达式成为Java不可或缺的一部分,这种情况将会改变。 让我们看一下相应的Java 8代码以及生成的调用堆栈。

Stream lengths = names.stream().map(name -> check(name));at LmbdaMain.check(LmbdaMain.java:19)
at LmbdaMain.lambda$0(LmbdaMain.java:37)
at LmbdaMain$$Lambda$1/821270929.apply(Unknown Source)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:512)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:502)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.LongPipeline.reduce(LongPipeline.java:438)
at java.util.stream.LongPipeline.sum(LongPipeline.java:396)
at java.util.stream.ReferencePipeline.count(ReferencePipeline.java:526)
at LmbdaMain.main(LmbdaMain.java:39)

这与Scala变得非常相似。 我们为更短,更简洁的代码,更复杂的调试和更长的综合调用堆栈付出了代价。

原因是,尽管javac已扩展为支持Lambda函数,但JVM仍然它们不了解 。 这是Java人士的一项设计决策,目的是保持JVM在较低级别运行,而又不会在其规范中引入新的元素。

尽管您可以辩论此决定的优缺点,但这意味着作为Java开发人员,无论我们是否愿意,当我们拿到罚单时弄清楚这些调用堆栈的成本现在都落在我们肩上。

Java 8中JavaScript

Java 8引入了全新JavaScript编译器。 现在,我们终于可以以高效,直接的方式集成Java + JS。 但是,我们编写的代码与我们调试的代码之间的不协调之处比这里更大。

这与Nashorn中的功能相同–

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("nashorn");String js = "var map = Array.prototype.map \n";
js += "var a = map.call(names, function(name) { return Java.type(\"LmbdaMain\").check(name) }) \n";
js += "print(a)";
engine.eval(js);

在这种情况下,字节代码是在运行时使用Lambda表达式的嵌套树动态生成的 。 我们的源代码与由JVM执行的结果字节码之间几乎没有关联。 现在,调用堆栈要长两个数量级 。 用T先生的凄美的话语- 我可怜那些需要调试调用堆栈的傻瓜 ,您将到达这里。

有任何疑问吗? (假设您可以一直滚动到此调用堆栈下方)。 在评论部分让我知道。

LmbdaMain [Java Application]
LmbdaMain at localhost:51287
Thread [main] (Suspended (breakpoint at line 16 in LmbdaMain))
LmbdaMain.wrap(String) line: 16
1525037790.invokeStatic_L_I(Object, Object) line: not available
1150538133.invokeSpecial_LL_I(Object, Object, Object) line: not available
538592647.invoke_LL_I(MethodHandle, Object[]) line: not available
1076496284.invokeStatic_LL_L(Object, Object, Object) line: not available
LambdaForm$NamedFunction.invokeWithArguments(Object...) line: 1147
LambdaForm.interpretName(LambdaForm$Name, Object[]) line: 625
LambdaForm.interpretWithArguments(Object...) line: 604
2150540.interpret_I(MethodHandle, Object, Object) line: not available
538592647.invoke_LL_I(MethodHandle, Object[]) line: not available
1076496284.invokeStatic_LL_L(Object, Object, Object) line: not available
LambdaForm$NamedFunction.invokeWithArguments(Object...) line: 1147
LambdaForm.interpretName(LambdaForm$Name, Object[]) line: 625
LambdaForm.interpretWithArguments(Object...) line: 604
92150540.interpret_I(MethodHandle, Object, Object) line: not available
38592647.invoke_LL_I(MethodHandle, Object[]) line: not available
1076496284.invokeStatic_LL_L(Object, Object, Object) line: not available
LambdaForm$NamedFunction.invokeWithArguments(Object...) line: 1147
LambdaForm.interpretName(LambdaForm$Name, Object[]) line: 625
LambdaForm.interpretWithArguments(Object...) line: 604
731260860.interpret_L(MethodHandle, Object, Object) line: not available
LambdaForm$NamedFunction.invoke_LL_L(MethodHandle, Object[]) line: 1108
1076496284.invokeStatic_LL_L(Object, Object, Object) line: not available
LambdaForm$NamedFunction.invokeWithArguments(Object...) line: 1147
LambdaForm.interpretName(LambdaForm$Name, Object[]) line: 625
LambdaForm.interpretWithArguments(Object...) line: 604
2619171.interpret_L(MethodHandle, Object, Object, Object) line: not available
1597655940.invokeSpecial_LLLL_L(Object, Object, Object, Object, Object) line: not available
LambdaForm$NamedFunction.invoke_LLLL_L(MethodHandle, Object[]) line: 1118
1076496284.invokeStatic_LL_L(Object, Object, Object) line: not available
LambdaForm$NamedFunction.invokeWithArguments(Object...) line: 1147
LambdaForm.interpretName(LambdaForm$Name, Object[]) line: 625
LambdaForm.interpretWithArguments(Object...) line: 604
2619171.interpret_L(MethodHandle, Object, Object, Object) line: not available
1353530305.linkToCallSite(Object, Object, Object, Object) line: not available
Script$\^eval\_._L3(ScriptFunction, Object, Object) line: 3
1596000437.invokeStatic_LLL_L(Object, Object, Object, Object) line: not available
1597655940.invokeSpecial_LLLL_L(Object, Object, Object, Object, Object) line: not available
LambdaForm$NamedFunction.invoke_LLLL_L(MethodHandle, Object[]) line: 1118
1076496284.invokeStatic_LL_L(Object, Object, Object) line: not available
LambdaForm$NamedFunction.invokeWithArguments(Object...) line: 1147
LambdaForm.interpretName(LambdaForm$Name, Object[]) line: 625
LambdaForm.interpretWithArguments(Object...) line: 604
484673893.interpret_L(MethodHandle, Object, Object, Object, Object, Object) line: not available
LambdaForm$NamedFunction.invoke_LLLLL_L(MethodHandle, Object[]) line: 1123
1076496284.invokeStatic_LL_L(Object, Object, Object) line: not available
LambdaForm$NamedFunction.invokeWithArguments(Object...) line: 1147
LambdaForm.interpretName(LambdaForm$Name, Object[]) line: 625
LambdaForm.interpretWithArguments(Object...) line: 604
282496973.interpret_L(MethodHandle, Object, Object, Object, long, Object) line: not available
93508253.invokeSpecial_LLLLJL_L(Object, Object, Object, Object, Object, long, Object) line: not available
1850777594.invoke_LLLLJL_L(MethodHandle, Object[]) line: not available
1076496284.invokeStatic_LL_L(Object, Object, Object) line: not available
LambdaForm$NamedFunction.invokeWithArguments(Object...) line: 1147
LambdaForm.interpretName(LambdaForm$Name, Object[]) line: 625
LambdaForm.interpretWithArguments(Object...) line: 604
282496973.interpret_L(MethodHandle, Object, Object, Object, long, Object) line: not available
293508253.invokeSpecial_LLLLJL_L(Object, Object, Object, Object, Object, long, Object) line: not available
1850777594.invoke_LLLLJL_L(MethodHandle, Object[]) line: not available
1076496284.invokeStatic_LL_L(Object, Object, Object) line: not available
LambdaForm$NamedFunction.invokeWithArguments(Object...) line: 1147
LambdaForm.interpretName(LambdaForm$Name, Object[]) line: 625
LambdaForm.interpretWithArguments(Object...) line: 604
1840903588.interpret_L(MethodHandle, Object, Object, Object, Object, long, Object) line: not available
2063763486.reinvoke(Object, Object, Object, Object, Object, long, Object) line: not available
850777594.invoke_LLLLJL_L(MethodHandle, Object[]) line: not available
1076496284.invokeStatic_LL_L(Object, Object, Object) line: not available
LambdaForm$NamedFunction.invokeWithArguments(Object...) line: 1147
LambdaForm.interpretName(LambdaForm$Name, Object[]) line: 625
LambdaForm.interpretWithArguments(Object...) line: 604
82496973.interpret_L(MethodHandle, Object, Object, Object, long, Object) line: not available
220309324.invokeExact_MT(Object, Object, Object, Object, long, Object, Object) line: not available
NativeArray$10.forEach(Object, long) line: 1304
NativeArray$10(IteratorAction).apply() line: 124
NativeArray.map(Object, Object, Object) line: 1315
1596000437.invokeStatic_LLL_L(Object, Object, Object, Object) line: not available
504858437.invokeExact_MT(Object, Object, Object, Object, Object) line: not available
FinalScriptFunctionData(ScriptFunctionData).invoke(ScriptFunction, Object, Object...) line: 522
ScriptFunctionImpl(ScriptFunction).invoke(Object, Object...) line: 207
ScriptRuntime.apply(ScriptFunction, Object, Object...) line: 378
NativeFunction.call(Object, Object...) line: 161
1076496284.invokeStatic_LL_L(Object, Object, Object) line: not available
1740189450.invokeSpecial_LLL_L(Object, Object, Object, Object) line: not available
LambdaForm$NamedFunction.invoke_LLL_L(MethodHandle, Object[]) line: 1113
1076496284.invokeStatic_LL_L(Object, Object, Object) line: not available
LambdaForm$NamedFunction.invokeWithArguments(Object...) line: 1147
LambdaForm.interpretName(LambdaForm$Name, Object[]) line: 625
LambdaForm.interpretWithArguments(Object...) line: 604
2619171.interpret_L(MethodHandle, Object, Object, Object) line: not available
LambdaForm$NamedFunction.invoke_LLL_L(MethodHandle, Object[]) line: 1113
1076496284.invokeStatic_LL_L(Object, Object, Object) line: not available
LambdaForm$NamedFunction.invokeWithArguments(Object...) line: 1147
LambdaForm.interpretName(LambdaForm$Name, Object[]) line: 625
LambdaForm.interpretWithArguments(Object...) line: 604
323326911.interpret_L(MethodHandle, Object, Object, Object, Object) line: not available
LambdaForm$NamedFunction.invoke_LLLL_L(MethodHandle, Object[]) line: 1118
1076496284.invokeStatic_LL_L(Object, Object, Object) line: not available
LambdaForm$NamedFunction.invokeWithArguments(Object...) line: 1147
LambdaForm.interpretName(LambdaForm$Name, Object[]) line: 625
LambdaForm.interpretWithArguments(Object...) line: 604
323326911.interpret_L(MethodHandle, Object, Object, Object, Object) line: not available
263793464.invokeSpecial_LLLLL_L(Object, Object, Object, Object, Object, Object) line: not available
LambdaForm$NamedFunction.invoke_LLLLL_L(MethodHandle, Object[]) line: 1123
1076496284.invokeStatic_LL_L(Object, Object, Object) line: not available
LambdaForm$NamedFunction.invokeWithArguments(Object...) line: 1147
LambdaForm.interpretName(LambdaForm$Name, Object[]) line: 625
LambdaForm.interpretWithArguments(Object...) line: 604
1484673893.interpret_L(MethodHandle, Object, Object, Object, Object, Object) line: not available
587003819.invokeSpecial_LLLLLL_L(Object, Object, Object, Object, Object, Object, Object) line: not available
811301908.invoke_LLLLLL_L(MethodHandle, Object[]) line: not available
1076496284.invokeStatic_LL_L(Object, Object, Object) line: not available
LambdaForm$NamedFunction.invokeWithArguments(Object...) line: 1147
LambdaForm.interpretName(LambdaForm$Name, Object[]) line: 625
LambdaForm.interpretWithArguments(Object...) line: 604
484673893.interpret_L(MethodHandle, Object, Object, Object, Object, Object) line: not available
LambdaForm$NamedFunction.invoke_LLLLL_L(MethodHandle, Object[]) line: 1123
1076496284.invokeStatic_LL_L(Object, Object, Object) line: not available
LambdaForm$NamedFunction.invokeWithArguments(Object...) line: 1147
LambdaForm.interpretName(LambdaForm$Name, Object[]) line: 625
LambdaForm.interpretWithArguments(Object...) line: 604
323326911.interpret_L(MethodHandle, Object, Object, Object, Object) line: not available
2129144075.linkToCallSite(Object, Object, Object, Object, Object) line: not available
Script$\^eval\_.runScript(ScriptFunction, Object) line: 3
1076496284.invokeStatic_LL_L(Object, Object, Object) line: not available
1709804316.invokeExact_MT(Object, Object, Object, Object) line: not available
FinalScriptFunctionData(ScriptFunctionData).invoke(ScriptFunction, Object, Object...) line: 498
ScriptFunctionImpl(ScriptFunction).invoke(Object, Object...) line: 207
ScriptRuntime.apply(ScriptFunction, Object, Object...) line: 378
NashornScriptEngine.evalImpl(ScriptFunction, ScriptContext, ScriptObject) line: 544
NashornScriptEngine.evalImpl(ScriptFunction, ScriptContext) line: 526
NashornScriptEngine.evalImpl(Source, ScriptContext) line: 522
NashornScriptEngine.eval(String, ScriptContext) line: 193
NashornScriptEngine(AbstractScriptEngine).eval(String) line: 264
LmbdaMain.main(String[]) line: 44

翻译自: https://www.javacodegeeks.com/2014/03/the-dark-side-of-lambda-expressions-in-java-8.html

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

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

相关文章

复旦大学长跑协会财务制度(初稿)

(一)活动资金来源及主要支出 1、资金主要来源:会费、学校的拨款,私人捐助、企业赞助等。 2、活动性支出:活动宣传、场地租用费、租借多媒体仪器费用及活动经费。事物性支出:协会运作所需物资(如文具等硬件)。 (二)财务报销原则 1、…

JQ实现弹幕效果

JQ实现弹幕效果&#xff0c;快来吐糟你的想法吧 效果图&#xff1a; 代码如下&#xff0c;复制即可使用&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8" /><title>JQ实现弹幕效果</title><style type"t…

Iterator作用

前言 下面的内容是我从百度知道拷贝出来的&#xff0c;也就不在贴出链接了。我总结下就是迭代器在集合中使用&#xff0c;用户不需要关心具体集合实现的是如何遍历&#xff08;不暴露细节&#xff09;&#xff0c;按照迭代器的方式遍历。 作用 Iterator模式是用于遍历集合类的标…

Django:URL映射

导航 跳转&#xff1a;视图简介 跳转&#xff1a;URL映射 跳转&#xff1a;一、URL中添加参数 跳转&#xff1a;二、指定默认的参数 跳转&#xff1a;三、URL中包含另一个urls模块 跳转&#xff1a;  include函数 跳转&#xff1a;四、path函数 跳转&#xff1a;  自定义ur…

php-v 查看不到版本,解決php -v查看到版本於phpinfo()打印的版本不一致問題

整個事件的起因是這樣的通過git拉取laraevl項目發現缺少.env文件&#xff0c;打算使用composer install生成一個.env文件&#xff0c;然后提示composer最低使用php版本7.1.3而檢測到我的版本為5.4.16。提示如下&#xff1a;然后使用phpinfo打印一下發現版本是7.2.6。打印結果如…

将jOOQ与Spring结合使用:排序和分页

JOOQ是一个库&#xff0c;可以帮助我们控制SQL。 它可以从我们的数据库生成代码&#xff0c;并允许我们使用其流畅的API来构建类型安全的数据库查询。 本教程前面的部分向我们介绍了如何配置应用程序的应用程序上下文&#xff0c;如何从数据库生成代码以及如何将CRUD操作添加到…

获取表的所有列名

selectname fromsyscolumns whereidobject_id(表名)下面这样也可以:selectcolumn_name frominformation_schema.columns wheretable_name news转载于:https://www.cnblogs.com/zhuboxingzbx/archive/2007/09/03/880049.html

天下武功唯快不破------实验吧

题目地址&#xff1a;http://www.shiyanbar.com/ctf/1854 打开链接 全是英文&#xff0c;能力有限&#xff0c;翻译一下&#xff0c;好像没其他东西了&#xff0c;查看一下源码 让用post请求&#xff0c;丢到burp改一下 看到response有一个FLAG: UDBTVF9USElTX1QwX0NINE5HRV9GT…

JS实现文本中查找并替换字符

JS实现文本中查找并替换字符 效果图&#xff1a; 代码如下&#xff0c;复制即可使用&#xff1a; <!DOCTYPE html><html> <head><style type"text/css">*{font-family:"微软雅黑";font-size:16px;margin:0;padding:0;letter-spaci…

数据依赖的公理系统

ArmStrong公理系统 学习数据依赖的公理系统是进行模式分解的算法的理论基础。而Armstrong公理系统是一个具有有效性和完备性的公理系统。 U是属性总体&#xff0c;F是函数依赖&#xff0c;对于R<U,F>推理规则如下&#xff1a; A1 自反律 &#xff1a;若Y⊆X⊆U&#xff0…

在没有IDE的情况下编译和运行Java

最近一个名为“ 不使用IDE编译Java软件包 ”的Java subreddit线程提出了一个问题&#xff1a;“是否有一个命令将软件包内的一组Java文件编译到一个单独的文件夹中&#xff08;以下简称为bin&#xff09;&#xff0c;以及如何我会去运行新的类文件吗&#xff1f;” 该帖子的作者…

java statement 返回类型,6.3 返回类型和返回语句 | Return type Return statement

无返回值函数对于返回类型是void的函数&#xff0c;return后不跟表达式。最后的 return; 可以没有而让程序隐式执行。在void函数中的return语句还有提前使函数退出的作用而不进行接下来的计算&#xff0c;如定义一个swap函数在二者相同时不继续运算直接退出&#xff1a;void sw…

异步调用 (转载)

异步操作通常用于执行完成时间可能较长的任务&#xff0c;如打开大文件、连接远程计算机或查询数据库。异步操作在主应用程序线程以外的线程中执行。应用程序调用方法异步执行某个操作时&#xff0c;应用程序可在异步方法执行其任务时继续执行。.NET框架能够对任何方法进行异步…

《Effective Java》读书笔记 Item 1:考虑静态工厂方法,而不是构造器

众所周知&#xff0c;要想能获取一个类的实例&#xff0c;该类得要提供一个public的构造器。但是《Effective Java》书中说还有一个方法&#xff0c;那就是提供静态工厂方法&#xff08;static factory method&#xff09;&#xff0c;该方法时静态&#xff0c;同时可以根据参数…

[转]MySQL 表锁和行锁机制

本文转自&#xff1a;http://www.cnblogs.com/itdragon/p/8194622.html MySQL 表锁和行锁机制 行锁变表锁&#xff0c;是福还是坑&#xff1f;如果你不清楚MySQL加锁的原理&#xff0c;你会被它整的很惨&#xff01;不知坑在何方&#xff1f;没事&#xff0c;我来给你们标记几个…

使用JS实现文字搬运工

使用JS实现文字搬运工 效果图&#xff1a; 代码如下&#xff0c;复制即可使用&#xff1a; <!DOCTYPE html> <html><head><meta http-equiv"Content-Type" content"text/html; charsetUTF-8"> <title>使用JS实现文字搬运工&…

ActiveMQ –经纪人网络解释–第3部分

现在&#xff0c;我们已经在本博客系列的第1部分和第2 部分中了解了ActiveMQ网络连接器的基础&#xff0c;在第3部分中&#xff0c;我们将研究ActiveMQ如何平衡连接到代理网络的使用者。 介绍 当可以无序处理队列中的消息时通常使用并发使用者&#xff0c;通常可以提高消息吞吐…

PJMEDIA之录音器的使用(capture sound to avi file)

为了熟悉pjmedia的相关函数以及使用方法&#xff0c;这里练习了官网上的一个录音器的例子。 核心函数&#xff1a; pj_status_t pjmedia_wav_writer_port_create(pj_pool_t * pool, const char * filename, unsigned clock_rate, unsigned channel_count, unsigned samples…

2007年暑期总结

又是一个没有回家的假期&#xff0c;一个月的鸡蛋炒拉面&#xff0c;一个月沉浸在编程的世界里……收获早已超越了技术本身&#xff0c;项目的实践&#xff0c;系统的架构&#xff0c;……更多的&#xff0c;是朋友们在一起的乐趣。A5闹鬼记&#xff0c;回去洗洗就睡了&#xf…

Linux下用户组、文件权限详解=------转载文

转载自-----原文地址&#xff1a; https://www.cnblogs.com/123-/p/4189072.html Linux下用户组、文件权限详解 用户组 在linux中的每个用户必须属于一个组&#xff0c;不能独立于组外。在linux中每个文件有所有者、所在组、其它组的概念 - 所有者 - 所在组 - 其它组 - 改变用…