目录 start
目录 end
|2018-06-21| 码云 | CSDN | OSChina
.class
文件定义了JVM中的类型,包括了域,方法,继承信息,注解和其他元数据[类装载器、双亲委托模型、命名空间、安全性](https://blog.csdn.net/yuan22003/article/details/6839335) java ClassLoader类解析-双亲委托机制
连接
所以一个类的定义就会有一个Class对象, 但是这个对象的类型呢?怎么判断, Class对象的类型就是他的值么?
主要用于反射 用到再学
JDK内置命令, 用来探视类文件内部和反编译class文件
常量池是为类文件中的其他常量元素提供快捷访问方式的区域。对于JVM来说常量池相当于符号表 参考博客
字节码是程序的中间表达形式,源码和机器码之间的产物
字节码是由源文件执行javac产生的
某些高级语言特性(语法糖)在字节码中给去掉了,例如循环结构,会转换成为分支指令
每个操作都由一个字节表示,因此叫做字节码
字节码是一种抽象表示方法
字节码进一步编译得到机器码
javap -c -p class文件
反编译字节码文件,-p 能看到私有属性
因为JVM没有CPU那样的寄存器,所以是采用的堆栈来计算的,称为操作数栈或者计算堆栈
[ ] 下面的内容需要继续阅读Java7程序员修炼之道
这个特性是针对 框架开发和非Java语言准备的
码农翻身:序列化: 一个老家伙的咸鱼翻身
对象转化为二进制流
简单的说就是类的版本控制, 标明类序列化时的版本, 版本一致表明这两个类定义一致
在进行反序列化时, JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。(InvalidCastException)
参考博客
当你一个类实现了Serializable接口,如果没有定义serialVersionUID,Eclipse会提供这个提示功能告诉你去定义 。 在Eclipse中点击类中warning的图标一下,Eclipse就会自动给定两种生成的方式。 如果不想定义它,在Eclipse的设置中也可以把它关掉的,设置如下: Window ==> Preferences ==> Java ==> Compiler ==> Error/Warnings ==>Potential programming problems 将Serializable class without serialVersionUID的warning改成ignore即可。
因为Java序列化的性能和存储开销都表现不好,而且不能跨语言, 所以一般不使用Java的序列化而是使用以下流行的库
Google开源的库 全称
Google Protocol Buffers
| Github : Protobuf
参考博客: Protobuf语言指南
较为详细, 只是版本有点旧
参考博客: 详解如何在NodeJS中使用Google的Protobuf | protocobuf Google 开源技术protobuf Google Protocol Buffer 的使用和原理
packageName.MessageName.proto
只是编解码的工具, 不支持读半包, 粘包拆包
// 用户数据信息
message Article {
required int32 articleId = 1; // 文章id
optinal string articleExcerpt = 4; // 文章摘要
repeated string articlePicture = 5; // 文章附图
}
上面定义了一个消息, 消息具有三个属性, 且行末的注释都会变成Javadoc注释
复杂类型
定义了enum枚举类型,嵌套的消息。甚至对原有的消息进行了扩展,也可以对字段设置默认值。添加注释等
package "com.github.kuangcp";
message Article {
required int32 article_id = 1;
optional string article_excerpt = 2;
repeated string article_picture = 3;
optional int32 article_pagecount = 4 [default = 0];
enum ArticleType {
NOVEL = 0;
PROSE = 1;
PAPER = 2;
POETRY = 3;
}
optional ArticleType article_type = 5 [default = NOVEL];
message Author {
required string name = 1; //作者的名字
optional string phone = 2;
}
optional Author author = 6;
repeated int32 article_numberofwords = 7 [packed=true];
reserved 9, 10, 12 to 15;
extensions 100 to 1000;
}
extend Article {
optional int32 followers_count = 101;
optional int32 likes_count= 102;
}
message Other {
optional string other_info = 1;
oneof test_oneof {
string code1 = 2;
string code2 = 3;
}
}
此外reserved关键字主要用于保留相关编号标签,主要是防止在更新proto文件删除了某些字段,而未来的使用者定义新的字段时重新使用了该编号标签。这会引起一些问题在获取老版本的消息时,譬如数据冲突,隐藏的一些bug等。所以一定要用reserved标记这些编号标签以保证不会被使用
当我们需要对消息进行扩展的时候,我们可以用extensions关键字来定义一些编号标签供第三方扩展。这样的好处是不需要修改原来的消息格式。就像上面proto文件,我们用extend关键字来扩展。只要扩展的字段编号标签在extensions定义的范围里。
对于基本数值类型,由于历史原因,不能被protobuf更有效的encode。所以在新的代码中使用packed=true可以更加有效率的encode。注意packed只能用于repeated 数值类型的字段。不能用于string类型的字段。
在消息Other中我们看到定义了一个oneof关键字。这个关键字作用比较有意思。当你设置了oneof里某个成员值时,它会自动清除掉oneof里的其他成员,也就是说同一时刻oneof里只有一个成员有效。这常用于你有许多optional字段时但同一时刻只能使用其中一个,就可以用oneof来加强这种效果。但需要注意的是oneof里的字段不能用required,optional,repeted关键字
导入另一个proto定义
import "article.proto";
- 使用上, 因为有多个消息类型, 那么会采用一个数值id作为code, 进行对应 方便沟通
只是安装2.5版本 参考博客: linux下Google的Protobuf安装及使用笔记 | 参考:proto buffer 安装 及 调用
./configure
make
然后 make check
然后 sudo make install
protoc --version
有版本则安装成功注意: ./configure 时, 默认会安装在/usr/local目录下,可以加
--prefix=/usr
来指定安装到/usr/lib下如果不加, 上述参数就要执行
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
当然,可以将这个环境变量的设置加在 .zshrc 或者 .bashrc 里
不然就会报错:protoc: error while loading shared libraries: libprotobuf.so.8: cannot open shared object file: No such file or directory
Google Protocol Buffer 的使用和原理
C++ 但是原理差不多
生成Java文件
touch hi.proto
package lm;
message helloworld{
required int32 id = 1;//ID
required string str = 2;//str
optional int32 opt = 3;//optional field
}
mkdir src && protoc --java_out=./src hi.proto
也可以使用该脚本更新协议 # proto文件中明确定义了一样的包结构就可以直接跑脚本
basePath='minigame/proto/proto'
targetPath='ssss'
rm -rf $targetPath \
&& mkdir $targetPath \
&& protoc $basePath/*.proto --java_out=$targetPath \
使用
// 实例化一个构建器
helloworld.Builder msg = helloworld.newBuilder();
// 填充信息
msg.setId(12);
源于Facebook, 支持多种语言: C++ C# Cocoa Erlang Haskell Java Ocami Perl PHP Python Ruby Smalltalk
JBOSS 内部使用的编解码框架