diff --git a/2016/11/database-books/index.html b/2016/11/database-books/index.html new file mode 100644 index 00000000..f5f33d3b --- /dev/null +++ b/2016/11/database-books/index.html @@ -0,0 +1,671 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 数据库书籍资料整理 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ 数据库书籍资料整理 +

+ + +
+ + + + +
+ + +

本文整理一些经典的数据库教材以及MySQL相关书籍。

+ +

http://en.wikipedia.org/wiki/Database
+http://en.wikipedia.org/wiki/Template:Databases
+http://en.wikipedia.org/wiki/Template:SQL

+

Ask HN: Help me find a good databases textbook https://news.ycombinator.com/item?id=377669
+Database Internals - Where to Begin? http://stackoverflow.com/q/770273
+Ask HN: good book or resources to get my SQL skills to the next level https://news.ycombinator.com/item?id=1370721
+Ask HN: Is there a K&R for SQL? https://news.ycombinator.com/item?id=5087439
+Tips for getting started with SQL? http://stackoverflow.com/q/110124

+

教材原理类书籍

+
    +
  1. 1986-2010,Silberschatz,《数据库系统概念》(Database System Concepts, 1st 1986, 6th 2010),home豆瓣:对数据库理论、概念有很清晰地介绍
  2. +
  3. 1996、1999、2002,Ramakrishnan & Gehrke,《数据库管理系统:原理与设计 Cow Book》(Database Management Systems, 3rd 2002),home豆瓣:第1作者2006年-2012年为Yahoo首席科学家,2012年跳槽到微软,该书为伯克利CS186、MIT、CMU教材
  4. +
  5. 2006、2010,Elmasri & Navathe,《数据库系统基础》(Fundamentals of Database Systems, 6th 2010),图灵2007,第6版豆瓣
  6. +
  7. 2005,Hellerstein & Stonebraker,"Readings in Database Systems", 3th 1998, 4th 2005,MITpresshome:被称为“Red Book”,经典论文收录集,第1作者是Berkeley Database Group的leader,第2作者是Ingres之父,Hellerstein的博士导师之一
  8. +
  9. 1975-2003,C. J. Date
    +,《数据库系统导论》(An Introduction to Database Systems, 2nd 1977, 8th
    +2003),豆瓣:作者曾在IBM工作,该书是最早的数据库教材
  10. +
  11. 1999、2008,Garcia-Molina & Ullman & Widom,《数据库系统全书 DSCB》(Database Systems: The Complete Book, 2nd 2008),home豆瓣:内容偏向介绍数据库的底层实现原理,三位作者来自Stanford,并且均获得Codd奖,获奖年份依次为1999年、2006年、2007年
  12. +
  13. 1992,Jim Gray,《事务处理:概念与技术》(Transaction Processing: Concepts and Techniques, amazon):介绍事务经典之作,不过略微过时。作者1998年图灵奖,1993年第2届Codd奖得主
  14. +
  15. 1997、2009,Bernstein & Newcomer,《事务处理原理》(Principles of Transaction Processing, 2nd 2009),豆瓣:目前最新、全面的书籍。作者来自Microsoft研究院,1994年第3届Codd奖得主
  16. +
  17. 1999、2011,M. Tamer Ozsu,《分布式数据库系统原理》(Principles of Distributed Database Systems, 3rd 2011),豆瓣
  18. +
+

SQL相关书籍

+
    +
  1. 2010,《SQL反模式》(SQL Antipatterns),豆瓣
  2. +
  3. 2009,《SQL学习指南》(Learning SQL),豆瓣
  4. +
  5. 1999-2008,《SQL技术手册》(SQL in a Nutshell, 2nd 2004, 3rd 2008),豆瓣:根据SQL2003 ANSI标准,同时涵盖MySQL、Oracle、PostgreSQL及SQL Server
  6. +
  7. 1995-2010,Joe Celko,《SQL权威指南》(Joe Celko's SQL for Smarties: Advanced SQL Programming, 1st 1995, 4th 2010),图灵2012豆瓣:全书652页,作者曾担任ANSl SQL标准委员会成员达10年之久,参与了SQL-89和SQL-92标准的制定
  8. +
  9. 2005,Joe Celko,《SQL编程风格》(Joe Celko's SQL Programming Style, amazon,图灵2008豆瓣
  10. +
  11. 1996、2002,Joe Celko,《SQL解惑》(Joe Celko's SQL Puzzles and Answers, 2nd 2002),图灵2008
  12. +
  13. 2005,Ben Forta,《MySQL必知必会》(MySQL Crash Course),home豆瓣
  14. +
+

MySQL书籍

+

http://en.wikipedia.org/wiki/Template:MySQL
+https://github.com/shlomi-noach/awesome-mysql
+http://en.wikipedia.org/wiki/Database_engine
+2014-01 Any recommended MySQL books for more advanced stuff? (self.mysql) http://redd.it/292u19
+What resources exist for Database performance-tuning? http://stackoverflow.com/q/761204
+2010-12 12 Best MySQL Database Books for Your Library http://www.thegeekstuff.com/2010/12/12-best-mysql-books/

+

MySQL管理

+
    +
  1. 2008、2013,《深入浅出MySQL数据库:开发优化与管理维护》,豆瓣:作者来自网易DBA小组
  2. +
  3. 2005、2008,《MySQL核心技术手册》(MySQL in a Nutshell, 2nd 2008),豆瓣:作者MySQL公司知识库编辑
  4. +
  5. 1999-2013,Paul DuBois,《MySQL技术内幕》(MySQL: Developer's Library, 2nd 2003, 5th 2013),第4版2008豆瓣,第5版豆瓣:全书886页,作者是“MySQL参考手册”(MySQL Reference Manual)的主要贡献者之一,其他书“MySQL Cookbook”(豆瓣
  6. +
  7. 2002、2007、2014,Paul DuBois,《MySQL Cookbook 中文版》,3rd 2014,第2版豆瓣:全书948页
  8. +
+

MySQL调优

+
    +
  1. 2011,《Effective MySQL之SQL语句最优化》(Effective MySQL Optimizing SQL Statements, amazon),豆瓣
  2. +
  3. 2009,简朝阳,《MySQL性能调优与架构设计》,豆瓣:作者目前就职于阿里巴巴
  4. +
  5. 2012,Sevta Smirnova,《MySQL排错指南》(MySQL Troubleshooting),豆瓣:Oracle公司MySQL部门bug分析支持团队的首席技术支持工程师
  6. +
  7. 2014,李海翔,《数据库查询优化器的艺术》,豆瓣:作者现任职于Oracle公司MySQL全球开发团队,从事查询优化技术的研究和MySQL查询优化器的开发工作
  8. +
  9. 2014,贺春旸,《Mysql管理之道:性能调优、高可用与监控》,豆瓣
  10. +
  11. 2004、2008、2012,Schwartz & Zaitsev & Tkachenko,《高性能MySQL:优化,备份,复制》(High Performance MySQL, 3rd 2012),home豆瓣:深入MySQL类top1书籍,第2作者和第3作者来自MySQL AB公司高性能开发组,2006年创办Percona公司
  12. +
  13. 2010,Charles Bell & Kindahl & Thalmann,《高可用MySQL:构建健壮的数据中心》(MySQL High Availability, amazon),豆瓣,第2版豆瓣:3位作者全部来自MySQL复制和备份小组,是复制、备份方面的开发人员及专家
  14. +
+

MySQL源码架构

+
    +
  1. 2010、2013,姜承尧,《MySQL技术内幕:InnoDB》,第2版豆瓣:2011至今,网易杭州研究院,数据库技术组 技术经理
  2. +
  3. 2007、2012,Charles Bell,《深入理解MySQL》(Expert MySQL, 2nd 2012),图灵2009豆瓣:全书466页,MySQL源代码分析,作者是MySQL核心开发人员
  4. +
  5. 2007,Sasha Pachev,《深入理解MySQL核心技术》(Understanding MySQL Internals, amazon),豆瓣:全书246页,纯粹的MySQL源代码分析,作者是前MysQL开发团队成员
  6. +
+ +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2016/11/java-books/index.html b/2016/11/java-books/index.html new file mode 100644 index 00000000..5936341c --- /dev/null +++ b/2016/11/java-books/index.html @@ -0,0 +1,673 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Java书籍资料整理 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ Java书籍资料整理 +

+ + +
+ + + + +
+ + +

https://en.wikipedia.org/wiki/Template:Java_(software_platform)
+http://c2.com/cgi/wiki?JavaIdioms
+http://c2.com/cgi/wiki?JavaDesignFlaws Java语言设计缺陷

+
    +
  1. 2011-06 Java Books Reading Order http://stackoverflow.com/q/6341593
  2. +
  3. 2009-03 Java书籍Top 10 http://coolshell.cn/articles/14.html
  4. +
  5. 2012-03 JVM程序员的阅读清单 http://blog.jobbole.com/15342/
  6. +
+ +
+

Java官方文档与书籍

+

http://docs.oracle.com/javase/8/
+http://docs.oracle.com/javase/tutorial/

+

Java Language and Virtual Machine Specifications http://docs.oracle.com/javase/specs/

+

Sun官方Addison-Wesley出版的Java Series,link

+
    +
  1. 1996-2014,Gosling, Joy, Steele, Bracha,《Java语言规范》(The Java Language Specification, 2nd 2000, 3rd 2005, Java SE 8 2014),Java 7 online,第3版豆瓣,Java 8中文豆瓣
  2. +
  3. 1996-2013,Lindholm, Yellin, Bracha, etc,《Java虚拟机规范》(The Java Virtual Machine Specification, 1st 1996, 2nd 1999, Java SE 7 2013, Java SE 8 2014),Java 7 online豆瓣
  4. +
  5. 1996-2005,Arnold, Gosling, etc,《Java程序设计语言》(The Java Programming Language, 1st 1996,2nd 1997,4th 2005),第4版豆瓣:涵盖J2SE 5.0,内容比《Java编程思想》精简,条理更清晰,覆盖面更广
  6. +
  7. 1998-2013,《Java教程》(The Java Tutorial: A Short Course on the Basics, 2nd 1998, 3rd 2001, 4th 2006, 5th 2013),第4版豆瓣:全书415页,涵盖Java 5.0和6.0,内容比《Java程序设计语言》简单,是官方在线指定文档
  8. +
  9. 1997,《Java经典问答》(The Java Faq, 1997),豆瓣
  10. +
  11. 1997.06,《Java语言编码规范》(Code Conventions for the Java Programming Language),oracle.com html, pdf
  12. +
+
+

Java书籍

+
    +
  1. 1998-2006,Bruce Eckel,《Java编程思想》(Thinking in Java, 1st 1998, 4th 2006),home豆瓣:内容有深度,但组织混乱,抓不住脉络,杂糅了Java与C++比较、设计模式等内容,2003年Jolt震撼大奖
  2. +
  3. 1996-2012,Cay S. Horstmann,《Java核心技术,2卷》(Core Java 2, 1st 1996, 8th 2007, 9th 2012),home,第10版卷1豆瓣、卷2豆瓣
  4. +
  5. 2001、2008,Joshua Bloch,《Effective Java》,2nd 2008,豆瓣:2002年Jolt震撼大奖
  6. +
  7. 2005,Joshua Bloch & Neal Gafter,《Java解惑》(Java Puzzlers: Traps, Pitfalls, and Corner Cases, amazon),home图灵2010豆瓣
  8. +
  9. Java语言精粹 Java: The Good Parts http://book.douban.com/subject/6516576/
  10. +
  11. 2006,Metsker,《Java设计模式》(Design Patterns in Java, amazon),豆瓣,修订版豆瓣
  12. +
  13. Herbert Schildt,《Java完全参考手册》(Java: The Complete Reference, 8th 2011),第8版豆瓣,第9版豆瓣:Oracle Press,全书1105页,参考手册,可读性不高,涵盖Java 7
  14. +
  15. Herbert Schildt,《Java编程入门教程》(Java: A Beginner's Guide),第6版豆瓣
  16. +
  17. 2012,Sarang,《Java 7编程高级进阶》(Java Programming, amazon),豆瓣:Oracle Press,内容条理清晰,但深度、广度不够,Java虚拟机技术总监Pampuch作序,客户端软件的首席架构师Coward技术校审
  18. +
  19. Jakarta Commons Cookbook中文版 https://book.douban.com/subject/1936665/
  20. +
+

https://github.com/iluwatar/java-design-patterns

+

Java并发编程

+
    +
  1. 2006,Goetz, Peierls, Joshua Bloch, Doug Lea & etc,《Java并发编程实战》(Java Concurrency in Practice, amazon),豆瓣:top1书籍,Sun官方书籍,相对偏向理论的并发编程书籍见“多处理器编程的艺术,修订版2012”
  2. +
  3. 2011,Subramaniam,《Java虚拟机并发编程》(Programming Concurrency on the JVM, amazon),豆瓣:全书216页,主要讲Scala下的Akka
  4. +
  5. 1999,Doug Lea,《Java并发编程:设计原则与模式》(Concurrent Programming in Java, 2nd 1999),豆瓣:过时
  6. +
  7. 2012,[西] González,《Java 7并发编程实战手册》(Java 7 Concurrency Cookbook, amazon),豆瓣:amazon评价不高,可作辅助阅读,难度低于Goetz版
  8. +
+

2012-12 Review : Java 7 Concurrency Cookbook,原文:mkyong.com,译文:importnew.com

+

Java高级内容(Java 7 & Java 8)

+
    +
  1. 2012,Evans & Verburg,《Java程序员修炼之道》(The Well-Grounded Java Developer, amazon),图灵2013豆瓣:全面解读Groovy、Scala在JVM上的应用
  2. +
  3. 2014,《Java 8实战》(Java 8 in Action, amazon),豆瓣
  4. +
  5. 2014,Horstmann,《写给大忙人看的Java SE 8》(Java SE 8 for the Really Impatient, amazon),豆瓣:极好的全面介绍Java 8
  6. +
  7. 2014,《Java 8函数式编程》(Java 8 Lambdas, amazon),豆瓣
  8. +
  9. 2014,Subramaniam,“Functional Programming in Java”, amazon豆瓣
  10. +
+

Java虚拟机与底层书籍

+
    +
  1. 2014,Scott Oaks,《Java性能权威指南》(Java Performance: The Definitive Guide),豆瓣
  2. +
  3. 2011,Charlie Hunt, Binu John,《Java性能优化权威指南》(Java Performance, amazon),豆瓣:第1作者是Oracle JVM性能主管工程师
  4. +
  5. 2000,Bill Venners,《深入Java虚拟机》(Inside the Java Virtual Machine, 2nd 2000),豆瓣
  6. +
  7. 2011、2013,周志明,《深入理解Java虚拟机:VM高级特性与最佳实践》,豆瓣:相比较陈涛版更偏向概念和理论
  8. +
  9. 2014,陈涛,《HotSpot实战》,豆瓣:内容有大量的HotSpot源码解析
  10. +
  11. 2015,高翔龙,《Java虚拟机精讲》,豆瓣
  12. +
  13. 2014,《大规模Java平台虚拟化与调优》
  14. +
  15. Scott Oaks, Java Performance: The Definitive Guide,豆瓣
  16. +
  17. 2015,OpenJDK cookbook,amazon
  18. +
+
+

偏向Java EE

+
    +
  1. 2004,Bruce Tate,《轻快的Java》(Better, Faster, Lighter Java, O'Reilly, amazon),豆瓣:2005年Jolt震撼大奖
  2. +
  3. 2005,Bruce Tate,《超越Java:探讨程序语言的未来》(Beyond Java, O'Reilly, amazon),豆瓣
  4. +
  5. 2010,Bruce Tate,《七周七语言:理解多种编程范型》(Seven Languages in Seven Weeks, Pragmatic, amazon),豆瓣:2011年Jolt生产力大奖
  6. +
+ +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2016/11/java-official-doc/index.html b/2016/11/java-official-doc/index.html new file mode 100644 index 00000000..e4fcfcdf --- /dev/null +++ b/2016/11/java-official-doc/index.html @@ -0,0 +1,674 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Java 官方文档整理 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ Java 官方文档整理 +

+ + +
+ + + + +
+ + +

本文整理一些学习Java需要翻阅或必须的官方文档资料。

+ +

Java SE文档

+

Java SE Technologies at a Glance http://www.oracle.com/technetwork/java/javase/tech/index.html

+

http://docs.oracle.com/javase/8/
+http://docs.oracle.com/javase/8/docs/index.html Platform Overview平台概览图
+http://docs.oracle.com/javase/8/javase-books.htm

+

Java Platform Overview (docs/technotes/guides)

+
    +
  1. Java Programming Language (guides/language)
  2. +
  3. Java Virtual Machine Technology (guides/vm)
  4. +
  5. JDK Tools and Utilities (technotes/tools)
  6. +
+

Java SE API:

+
    +
  1. Base Libraries (guides/#base):
  2. +
+ +
    +
  1. Integration Libraries (guides/#integration): IDL (CORBA, org.omg.*), JDBC (java.sql & javax.sql), RMI (java.rmi), RMI-IIOP (org.omg.*) JNDI (javax.naming), Scripting (javax.script)
  2. +
  3. User Interface Libraries (guides/#userinterface): Swing, Java 2D, AWT, Accessibility, Drag and Drop, Input Methods, Image I/O, Print Service, Sound
  4. +
+

http://docs.oracle.com/javase/8/docs/technotes/guides/scripting/

+

中文API文档:
+http://download.oracle.com/technetwork/java/javase/6/docs/zh/api/
+http://www.cjsdn.net/Doc/JDK60/

+
+

Java虚拟机

+

https://en.wikipedia.org/wiki/Template:Java_Virtual_Machine
+https://en.wikipedia.org/wiki/Java_performance

+

JDK源码
+https://github.com/dmlloyd/openjdk
+https://github.com/openjdk-mirror/jdk7u-jdk
+https://github.com/openjdk-mirror/jdk7u-hotspot

+

虚拟机与性能
+http://en.wikipedia.org/wiki/Template:Java_%28software_platform%29
+http://en.wikipedia.org/wiki/Template:Java_Virtual_Machine
+http://en.wikipedia.org/wiki/Java_performance
+http://openjdk.java.net/groups/hotspot/

+

Java SE HotSpot at a Glancelink

+
    +
  1. HotSpot Engine Architecture,link
  2. +
  3. HotSpot Thread Implementation (Solaris),link
  4. +
  5. HotSpot Garbage Collection,link
  6. +
+
    +
  • Memory Management Whitepaper[pdf]link:最权威、最完整文档
  • +
  • Garbage Collector Ergonomics,link
  • +
  • Garbage Collection Tuning,link
  • +
  • Garbage First ("G1") Garbage Collector,link
  • +
+
    +
  1. HotSpot Ergonomics,link
  2. +
  3. HotSpot Performance and Tuning,link
  4. +
+
    +
  • 2007.10, Java SE 6.0 Performance White Paper,link
  • +
  • 2005.03, J2SE 5.0 Performance White Paper,link
  • +
+
    +
  1. HotSpot Publications,link
  2. +
+

Troubleshooting Java SE 8,link 资料汇总

+
    +
  1. Java Troubleshooting Guide Java SE 8,link
  2. +
  3. Troubleshooting Guide for Java SE 6 with HotSpot VM,link
  4. +
  5. Troubleshooting Guide for HotSpot VM (JDK 7),link
  6. +
+ +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2016/11/lang-and-compiler-books/index.html b/2016/11/lang-and-compiler-books/index.html new file mode 100644 index 00000000..43097ac3 --- /dev/null +++ b/2016/11/lang-and-compiler-books/index.html @@ -0,0 +1,637 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 编程语言与编译器书籍资料整理 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ 编程语言与编译器书籍资料整理 +

+ + +
+ + + + +
+ + +

本文整理编程语言与编译器相关的经典书籍。

+ +

https://zh.wikipedia.org/wiki/Template:程序设计语言
+https://en.wikipedia.org/wiki/Template:IPC
+https://en.wikipedia.org/wiki/Programming_language#Further_reading

+

Language Books/Tutorials for popular languages http://stackoverflow.com/q/22873

+

编程语言、程序分析相关书籍:

+
    +
  1. 1999、2005、2009,Michael L. Scott,《程序设计语言:实践之路》(Programming Language Pragmatics, 1st 1999, 3rd 2009),home,第3版豆瓣:全书800多页,内容优于Sebesta版,有16页参考文献,涵盖程序语言、编译原理、计算机体系结构等多个子学科
  2. +
  3. 1993-2012,Robert W. Sebesta,《程序设计语言概念》(Concepts of Programming Languages, 10th 2012, 11th 2015),第10版豆瓣:全书600页左右,内容编程语言发展历史概述,以及分别介绍、比较
  4. +
  5. 2002、2004,Benjamin C. Pierce,《类型和程序设计语言》(Types and Programming Languages, amazon),home豆瓣
  6. +
  7. 1993,Glynn Winskel,《程序设计语言的形式语义》(The Formal Semantics of Programming Languages, amazon),豆瓣
  8. +
  9. 2002,John Mitchell,《程序设计语言概念》(Concepts in Programming Languages),home豆瓣:作者来自Stanford,courses,内容主要讲Lisp及其他
  10. +
  11. 1996,John Mitchell,《程序设计语言理论基础》(Foundations for Programming Languages),豆瓣
  12. +
  13. 2004,“Concepts, Techniques, and Models of Computer Programming”,CTM,wikihome
  14. +
  15. 2010,Bruce Tate,《七周七语言:理解多种编程范型》(Seven Languages in Seven Weeks, Pragmatic),豆瓣:书中介绍了Ruby、Io、Prolog、Scala、Erlang、Clojure和Haskell这七种语言
  16. +
  17. 2010,Martin Fowler,《领域特定语言》(Domain-Specific Languages, amazon),homeinfoq豆瓣
  18. +
  19. 2010,《领域专用语言实战》(DSLs in Action),图灵2013豆瓣
  20. +
  21. 2013,[日]西尾泰和,《代码之髓:编程语言核心概念》,图灵2014豆瓣
  22. +
  23. 2014,Neal Ford,《函数式编程思维》,豆瓣:涉及Java、Clojure、Scala
  24. +
+
+

编译器相关书籍:

+
    +
  1. 1986、2007,Aho & Sethi & Ullman,龙书《编译原理》(Compilers: Principles, Techniques, and Tools, 1st 1986, 2nd 2006),home豆瓣:侧重理论
  2. +
  3. 1997、2002,Appel,虎书《现代编译原理》(Modern Compiler Implementation in Java/C/ML, amazon),home,C语言,图灵2006豆瓣;Java语言,豆瓣:作者TOPLAS杂志主编,介于龙书,鲸书之间,算是实践中有理论
  4. +
  5. 2004、2011,Cooper & Torczon,《编译器设计》(Engineering a Compiler,2nd 2011),豆瓣书评:两位作者均来自Rice Univ,博士导师都为Kennedy
  6. +
  7. 1997,Muchnick,鲸书《高级编译器设计与实现》(Advanced Compiler Design and Implementation, amazon),豆瓣:名气次于龙书和虎书,内容侧重编译器后端优化
  8. +
  9. 1988、1991、2009,《编译器构造》(Crafting a Compiler, 1st 1988, 3rd 2009),豆瓣:该书不是很出名,但相对“龙书”和“虎书”读性很高
  10. +
  11. 1996、2011,Richard Jones & etc,《垃圾回收算法手册》(The Garbage Collection Handbook, amazon),home,第2版豆瓣:GC最佳书籍
  12. +
  13. 2016,中村成洋,《垃圾回收的算法与实现》,豆瓣
  14. +
  15. 2001,Allen & Kennedy,《现代体系结构的优化编译器》(Optimizing Compilers for Modern Architectures, amazon),豆瓣:两位作者均来自Rice Univ,其中Kennedy在1999年获得ACM SIGPLAN成就奖,该奖项的第3届得主
  16. +
+ +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2016/12/itext-pdf/index.html b/2016/12/itext-pdf/index.html new file mode 100644 index 00000000..47b44414 --- /dev/null +++ b/2016/12/itext-pdf/index.html @@ -0,0 +1,618 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + iText处理pdf书签和标注代码乱记 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ iText处理pdf书签和标注代码乱记 +

+ + +
+ + + + +
+ + +

将文档1中的书签转存到文档2​:

+ +
1
2
3
4
5
6
7
PdfReader reader1 = new PdfReader("in1.pdf");
List<HashMap<String, Object>> bookmarks = SimpleBookmark.getBookmark(reader1);

PdfReader reader2 = new PdfReader("in2.pdf");
PdfStamper stamper = new PdfStamper(reader2, new FileOutputStream("out.pdf"));
stamper.getWriter().setOutlines(bookmarks);
stamper.close();
+

导出书签文件​:

+
1
2
3
4
5
6
7
8
9
10
PdfReader reader = new PdfReader("in.pdf");
List<HashMap<String, Object>> bookmarks = SimpleBookmark.getBookmark(reader);
SimpleBookmark.exportToXML(bookmarks, new FileWriter("out.xml"), "utf-8", false);

导入书签到文件​:
PdfReader reader = new PdfReader("in.pdf");
List<HashMap<String, Object>> bookmarks = SimpleBookmark.importFromXML(new FileReader("out.xml"));
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("out.pdf"));
stamper.getWriter().setOutlines(bookmarks);
stamper.close();
+

将文档1中的标注(包括超链接)转存到文档2​:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
PdfReader reader1 = new PdfReader("in1.pdf");
PdfReader reader2 = new PdfReader("in2.pdf");
Document document = new Document(reader2.getPageSize(3));
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("out.pdf"));
document.open();

List<HashMap<String, Object>> bookmarks = SimpleBookmark.getBookmark(reader1);
writer.setOutlines(bookmarks);

int num = reader1.getNumberOfPages();
for (int i = 1; i <= num; i++) {
PdfImportedPage page = writer.getImportedPage(reader2, i);
PdfContentByte content = writer.getDirectContent();
content.addTemplate(page, 0, 0);

PdfDictionary pageDict = reader1.getPageN(i);
PdfArray annotArray = pageDict.getAsArray(PdfName.ANNOTS);
for (int j = 0; annotArray != null && j < annotArray.size(); ++j) {
PdfDictionary curAnnot = annotArray.getAsDict(j);
PdfAnnotation pdfAnnot = new PdfAnnotation(writer, null);
pdfAnnot.putAll(curAnnot);
writer.addAnnotation(pdfAnnot);
}
document.newPage();
}

document.close();
reader1.close();
reader2.close();
+

如果仅仅读取全部链接,只需将上述代码18行开始的for循环修改为:

+
1
2
3
4
5
6
7
8
for (int j = 0; annotArray != null && j < annotArray.size(); ++j) {
PdfDictionary curAnnot = annotArray.getAsDict(j);
if (PdfName.LINK.equals(curAnnot.getAsName(PdfName.SUBTYPE))) {
PdfAnnotation pdfAnnot = new PdfAnnotation(writer, null);
pdfAnnot.putAll(curAnnot);
writer.addAnnotation(pdfAnnot);
}
}
+

参考资料:

+
    +
  1. iText 5 examples - iText 5 actions and annotations http://developers.itextpdf.com/content/itext-5-examples
  2. +
  3. iText in Action, 2nd 2010, 7. Making documents interactive https://www.manning.com/books/itext-in-action-second-edition
  4. +
+ +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2016/12/java-8-stream-api/index.html b/2016/12/java-8-stream-api/index.html new file mode 100644 index 00000000..22771f16 --- /dev/null +++ b/2016/12/java-8-stream-api/index.html @@ -0,0 +1,686 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Java 8 的 Stream API 笔记 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ Java 8 的 Stream API 笔记 +

+ + +
+ + + + +
+ + +

Java 8增加了函数式编程的能力,通过流(Stream)API来支持对集合的filter/map/reduce操作。流是Java 8中处理集合的关键抽象概念,实现声明式的集合处理方式。

+ +

Java 8流API示例

+

对集合的filter、map和reduce操作,示例代码如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 计算偶数个数
List<Integer> list = Arrays.asList(3, 2, 12, 5, 6, 11, 13);
long count = list.stream()
.filter(x -> x % 2 == 0).count();
System.out.println(count);

// 筛选出偶数列表
List<Integer> evenList = list.stream()
.filter(x -> x % 2 == 0).collect(Collectors.toList());
System.out.println(evenList);

// 筛选出偶数列表, 然后全部元素加1
List<Integer> plusList = list.stream()
.filter(x -> x % 2 == 0)
.map(x -> x + 1).collect(Collectors.toList());
System.out.println(plusList);

// 全部偶数求和
int sum = list.stream()
.filter(x -> x % 2 == 0)
.mapToInt(Integer::intValue).sum();
System.out.println(sum);

// 全部偶数求和
sum = list.stream()
.filter(x -> x % 2 == 0)
.reduce(0, (x, y) -> x + y);
System.out.println(sum);
+

流与集合的区别

+

流(Stream)和集合(collection)有以下区别 [doc]:

+
    +
  • 无存储(no storage)。流并不是存储元素的数据结构。流,通过计算的操作流水线来传输数据源。数据源,比如数据结构、数组、生成器函数或I/O通道。
  • +
  • 原生函数式(functional in nature)。对流进行操作会产生结果,但并不会修改数据源。比如,筛选流,是生成一个不包含被筛选掉的元素新流,而不是从原集合中删除元素。
  • +
  • 惰性读取(laziness-seeking)。很多对流的操作,比如筛选(filtering)、映射(mapping)或去重(duplicate removal),能够被惰性实现,以便于性能的优化。比如,“找出第一个由三个连续单词组成的String”,并不需要检测全部的输入字符串。流操作被划分为中间操作(用于生成流)和终止操作(用于生成值或副作用)。中间操作总是惰性的。
  • +
  • 可能是无界的(possibly unbounded)。集合的大小是必须确定的,但流并不是。像limit(n) 或 findFirst()这样的逻辑短路操作,允许在有限时间内完成对无限流的计算。
  • +
  • 可消耗的(consumable)。流的元素在流的生命周期中只能被访问一次。类似于 Iterator,要想重新访问同一个元素,必须生成新的流。
  • +
+

流操作与流水线

+

当使用Stream时,会通过三个阶段来建立一个操作流水线 [ref]。

+
    +
  1. 创建一个Stream。
  2. +
  3. 在一个或多个步骤中,指定将初始Stream转换为另一个Stream的中间操作
  4. +
  5. 使用一个终止操作来产生一个结果。该操作会强制它之前的延迟操作立即执行。在这之后,该Stream就不会再被使用了。
  6. +
+

整个流操作流水线,如图所示 [ref]:

+

流操作流水线

+

Java 8的流创建、中间操作和终止操作的API汇总表,如下 [ref]

+ + + + + + + + + + + + + + + + +
创建流中间操作终止操作

Collection
stream()
parallelStream()

Stream, IntStream, LongStream, DoubleStream
static generate() 无序
static of(..)
static empty()
static iterate(..)
static concat(..)
static builder()

IntStream, LongStream
static range(..)
static rangeClosed(..)

Arrays
static stream(..)

BufferedReader
lines(..)

Files
static list(..)
static walk(..)
static find(..)

JarFile
stream()

ZipFile
stream()

Pattern
splitAsStream(..)

SplittableRandom
ints(..) 无序
longs(..) 无序
doubles(..) 无序

Random
ints(..)
longs(..)
doubles(..)

ThreadLocalRandom
ints()
longs(..)
doubles(..)

BitSet
stream()

CharSequence (String)
IntStream chars()
IntStream codePoints()

StreamSupport (low level)
static doubleStream(..)
static intStream(..)
static longStream(..)
static stream(..)

BaseStream
sequential()
parallel()
unordered()
onClose(..)

Stream
filter(..)
map(..)
mapToInt(..)
mapToLong(..)
mapToDouble(..)
flatMap(..)
flatMapToInt(..)
flatMapToLong(..)
flatMapToDouble(..)
distinct() 有状态
sorted(..) 有状态
peek(..)
limit(..) 有状态, 逻辑短路
skip(..) 有状态

IntStream、LongStream和DoubleStream方法与Stream类似, 其中额外的方法如下:

IntStream
mapToObj(..)
asLongStream()
asDoubleStream()
boxed()

LongStream
mapToObj(..)
asDoubleStream()
boxed()

DoubleStream
mapToObj(..)
boxed()

BaseStream
iterator()
spliterator()

Stream
forEach(..)
forEachOrdered(..)
toArray(..)
reduce(..)
collect(..)
min(..)
max(..)
count()
anyMatch(..) 逻辑短路
allMatch(..) 逻辑短路
noneMatch(..) 逻辑短路
findFirst() 逻辑短路
findAny() 逻辑短路*, 不确定*

IntStream、LongStream和DoubleStream方法与Stream类似, 其中额外的方法如下:

IntStream, LongStream, DoubleStream
sum()
average()
summaryStatistics()

+

筛选与映射操作

+

筛选与映射操作,即上文所说的中间操作。相关的API如下:

+
1
2
3
Stream<T> filter(Predicate<? super T> predicate)
<R> Stream<R> map(Function<? super T,? extends R> mapper)
<R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)
+

filter(..),筛选出元素符合某个条件的新流。map(..),用于对元素作某种形式的转换。flatMap(..),用于将多个子流合并为一个新流。

+

其他的中间操作有,提取子流,limit(..)(提取前n个)和skip(..)(丢弃前n个);有状态的转换,distinct()(过滤重复元素)和sorted(..)(排序),以及主要用于日志调试的peek(..)

+
1
2
3
4
5
Stream<T> limit(long maxSize)
Stream<T> skip(long n)
Stream<T> distinct()
Stream<T> sorted(Comparator<? super T> comparator)
Stream<T> peek(Consumer<? super T> action)
+

归约操作与收集器

+

流有多种形式的通用的归约操作,reduce(..)collect(..),同时也有多种特化的归约形式,比如 sum()min(..)max(..)count()等。reduce(..)collect(..)的方法签名如下:

+
1
2
3
4
5
Optional<T> reduce(BinaryOperator<T> accumulator)
T reduce(T identity, BinaryOperator<T> accumulator)
<U> U reduce(U identity, BiFunction<U,? super T,U> accumulator,
BinaryOperator<U> combiner)
<R,A> R collect(Collector<? super T,A,R> collector)
+

sum()min(..)max(..)count()等特化的归约操作,是reduce(..)归约操作的特殊化,内部实现依赖reduce(..),相应JDK的实现源码可以作为印证。

+

IntStream的sum(..)的JDK现实源码为 [github]:

+
1
2
3
4
@Override
public final int sum() {
return reduce(0, Integer::sum);
}
+

IntStream的min(..)的JDK现实源码为 [github]:

+
1
2
3
4
@Override
public final OptionalInt min() {
return reduce(Math::min);
}
+

Stream的count()的JDK现实源码为 [github]:

+
1
2
3
4
@Override
public final long count() {
return mapToLong(e -> 1L).sum();
}
+

如果不想将流归约为单个值,而只要查看集合被流操作后的结果,需要使用收集器(collector)。上文已经见到,将流收集为List:

+
1
2
List<Integer> evenList = list.stream()
.filter(..).collect(Collectors.toList());
+

Collectors是收集器工具类,提供获取预定义收集器(实现接口Collector)的静态方法。Collectors类,除了将流收集为List,还可以是Map、Set、String,或者也能进行统计操作,如求和、计算平均值、最大值、最小值。Collectors的全部静态方法列表如下:

+
    +
  • averaging[Double|Int|Long]
  • +
  • collectingAndThen
  • +
  • counting
  • +
  • groupingBy
  • +
  • groupingByConcurrent
  • +
  • joining
  • +
  • mapping
  • +
  • maxBy
  • +
  • minBy
  • +
  • partitioningBy
  • +
  • reducing
  • +
  • summarizing[Double|Int|Long]
  • +
  • summing[Double|Int|Long]
  • +
  • toCollection
  • +
  • toConcurrentMap
  • +
  • toList
  • +
  • toMap
  • +
  • toSet
  • +
+ +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2016/12/mybatis-generator/index.html b/2016/12/mybatis-generator/index.html new file mode 100644 index 00000000..96ca3273 --- /dev/null +++ b/2016/12/mybatis-generator/index.html @@ -0,0 +1,629 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MyBatis 生成器的表注释 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ MyBatis 生成器的表注释 +

+ + +
+ + + + +
+ + +

MyBatis是流行的持久化框架,通过抽象底层的JDBC代码,在类对象和数据库列之间自动映射SQL的参数和结果,以SQL为映射的间接层,实现SQL映射器。MyBatis Generator (MBG) 是一个Mybatis的代码生成器,内省数据库的表,然后自动生成映射表的实体类,并生成CRUD(插入,查询,更新,删除)操作的样板代码。MyBatis,之前所在的公司在用,生成器也在用。虽然生成器大大提供了开发效率,但生成的代码可读性比较低,尤其是自动生成的实体类,如下:

+ +
1
2
3
4
5
/**
* This field was generated by MyBatis Generator. This field corresponds to the database column author.book_id
* @mbggenerated Tue Jan 19 13:37:24 CST 2016
*/
private Integer bookId;
+

这些自动生成注释,没有实质性信息,其实真正有用的是,设计表时,该字段的用途,即表字段的注释。

+

addRemarkComments选项

+

庆幸的是,MyBatis生成器在版本1.3.3中添加了,addRemarkComments选项 [github],可以在生成的实体类中附带表字段的注释。addRemarkComments官方文档的介绍 [doc]:

+
+

This property is used to specify whether MBG will include table and column remarks from db table in the generated comments. The property supports these values:

+
    +
  • false: This is the default value When the property is false or unspecified, all generated comments will not include table and column remarks from db table when the element was generated.
  • +
  • true: When the property is true, table and columns remarks from db table will be added to the generated comments.
  • +
+

Warning: If suppressAllComments option is true, this option will be ignored.

+
+

使用方法很简单,只需将MyBatis生成器的配置文件中的commentGenerator节点修改为:

+
1
2
3
<commentGenerator>
<property name="addRemarkComments" value="true" />
</commentGenerator>
+

自定义注释生成器类

+

通过addRemarkComments选项生成的实体类的注释不够精简。于是笔者参考MyBatis的默认的注释生成器DefaultCommentGenerator[github],对其进行改造成如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package com.test.mbg;

import java.util.Date;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.JavaElement;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.mybatis.generator.config.MergeConstants;
import org.mybatis.generator.internal.DefaultCommentGenerator;
import org.mybatis.generator.internal.util.StringUtility;

/**
* 官方类似的功能见,在版本1.3.3中添加的 addRemarkComments <br>
* http://www.mybatis.org/generator/configreference/commentGenerator.html <br>
* https://github.com/mybatis/generator/issues/23
*
* @see DefaultCommentGenerator#addRemarkComments
*/
public class RemarksCommentGenerator extends DefaultCommentGenerator {

@Override
public void addModelClassComment(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
topLevelClass.addJavaDocLine("/**");

String remarks = introspectedTable.getRemarks();
if (StringUtility.stringHasValue(remarks)) {
String[] remarkLines = remarks.split(System.getProperty("line.separator"));
for (String remarkLine : remarkLines) {
topLevelClass.addJavaDocLine(" * " + remarkLine);
}
}

topLevelClass.addJavaDocLine(" * ");
StringBuilder sb = new StringBuilder();
sb.append(" * ");
sb.append(introspectedTable.getFullyQualifiedTable());
topLevelClass.addJavaDocLine(sb.toString());
topLevelClass.addJavaDocLine(" *");
addJavadocTag(topLevelClass, false);
topLevelClass.addJavaDocLine(" */");
}

public void addFieldComment(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) {
field.addJavaDocLine("/**");

String remarks = introspectedColumn.getRemarks();
if (StringUtility.stringHasValue(remarks)) {
String[] remarkLines = remarks.split(System.getProperty("line.separator"));
for (String remarkLine : remarkLines) {
field.addJavaDocLine(" * " + remarkLine);
}
}

field.addJavaDocLine(" *");
StringBuilder sb = new StringBuilder();
sb.append(" * ");
sb.append(introspectedTable.getFullyQualifiedTable());
sb.append('.');
sb.append(introspectedColumn.getActualColumnName());
field.addJavaDocLine(sb.toString());
field.addJavaDocLine(" *");
addJavadocTag(field, false);
field.addJavaDocLine(" */");
}

public void addFieldComment(Field field, IntrospectedTable introspectedTable) {
field.addJavaDocLine("/**");
addJavadocTag(field, false);
field.addJavaDocLine(" */");
}

public void addGetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) {
method.addJavaDocLine("/**");
addJavadocTag(method, false);
method.addJavaDocLine(" */");
}

public void addSetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) {
method.addJavaDocLine("/**");
addJavadocTag(method, false);
method.addJavaDocLine(" */");
}

protected void addJavadocTag(JavaElement javaElement, boolean markAsDoNotDelete) {
StringBuilder sb = new StringBuilder();
sb.append(" * ");
sb.append(MergeConstants.NEW_ELEMENT_TAG);
if (markAsDoNotDelete) {
sb.append(" do_not_delete_during_merge"); //$NON-NLS-1$
}
String s = getDateString();
if (s != null) {
sb.append(' ');
sb.append(s);
}
javaElement.addJavaDocLine(sb.toString());
}

protected String getDateString() {
return DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
}
}
+

MyBatis的配置文件修改为:

+
1
2
<commentGenerator type="com.test.mbg.RemarksCommentGenerator">
</commentGenerator>
+

运行MyBatis生成器

+

改用自定义的RemarksCommentGenerator后,运行MyBatis插件可能会报错。需要使用Java来运行MyBatis生成器,代码如下 [doc]:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.test.mbg;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

/**
* 使用Java运行 MyBatis Generator
* http://www.mybatis.org/generator/running/runningWithJava.html
*/
public class MyBatisGen {

public static void main(String[] args) throws Exception {
String fileName = "F:/code/mybatis-generator.xml";
File configFile = new File(fileName);
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
}
}
+ +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2016/12/software-dev-books/index.html b/2016/12/software-dev-books/index.html new file mode 100644 index 00000000..8a05abae --- /dev/null +++ b/2016/12/software-dev-books/index.html @@ -0,0 +1,730 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 软件开发书籍资料整理 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ 软件开发书籍资料整理 +

+ + +
+ + + + +
+ + +

本文整理软件开发、项目管理、软件工程相关的书籍。

+ +

开发类书籍

+
    +
  1. 2011-03 What is the single most influential book every programmer should read? (stackoverflow.com) https://news.ycombinator.com/item?id=2272722
  2. +
  3. 2012-08 国外程序员推荐:每个程序员都应读的书 (译SO帖子) http://blog.jobbole.com/5886/
  4. +
  5. 2011-08 Jurgen Appelo:2011年最热门的敏捷书籍排行榜 http://www.infoq.com/cn/news/2011/08/top-agile-books
  6. +
+

软件开发综合类书籍

+
    +
  1. 1993、2004,Steve McConnell,《代码大全》(Code Complete: A Practical Handbook of Software Construction, Microsoft Press, 2nd 2004),豆瓣:全书944页,1994年Jolt震撼大奖,1999–2002任IEEE Software主编
  2. +
  3. 2006,Pete Goodliffe,《编程匠艺》(Code Craft: The Practice of Writing Excellent Code, amazon),豆瓣:全书582页
  4. +
+

设计模式与重构类书籍(代码组织结构、修改、阅读)

+
    +
  1. 1994,GoF,《设计模式:可复用面向对象软件的基础》(Design Patterns: Elements of Reusable Object-Oriented Software, amazon),豆瓣
  2. +
  3. 2001、2004,Shalloway & Trott,**《**设计模式解析》(Design Patterns Explained, 2nd 2004),图灵2010豆瓣:全书312页,Java描述
  4. +
  5. 2012,《元素模式》(Elemental Design Patterns, amazon),豆瓣
  6. +
  7. Martin Fowler, wiki
  8. +
+
    +
  • 1996,《分析模式:可复用的对象模型》(Analysis Patterns: Reusable Object Models, amazon),豆瓣
  • +
  • 1999,《重构:改善既有代码的设计》(Refactoring: Improving the Design of Existing Code, amazon),home豆瓣:经典,内容类似参考手册形式,可读性不高
  • +
  • 2002,《企业应用架构模式(Po****EAA)》(Patterns of Enterprise Application Architecture, amazon),home豆瓣
  • +
+
    +
  1. Robert C. Martin,wiki:1991年创立Object Mentor公司[ref]
  2. +
+
    +
  • 2002,《敏捷软件开发:原则、模式与实践(PPP**)》(Agile Software Development: Principles, Patterns and Practices, amazon),豆瓣:全书476页,2003年Jolt震撼大奖,该书面向代码层面,最早整理汇编SOLID原则**
  • +
  • 2008,《代码整洁之道》(Clean Code: A Handbook of Agile Software Craftsmanship, amazon),豆瓣:全书388页,每个程序员都应读的最具影响力的书排名第13,“虽然《代码整洁之道》和《代码大全》有很多共同之处,但它有更为简洁更为实际的清晰例子”[ref]
  • +
  • 2011,《程序员的职业素养》(The Clean Coder: A Code of Conduct for Professional Programmers, amazon),豆瓣:全书178页,内容充斥着作者自己经历故事,大量围绕“我”的文字,不够精简,很难抓到作者阐述要点
  • +
+
    +
  1. 2000,Schmidt, Stal, Buschmann, Rohnert,《面向模式的软件体系结构,卷2:用于并发和网络化对象的模式(****POSA)》(Pattern-Oriented Software Architecture, amazon),共5卷图灵图灵2013豆瓣
  2. +
+

其他书籍

+
    +
  1. 2004,Joshua Kerievsky,《重构与模式》(Refactoring to Patterns, amazon),豆瓣:2005年Jolt生产力大奖,amazon有评论批评该书例子过于复杂[ref]
  2. +
  3. 2004,Michael Feathers,《修改代码的艺术》(Working Effectively with Legacy Code, amazon),豆瓣:作者Object Mentor公司成员,该书更直白的书名应为“遗留代码修改FAQ”,简介“本书是继《重构》和《重构与模式》之后探讨修改代码技术的又一里程碑式的著作,而且从涵盖面和深度上都超过了前两部经典”
  4. +
  5. 2011,Boswell & Foucher,《编写可读代码的艺术》(The Art of Readable Code, O'Reilly, amazon),豆瓣:全书178页
  6. +
  7. 2003,Diomidis Spinellis,《代码阅读》(Code Reading: The Open Source Perspective, amazon),豆瓣:2004年Jolt生产力大奖
  8. +
  9. 2006,Diomidis Spinellis,《代码质量》(Code Quality: The Open Source Perspective, amazon),豆瓣:2007年Jolt生产力大奖
  10. +
  11. 1998,《反模式:危机中软件架构和项目的重构》(AntiPatterns, amazon),豆瓣:1999年Jolt生产力大奖
  12. +
  13. 2014,《软件设计重构》(Refactoring for Software Design Smells) ,豆瓣
  14. +
+

软件代码实例书籍

+
    +
  1. 2008,Oram & Wilson,《开源软件架构 AOSA》(The Architecture of Open Source Applications, amazon),图灵(卷1、卷2均有部分翻译),home:Oram是O'Reilly Media的编辑,Wilson是Dr. Dobb's 杂志的特约编辑
  2. +
  3. 2010,Oram & Wilson,《软件之道:软件开发争议问题剖析》(Making Software: What Really Works, and Why We Believe It, O'Reilly, amazon),豆瓣
  4. +
  5. 2007,Oram & Wilson,《代码之美:38位大师级程序员解释其思考方式》(Beautiful Code: Leading Programmers Explain How They Think, O'Reilly, amazon),豆瓣:2008年Jolt震撼大奖
  6. +
  7. 2009,Diomidis Spinellis,《架构之美》(Beautiful Archiecture: Leading Thinkers Reveal the Hidden Beauty in Software Design, O'Reilly, amazon),豆瓣:编者是《代码阅读》作者
  8. +
+

AOSA部分译文:

+
    +
  1. AOSA 卷1:NoSQL生态系统 http://www.oschina.net/translate/the-nosql-ecosystem
  2. +
  3. AOSA 卷4 https://github.com/aosabook/500lines
  4. +
  5. 2014-07 AOSA: 500 Lines or Less (Early preview) (github.com) https://news.ycombinator.com/item?id=8004077
  6. +
+

编程实践与ThoughtWorks书籍

+
    +
  1. 1999,Andy Hunt & David Thomas,《注重实效的程序员》(The Pragmatic Programmer: From Journeyman to Master,amazon),豆瓣:两位作者是敏捷宣言17人,“Pragmatic Bookshelf”系列书籍第1本,两位作者为“Pragmatic Programmers, LLC”公司创立者[ref]
  2. +
  3. 2006,Subramaniam & Andy Hunt,《敏捷开发修炼:高效程序员的45个习惯》(Practices of an Agile Developer, Pragmatic, amazon),豆瓣:2007年Jolt生产力大奖
  4. +
  5. 2008,Andy Hunt,《程序员的思维修炼:开发认知潜能的九堂课》(Pragmatic Thinking and Learning, Pragmatic, amazon):注重实效的思考与学习
  6. +
  7. 2008,Neal Ford,《卓有成效的程序员》(The Productive Programmer, O'Reilly, amazon),豆瓣:Neal Ford is an Application Architect at ThoughtWorks
  8. +
  9. 2008,《软件开发沉思录:ThoughtWorks文集》(The Thoughtworks Anthology, Pragmatic, amazon),豆瓣
  10. +
  11. 2012,《软件开发与创新:ThoughtWorks文集》(The ThoughtWorks Anthology, Volume 2, Pragmatic, amazon),豆瓣
  12. +
+
+
    +
  1. 2005,Rothman & Derby,《门后的秘密》(Behind Closed Doors: Secrets of Great Management, Pragmatic),豆瓣
  2. +
  3. 2005,Richardson & Gwaltney,《软件项目成功之道》(Ship it! A Practical Guide to Successful Software Projects, Pragmatic, amazon),豆瓣
  4. +
  5. 2007,Rothman,《项目管理修炼之道》,(Manage It!: Your Guide to Modern, Pragmatic Project Management, Pragmatic),豆瓣:2008年Jolt生产力大奖
  6. +
  7. 2009,Paul Butcher,《软件调试修炼之道》(Debug It!: Find, Repair, and Prevent Bugs in Your Code, Pragmatic
  8. +
  9. 2009,《软件开发者路线图》(Apprenticeship Patterns: Guidance for the Aspiring Software Craftsman,O'Reilly, amazon),豆瓣
  10. +
+

软件工程项目管理类

+

https://en.wikipedia.org/wiki/Template:Software_engineering
+https://en.wikipedia.org/wiki/History_of_software_engineering

+

综合类书籍

+
    +
  1. 2002,Robert Glassmsa,《软件工程的事实与谬误》(Facts and Fallacies of Software Engineering, amazon),豆瓣
  2. +
+

轻量级软件开发方法(XP与Scrum)

+
    +
  1. 1999、2005,Kent Beck,《解析极限编程:拥抱变化(XPE)》(Extreme Programming Explained: Embrace Change, 2nd 2005),豆瓣:2000年Jolt生产力大奖
  2. +
  3. 2000,Beck & Fowler,《规划极限编程》(Planning Extreme Programming, amazon),豆瓣
  4. +
  5. 2001,Pete McBreen,《软件工艺》(Software Craftsmanship: The New Imperative, amazon),豆瓣:2002年Jolt生产力大奖
  6. +
  7. 2002,Kent Beck,《测试驱动开发(TDD)》(Test-Driven Development: By Example, amazon),豆瓣:2003年Jolt生产力大奖
  8. +
  9. 2007,Kent Beck,《实现模式》(Implementation Patterns, AW, amazon),豆瓣
  10. +
  11. 2004,Ken Schwaber,《Scrum敏捷项目管理》(Agile Project Management with Scrum. Microsoft Press, amazon),豆瓣
  12. +
  13. 2001、2006,Alistair Cockburn,《敏捷软件开发》(Agile Software Development: The Cooperative Game, 2nd 2006, amazon),豆瓣:2002年Jolt生产力大奖、2007年Jolt震撼大奖,该书面向项目管理层面
  14. +
  15. 2007,Shore & Warden,《敏捷开发的艺术》(The Art of Agile Development, amazon),豆瓣
  16. +
  17. 2009,Mike Cohn,《Scrum敏捷软件开发》(Succeeding with Agile: Software Development using Scrum),豆瓣
  18. +
  19. 2008,Henrik Kniberg,《硝烟中的Scrum和XP》,infoq minibook
  20. +
  21. 2011,Henrik Kniberg,《精益开发实战:用看板管理大型项目》(Lean from the Trenches: Managing Large-Scale Projects with Kanban, amazon),豆瓣
  22. +
+

2009-05 敏捷书籍推荐 http://www.infoq.com/cn/news/2009/05/recommended-agile-books
+2010-09 DZone's Top 10 Agile and Lean Development Books http://agile.dzone.com/articles/dzones-top-10-agile-and-lean
+2010-08 最热门的敏捷书籍 http://www.infoq.com/cn/news/2010/08/top-agile-books
+2011-08 2011年最热门的敏捷书籍排行榜 http://www.infoq.com/cn/news/2011/08/top-agile-books

+
+

软件项目管理(Fred Brooks & Tom DeMarco)

+
    +
  1. 1975、1995,Fred Brooks,《人月神话:大型系统开发管理文集》(The Mythical Man-Month: Essays on Software Engineering, AW, 2nd 1995, amazon),豆瓣
  2. +
  3. 2010,Fred Brooks,《设计原本:计算机科学巨匠Frederick P.Brooks的思考》(The Design of Design: Essays from a Computer Scientist, AW, amazon),豆瓣
  4. +
  5. 1987、1999,Tom DeMarco,《人件》(Peopleware: Productive Projects and Teams, 2nd 1999, 3rd 2013),豆瓣,第3版豆瓣
  6. +
  7. 2012,《进化:从孤胆极客到高效团队》(Team Geek, amazon),豆瓣:2013年Jolt大奖提名,两位作者为Google项目团队的负责人
  8. +
  9. 2007,《软件人才管理的艺术》(Managing Humans, amazon),豆瓣
  10. +
  11. 1997,Tom DeMarco,《最后期限》(The Deadline: A Novel About Project Management, amazon),豆瓣:1998年Jolt生产力大奖
  12. +
  13. 2003,Tom DeMarco,《与熊共舞:软件项目风险管理》(Waltzing with Bears, amazon),豆瓣:2004年Jolt震撼大奖
  14. +
  15. 2008,Tom DeMarco,《项目百态:深入理解软件项目行为模式》(Adrenaline Junkies and Template Zombies: Understanding Patterns of Project Behavior, amazon),豆瓣:2009年Jolt震撼大奖
  16. +
  17. 2005、2008,Scott Berkun,《项目管理之美》(Making Things Happen: Mastering Project Management, O'Reilly, amazon),豆瓣:2006年Jolt生产力大奖
  18. +
  19. 1999、2003,Edward Yourdon,《死亡之旅》(Death March, Prentice Hall, 2nd 2003, amazon),豆瓣
  20. +
+

著名软件项目

+
    +
  1. 1994,《观止:微软创建NT和未来的夺命狂奔》(Show Stopper!, amazon),豆瓣
  2. +
  3. 2008,Scott Rosenberg,《梦断代码》(Dreaming In Code, amazon),豆瓣
  4. +
+
+

Steve McConnell,wiki

+
    +
  1. 1993,Steve Maguire,《编程精粹:编写高质量C语言代码》(Writing Solid Code, amazon),豆瓣:与代码大全齐名,1994年Jolt生产力大奖
  2. +
  3. 1996,《快速软件开发》(Rapid Development: Taming Wild Software Schedules, Microsoft Press, amazon),豆瓣:1997年Jolt震撼大奖
  4. +
  5. 1997,《微软项目:求生法则》(Software Project Survival Guide, Microsoft Press, amazon),豆瓣
  6. +
+ +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2017/01/mysql-data-types/index.html b/2017/01/mysql-data-types/index.html new file mode 100644 index 00000000..52c14e18 --- /dev/null +++ b/2017/01/mysql-data-types/index.html @@ -0,0 +1,792 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MySQL数据库字段类型杂记 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ MySQL数据库字段类型杂记 +

+ + +
+ + + + +
+ + +

文本整理MySQL字段类型的常见问题和用法。

+

数值类型

+

int和int(3)

+

新手在定义整数字段时,常常想当然通过,如int(3),来限制整数的有效长度,然而这样仅仅只是指定了显示宽度。选择有效长度不同的整数,需要使用tinyint(1个字节)、smallint(2个字节)、mediumint(3个字节)、int(4个字节)或bigint(8个字节)。MySQL的相关文档如下[doc]:

+ +
+

MySQL supports an extension for optionally specifying the display width of integer data types in parentheses following the base keyword for the type. For example, INT(4) specifies an INT with a display width of four digits.

+
+
+

The display width does not constrain the range of values that can be stored in the column. Nor does it prevent values wider than the column display width from being displayed correctly. For example, a column specified as SMALLINT(3) has the usual SMALLINT range of -32768 to 32767, and values outside the range permitted by three digits are displayed in full using more than three digits.

+
+
+

When used in conjunction with the optional (nonstandard) attribute ZEROFILL, the default padding of spaces is replaced with zeros. For example, for a column declared as INT(4) ZEROFILL, a value of 5 is retrieved as 0005.

+
+

如下示例,字段bar类型是int(3),但依然能够正确保存数值12345

+
1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> create table test (foo int(3) zerofill, bar int(3) zerofill, baz int);
Query OK, 0 rows affected (0.16 sec)

mysql> insert into test values (42, 12345, 12345);
Query OK, 1 row affected (0.00 sec)

mysql> select * from test;
+------+-------+-------+
| foo | bar | baz |
+------+-------+-------+
| 042 | 12345 | 12345 |
+------+-------+-------+
1 row in set (0.00 sec)
+

bit和bool

+

MySQL同时支持bitbool类型,但bool仅仅是tinyint(1)的同义词,创建的字段值的范围并不是01truefalse,而是-128127。如下所示:

+
1
2
3
4
5
6
7
8
9
10
11
mysql> create table test (foo bool, bar bit);
Query OK, 0 rows affected (0.10 sec)

mysql> desc test;
+---------+------------+--------+-------+-----------+---------+
| Field | Type | Null | Key | Default | Extra |
|---------+------------+--------+-------+-----------+---------|
| foo | tinyint(1) | YES | | <null> | |
| bar | bit(1) | YES | | <null> | |
+---------+------------+--------+-------+-----------+---------+
2 rows in set (0.00 sec)
+

字符串类型

+

长度和编码

+

从MySQL 4.1开始(2004年10月),用字符单位解释在字符列定义中的长度规范。(以前的一些MySQL版本以字节解释长度)。官方文档描述如下[doc]

+
+

In MySQL 4.1 and up , string data types include some features that you may not have encountered in working with versions of MySQL prior to 4.1:

+
+
+

MySQL interprets length specifications in character column definitions in character units. (Before MySQL 4.1, column lengths were interpreted in bytes.) This applies to CHAR, VARCHAR, and the TEXT types.

+
+

MySQL服务器默认的字符集latin1,使用的校对规则latin1_swedish_ci [doc](校对规则是在字符集内用于比较字符的一套规则)。若要保存中文,典型的做法是使用utf8编码。但MySQL的utf8编码最多只能保存使用utf8编码后长度是3个字节的字符,即只支持基本多文种平面。使用MySQL的utf8保存常见的字符基本上没有问题,但对于生僻字或emoji字符就无能为力了。emoji的中的笑脸(grinning face)的Unicode编码,如下 [ref1][ref2]:

+ + + + + + + + + + + + + + + + + +
表情UnicodeUTF-16UTF8
😀U+1F6040xD83D 0xDE040xF0 0x9F 0x98 0x84
+

emoji位于辅助多文种平面,utf8需要4个字节保存。为了解决这个问题,MySQL 5.5.3开始支持utf8mb4,支持辅助多文种平面,每个字符最大4个字节 [doc]。除了utf8,MySQL还支持ucs2utf16utf32等,完整列表如下 [ref]

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
字符集支持的字符每个字符需要的存储空间
utf8基本多文种平面1, 2, 或 3 个字节
ucs2基本多文种平面2字节
utf8mb4基本多文种平面和辅助多文种平面1, 2, 3,或4字节
utf16基本多文种平面和辅助多文种平面2或4字节
utf16le基本多文种平面和辅助多文种平面2或4字节
utf32基本多文种平面和辅助多文种平面4字节
+

##varchar和text

+

MySQL支持多种字符串类型, 如下表所示:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
类型最大字节长度最大utf8字符数
char(M)M,M为0~255之间的整数85个utf8字符
varchar(M)M,M为0~65,535之间的整数21,844个utf8字符
tinytext 255 (28−1) 字节85个utf8字符
text65,535 (216−1) 字节 = 64 KB21,844个utf8字符
mediumtext16,777,215 (224−1) 字节 = 16 MB5,592,405个utf8字符
longtext4,294,967,295 (232−1) 字节 = 4 GB1,431,655,765个utf8字符
+

字符串类型实际支持的最大字符数与编码有关。比如,varchar类型在utf8编码下最大支持保存21,844 (65,535 / 3 = 21,844) 个字符,而utf8mb4编码下最大支持保存16,383 (65,535 / 4 = 16,383) 个字符。

+

另外,MySQL表行最大总长度为65,535字节 [doc], 所以varchar类型字段的最大字符数会被表中其他字段所占用的存储空间挤掉。blobtext类型的字段不会受表行总长度的限制,因为字段存储的实际内容和表行是分离的,只会占用表行的9到12个字节。

+
1
2
3
4
5
6
7
mysql> create table test ( foo varchar(21845) character set utf8 );
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
mysql> create table test ( foo varchar(21844) character set utf8 );
Query OK, 0 rows affected (0.19 sec)

mysql> create table test2 ( foo varchar(16384) character set utf8mb4 );
ERROR 1074 (42000): Column length too big for column 'foo' (max = 16383); use BLOB or TEXT instead
+

日期和时间类型

+

MySQL支持的日期和时间类型如下表所示 [doc]:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
日期和时间类型字节最小值最大值
date41000-01-019999-12-31
datetime81000-01-01 00:00:00.0000009999-12-31 23:59:59.999999
timestamp41970-01-01 00:00:01.0000002038-01-19 03:14:07.999999
time3-838:59:59.000000838:59:59.000000
year119012155
+

参考资料

+
    +
  1. MySQL 5.7 Reference Manual, 12 Data Types http://dev.mysql.com/doc/refman/5.7/en/data-types.html
  2. +
  3. MySQL 5.7 Reference Manual, 10.1 Character Set Support http://dev.mysql.com/doc/refman/5.5/en/charset.html
  4. +
  5. MySQL 5.7 Reference Manual, C.10.4 Limits on Table Column Count and Row Size http://dev.mysql.com/doc/refman/5.7/en/column-count-limit.html
  6. +
  7. Difference between “int” and “int(3)” data types in mysql http://stackoverflow.com/q/5562322
  8. +
  9. Which MySQL Datatype to use for storing boolean values? http://stackoverflow.com/q/289727
  10. +
  11. MySQL: Large VARCHAR vs. TEXT? http://stackoverflow.com/q/2023481
  12. +
  13. TINYTEXT, TEXT, MEDIUMTEXT, and LONGTEXT maximum storage sizes http://stackoverflow.com/q/13932750
  14. +
+ +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2017/03/java-executor/index.html b/2017/03/java-executor/index.html new file mode 100644 index 00000000..cdcc4f30 --- /dev/null +++ b/2017/03/java-executor/index.html @@ -0,0 +1,756 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Java Executor 框架笔记 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ Java Executor 框架笔记 +

+ + +
+ + + + +
+ + +

本文整理 Java 并发框架 Executor 的用法,并对结合 JDK 相关的实现源码作简单分析。

+

任务与线程池

+

先来看下 Executor 框架的 javadoc 描述 [ ref1 ref2 ]

+ +

接口:

+
    +
  • Executor 是一个简单的标准化接口,用于定义类似于线程的自定义子系统,包括线程池、异步 IO 和轻量级任务框架。根据所使用的具体 Executor 类的不同,可能在新创建的线程中,现有的任务执行线程中,或者调用 execute() 的线程中执行任务,并且可能顺序或并发执行。
  • +
  • ExecutorService 提供了多个完整的异步任务执行框架。ExecutorService 管理任务的排队和安排,并允许受控制的关闭。ScheduledExecutorService 子接口及相关的接口添加了对延迟的和定期任务执行的支持。ExecutorService 提供了安排异步执行的方法,可执行由 Callable 表示的任何函数,结果类似于 Runnable。
  • +
  • Future 返回函数的结果,允许确定执行是否完成,并提供取消执行的方法。RunnableFuture 是拥有 run 方法的 Future,run 方法执行时将设置其结果。
  • +
+

实现:

+ +

涉及到的类与接口的层次结构,如下图所示:

+Executor 相关类 +任务相关类 +

线程池

+

Executor,此接口提供一种将任务提交与每个任务将如何运行的机制(包括线程使用的细节、调度等)分离开来的方法。接口只定义唯一一个方法:

+
1
2
void execute(Runnable command)
在未来某个时间执行给定的命令
+

实现 Executor 接口,就是定义某种运行任务的机制。最简单的运行任务的机制是,在调用者的线程中立即运行已提交的任务,如下:

+
1
2
3
4
5
class DirectExecutor implements Executor {
public void execute(Runnable r) {
r.run();
}
}
+

或者,以下实现将为每个任务生成一个新线程:

+
1
2
3
4
5
class ThreadPerTaskExecutor implements Executor {
public void execute(Runnable r) {
new Thread(r).start();
}
}
+

更典型的执行任务的方式是,使用线程池(Thread pool)。

+

JDK 下的 Executors 类提供创建线程池的静态工厂方法:

+
    +
  1. newFixedThreadPool:固定大小线程池,创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程
  2. +
  3. newCachedThreadPool:无界线程池,创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们
  4. +
  5. newSingleThreadExecutor:单个后台线程池,创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程
  6. +
  7. newScheduledThreadPool:任务调度线程池,创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行
  8. +
+

这 4 个工厂方法返回的类型是 ExecutorService,该接口扩展自 Executor。ExecutorService 提供了管理终止的方法,以及可为跟踪一个或多个异步任务执行状况而生成 Future 的方法。

+

现在让我们来看看创建线程池的静态工厂方法,对应的实现源码 [ src ]:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
}
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()));
}
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
+

可以看到 newFixedThreadPoolnewCachedThreadPoolnewSingleThreadExecutor 内部都是通过类 ThreadPoolExecutor 实现。ThreadPoolExecutor 的构造方法的 javadoc 如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue)

用给定的初始参数和默认的线程工厂及被拒绝的执行处理程序创建新的 ThreadPoolExecutor。使用 Executors 工厂方法之一比使用此通用构造方法方便得多。

参数:
corePoolSize - 池中所保存的线程数,包括空闲线程。
maximumPoolSize - 池中允许的最大线程数。
keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
unit - keepAliveTime 参数的时间单位。
workQueue - 执行前用于保持任务的队列。此队列仅保持由 execute 方法提交的 Runnable 任务。
+

ThreadPoolExecutor 的处理流程如下图所示(参考自《Java并发编程的艺术》第9章 Java中的线程池):
+线程池的主要处理流程
+ThreadPoolExecutor 执行示意图

+

基本上预定义的三个线程池已经满足常见的使用需求,若有特殊需求也可以,特殊构造 ThreadPoolExecutor 实例。此类提供 protected 的 beforeExecuteafterExecute 钩子 (hook) 方法,就是预留扩展用的。

+

ScheduledExecutorService 类提供的方法:

+
1
2
3
4
5
6
7
8
ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit)
创建并执行在给定延迟后启用的 ScheduledFuture
ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)
创建并执行在给定延迟后启用的一次性操作
ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期
ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
创建并执行一个在给定初始延迟后首次启用的定期操作,随后,在每一次执行终止和下一次执行开始之间都存在给定的延迟
+

用法就如文档所示,不展开描述。

+

提交任务

+

若直接使用线程运行任务,则典型的做法是创建 Runnable 接口实例,然后启动线程,如下:

+
1
2
3
4
5
Runnable r = ...
Thread worker = new Thread(r);
worker.start();
worker.join();
int result = getSavedValue();
+

Runnable 实例是没有直接的办法获取运行结果的返回值的,若要获取,需要添加额外的代码,如示例中 getSavedValue

+

Executor 框架下,使用 ExecutorService 的 submit 方法提交任务。

+
1
2
<T> Future<T> submit(Callable<T> task)
提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future。该 Future 的 get 方法在成功完成时将会返回该任务的结果。
+

Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。但是 Callable 会返回结果,并且可以抛出经过检查的异常。 submit 方法也可以接受 Runnable 参数,但阅读内部实现代码的话,就可以看到,最终还是会通过 Executors 类的 callable 方法,将 Runnable 转换成 Callable [ src src ]。Runnable 是为线程设计的,Callable 是为任务设计。任务和线程概念上分离,这样线程如何运用任务,即运行任务的机制,就可以按具体情况定义了。

+

上文提到 ExecutorService 扩展自 Executor 接口,那么现在就看下 submit 方法实现源码 [ src ]:

+
1
2
3
4
5
6
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
+

可以看到内部实现其实就是调用 execute,但传入参数和返回结果包裹了 Callable 和 Future。execute 方法跟具体实现有关,对于 ThreadPoolExecutor 的实现逻辑,代码会根据线程大小,以及任务队列 workQueue 和工作线程 worker 状况,做出相应选择:[ doc src ]:

+
    +
  • 如果运行的线程少于 corePoolSize,则 Executor 始终首选添加新的线程,而不进行排队。
  • +
  • 如果运行的线程等于或多于 corePoolSize,则 Executor 始终首选将请求加入队列,而不添加新的线程。
  • +
  • 如果无法将请求加入队列,则创建新的线程,除非创建此线程超出 maximumPoolSize,在这种情况下,任务将被拒绝。
  • +
+

使用 ExecutorService

+

ExecutorService 示例:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package concurrent;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

public class ExecutorMain {

public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
ExecutorService pool = Executors.newFixedThreadPool(10);

List<Future<Integer>> futures = new ArrayList<>();
futures.add(pool.submit(() -> {
Thread.sleep(2000);
System.out.println("return 1");
return 1;
}));
futures.add(pool.submit(() -> {
Thread.sleep(1000);
System.out.println("return 2");
return 2;
}));
futures.add(pool.submit(() -> {
Thread.sleep(3000);
System.out.println("return 3");
return 3;
}));

for (Future<Integer> future : futures) {
Integer result = future.get();
System.out.println("get " + result);
}
pool.shutdown();
}
}
+

输出结果:

+
1
2
3
4
5
6
return 2
return 1
get 1
get 2
return 3
get 3
+

为什么输出结果是这样呢?查文档知道,Future 的 get 方法,若已经完成,则直接返回,否则会等待计算完成,然后获取其结果。在示例代码中,任务1 需要 2 秒完成,任务2 需要 1 秒完成,任务3 需要 3 秒完成。自然,在线程池中完成次序是,任务2 - 任务1 - 任务3。main 主线程,先是获取 get 任务1 的执行结果,需要等待 2 秒,在去获取 get 任务2 的执行结果,此时该任务已经完成,直接返回,接下来是获取 get 任务3 的执行结果,任务3 耗时 3 秒,此时时间线是第 2 秒,所以需等 1 秒,才能获取 get 执行结果。

+

使用 ExecutorService,若想按任务完成次序获取执行结果,可以将代码中 for 循环,修改为轮询方式,就不断地在调用 get 前,先用 isDone 判断是否任务已经完成。代码如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
while (true) {
Iterator<Future<Integer>> iter = futures.iterator();
if (!iter.hasNext()) break;
while (iter.hasNext()) {
Future<Integer> future = iter.next();
if (future.isDone()) {
Integer result = future.get();
System.out.println("get " + result);
iter.remove();
}
}
}
+

输出结果:

+
1
2
3
4
5
6
return 2
get 2
return 1
get 1
return 3
get 3
+

这种实现方式,虽然可行,但相当繁琐。幸运的是,JDK 还提供一种更好的方法,CompletionService

+

使用 CompletionService

+

CompletionServiceExecutorBlockingQueue 的功能融合在一起。你可以将 Callable 任务提交给它来执行,然后使用类似于队列操作的 takepoll 等方法来获得已完成的结果,而这些结果会在完成时将被封装为 Future。ExecutorCompletionService 实现了 CompletionService。ExecutorCompletionService 的实现非常简单。在构造函数中创建一个 BlockingQueue 来保存计算完成的结果。当计算完成时,调用 FutureTask 中的 done 方法。当提交某个任务时,该任务将首先包装为一个 QueueingFuture,这是 FutureTask 一个子类,然后再改写子类的 done 方法,并将结果放入 BlockingQueue 中,take 和 poll 方法委托给了 BlockingQueue,这些方法会在得出结果之前阻塞。[ Goetz 2006, 6.3.5 ]

+

可以看出整个实现逻辑核心在于重写 FutureTask 的 done 方法,正如这个方法的 javadoc 所述,定义该方法的目的就是如此:

+
1
2
protected void done()
当此任务转换到状态 isDone(不管是正常地还是通过取消)时,调用受保护的方法。默认实现不执行任何操作。子类可以重写此方法,以调用完成回调或执行簿记
+

再来看下,BlockingQueue 的实现源码 [ src ],以及 submit 任务是对应的实现源码 [ src ]:

+
1
2
3
4
5
6
public Future<V> submit(Callable<V> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<V> f = newTaskFor(task);
executor.execute(new QueueingFuture(f));
return f;
}
+
1
2
3
4
5
6
7
8
private class QueueingFuture extends FutureTask<Void> {
QueueingFuture(RunnableFuture<V> task) {
super(task, null);
this.task = task;
}
protected void done() { completionQueue.add(task); }
private final Future<V> task;
}
+

然后再看下 ExecutorCompletionService 的 take 和 poll 方法的实现源码 [ src ]:

+
1
2
3
4
5
6
7
public Future<V> take() throws InterruptedException {
return completionQueue.take();
}

public Future<V> poll() {
return completionQueue.poll();
}
+

整个实现逻辑正如上面文字所述。

+

上文示例的 ExecutorMain,现在用 CompletionService 重现实现如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package concurrent;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

public class CompletionServiceMain {

public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService pool = Executors.newFixedThreadPool(10);
CompletionService<Integer> service = new ExecutorCompletionService<>(pool);

List<Future<Integer>> futures = new ArrayList<>();
futures.add(service.submit(() -> {
Thread.sleep(2000);
System.out.println("return 1");
return 1;
}));
futures.add(service.submit(() -> {
Thread.sleep(1000);
System.out.println("return 2");
return 2;
}));
futures.add(service.submit(() -> {
Thread.sleep(3000);
System.out.println("return 3");
return 3;
}));

for (int i = 0; i < futures.size(); i++) {
Integer result = service.take().get();
System.out.println("get " + result);
}
pool.shutdown();
}
}
+

运行结果,就是依次输出,任务2 - 任务1 - 任务3:

+
1
2
3
4
5
6
return 2
get 2
return 1
get 1
return 3
get 3
+

Guava 的 ListenableFuture

+

CompletionService 的逻辑是,任务完成后,依次添加到完成队列中,然后让主线程主动去获取这些已经完成的任务。其实这种主线程主动模式,也可以修为被动模式,即任务完成后主动以事件回调的形式通知主线程,主动方从主线程换成了任务本身。这种方式就消除了等待任务完成的过程。可惜的是直到 Java 8 新添加的 CompletableFuture 才支持实现这种机制。在 Java 8 之前,需要借助第三方库,比如 Guava 提供的 ListenableFuture。使用 CompletableFuture 需要了解 lambda 以及函数式编程相关知识,本文暂不展开,本文只讨论 ListenableFuture。来看下 Guava 的 ListenableFuture 主要涉及到的类 [ doc ]:

+
    +
  • ListeningExecutorService:扩展自 ExecutorService 接口,但不同的是,提交 submit 过去的任务返回的是 ListenableFuture 实例。
  • +
  • ListenableFuture:扩展自 Future 接口,唯一新增的方法是 addListener,用于添加 Future 完成后的回调监听器。
  • +
  • MoreExecutors:工具类,类似于 JDK 的 Executors,主要提供 Executor 的桥接、转换和构造的工具方法。
  • +
  • Futures:工具类,提供 Future 接口相关的静态工具方法,如静态方法 addCallback 用于添加任务执行的回调监听器,包括对任务执行成功的 onSuccess 事件和执行失败(抛出异常或被取消)的 onFailure 事件。
  • +
  • ListenableFutureTask:实现 ListenableFuture 接口的 FutureTask。
  • +
+

这些类如何使用呢?还是先来看下示例代码吧。

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package concurrent;

import com.google.common.util.concurrent.*;
import java.util.concurrent.Executors;

public class ListenableFutureMain {

public static void main(String[] args) {
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));

ListenableFuture<Integer> task = service.submit(() -> {
Thread.sleep(2000);
return 42;
});
Futures.addCallback(task, new FutureCallback<Integer>() {
public void onSuccess(Integer result) {
System.out.println("onSuccess " + result);
}
public void onFailure(Throwable t) {
System.out.println("onFailure");
}
});

service.shutdown();
}
}
+

简单解释下。MoreExecutors 工具类的 listeningDecorator 方法将 JDK 创建的 ExecutorService 装饰为 ListeningExecutorService。接下来,创建的任务,并提交 submit 到这个 ExecutorService 里。submit 方法返回 ListenableFuture 接口实例(内部实现其实就是 ListenableFutureTask 对象)。Futures 工具类的 addCallback 方法用于添加在任务执行回调的监听器。

+

类似于 JDK 的 CompletionService,实现 Guava 的 ListeningExecutorService 也是通过重写 FutureTask 的 done 方法完成的。FutureTask 对应的子类就是 ListenableFutureTask(事实上,Guava 版本 19 开始 ListenableFutureTask 类替换成立了 TrustedListenableFutureTask 类 [ github ],这里暂不展开分析)。实现 ListenableFutureTask 的核心代码如下 [ src ]:

+
1
2
3
4
5
6
7
8
9
10
11
private final ExecutionList executionList = new ExecutionList();

@Override
public void addListener(Runnable listener, Executor exec) {
executionList.add(listener, exec);
}

@Override
protected void done() {
executionList.execute();
}
+

之前查看 submit 方法实现源码时,看到该方法内部会调用 newTaskFor 方法创建 FutureTask。相应的 JDK 的 AbstractExecutorService 的 newTaskFor 也 Guava 的 AbstractListeningExecutorService 被重写为 [ src ]:

+
1
2
3
@Override protected final <T> ListenableFutureTask<T> newTaskFor(Callable<T> callable) {
return ListenableFutureTask.create(callable);
}
+

这样在线程池中运行任务的不再是 FutureTask,而变成了 ListenableFutureTask。任务完成后调用 done 方法,而 done 方法就去执行该任务关联的监听器列表,即 executionList.execute()

+

再来看下 Futures 工具类的 addCallback 方法的实现 [ src ]:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public static <V> void addCallback(final ListenableFuture<V> future,
final FutureCallback<? super V> callback, Executor executor) {
Preconditions.checkNotNull(callback);
Runnable callbackListener = new Runnable() {
@Override
public void run() {
final V value;
try {
// TODO(user): (Before Guava release), validate that this
// is the thing for IE.
value = getUninterruptibly(future);
} catch (ExecutionException e) {
callback.onFailure(e.getCause());
return;
} catch (RuntimeException e) {
callback.onFailure(e);
return;
} catch (Error e) {
callback.onFailure(e);
return;
}
callback.onSuccess(value);
}
};
future.addListener(callbackListener, executor);
}
+

ListenableFuture API 功能的完整介绍参见 ListenableFutureExplained,本文不再展开。

+

Fork/Join 框架

+

一个大的任务可能会由多个子任务组成,比如整个任务A,由任务B 和任务C 组成,而任务B 又可以被分解为任务D 和任务E,如下图所示。任务分解组合问题,利用 ListenableFuture 的回调将子任务组合起来是一种解决办法,但还是不够优雅简洁。Java 7 引入的 Fork/Join 框架,就是以这种方式设计的。Fork/Join 框架编程的风格就是,将任务分解为多个子任务,并行执行,然后将结果组合起来,即分而治之。ExecutorService 适合解决相互独立的任务,而 Fork/Join 框架适合解决任务分解组合的情况 [ ref ]。

+任务的分治 +

其实整个 java.util.concurrent 包是由 JSR-166 规范引入的,Fork/Join 框架就是其中的 jsr166y。JSR-166 由 Doug Lea 主导,是主要设计和代码实现者,而 jsr166y 最初源自他发表于 2000 年的论文“A Java Fork/Join Framework”(msa pdf)。

+

工作窃取

+

Fork/Join 框架采用工作窃取(work stealing)的任务调度机制 [ ref ]:

+
    +
  • 每一个工作线程维护自己的调度队列中的可运行任务。
  • +
  • 队列以双端队列 deque 的形式被维护,不仅支持 LIFO(last-in-first-out 后进先出)的 push 和 pop 操作,还支持 FIFO(first-in-first-out 先进先出)的 take 操作。
  • +
  • 对于一个给定的工作线程来说,任务所产生的子任务将会被放入到工作者自己的双端队列 deque 中。
  • +
  • 工作线程使用 LIFO(最早的优先)的顺序,通过弹出任务来处理队列中的任务。
  • +
  • 当一个工作线程的本地没有任务去运行的时候,它将使用 FIFO 的规则尝试随机的从别的工作线程中拿(“窃取 steal”)一个任务去运行。
  • +
  • 当一个工作线程触及了 join 操作,如果可能的话它将处理其他任务,直到目标任务被告知已经结束(通过 isDone 方法)。所有的任务都会无阻塞的完成。
  • +
  • 当一个工作线程无法再从其他线程中获取任务和失败处理的时候,它就会退出(通过 yields, sleeps, 和/或者优先级调整)并经过一段时间之后再度尝试直到所有的工作线程都被告知他们都处于空闲的状态。在这种情况下,他们都会阻塞直到其他的任务再度被上层调用。
  • +
+work stealing +

使用 LIFO 规则来处理每个工作线程的自己任务,窃取别的工作线程的任务却使用 FIFO 规则,这是一种被广泛使用的进行递归 fork/join 设计的一种调优手段。这种模式有以下两个优点:它通过窃取工作线程队列反方向的任务减少了竞争。同时,它利用了递归的分治算法越早的产生大任务这一特点。因此,更早期被窃取的任务有可能会提供一个更大的单元任务,从而使得窃取线程能够在将来进行递归分解。

+

这些规则的结果是,拥有相对细粒度的基本任务,比那些仅仅使用粗粒度划分或没有使用递归分解的任务运行更快。

+

使用示例

+

ForkJoinPool 类是用于执行 ForkJoinTask 的 ExecutorService。在构造过程中,可以在构造函数中指定线程池的大小。如果使用的是默认的无参构造函数,那么会创建大小等同于可用处理器数量的线程池。ForkJoinPool 类的典型方法:

+
1
2
3
4
5
6
public void execute(ForkJoinTask<?> task)
异步,不需要等待计算结果,只是将任务提交给线程池
public <T> T invoke(ForkJoinTask<T> task)
同步,等待计算结束,并返回计算结果值
public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task)
异步,不需要等待计算结果,只是将任务提交给线程池
+

提交到 ForkJoinPool 中的任务由 ForkJoinTask 抽象类表示。ForkJoinTask 的实现子类有 RecursiveActionRecursiveTask,以及 Java 8 新增的 CountedCompleter。RecursiveAction 用于没有返回结果的任务,RecursiveTask 用于返回结果的任务。CountedCompleter 用于完成动作会触发另外一个动作的任务 [ javadoc ]。

+

计算斐波那契数(Fibonacci number)是一个经典的分而治之的问题。Doug Lea 的论文以及 RecursiveTask 的 javadoc 都以斐波那契数为例进行说明。斐波那契数定义公式为:

+

Fn=Fn1+Fn2F_{n}=F_{n-1}+F_{n-2} +

+

F0=0,F1=1F_{0}=0, F_{1}=1 +

+

使用 Fork/Join 框架计算斐波那契数的示例代码如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package concurrent;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

public class ForkJoinMain {

public static class Fibonacci extends RecursiveTask<Integer> {
final int n;

public Fibonacci(int n) {
this.n = n;
}

protected Integer compute() {
if (n <= 1)
return n;
Fibonacci f1 = new Fibonacci(n - 1);
Fibonacci f2 = new Fibonacci(n - 2);
f1.fork();
return f2.compute() + f1.join();
}
}

public static void main(String[] args) throws Exception {
ForkJoinPool pool = new ForkJoinPool();
Fibonacci fib = new Fibonacci(3);
pool.invoke(fib); // 等待计算完成
Integer result = fib.get();
System.out.println(result);
}
}
+

这个计算过程如下图所示:

+

fork-join

+

参考资料

+
    +
  1. Java 并发编程实战,Goetz,2006;第6章 任务执行 https://book.douban.com/subject/10484692/
  2. +
  3. Java并发编程的艺术,方腾飞,2015 https://book.douban.com/subject/26591326/
  4. +
  5. ExecutorService vs ExecutorCompletionService in Java https://dzone.com/articles/executorservice-vs
  6. +
  7. Java's Fork/Join vs ExecutorService - when to use which? https://stackoverflow.com/q/21156599
  8. +
  9. Java Fork Join框架 (三) 设计 http://ifeve.com/a-java-fork-join-framework-3-2/
  10. +
+ +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2017/04/javac-api/index.html b/2017/04/javac-api/index.html new file mode 100644 index 00000000..8b12524b --- /dev/null +++ b/2017/04/javac-api/index.html @@ -0,0 +1,859 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Java 编译器 javac 及 Lombok 实现原理解析 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ Java 编译器 javac 及 Lombok 实现原理解析 +

+ + +
+ + + + +
+ + +

javac 是 Java 代码的编译器[1][2],初学 Java 的时候就应该接触过。本文整理一些 javac 相关的高级用法。Lombok 库,大家平常一直在使用,但可能并不知道实现原理解析,其实 Lombok 实现上依赖的是 Java 编译器的注解处理 API(JSR-296[3],本文同时尝试解析 Lombok 的实现原理。

+ +

先来看下 javac 命令行工具。javac 命令行工具,官方文档有完整的使用说明[4],当然也可以,运行 javac -helpman javac 查看帮助信息。下面是经典的 hello world 代码:

+
1
2
3
4
5
6
package com.example;
public class Greeting {
public static void main(String[] args) {
System.out.println("hello world");
}
}
+

编译与运行:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ tree   # 代码目录结构
.
├── pom.xml
└── src
└── main
├── java
│ └── com
│ └── example
   │   └── Greeting.java
└── resources
$ mkdir -p target/classes # 创建 class 文件的存放目录
$ javac -d target/classes src/main/java/com/example/Greeting.java
$ java -cp target/classes com.example.Greeting
hello world
+

除了使用命令行工具编译 Java 代码,JDK 6 增加了规范“JSR-199: Java Compiler API”和“JSR-296: Pluggable Annotation Processing API”,开始还提供相关的 Java 编译器 API。Java 编译器的实现代码和 API 的整体结构如图所示[2:1][5]

+

Compiler Package Overview

+

绿色标注的包是官方 API(Official API),即 JSR-199 和 JSR-296,黄色标注的包为Supported API,紫色标注的包代码全部在 com.sun.tools.javac.* 包下,为内部 API(Internal API)和实现类。完整的包说明如下[2:2][5:1][6]

+
    +
  • javax.annotation.processing - 注解处理 (JSR-296)
  • +
  • javax.lang.model - 注解处理和编译器 Tree API 使用的语言模型 (JSR-296) + +
  • +
  • javax.tools - Java 编译器 API (JSR-199)
  • +
  • com.sun.source.* - 编译器的 Tree API,支持对抽象语法树做只读访问
  • +
  • com.sun.tools.javac.* - 内部 API 和实现类 +
      +
    • com.sun.tools.javac.api - javax.tools 包下的 JavaCompiler 和其他 API 的实现
    • +
    • com.sun.tools.javac.code - javax.lang.model.* 包下的 API 的实现
    • +
    • com.sun.tools.javac.comp - 编译器主要处理阶段的实现
    • +
    • com.sun.tools.javac.file - 实现访问文件系统,包括 javax.tools.StandardFileManager 的实现
    • +
    • com.sun.tools.javac.jvm - class 文件的读写,编译器的字节码生成阶段的实现
    • +
    • com.sun.tools.javac.main - 代码编译的入口实现
    • +
    • com.sun.tools.javac.model - javax.lang.model.* 包的其他实现
    • +
    • com.sun.tools.javac.parser - 读取 Java 源代码,并生成语法树
    • +
    • com.sun.tools.javac.processing - 注解处理 API 的实现
    • +
    • com.sun.tools.javac.resources - 本地化文本和版本号的资源文件
    • +
    • com.sun.tools.javac.tree - 编译器语法树相关的表示类和工具类,com.sun.source.* 包下的 API 的实现
    • +
    • com.sun.tools.javac.util - 基础工具类
    • +
    +
  • +
+

全部源码都位于 JDK 源码的 langtools 目录下。对外的 API,被编译到 rt.jarcom.sun.source.*com.sun.tools.javac.* 包,被编译到 tools.jar,在 JDK 下的具体位置是 $JAVA_HOME\lib\tools.jar。值得一提的是,langtools 目录,除了包含 javac 的实现外,还实现了 javadocjavah 等命令,编译后也是在 tools.jar 下。

+

另外,由于是内部 API 和实现类,com.sun.tools.javac.* 包下全部代码中都有标注警告:

+
+

This is NOT part of any supported API. If you write code that depends on this, you do so at your own risk. This code and its internal interfaces are subject to change or deletion without notice.

+
+

Java 编译器 API

+

首先,看下 JSR-199 引入的 Java 编译器 API(Java Compiler API)。在没有引入 JSR-199 之前,如果要通过编程方式编译 Java 代码,只能使用 com.sun.tools.javac.* 包下提供内部 API。上文提到的使用命令 javac 编译 Greeting.java 的等价写法如下:

+
1
2
3
4
5
6
7
8
import com.sun.tools.javac.main.Main;

public class JavacMain {
public static void main(String[] args) {
Main compiler = new Main("javac");
compiler.compile(new String[]{"src/main/com/example/Greeting.java", "-d", "target/classes"});
}
}
+

事实上,javac 命令的底层实现就是执行 com.sun.tools.javac.Main 类。执行 javac 命令,等价于执行 java -cp $JAVA_HOME/lib/tools.jar com.sun.tools.javac.Main

+
1
2
# 直接执行 com.sun.tools.javac.Main 类编译 Java 源代码
java -cp $JAVA_HOME/lib/tools.jar com.sun.tools.javac.Main -d target/classes src/main/java/com/example/Greeting.java
+

JSR-199,提供了 Java 编译器 API,对应的是 javax.tools.* 包。阅读包的 javadoc 容易发现,API 最核心是 javax.tools.JavaCompiler 接口,该类的 javadoc 阐述了如何使用该类,可以阅读。使用 Java 编译器 API 编译 Java 源代码,示例如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import javax.tools.*;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;

public class Jsr199Main {
public static void main(String[] args) throws IOException {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();

StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);

File file = new File("src/main/java/com/example/Greeting.java");
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(Arrays.asList(file));
List<String> options = Arrays.asList("-d", "target/classes");

compiler.getTask(null, fileManager, diagnostics, options, null, compilationUnits).call();

fileManager.close();
}
}
+

上述两种编程方式编译 Java 代码的方式,在 javac 命令的 man[4:1] 文档的 “Programmatic Interface” 小节也有提及,有兴趣可以阅读。

+

在实际开发过程中,我们基本上都是使用 Maven 或 Gradle 编译 Java 代码。Maven 编译 Java 代码,依赖的是 Maven 的 maven-compiler-plugin 插件。那么 maven-compiler-plugin 插件底层实现是否使用了 javax.tools.JavaCompiler 呢?查阅官网文档后,容易发现实际情况和猜想的一样(其实也是显而易见的结论) [doc]:

+
+

The Compiler Plugin is used to compile the sources of your project. Since 3.0, the default compiler is javax.tools.JavaCompiler (if you are using java 1.6) and is used to compile Java sources. If you want to force the plugin using javac, you must configure the plugin option forceJavacCompilerUse.

+
+

类似的,Gradle 编译 Java 代码,底层也使用了 Java 编译器 API,可以参见源码 JdkJavaCompiler [github]。

+

javac 的编译过程

+

上文提到,JSR-269,可插拔式注解处理 API(Pluggable Annotation Processing API)。注解处理,是编译过程中的其中一个阶段。要理解注解处理,需要先了解 Java 代码的编译过程。完整的编译过程如下图所示[7]

+

javac-flow.png

+

整个过程就是:

+
    +
  1. 源代码经过词法解析和语法解析(parse),生成抽象语法树(abstract syntax tree)。然后遍历抽象语法树,将遇到的符号填充入符号表(enter symbol table)。
  2. +
  3. 注解处理(annotation processing),所有注解处理器会被处理,若处理器生成新的代码或 class 文件,编译过程会重新开始,直到没有新的文件生成。每一次循环称为一个 round,也就是上图的回环过程。
  4. +
  5. 语义分析和字节码生成,包括标注(attribute)、数据及控制流分析(flow)、解语法糖(desugar)、字节码生成(generate)。
  6. +
+

把上述编译过程对应到代码中,javac 编译动作的入口是 com.sun.tools.javac.main.JavaCompiler 类,上述 3 个过程的代码逻辑集中在这个类的 compile()和 compile2()方法,如下图所示,整个编译过程主要的处理由图中标注的 8 个方法来完成[8]

+JavaCompiler compile +

具体来看下,词法解析和语法解析。Java 的词法和语法规则,在《Java语言规范》(The Java Language Specification)中定义。从底层实现上来看,com.sun.tools.javac.parser.Scanner 类,按照单个字符的方式读取 Java 源文件中的关键字和标示符等内容,然后将其转换为符合 Java 语法规范(JLS ch3)的 Token 序列。例如,针对语句 int y = x + 1; 的词法解析过程如下图所示[9]

+词法解析 +

然后,com.sun.tools.javac.parser.JavacParser 类,读取 Token 序列,将 Token 序列构造为抽象语法树 com.sun.tools.javac.tree.JCTree。语句 int y = x + 1;,生成的抽象语法树,如下图所示[9:1]

+抽象语法树 +

该语句对应的 JCTree.JCVariableDecl 对象,在 IDEA 的 debug 模式下查看,如下图所示:

+IDEA debug +

语法树中的每一个语法节点,实际上都直接或者间接地继承了 JCTree 类,并且都以静态内部类的形式定义在 JCTree 类中。Java 源文件的完整的词法解析和语法解析,由 JavacParserparseCompilationUnit 方法完成。解析完成后,方法返回 JCTree.JCCompilationUnit 类。JCTree.JCCompilationUnit 类,为某个 Java 源文件解析后的整个语法树的根节点。

+

上文提到,com.sun.source.* 包下暴露的 Tree API,提供对语法树只能做只读操作。com.sun.tools.javac.tree 包,是 com.sun.source.* 包下的 API 的实现。com.sun.source.tree.Tree 接口对应的实现类为 JCTreeTree 的子接口的实现类为 JCTree 的子类,并一一对应,比如,com.sun.source.tree.ClassTree 对应的实现类为 JCTree.JCClassDeclTree 接口及其子接口只暴露只读方法,而 JCTree 类及其子类,大部分的内部定义字段都是 public,可以直接读写。

+

主要的语法树节点 JCTree 子类,如下:

+
    +
  • JCTree.JCStatement:声明语句的语法树节点。主要的子类包括: +
      +
    • JCTree.JCBlock:语句块(JLS 14.2
    • +
    • JCTree.JCClassDecl:类声明(JLS 8.1
    • +
    • JCTree.JCForLoopfor 语句(JLS 14.14.1
    • +
    • JCTree.JCEnhancedForLoop:增强for语句(JLS 14.14.2
    • +
    • JCTree.JCIfif 语句(JLS 14.9
    • +
    • JCTree.JCReturnreturn 语句(JLS 14.7
    • +
    • JCTree.JCVariableDecl:变量声明,比如 int x = 0 语句(JLS 14.4
    • +
    • 其他(不一一列举)
    • +
    +
  • +
  • JCTree.JCExpression:表达式的语法树节点。主要的子类包括: +
      +
    • JCAssign:赋值语句表达式,比如 x = 0 语句(JLS 15.26
    • +
    • JCIdent:标识符表达式,比如 x 标识符(JLS 3.8
    • +
    • JCBinary:二元运算符,比如 x + 1 语句(JLS 15.18
    • +
    • JCLiteral:字面量运算符表达式,比如 1 字面量(JLS 3.10
    • +
    • JCTree.JCPrimitiveTypeTree:基础类型,比如 int 等类型(JLS 4.2
    • +
    +
  • +
  • JCTree.JCMethodDecl:方法声明(JLS 8.4
  • +
  • JCTree.JCCompilationUnit:编译单元,对应单个源文件内的全部内容(JLS 7.3
  • +
+

全部的各个类型的树节点的类定义,可以参见 JCTreeTree 类的 javadoc 或源代码。

+

在构造抽象语法树后,就是符号表填充阶段。在符号表填充阶段,会扫描 JCTree 语法树,遇到类型、变量、方法定义时,会它们的信息存储到符号表中,方便后续阶段进行快速查询。符号,对应的是 com.sun.tools.javac.code.Symbol 类。而 Symbol 类,是 javax.lang.model 包下 Element 的实现类,Symbol 子类是对应 Element 子类的实现。

+

Element 提供 ElementKind getKind() 方法,能获取元素类型(ElementKind)。全部的 ElementKind 共 17 种:ANNOTATION_TYPE(注解)、CLASS(类)、CONSTRUCTOR(构造方法)、ENUM(枚举)、ENUM_CONSTANT(枚举值)、EXCEPTION_PARAMETER(异常参数)、FIELD(字段)、INSTANCE_INIT(实例初始化语句块)、INTERFACE(接口)、LOCAL_VARIABLE(本地变量)、METHOD(方法)、PACKAGE(包)、PARAMETER(参数)、RESOURCE_VARIABLE(资源变量)、STATIC_INIT(静态初始化语句块)、TYPE_PARAMETER(类型参数) 以及 OTHER(其他)。

+

全部 Element 子类以及对应的 Symbol 子类,如下:

+
    +
  • PackageElement:表示包 package +
      +
    • 实现类:Symbol.PackageSymbol
    • +
    • 元素类型 ElementKindPACKAGE(包)
    • +
    +
  • +
  • TypeElement:表示类 class 或接口 interface 等 +
      +
    • 实现类:Symbol.ClassSymbol
    • +
    • 元素类型 ElementKindANNOTATION_TYPE(注解)、INTERFACE(接口)、ENUM(枚举)、CLASS(类)
    • +
    +
  • +
  • VariableElement:表示字段、枚举值、方法参数、本地变量、资源变量、异常参数 +
      +
    • 实现类:Symbol.VarSymbol
    • +
    • 元素类型 ElementKindEXCEPTION_PARAMETER(异常参数)、PARAMETER(参数)、ENUM_CONSTANT(枚举值)、RESOURCE_VARIABLE(资源变量)、LOCAL_VARIABLE(本地变量)、FIELD(字段)
    • +
    +
  • +
  • ExecutableElement:表示方法、构造方法、初始化语句块 +
      +
    • 实现类:Symbol.MethodSymbol
    • +
    • 元素类型 ElementKindCONSTRUCTOR(构造方法)、STATIC_INIT(静态初始化语句块)、INSTANCE_INIT(实例初始化语句块)、METHOD(方法)
    • +
    +
  • +
  • TypeParameterElement:表示参数化类型,即泛型尖括号内的类型 +
      +
    • 实现类:Symbol.TypeVariableSymbol
    • +
    • 元素类型 ElementKindTYPE_PARAMETER(类型参数)
    • +
    +
  • +
+

在填充符号表后,就是语义分析和代码生成,包括标注(attribute)、数据及控制流分析(flow)、解语法糖(desugar)、字节码生成(generate)阶段。

+

在实际开发时,比如常见的“找不到符号(cannot find symbol)”编译报错,就是在标注阶段的名称消解(name resolution)时触发的。编译报错示例代码,如下:

+
1
2
3
public class CantResolve {
int foo = bar;
}
+

编译错误的提示内容:

+
1
2
3
找不到符号
符号: 变量 bar
位置: 类 CantResolve
+

编译过程的各个阶段的更详细的阐述可以阅读书籍[8:1][10],本文不再展开。

+

可插拔式注解处理 API

+

JSR-296 定义的可插拔式注解处理 API 在 javax.annotation.processing 包下,最核心的接口是 javax.annotation.processing.Processor,通过实现这个接口来定义自己的注解处理器。

+

编译器工具与 Processor 实现类的交互过程是:

+
    +
  • 如果存在没有被使用的 Processor 对象,就调用无参构造方法创建一个 Processor 实例。
  • +
  • 然后,编译器工具调用注解处理器的 init 方法,初始化注解处理器,方法参数是 ProcessingEnvironment 对象(注解处理的执行环境,从环境中获得相关工具类,比如 Elements)。
  • +
  • 之后,编译器工具调用注解处理器的 getSupportedAnnotationTypes(查询该注解处理器支持的注解集合)、getSupportedOptions(查询该注解处理器支持的参数选项集合)、getSupportedSourceVersion(查询该注解处理器支持的源代码版本)方法。
  • +
  • 最后,调用注解处理器的 process 方法。
  • +
+

注解处理会执行多轮(round),每轮都会调用 process 方法,调用时传入在上一轮的源代码和 class 文件中找到的该注解处理器支持的注解子集。在处理注解期间,如果任何注解处理器生成了新的源文件或 class 文件,编译器将回到解析、填充符号表、注解处理的过程,直到没有新的文件生成。

+

init 方法的参数 ProcessingEnvironment 对象,为注解处理的执行环境,从环境中获得相关工具类,比如,Elements 类,用于操作 Element 元素;Filer 类,用于生成新的文件;Messager 类,用于报告编译错误、告警或其他消息。另外,ProcessingEnvironment,也可以获得传递给注解处理器参数选项。

+

AbstractProcessor 抽象类,实现类了 Processor 接口,用于简化实际的注解处理器类的实现。该类通过读取 @SupportedAnnotationTypes@SupportedOptions@SupportedSourceVersion 注解值,来实现 Processor 接口对应的三个方法。

+

用命令行编译代码时,javac 编译器,会搜索可用的注解处理器。搜索路径可以通过参数选项 -processorpath 指定,如果未指定,将使用 classpath。注解处理器,可以通过 -processor 参数选项指定。若未通过 -processor 参数选项指定,注解处理器会使用 SPI 方式定位,在搜索路径查找 META-INF/services/javax.annotation.processing.Processor 文件。文件中填写的是注解处理器类名(多个的话,换行填写),编译器就会自动使用这里填写的注解处理器进行注解处理。另外,编译器 API 的 CompilationTasksetProcessors 方法也可以传入注解处理器。

+

如果注解处理器支持参数选项,编译时,参数选项可以用 -Akey[=value] 的方式传递[4:2]

+

扫描语法树

+

JDK 源码的 langtools 目录下,提供了示例注解处理器 CheckNamesProcessor,一个检查命名的注解处理器。CheckNamesProcessor 注解处理器,内部实现了 javax.lang.model.util 包下 ElementScanner,用来扫描 Element 元素符号,然后检查类命名、方法命名、字段命名、参数命名等是否符合命名规范,如果不符合命名规范,就打印编译器告警。

+

javax.lang.model.util.ElementScanner8 类用于扫描 Element 的核心方法:

+
1
public final R scan(Element e)
+

对语法树的扫描,com.sun.source.util 包下,提供了语法树扫描器 TreeScanner,用于扫描语法树上的树节点 Tree。类似的,com.sun.tools.javac.tree.TreeScanner,用于扫描语法树上的树节点 JCTree

+

com.sun.source.util.TreeScanner 类用于扫描语法树的核心方法:

+
1
public R scan(Tree node, P p)
+

com.sun.tools.javac.tree.TreeScanner 类用于扫描语法树的核心方法:

+
1
public void scan(JCTree tree)
+

需要注意的是,注解处理器的 process 方法,传递过来的是 Element 对象,需要先获得 Element 对象关联的 TreeJCTree 对象,才能扫描语法树。工具类 com.sun.source.util.Trees 提供了这样的桥接能力,该类的实现类为 com.sun.tools.javac.api.JavacTreesTrees 的相关方法:

+
1
2
3
4
// 通过 ProcessingEnvironment 获得 Trees 对象
public static Trees instance(ProcessingEnvironment env)
// 通过 Element 获得 Tree
public abstract Tree getTree(Element element);
+

类似的,JavacTrees 的相关方法:

+
1
2
3
4
// 通过 ProcessingEnvironment 获得 JavacTrees 对象
public static JavacTrees instance(ProcessingEnvironment env)
// 通过 Element 获得 JCTree
public JCTree getTree(Element element)
+

使用 ElementScannerTreeScanner 扫描语法树的示例注解处理器,参见 VisitProcessor

+

修改语法树

+

在语法解析时,JavacParser 类,底层实现上利用 TreeMaker 类构造的语法树各个节点。TreeMaker 类,封装了创建语法树节点的方法,部分常用的方法举例:

+
    +
  • TreeMaker.Assign 方法:用于生成赋值语句的语法树节点 JCTree.JCAssign
  • +
  • TreeMaker.Binary 方法:用于生成二元操作符的语法树节点 JCTree.JCBinary
  • +
  • TreeMaker.Block 方法:用于生成语句块的语法树节点 JCTree.JCBlock
  • +
  • TreeMaker.VarDef 方法:用于生成变量定义的语法树节点 JCTree.JCVariableDecl
  • +
  • TreeMaker.MethodDef 方法:用于生成方法定义的语法树节点 JCTree.JCMethodDecl
  • +
  • 等等
  • +
+

在注解处理阶段,init 方法传入了 ProcessingEnvironment 对象,通过该对象可以获得当前上下文中的 TreeMaker 对象,然后就可以利用 TreeMaker 创建新的语法树节点。

+

语句 int y = x + 1;,使用 TreeMaker 构造对应的 JCTree.JCVariableDecl,示例代码如下:

+
1
2
3
4
5
6
Name x = ...
Name y = names.fromString("y");
// x + 1
JCTree.JCBinary binary = maker.Binary(JCTree.Tag.PLUS, maker.Ident(x), maker.Literal(TypeTag.INT, 1));
// int y = x + 1
JCTree.JCVariableDecl decl = maker.VarDef(maker.Modifiers(0), y, maker.TypeIdent(TypeTag.INT), binary);
+

因为 JCTree 类及其子类的大部分的内部定义字段都是 public,可以直接读写,所以要想修改语法树,可以直接相关字段的值。比如,把 int y = x + 1 语句对应的 JCTree.JCVariableDecl 树节点改为 int y = 42,可以直接修改 JCTree.JCVariableDeclinit 字段,示例代码如下:

+
1
2
JCTree.JCVariableDecl decl = ...
decl.init = maker.Literal(TypeTag.INT, 42);
+

修改语法树的示例代码,参见 PlusProcessor 注解处理器。该示例注解处理器,修改 @PlusOne 注解标注的方法的内部实现,改造后的方法的逻辑为,返回请求参数值加 1 后的值。比如,修改语法树前,func 方法实现如下:

+
1
2
3
4
@PlusOne
public int func(int x) {
return x * x;
}
+

PlusProcessor 注解处理器修改语法树后,func 方法变成:

+
1
2
3
public int func(int x) {
return x + 1;
}
+

修改方法内部实现的核心代码如下:

+
1
2
3
4
5
6
7
8
private void modifyToPlusOneMethod(JCTree.JCMethodDecl methodDecl) {
JCTree.JCVariableDecl param = methodDecl.params.head;
// x + 1
JCTree.JCBinary binary = maker.Binary(JCTree.Tag.PLUS, maker.Ident(param.name), maker.Literal(TypeTag.INT, 1));
JCTree.JCReturn ret = maker.Return(binary);
// 修改方法内部实现
methodDecl.body.stats = List.of(ret);
}
+

这个注解处理器仅仅用于示例,没有其他实际用途。实际开发中,Lombok 库被广泛使用,其底层实现就是利用注解处理器修改由 Lombok 注解(@Data@Getter@Setter 等)标注的代码的语法树,自动生成样板代码。针对 Lombok 库实现原理的解析,参见下文。

+

创建新文件

+

可插拔式注解处理 API,定义了 javax.annotation.processing.Filer 接口,这个接口提供了让注解处理器创建新文件的能力。createSourceFile 方法,用于创建新的源代码文件,createClassFile,用于创建新的 class 文件。

+

来看下示例代码,GreetingProcessor 注解处理器。该注解处理器功能就是基于 Filer 自动生成 Greeting 类(打印 "hello world")。核心代码片段如下:

+
1
2
3
4
5
6
7
8
9
10
private boolean generateGreeting(String className) throws Exception {
byte[] bytes = Files.readAllBytes(Paths.get(this.getClass().getResource("/Greeting.tpl").toURI()));
String greetingTemplate = new String(bytes, StandardCharsets.UTF_8);
String greetingSourceCode = String.format(greetingTemplate, LocalDateTime.now(), className);
JavaFileObject fileObject = filer.createSourceFile(className);
try (PrintWriter writer = new PrintWriter(fileObject.openWriter())) {
writer.println(greetingSourceCode);
}
return true;
}
+

模板文件 Greeting.tpl 的内容为:

+
1
2
3
4
5
6
7
8
import javax.annotation.Generated;

@Generated(value = "by GreetingProcessor", date = "%s")
public class %s {
public static void main(String[] args) {
System.out.println("hello world");
}
}
+

在实际开发中,MapStruct 是流行的用于 Bean 之间映射的工具库之一,其底层实现就是基于注解处理器 API。阅读源码,容易发现 MapStruct 库内部实现的注解处理器是 org.mapstruct.ap.MappingProcessorjavadocgithub)。MappingProcessor 注解处理器生成的 Mapper 实现类,底层调用的就是 Filer 接口的 createSourceFile 方法,参见源代码 github。另外,MapStruct 库的注解处理器生成源代码文件利用了模板引擎 FreeMarker 库,可以参见 javadocgithub

+

另外值得一提的是,除了模板引擎,生成源代码文件也可以使用 JavaPoet 工具库,JavaPoet 库提供 Java API 来生成 .java 源文件。笔者基于 JavaPoet 库,实现了能处理类似 Lombok 的 @Builder 注解的 BuilderProcessor 注解处理器,有兴趣的话可以查阅(附注:实际的 Lombok 的 @Builder 注解实现原理是修改语法树,并不是生成新的 Builder 类文件)。

+

Lombok 的实现原理

+

依赖 JSR-269 实现的第三方工具库有很多[11],比如代码自动生成的 LombokMapStruct 和 Google Auto,代码检查的 Checker 和 Google Error Prone,编译阶段完成依赖注入的 Google Dagger 2 等。笔者在实际开发中就经常使用 Lombok 库和 MapStruct 库。MapStruct 库的实现原理,上文已经做了简单介绍。现在来看下 Lombok 的实现原理。

+

Lombok 提供 @NonNull@Getter, @Setter, @ToString, @EqualsAndHashCode, @Data 等注解,自动生成常见样板代码 boilerplate,解放开发效率。Lombok 支持 javac 和 ecj (Eclipse Compiler for Java)。对于 javac 编译器对应的注解处理器是 LombokProcessor,然后经过一些处理过程,每个注解都会有特定的 handler 来处理,@NonNull 对应 HandleNonNull@Getter 对应 HandleGetter@Setter 对应 HandleSetter@ToString 对应 HandleToString@EqualsAndHashCode 对应 HandleEqualsAndHashCode@Data 对应 HandleData。如果想要改造 Lombok 项目,让 Lombok 支持新的注解,其实就是添加新的 handler。关于 Lombok 原理以及如何为 Lombok 贡献代码,文档 “Documentation for lombok developers”[12],也有简单介绍,可以阅读。

+

阅读这些 handler 的实现,可以看到样板代码的生成依赖的就是 com.sun.tools.javac.* 包。最新版的 Lombok 源码太繁杂了,可以从早期版本入手,比如 v0.8.1 版本。

+

现在来看下如何实现 @Getter 注解。@Getter 注解的功能,就是自动生成类字段的 getter 方法,如果注解加到 class 上,就生成类的全部字段的 getter 方法。假设字段名叫 foo,那边生成的 getter 方法如下所示:

+
1
2
3
public int getFoo() {
return foo;
}
+

参考 Lombok v0.8.1 和 v0.9.3 的 HandleGetter 实现源码(从 v0.9.3 版本开始,@Getter 注解支持加到 class 上,之前只能加到字段上),提取出其中的核心代码,实现 @Getter 的示例代码如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private void handleGetter(JCTree.JCClassDecl classDecl) {
List<JCTree> methodDecls = List.nil();
for (JCTree tree : classDecl.defs) {
if (tree instanceof JCTree.JCVariableDecl) {
// 创建 getter 方法
JCTree.JCVariableDecl fieldDecl = (JCTree.JCVariableDecl) tree;
String methodGetterName = Utils.toGetterName(fieldDecl);
if (!Utils.methodExists(methodGetterName, classDecl)) {
JCTree.JCMethodDecl methodGetter = this.createGetter(fieldDecl);
methodDecls = methodDecls.append(methodGetter);
}
}
}
classDecl.defs = classDecl.defs.appendList(methodDecls);
}

// 生成 getter 方法
private JCTree.JCMethodDecl createGetter(JCTree.JCVariableDecl field) {
JCTree.JCStatement returnStatement = maker.Return(maker.Ident(field));
JCTree.JCBlock methodBody = maker.Block(0, List.of(returnStatement));
Name methodName = names.fromString(Utils.toGetterName(field));
JCTree.JCExpression methodType = (JCTree.JCExpression) field.getType();

return maker.MethodDef(maker.Modifiers(Flags.PUBLIC), methodName, methodType,
List.nil(), List.nil(), List.nil(), methodBody, null);
}
+

容易发现,实现 @Getter 注解依赖的 JCTreeTreeMaker 等相关类,这些类在上文都已经提及并介绍,不再复述。

+

为了加深对 javac 内部 API 的理解,笔者参考 Lombok 的源码,实现了支持类似 Lombok 的 @Data@Getter@Setter@Slf4j 注解的注解处理器MyLombokProcessor,代码参见 GitHub。

+

附注:本文的示例代码的完整代码,都可以在 GitHub 的 annotation-processor-demo[13] 仓库上找到。

+

参考资料

+
+
+
    +
  1. OpenJDK: The Java programming language Compiler Group http://openjdk.java.net/groups/compiler/ ↩︎

    +
  2. +
  3. The Java Programming Language Compiler, javac https://docs.oracle.com/javase/8/docs/technotes/guides/javac/ ↩︎ ↩︎ ↩︎

    +
  4. +
  5. 2011-05 How does lombok work? http://stackoverflow.com/q/6107197 ↩︎

    +
  6. +
  7. javac https://docs.oracle.com/javase/8/docs/technotes/tools/unix/javac.html https://www.mankier.com/1/javac ↩︎ ↩︎ ↩︎

    +
  8. +
  9. OpenJDK: Compiler Package Overview https://openjdk.org/groups/compiler/doc/package-overview/index.html ↩︎ ↩︎

    +
  10. +
  11. OpenJDK: The Hitchhiker's Guide to javac https://openjdk.org/groups/compiler/doc/hhgtjavac/index.html ↩︎

    +
  12. +
  13. OpenJDK: Compilation Overview https://openjdk.org/groups/compiler/doc/compilation-overview/index.html ↩︎

    +
  14. +
  15. 深入理解Java 7虚拟机,周志明 第2版2013:第10章 早期 (编译期) 优化 ↩︎ ↩︎

    +
  16. +
  17. 莫枢 RednaxelaFX :JVM分享——Java程序的编译、加载与执行 http://www.valleytalk.org/2011/07/28/java-程序的编译,加载-和-执行/ ↩︎ ↩︎

    +
  18. +
  19. 深入解析Java编译器:源码剖析与实例详解,马智 2019 ↩︎

    +
  20. +
  21. Awesome Java Annotation Processing https://github.com/gunnarmorling/awesome-annotation-processing ↩︎

    +
  22. +
  23. Documentation for lombok developers https://projectlombok.org/contributing/ ↩︎

    +
  24. +
  25. annotation-processor-demo https://github.com/yulewei/annotation-processor-demo ↩︎

    +
  26. +
+
+ +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2017/05/java-method-parameter/index.html b/2017/05/java-method-parameter/index.html new file mode 100644 index 00000000..cdf40c09 --- /dev/null +++ b/2017/05/java-method-parameter/index.html @@ -0,0 +1,686 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Java 运行时获取方法参数名 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ Java 运行时获取方法参数名 +

+ + +
+ + + + +
+ + +

本文整理 Java 运行时获取方法参数名的两种方法,Java 8 的最新的方法和 Java 8 之前的方法。

+

Java 8 的新特性

+

翻阅 Java 8 的新特性,可以看到有这么一条“JEP 118: Access to Parameter Names at Runtime”。这个特性就是为了能运行时获取参数名新加的。这个 JEP 只是功能增强的提案,并没有最终实现的 JDK 相关的 API 的介绍。查看“Enhancements to the Reflection API” 会看到如下介绍:

+ +
+

Enhancements in Java SE 8
+Method Parameter Reflection: You can obtain the names of the formal parameters of any method or constructor with the method java.lang.reflect.Executable.getParameters. However, .class files do not store formal parameter names by default. To store formal parameter names in a particular .class file, and thus enable the Reflection API to retrieve formal parameter names, compile the source file with the -parameters option of the javac compiler.

+
+ +

javac 文档中关于 -parameters 的介绍如下 [ doc man ]:

+
+

-parameters
+Stores formal parameter names of constructors and methods in the generated class file so that the method java.lang.reflect.Executable.getParameters from the Reflection API can retrieve them.

+
+

现在试验下这个特性。有如下两个文件:

+
1
2
3
4
5
6
7
package com.test;

public class TestClass {
public int sum(int num1, int num2) {
return num1 + num2;
}
}
+
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.test;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

public class Java8Main {
public static void main(String[] args) throws NoSuchMethodException {
Method method = TestClass.class.getDeclaredMethod("sum", int.class, int.class);
Parameter[] parameters = method.getParameters();
for (Parameter parameter : parameters) {
System.out.println(parameter.getType().getName() + " " + parameter.getName());
}
}
}
+

先试试 javac 不加 -parameters 编译,结果如下:

+
1
2
3
4
$ javac -d "target/classes" src/main/java/com/test/*.java
$ java -cp "target/classes" com.test.Java8Main
int arg0
int arg1
+

加上 -parameters 后,运行结果如下:

+
1
2
3
4
$ javac -d "target/classes" -parameters src/main/java/com/test/*.java
$ java -cp "target/classes" com.test.Java8Main
int num1
int num2
+

可以看到,加上 -parameters 后,正确获得了参数名。实际开发中,很少直接用命令行编译 Java 代码,项目一般都会用 maven 管理。在 maven 下,只需修改 pom 文件的 maven-compiler-plugin 插件配置即可,就是加上了 compilerArgs 节点 [ doc ],如下:

+
1
2
3
4
5
6
7
8
9
10
11
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
+

实现原理

+

“Enhancements in Java SE 8”提到,参数名信息回存储在 class 文件中。现在试试用 javap doc man)命令反编译生成的 class 文件。反编译 class 文件:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
$ javap -v -cp "target/classes" com.test.TestClass
Classfile /Users/yulewei/IdeaProjects/hellojava/target/classes/com/test/TestClass.class
Last modified 2017-5-2; size 305 bytes
MD5 checksum 24b99fec7f3062f5de1c3ca4270a1d36
Compiled from "TestClass.java"
public class com.test.TestClass
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #3.#15 // java/lang/Object."<init>":()V
#2 = Class #16 // com/test/TestClass
#3 = Class #17 // java/lang/Object
#4 = Utf8 <init>
#5 = Utf8 ()V
#6 = Utf8 Code
#7 = Utf8 LineNumberTable
#8 = Utf8 sum
#9 = Utf8 (II)I
#10 = Utf8 MethodParameters
#11 = Utf8 num1
#12 = Utf8 num2
#13 = Utf8 SourceFile
#14 = Utf8 TestClass.java
#15 = NameAndType #4:#5 // "<init>":()V
#16 = Utf8 com/test/TestClass
#17 = Utf8 java/lang/Object
{
public com.test.TestClass();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 3: 0

public int sum(int, int);
descriptor: (II)I
flags: ACC_PUBLIC
Code:
stack=2, locals=3, args_size=3
0: iload_1
1: iload_2
2: iadd
3: ireturn
LineNumberTable:
line 6: 0
MethodParameters:
Name Flags
num1
num2
}
SourceFile: "TestClass.java"
+

在结尾的 MethodParameters 属性就是,实现运行时获取方法参数的核心。这个属性是 Java 8 的 class 文件新加的,具体介绍可以参考官方“Java 虚拟机官方”文档的介绍,“4.7.24. The MethodParameters Attribute”,doc

+

class 文件中的调试信息

+

上文介绍了 Java 8 通过新增的反射 API 运行时获取方法参数名。那么在 Java 8 之前,有没有办法呢?或者在编译时没有开启 -parameters 参数,又如何动态获取方法参数名呢?其实 class 文件中保存的调试信息就可以包含方法参数名。

+

javac-g 选项可以在 class 文件中生成调试信息,官方文档介绍如下 [ doc man ]:

+
+

-g
+Generates all debugging information, including local variables. By default, only line number and source file information is generated.
+-g:none
+Does not generate any debugging information.
+-g:[keyword list]
+Generates only some kinds of debugging information, specified by a comma separated list of keywords. Valid keywords are:
+   source
+     Source file debugging information.
+   lines
+     Line number debugging information.
+   vars
+     Local variable debugging information.

+
+

可以看到默认是包含源代码信息和行号信息的。现在试验下不生成调试信息的情况:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
$ javac -d "target/classes" src/main/java/com/test/*.java -g:none
$ javap -v -cp "target/classes" com.test.TestClass
Classfile /Users/yulewei/IdeaProjects/hellojava/target/classes/com/test/TestClass.class
Last modified 2017-5-2; size 177 bytes
MD5 checksum 559f5448154e4d7dd089f8155d8d0f55
public class com.test.TestClass
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #3.#9 // java/lang/Object."<init>":()V
#2 = Class #10 // com/test/TestClass
#3 = Class #11 // java/lang/Object
#4 = Utf8 <init>
#5 = Utf8 ()V
#6 = Utf8 Code
#7 = Utf8 sum
#8 = Utf8 (II)I
#9 = NameAndType #4:#5 // "<init>":()V
#10 = Utf8 com/test/TestClass
#11 = Utf8 java/lang/Object
{
public com.test.TestClass();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return

public int sum(int, int);
descriptor: (II)I
flags: ACC_PUBLIC
Code:
stack=2, locals=3, args_size=3
0: iload_1
1: iload_2
2: iadd
3: ireturn
}
+

对比上文的反编译结果,可以看到,输出结果中的 Compiled from "TestClass.java" 没了,Constant pool 中也不再有 LineNumberTableSourceFilecode 属性里的 LocalVariableTable 属性也没了(当然,因为编译时没加 -parameters 参数,MethodParameters 属性自然也没了)。若选择不生成这两个属性,对程序运行产生的最主要的影响就是,当抛出异常时,堆栈中将不会显示出错代码所属的文件名和出错的行号,并且在调试程序的时候,也无法按照源码行来设置断点。

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
$ javac -d "target/classes" src/main/java/com/test/*.java -g:vars
$ javap -v -cp "target/classes" com.test.TestClass
Classfile /Users/yulewei/IdeaProjects/hellojava/target/classes/com/test/TestClass.class
Last modified 2017-5-2; size 302 bytes
MD5 checksum d430f817e0e2cfafc9095279c67aaa72
public class com.test.TestClass
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #3.#15 // java/lang/Object."<init>":()V
#2 = Class #16 // com/test/TestClass
#3 = Class #17 // java/lang/Object
#4 = Utf8 <init>
#5 = Utf8 ()V
#6 = Utf8 Code
#7 = Utf8 LocalVariableTable
#8 = Utf8 this
#9 = Utf8 Lcom/test/TestClass;
#10 = Utf8 sum
#11 = Utf8 (II)I
#12 = Utf8 num1
#13 = Utf8 I
#14 = Utf8 num2
#15 = NameAndType #4:#5 // "<init>":()V
#16 = Utf8 com/test/TestClass
#17 = Utf8 java/lang/Object
{
public com.test.TestClass();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/test/TestClass;

public int sum(int, int);
descriptor: (II)I
flags: ACC_PUBLIC
Code:
stack=2, locals=3, args_size=3
0: iload_1
1: iload_2
2: iadd
3: ireturn
LocalVariableTable:
Start Length Slot Name Signature
0 4 0 this Lcom/test/TestClass;
0 4 1 num1 I
0 4 2 num2 I
}
+

可以看到,code 属性里的出现了 LocalVariableTable 属性,这个属性保存的就是方法参数和方法内的本地变量。在演示代码的 sum 方法中没有定义本地变量,若存在的话,也将会保存在 LocalVariableTable 中。

+

javap-v 选项会输出全部反编译信息,若只想看行号和本地变量信息,改用 -l 即可。输出结果如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ javap -l -cp "target/classes" com.test.TestClass
public class com.test.TestClass {
public com.test.TestClass();
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/test/TestClass;

public int sum(int, int);
LocalVariableTable:
Start Length Slot Name Signature
0 4 0 this Lcom/test/TestClass;
0 4 1 num1 I
0 4 2 num2 I
}
+

若要全部生成全部提示信息,编译参数需要改为 -g:source,lines,vars。一般在 IDE 下调试代码都需要调试信息,所以这三个参数默认都会开启。IDEA 下的 javac 默认参数设置,如图:

+

IDEA 默认的 javac 设置

+

若使用 maven,maven 的默认的编译插件 maven-compiler-plugin 也会默认开启这三个参数 [doc],经实际验证也包括了LocalVariableTable

+

同样的,gradle 默认也会包含调试信息 [ doc ]。

+

代码如何实现

+

上文中讲了 class 文件中的调试信息中 LocalVariableTable 属性里就包含方法名参数,这就是运行时获取方法参数名的方法。读取这个属性,JDK 并没有提供 API,只能借助第三方库解析 class 文件实现。

+

要解析 class 文件典型的工具库有 ObjectWeb 的 ASM(wikihomemvnjavadoc)、Apache 的 Commons BCEL(wikihomemvnjavadoc)、 日本教授开发的 Javassist(wikigithubmvnjavadoc)等。其中 ASM 使用最广,使用 ASM 的知名开源项目有,AspectJ, CGLIB, Clojure, Groovy, JRuby, Jython, TopLink等等 [ ref ]。当然使用 BCEL 的项目也很多 [ ref ]。ASM 相对其他库的 jar 更小,运行速度更快 [ javadoc ]。目前 asm-5.0.1.jar 文件大小 53 KB,BCEL 5.2 版本文件大小 520 KB,javassist-3.20.0-GA.jar 文件大小 751 KB。jar 包文件小,自然意味着代码量更少,提供的功能自然也少了。

+

BCEL

+

先来看看用 BCEL 获取方法参数名的写法,代码如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.test;
import org.apache.bcel.Repository;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.LocalVariable;
import org.apache.bcel.classfile.LocalVariableTable;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.Type;

public class BcelMain {

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
java.lang.reflect.Method m = TestClass.class.getDeclaredMethod("sum", int.class, int.class);
JavaClass clazz = Repository.lookupClass("com.test.TestClass");
Method bcelMethod = clazz.getMethod(m);
LocalVariableTable lvt = bcelMethod.getLocalVariableTable();
for (LocalVariable lv : lvt.getLocalVariableTable()) {
System.out.println(lv.getName() + " " + lv.getSignature() + " " + Type.getReturnType(lv.getSignature()));
}
}
}
+

输出结果:

+
1
2
3
this  Lcom/test/TestClass;  com.test.TestClass
num1 I int
num2 I int
+

ASM

+

ASM 的写法如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.test;
import org.objectweb.asm.*;

public class AsmMain {

public static void main(String[] args) throws Exception {
ClassReader classReader = new ClassReader("com.test.TestClass");
classReader.accept(new ParameterNameDiscoveringVisitor("sum", "(II)I"), 0);
}

private static class ParameterNameDiscoveringVisitor extends ClassVisitor {
private final String methodName;
private final String methodDesc;

public ParameterNameDiscoveringVisitor(String name, String desc) {
super(Opcodes.ASM5);
this.methodName = name;
this.methodDesc = desc;
}

@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
if (name.equals(this.methodName) && desc.equals(methodDesc))
return new LocalVariableTableVisitor();
return null;
}
}

private static class LocalVariableTableVisitor extends MethodVisitor {

public LocalVariableTableVisitor() {
super(Opcodes.ASM5);
}

@Override
public void visitLocalVariable(String name, String description, String signature, Label start, Label end, int index) {
System.out.println(name + " " + description);
}
}
}
+

Spring 框架

+

若使用 Spring 框架,对于运行时获取参数名,Spring 提供了内建支持,对应的实现类为 DefaultParameterNameDiscovererjavadoc)。该类先尝试用 Java 8 新的反射 API 获取方法参数名,若无法获取,则使用 ASM 库读取 class 文件的 LocalVariableTable,对应的代码分别为 StandardReflectionParameterNameDiscovererLocalVariableTableParameterNameDiscoverer

+

参考资料

+ + +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2017/11/zookeeper-note/index.html b/2017/11/zookeeper-note/index.html new file mode 100644 index 00000000..139391eb --- /dev/null +++ b/2017/11/zookeeper-note/index.html @@ -0,0 +1,860 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ZooKeeper 学习笔记 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ ZooKeeper 学习笔记 +

+ + +
+ + + + +
+ + +

ZooKeeper 介绍

+

ZooKeeper(wikihomegithub) 是用于分布式应用的开源的分布式协调服务。通过暴露简单的原语,分布式应用能在之上构建更高层的服务,如同步、配置管理和组成员管理等。在设计上易于编程开发,并且数据模型使用了熟知的文件系统目录树结构 [ doc ]。

+ +

共识与 Paxos

+

在介绍 ZooKeeper 之前,有必要了解下 Paxos 和 Chubby。2006 年 Google 在 OSDI 发表关于 BigtableChubby 的两篇会议论文,之后再在 2007 年 PODC 会议上发表了论文“Paxos Made Live”,介绍 Chubby 底层实现的共识(consensus)协议 Multi-Paxos,该协议对 Lamport 的原始 Paxos 算法做了改进,提高了运行效率 [ ref ]。Chubby 作为锁服务被 Google 应用在 GFS 和 Bigtable 中。受 Chubby 的影响,来自 Yahoo 研究院的 Benjamin Reed 和 Flavio Junqueira 等人开发了被业界称为开源版的 Chubby 的 ZooKeeper(内部实现事实上稍有不同 [ ref ]),底层的共识协议为 ZAB。Lamport 的 Paxos 算法出了名的难懂,如何让算法更加可理解(understandable),便成了 Stanford 博士生 Diego Ongaro 的研究课题。Diego Ongaro 在 2014 年发表了介绍 Raft 算法的论文,“In search of an understandable consensus algorithm”。Raft 是可理解版的 Paxos,很快就成为解决共识问题的流行协议之一。这些类 Paxos 协议和 Paxos 系统之间的关系,如下 [ Ailijiang2016 ]:

+Paxos 协议和 Paxos 系统 +

Google 的 Chubby 没有开源,在云计算和大数据技术的风口下,Yahoo 开源的 ZooKeeper 便在工业界流行起来。ZooKeeper 重要的时间线如下:

+
    +
  • 2007 年 11 月 ZooKeeper 1.0 在 SourceForge 上发布 [ ref ]
  • +
  • 2008 年 6 月开始从 SourceForge 迁移到 Apache [ ref ],在 10 月 Zookeeper 3.0 发布,并成为 Hadoop 的子项目 [ ref1 ref2 ]
  • +
+

关于 ZooKeeper 名字的来源,Flavio Junqueira 和 Benjamin Reed 在介绍 ZooKeeper 的书中有如下阐述:

+
+

ZooKeeper 由雅虎研究院开发。我们小组在进行 ZooKeeper 的开发一段时间之后,开始推荐给其他小组,因此我们需要为我们的项目起一个名字。与此同时,小组也一同致力于 Hadoop 项目,参与了很多动物命名的项目,其中有广为人知的 Apache Pig 项目(http://pig.apache.org)。我们在讨论各种各样的名字时,一位团队成员提到我们不能再使用动物的名字了,因为我们的主管觉得这样下去会觉得我们生活在动物园中。大家对此产生了共鸣,分布式系统就像一个动物园,混乱且难以管理,而 ZooKeeper 就是将这一切变得可控。

+
+

体系结构

+

ZooKeeper 服务由若干台服务器构成,其中的一台通过 ZAB 原子广播协议选举作为主控服务器(leader),其他的作为从属服务器(follower)。客户端可以通过 TCP 协议连接任意一台服务器。如果客户端是读操作请求,则任意一个服务器都可以直接响应请求;如果是更新数据操作(写数据或者更新数据)。则只能由主控服务器来协调更新操作;如果客户端连接的是从属服务器,则从属服务器会将更新据请求转发到主控服务器,由其完成更新操作。主控服务器将所有更新操作序列化,利用 ZAB 协议将数据更新请求通知所有从属服务器,ZAB 保证更新操作。

+

zookeeper-service

+

读和写操作,如下图所示 [ Haloi2015 ]:
+ZooKeeper 读和写操作

+

ZooKeeper 的任意一台服务器都可以响应客户端的读操作,这样可以提高吞吐量。Chubby 在这点上与 ZooKeeper 不同,所有读/写操作都由主控服务器完成,从属服务器只是为了提高整个协调系统的可用性,即主控服务器发生故障后能够在从属服务器中快速选举出新的主控服务器。在带来高吞吐量优势的同时,ZooKeeper 这样做也带来潜在的问题:客户端可能会读到过期数据,因为即使主控服务器已经更新了某个内存数据,但是 ZAB 协议还未能将其广播到从属服务器。为了解决这一问题,在 ZooKeeper 的接口 API 函数中提供了 sync 操作,应用可以根据需要在读数据前调用该操作,其含义是:接收到 sync 命令的从属服务器从主控服务器同步状态信息,保证两者完全一致。这样如果在读操作前调用 sync 操作,则可以保证客户端一定可以读取到最新状态的数据。

+

数据模型

+

ZooKeeper 所提供的命名空间跟标准文件系统很相似。路径中一系列元素是用斜杠(/)分隔的。每个节点在 ZooKeper 命名空间中是用路径来识别的。在 ZooKeeper 术语下,节点被称为 znode。默认每个 znode 最大只能存储 1M 数据(可以通过配置参数修改),这与 Chubby 一样是出于避免应用将协调系统当作存储系统来用。znode 只能使用绝对路径,相对路径不能被 ZooKeeper 识别。znode 命名可以是任意 Unicode 字符。唯一的例外是,名称"/zookeeper"。命名为"/zookeeper"的 znode,由 ZooKeeper 系统自动生成,用配额(quota)管理。

+ZooKeeper 数据模型 +

ZooKeeper 使用

+

安装与配置

+

ZooKeeper 安装与启动:

+
1
2
3
4
5
6
7
8
9
10
11
12
$ brew info zookeeper
zookeeper: stable 3.4.10 (bottled), HEAD
Centralized server for distributed coordination of services
https://zookeeper.apache.org/
... 省略
$ brew install zookeeper
$ zkServer start # 启动
$ zkServer stop # 终止
$ zkServer help
ZooKeeper JMX enabled by default
Using config: /usr/local/etc/zookeeper/zoo.cfg
Usage: ./zkServer.sh {start|start-foreground|stop|restart|status|upgrade|print-cmd}
+

若不修改配置文件,默认是单机模式启动。若要使用集群模式,需要修改 /usr/local/etc/zookeeper/zoo.cfg(默认路径)。示例 zoo.cfg [ doc ]:

+
1
2
3
4
5
6
7
8
tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181
initLimit=5
syncLimit=2
server.1=192.168.211.11:2888:3888
server.2=192.168.211.12:2888:3888
server.3=192.168.211.13:2888:3888
+

clientPort:客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。
+server.X=YYY:A:B

+
    +
  • X:表示的服务器编号;
  • +
  • YYY:表示服务器的ip地址;
  • +
  • A:表示服务器节点间的通信端口,用于 follower 和 leader 节点的通信;
  • +
  • B:表示选举端口,表示选举新 leader 时服务器间相互通信的端口,当 leader 挂掉时,其余服务器会相互通信,选择出新的 leader。
  • +
+

若想在单台主机上试验集群模式,可以将 YYY 都修改为 localhost,并且让两个端口 A:B 也相互不同(比如:2888:3888, 2889:3889, 2890:3890),即可实现伪集群模式。示例 zoo.cfg 如下 [ doc ]:

+
1
2
3
server.1=localhost:2888:3888
server.2=localhost:2889:3889
server.3=localhost:2890:3890
+

zkCli 支持的全部命令:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ zkCli help
ZooKeeper -server host:port cmd args
stat path [watch]
set path data [version]
ls path [watch]
delquota [-n|-b] path
ls2 path [watch]
setAcl path acl
setquota -n|-b val path
history
redo cmdno
printwatches on|off
delete path [version]
sync path
listquota path
rmr path
get path [watch]
create [-s] [-e] path data acl
addauth scheme auth
quit
getAcl path
close
connect host:port
+

节点类型及其操作

+

Zookeeper 支持两种类型节点:持久节点(persistent znode)和临时节点(ephemeral znode)。持久节点不论客户端会话情况,一直存在,只有当客户端显式调用删除操作才会消失。而临时节点则不同,会在客户端会话结束或者发生故障的时候被 ZooKeeper 系统自动清除。另外,这两种类型的节点都可以添加是否是顺序(sequential)的特性,这样就有了:持久顺序节点和临时顺序节点。

+

(1) 持久节点(persistent znode)

+

使用 create 创建节点(默认持久节点),以及使用 get 查看该节点:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ zkCli -server 127.0.0.1  # 启动客户端
[zk: localhost:2181(CONNECTED) 1] create /zoo 'hello zookeeper'
Created /zoo
[zk: localhost:2181(CONNECTED) 2] get /zoo
hello zookeeper
cZxid = 0x8d
ctime = Thu Nov 08 20:42:55 CST 2017
mZxid = 0x8d
mtime = Thu Nov 08 20:42:55 CST 2017
pZxid = 0x8d
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 15
numChildren = 0
+

create 创建子节点,以及使用 ls 查看全部子节点:

+
1
2
3
4
5
6
7
8
[zk: localhost:2181(CONNECTED) 3] create /zoo/duck ''
Created /zoo/duck
[zk: localhost:2181(CONNECTED) 4] create /zoo/goat ''
Created /zoo/goat
[zk: localhost:2181(CONNECTED) 5] create /zoo/cow ''
Created /zoo/cow
[zk: localhost:2181(CONNECTED) 6] ls /zoo
[cow, goat, duck]
+

delete 删除节点,以及使用 rmr 递归删除:

+
1
2
3
4
5
6
7
8
[zk: localhost:2181(CONNECTED) 7] delete /zoo/duck
[zk: localhost:2181(CONNECTED) 8] ls /zoo
[cow, goat]
[zk: localhost:2181(CONNECTED) 9] delete /zoo
Node not empty: /zoo
[zk: localhost:2181(CONNECTED) 10] rmr /zoo
[zk: localhost:2181(CONNECTED) 11] ls /zoo
Node does not exist: /zoo
+

(2) 临时节点(ephemeral znode)

+

和持久节点不同,临时节点不能创建子节点:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ zkCli  # 启动第1个客户端
[zk: localhost:2181(CONNECTED) 0] create -e /node 'hello'
Created /node
[zk: localhost:2181(CONNECTED) 40] get /node
hello
cZxid = 0x97
ctime = Thu Nov 08 21:01:25 CST 2017
mZxid = 0x97
mtime = Thu Nov 08 21:01:25 CST 2017
pZxid = 0x97
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x161092a0ff30000
dataLength = 5
numChildren = 0
[zk: localhost:2181(CONNECTED) 1] create /node/child ''
Ephemerals cannot have children: /node/child
+

临时节点在客户端会话结束或者发生故障的时候被 ZooKeeper 系统自动清除。现在试验下的针对临时节点自动清除的监视:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ zkCli  # 启动第2个客户端
[zk: localhost:2181(CONNECTED) 0] create -e /node 'hello'
Node already exists: /node
[zk: localhost:2181(CONNECTED) 1] stat /node true
cZxid = 0x97
ctime = Thu Nov 08 21:01:25 CST 2017
mZxid = 0x97
mtime = Thu Nov 08 21:01:25 CST 2017
pZxid = 0x97
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x161092a0ff30000
dataLength = 5
numChildren = 0
+

若客户端1,退出 quit 或崩溃,客户端2将收到监视事件:

+
1
2
3
4
[zk: localhost:2181(CONNECTED) 2]
WATCHER::

WatchedEvent state:SyncConnected type:NodeDeleted path:/node
+

(3) 顺序节点(sequential znode)

+

顺序节点在其创建时 ZooKeeper 会自动在 znode 名称上附加上顺序编号。顺序编号,由父 znode 维护,并且单调递增。顺序编号,由 4 字节的有符号整数组成,并被格式化为 0 填充的 10 位数字。

+
1
2
3
4
5
6
7
8
9
10
[zk: localhost:2181(CONNECTED) 1] create /test ''
Created /test
[zk: localhost:2181(CONNECTED) 2] create -s /test/seq ''
Created /test/seq0000000000
[zk: localhost:2181(CONNECTED) 3] create -s /test/seq ''
Created /test/seq0000000001
[zk: localhost:2181(CONNECTED) 4] create -s /test/seq ''
Created /test/seq0000000002
[zk: localhost:2181(CONNECTED) 5] ls /test
[seq0000000000, seq0000000001, seq0000000002]
+

客户端 API

+ +

ZooKeeper 提供的主要 znode 操作 API 如下表所示:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
API 操作描述CLI 命令
create创建 znodecreate
delete删除 znodedelete/rmr/delquota
exists检查 znode 是否存在stat
getChildren读取 znode 全部的子节点ls/ls2
getData读取 znode 数据get/listquota
setData设置 znode 数据set/setquota
getACL读取 znode 的 ACLgetACL
setACL设置 znode 的 ACLsetACL
sync同步sync
+

Java 的 ZooKeeper 类实现了上述提供的 API。

+

Zookeeper 底层是 Java 实现,zkCli 命令行工具底层也是 Java 实现,对应的 Java 实现类为 org.apache.zookeeper.ZooKeeperMain [ src1 src2 ]。ZooKeeper 3.5.x 下,CLI 命令与底层实现 API 对应关系:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
命名 CLIJava API (ZooKeeper 类)
addauth scheme authpublic void addAuthInfo(String scheme, byte[] auth)
closepublic void close()
create [-s] [-e] path data aclpublic String create(final String path, byte data[], List acl, CreateMode createMode)
delete path [version]public void delete(String path, int version)
delquota [-n|-b] pathpublic void delete(String path, int version)
get path [watch]public byte[] getData(String path, boolean watch, Stat stat)
getAcl pathpublic List getACL(final String path, Stat stat)
listquota pathpublic byte[] getData(String path, boolean watch, Stat stat)
ls path [watch]public List getChildren(String path, Watcher watcher, Stat stat)
ls2 path [watch]-
quitpublic void close()
rmr pathpublic void delete(final String path, int version)
set path data [version]public Stat setData(String path, byte[] data, int version)
setAcl path aclpublic Stat setACL(final String path, List acl, int aclVersion)
setquota -n|-b val pathpublic Stat setData(String path, byte[] data, int version)
stat path [watch]public Stat exists(String path, boolean watch)
sync pathpublic void sync(String path, AsyncCallback.VoidCallback cb, Object ctx)
+

监视点(watch)

+

ZooKeeper 提供了处理变化的重要机制一一监视点(watch)。通过监视点,客户端可以对指定的 znode 节点注册一个通知请求,在发生变化时就会收到一个单次的通知。当应用程序注册了一个监视点来接收通知,匹配该监视点条件的第一个事件会触发监视点的通知,并且最多只触发一次。例如,当 znode 节点也被删除,客户端需要知道该变化,客户端在 /z 节点执行 exists 操作并设置监视点标志位,等待通知,客户端会以回调函数的形式收到通知。

+

ZooKeeper 的 API 中的读操作:getData、getChildren 和 exists,均可以选择在读取的 znode 节点上设置监视点。使用监视点机制,我们需要实现 Watcher 接口类,该接口唯一方法为 process:

+
1
void process(WatchedEvent event)
+

WatchedEvent 数据结构包括以下信息:

+
    +
  • ZooKeeper会话状态(KeeperState):Disconnected、SyncConnected、AuthFailed、ConnectedReadOnly 、SaslAuthenticated、Expired。
  • +
  • 事件类型(EventType):NodeCreated 、NodeDeleted 、NodeDataChanged、NodeChildrenChanged 和 None 。
  • +
  • 若事件类型不是 None,还包括 znode 路径。
  • +
+

若收到 WatchedEvent, 在 zkCli 中会输出类似如下结果:

+
1
WatchedEvent state:SyncConnected type:NodeDeleted path:/node
+

监视点有两种类型:数据监视点和子节点监视点。创建、删除或设置一个 znode 节点的数据都会触发数据监视点,exists 和 getData 这两个操作可以设置数据监视点。只有 getChildren 操作可以设置子节点监视点,这种监视点只有在 znode 子节点创建或删除时才被触发。对于每种事件类型,我们通过以下调用设置监视点:

+

NodeCreated
+   通过 exists 调用设置一个监视点。
+NodeDeleted
+   通过 exists 或 getData 调用设置监视点。
+NodeDataChanged
+   通过 exists 或getData 调用设置监视点。
+NodeChildrenChanged
+   通过 getChildren 调用设置监视点。

+

Java 示例代码

+

在 Java 下使用 ZooKeeper 需要先添加如下 maven 依赖:

+
1
2
3
4
5
6
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.11</version>
<type>pom</type>
</dependency>
+

ZookeeperDemo 示例,展示了建立连接会话,以及对 znode 的创建、读取、修改、删除和设置监视点等操作:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import java.io.IOException;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;

public class ZookeeperDemo {

public static void main(String[] args) throws KeeperException, InterruptedException, IOException {
// 创建服务器连接
ZooKeeper zk = new ZooKeeper("127.0.0.1:2181", 100, new Watcher() {
// 监控所有被触发的事件
public void process(WatchedEvent event) {
System.out.printf("WatchedEvent state:%s type:%s path:%s\n", event.getState(), event.getType(), event.getPath());
}
});

// 创建节点
zk.create("/zoo", "hello ZooKeeper".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
// 读取节点数据
Stat stat = new Stat();
System.out.println(new String(zk.getData("/zoo", false, stat)));
printStat(stat);

// 创建子节点
zk.create("/zoo/duck", "hello duck".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zk.create("/zoo/goat", "hello goat".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zk.create("/zoo/cow", "hello cow".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

// 读取子节点列表,并设置监视点
System.out.println(zk.getChildren("/zoo", true));

// 读取子节点数据,并设置监视点
System.out.println(new String(zk.getData("/zoo/duck", true, null)));

// 修改子节点数据
zk.setData("/zoo/duck", "hi duck".getBytes(), -1);
// 读取修改后的子节点数据
System.out.println(new String(zk.getData("/zoo/duck", true, null)));

// 删除子节点
zk.delete("/zoo/duck", -1);
zk.delete("/zoo/goat", -1);
zk.delete("/zoo/cow", -1);
// 删除父节点
zk.delete("/zoo", -1);

// 关闭连接
zk.close();
}

private static void printStat(Stat stat) {
System.out.println("cZxid = 0x" + Long.toHexString(stat.getCzxid()));
System.out.println("ctime = " + DateFormatUtils.format(stat.getCtime(), "yyyy-MM-dd HH:mm:ss"));
System.out.println("mZxid = 0x" + Long.toHexString(stat.getMzxid()));
System.out.println("mtime = " + DateFormatUtils.format(stat.getMtime(), "yyyy-MM-dd HH:mm:ss"));
System.out.println("pZxid = 0x" + Long.toHexString(stat.getPzxid()));
System.out.println("cversion = " + stat.getCversion());
System.out.println("dataVersion = " + stat.getVersion());
System.out.println("aclVersion = " + stat.getAversion());
System.out.println("ephemeralOwner = 0x" + Long.toHexString(stat.getEphemeralOwner()));
System.out.println("dataLength = " + stat.getDataLength());
System.out.println("numChildren = " + stat.getNumChildren());
}
}
+

输出结果:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
WatchedEvent state:SyncConnected type:None path:null
hello ZooKeeper
cZxid = 0x1e1
ctime = 2017-11-20 12:18:36
mZxid = 0x1e1
mtime = 2017-11-20 12:18:36
pZxid = 0x1e1
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 15
numChildren = 0
[cow, goat, duck]
hello duck
WatchedEvent state:SyncConnected type:NodeDataChanged path:/zoo/duck
hi duck
WatchedEvent state:SyncConnected type:NodeDeleted path:/zoo/duck
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/zoo
+

ZooInspector

+

ZooInspector 是 ZooKeeper 3.3.0 开始官方提供的可视化查看和编辑 ZooKeeper 实例的工具 [ ZOOKEEPER-678 ]。源码位于目录 src/contrib/zooinspector 下,GitHub 地址为:link。可以根据 README.txt 的说明运行使用。或者可以直接用 ZOOKEEPER-678 下提供的可执行 jar 包。

+ZooInspector +

参考资料

+
    +
  1. 官方文档:ZooKeeper http://zookeeper.apache.org/doc/current/index.html
  2. +
  3. 2010-11 许令波:分布式服务框架 Zookeeper https://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/
  4. +
  5. ZooKeeper:分布式过程协同技术详解,Benjamin Reed & Flavio Junqueira,2013,豆瓣
  6. +
  7. Apache ZooKeeper Essentials, Haloi 2015,豆瓣
  8. +
  9. 从Paxos到Zookeeper,阿里倪超 2015,豆瓣
  10. +
  11. 大数据日知录:架构与算法,张俊林 2014,第5章 分布式协调系统,豆瓣
  12. +
  13. 2010,Patrick Hunt, Mahadev Konar, Flavio Paiva Junqueira, Benjamin Reed: ZooKeeper: Wait-free Coordination for Internet-scale Systems. USENIX ATC 2010,dblpmsausenix
  14. +
+ +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2018/01/java-ffi/index.html b/2018/01/java-ffi/index.html new file mode 100644 index 00000000..b8f38dc1 --- /dev/null +++ b/2018/01/java-ffi/index.html @@ -0,0 +1,709 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Java 外部函数接口:JNI, JNA, JNR | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ Java 外部函数接口:JNI, JNA, JNR +

+ + +
+ + + + +
+ + +

遇到的问题

+

前段时间开发的时候,遇到一个问题,就是如何用 Java 实现 chdir?网上搜索一番,发现了 JNR-POSIX 项目 [ stackoverflow ]。俗话说,好记性不如烂笔头。现在将涉及到的相关知识点总结成笔记。

+ +

其实针对 Java 实现 chdir 问题,官方 20 多年前就存在对应的 bug,即 JDK-4045688 'Add chdir or equivalent notion of changing working directory'。这个 bug 在 1997.04 创建,目前的状态是 Won't Fix(不予解决),理由大致是,若实现与操作系统一样的进程级别的 chdir,将影响 JVM 上的全部线程,这样引入了可变(mutable)的全局状态,这与 Java 的安全性优先原则冲突,现在添加全局可变的进程状态,已经太迟了,对不变性(immutability)的支持才是 Java 要实现的特性。

+

chdir 是平台相关的操作系统接口,POSIX 下对应的 APIint chdir(const char *path);,而 Windows 下对应的 APIBOOL WINAPI SetCurrentDirectory(_In_ LPCTSTR lpPathName);,另外 Windows 下也可以使用 MSVCRT 中 APIint _chdir(const char *dirname);(MSVCRT 下内部实现其实就是调用 SetCurrentDirectory [ reactos ] )。

+

Java 设计理念是跨平台,"write once, run anywhere"。很平台相关的 API,虽然各个平台都有自己的类似的实现,但存在会差异。除了多数常见功能,Java 并没有对全部操作系统接口提供完整支持,比如很多 POSIX API。除了 chdir,另外一个典型的例子是,在 Java 9 以前 JDK 获取进程 id 一直没有简洁的方法 [ stackoverflow ],最新发布的 Java 9 中的 JEP 102(Process API Updates)才增强了进程 API。获取进程 id 可以使用以下方式 [ javadoc ]:

+
1
long pid = ProcessHandle.current().pid();
+

相比其他语言,Pyhon 和 Ruby,对操作系统相关的接口都有更多的原生支持。Pyhon 和 Ruby 实现的相关 API 基本上都带有 POSIX 风格。比如上文提到,chdirgetpid,在 Pyhon 和 Ruby 下对应的 API 为:Pyhon 的 os 模块 os.chdir(path)os.getpid();Ruby 的 Dir 类的 Dir.chdir( [ string] ) 类方法和 Process 类的 Process.pid 类属性。Python 解释器的 chdir 对应源码为 posixmodule.c#L2611,Ruby 解释器的 chdir 对应源码为 dir.c#L848win32.c#L6741

+

JNI 实现 getpid

+

Java 下要想实现本地方法调用,需要通过 JNI。关于 JNI 的介绍,可以参阅“Java核心技术,卷II:高级特性,第9版2013”的“第12章 本地方法”,或者读当年 Sun 公司 JNI 设计者 Sheng Liang(梁胜)写的“Java Native Interface: Programmer's Guide and Specification”。本文只给出实现 getpid 的一个简单示例。

+

首先使用 Maven 创建一个简单的脚手架:

+
1
2
3
4
5
mvn archetype:generate     \
-DgroupId=com.test \
-DartifactId=jni-jnr \
-DpackageName=com.test \
-DinteractiveMode=false
+

com.test 包下添加 GetPidJni 类:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.test;

public class GetPidJni {
public static native long getpid();

static {
System.loadLibrary("getpidjni");
}

public static void main(String[] args) {
System.out.println(getpid());
}
}
+

javac 编译代码 GetPidJNI.java,然后用 javah 生成 JNI 头文件:

+
1
2
3
$ mkdir -p target/classes
$ javac src/main/java/com/test/GetPidJni.java -d "target/classes"
$ javah -cp "target/classes" com.test.GetPidJni
+

生成的 JNI 头文件 com_test_GetPidJni.h,内容如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_test_GetPidJni */

#ifndef _Included_com_test_GetPidJni
#define _Included_com_test_GetPidJni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_test_GetPidJni
* Method: getpid
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_com_test_GetPidJni_getpid
(JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif
+

现在有了头文件声明,但还没有实现,手动敲入 com_test_GetPidJni.c

+
1
2
3
4
5
6
#include "com_test_GetPidJni.h"

JNIEXPORT jlong JNICALL
Java_com_test_GetPidJni_getpid (JNIEnv * env, jclass c) {
return getpid();
}
+

编译 com_test_GetPidJni.c,生成 libgetpidjni.dylib

+
1
$ gcc -I $JAVA_HOME/include -I $JAVA_HOME/include/darwin -dynamiclib -o libgetpidjni.dylib com_test_GetPidJni.c
+

生成的 libgetpidjni.dylib,就是 GetPidJni.java 代码中的 System.loadLibrary("getpidjni");,需要加载的 lib。

+

现在运行 GetPidJni 类,就能正确获取 pid:

+
1
$ java -Djava.library.path=`pwd` -cp "target/classes" com.test.GetPidJni
+

JNI 的问题是,胶水代码(黏合 Java 和 C 库的代码)需要程序员手动书写,对不熟悉 C/C++ 的同学是很大的挑战。

+

JNA 实现 getpid

+

JNA(Java Native Access, wiki, github, javadoc, mvn),提供了相对 JNI 更加简洁的调用本地方法的方式。除了 Java 代码外,不再需要额外的胶水代码。这个项目最早可以追溯到 Sun 公司 JNI 设计者 Sheng Liang 在 1999 年 JavaOne 上的分享。2006 年 11月,Todd Fast (也来自 Sun 公司) 首次将 JNA 发布到 dev.java.net 上。Todd Fast 在发布时提到,自己在这个项目上已经断断续续开发并完善了 6-7 年时间,项目刚刚在 JDK 5 上重构和重设计过,还可能有很多缺陷或缺点,希望其他人能浏览代码并参与进来。Timothy Wall 在 2007 年 2 月重启了这项目,引入了很多重要功能,添加了 Linux 和 OSX 支持(原本只在 Win32 上测试过),加强了 lib 的可用性(而非仅仅基本功能可用)[ ref ]。

+

看下示例代码:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import com.sun.jna.Library;
import com.sun.jna.Native;

public class GetPidJNA {

public interface LibC extends Library {
long getpid();
}

public static void main(String[] args) {
LibC libc = Native.loadLibrary("c", LibC.class);
System.out.println(libc.getpid());
}
}
+

JNR 实现 getpid

+

最初,JRuby 的核心开发者 Charles Nutter 在实现 Ruby 的 POSIX 集成时就使用了 JNA [ ref ]。但过了一段时候后,开始开发 JNR(Java Native Runtime, github, mvn) 替代 JNA。Charles Nutter 在介绍 JNR 的 slides 中阐述了原因:

+
1
2
3
4
5
Why Not JNA?
- Preprocessor constants?
- Standard API sets out of the box
- C callbacks?
- Performance?!?
+

即,(1) 预处理器的常量支持(通过 jnr-constants 解决);(2) 开箱即用的标准 API(作者实现了 jnr-posix, jnr-x86asm, jnr-enxio, jnr-unixsocket);(3) C 回调 callback 支持;(4) 性能(提升 8-10 倍)。

+JNR 各个模块的层次结构 +

使用 JNR-FFI(github, mvn)实现 getpid,示例代码:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
import jnr.ffi.LibraryLoader;

public class GetPidJnr {

public interface LibC {
long getpid();
}

public static void main(String[] args) {
LibC libc = LibraryLoader.create(LibC.class).load("c");
System.out.println(libc.getpid());
}
}
+

使用 JNR-POSIX(github, mvn)实现 chdirgetpid,示例代码:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import jnr.posix.POSIX;
import jnr.posix.POSIXFactory;

public class GetPidJnrPosix {

private static POSIX posix = POSIXFactory.getPOSIX();

public static void main(String[] args) {
System.out.println(posix.getcwd());
posix.chdir("..");
System.out.println(posix.getcwd());
System.out.println(posix.getpid());
}
}
+

JMH 性能比较

+

性能测试代码为 BenchmarkFFI.javagithub),测试结果如下:

+
1
2
3
4
5
6
7
8
# JMH version: 1.19
# VM version: JDK 1.8.0_144, VM 25.144-b01

Benchmark Mode Cnt Score Error Units
BenchmarkFFI.testGetPidJna thrpt 10 8225.209 ± 206.829 ops/ms
BenchmarkFFI.testGetPidJnaDirect thrpt 10 10257.505 ± 736.135 ops/ms
BenchmarkFFI.testGetPidJni thrpt 10 77852.899 ± 3167.101 ops/ms
BenchmarkFFI.testGetPidJnr thrpt 10 58261.657 ± 5187.550 ops/ms
+

即:JNI > JNR > JNA (Direct Mapping) > JNA (Interface Mapping)。相对 JNI 的实现性能,其他三种方式,从大到小的性能百分比依次为:74.8% (JNR), 13.2% (JnaDirect), 10.6% (JNA)。在博主电脑上测试,JNR 相比 JNA 将近快了 6-7 倍(JNR 作者 Charles Nutter 针对 getpid 的测试结果是 JNR 比 JNA 快 8-10 倍 [ twitter slides ])。

+

实现原理

+

JNA 源码简析

+

先来看下 JNA,JNA 官方文档 FunctionalDescription.md,对其实现原理有很好的阐述。这里将从源码角度分析实现的核心逻辑。

+

回顾下代码,我们现实定义了接口 LibC,然后通过 Native.loadLibrary("c", LibC.class) 获取了接口实现。这一步是怎么做到的呢?翻下源码 Native.java#L547 就知道,其实是通过**动态代理(dynamic proxy)**实现的。使用动态代理需要实现 InvocationHandler 接口,这个接口的实现在 JNA 源码中是类 com.sun.jna.Library.Handler。示例中的 LibC 接口定义的全部方法,将全部分派到 Handler 的 invoke 方法下。

+
1
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
+

然后根据返回参数的不同,分派到 Native 类的,invokeXxx 本地方法:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* Call the native function.
*
* @param function Present to prevent the GC to collect the Function object
* prematurely
* @param fp function pointer
* @param callFlags calling convention to be used
* @param args Arguments to pass to the native function
*
* @return The value returned by the target native function
*/
static native int invokeInt(Function function, long fp, int callFlags, Object[] args);

static native long invokeLong(Function function, long fp, int callFlags, Object[] args);

static native Object invokeObject(Function function, long fp, int callFlags, Object[] args);
...
+

比如,long getpid() 会被分派到 invokeLong,而 int chmod(String filename, int mode) 会被分派到 invokeInt。invokeXxx 本地方法参数:

+
    +
  • 参数 Function function,记录了 lib 信息、函数名称、函数指针地址、调用惯例等元信息;
  • +
  • 参数 long fp,即函数指针地址,函数指针地址通过 Native#findSymbol()获得(底层是 Linux API dlsym 或 Windows API GetProcAddress )。
  • +
  • 参数 int callFlags,即调用约定,对应 cdecl 或 stdcall。
  • +
  • 参数 int callFlags,即函数入参,若无参数,args 大小为 0,若有多个参数,原本的入参被从左到右依次保存到 args 数组中。
  • +
+

再来看下 invokeXxx 本地方法的实现 dispatch.c#L2122invokeIntinvokeLong 实现源码类似):

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
* Class: com_sun_jna_Native
* Method: invokeInt
* Signature: (Lcom/sun/jna/Function;JI[Ljava/lang/Object;)I
*/
JNIEXPORT jint JNICALL
Java_com_sun_jna_Native_invokeInt(JNIEnv *env, jclass UNUSED(cls),
jobject UNUSED(function), jlong fp, jint callconv,
jobjectArray arr)
{
ffi_arg result;
dispatch(env, L2A(fp), callconv, arr, &ffi_type_sint32, &result);
return (jint)result;
}
+

即,全部 invokeXxx 本地方法统一被分派到 dispatch 函数 dispatch.c#L439

+
1
2
3
static void
dispatch(JNIEnv *env, void* func, jint flags, jobjectArray args,
ffi_type *return_type, void *presult)
+

这个 dispatch 函数是全部逻辑的核心,实现最终的本地函数调用。

+

我们知道,发起函数调用,需要构造一个栈帧stack frame)。构造栈帧,涉及到参数压栈次序(参数从左到右压入还是从右到左压入)和清理栈帧(调用者清理还是被调用者清理)等实现细节问题。不同的编译器在不同的 CPU 架构下有不同的选择。构造栈帧的具体实现细节的选择,被称为调用惯例calling convention)。按照调用惯例构造整个栈帧,这个过程由编译器在编译阶段完成的。比如要想发起 sum(2, 3) 这个函数调用,编译器可能会生成如下等价汇编代码:

+
1
2
3
4
5
; 调用者清理堆栈(caller clean-up),参数从右到左压入栈
push 3
push 2
call _sum ; 将返回地址压入栈, 同时 sum 的地址装入 eip
add esp, 8 ; 清理堆栈, 两个参数占用 8 字节
+

dispatch 函数是,需要调用的函数指针地址、输入参数和返回参数,全部是运行时确定。要想完成这个函数调用逻辑,就要运行时构造栈帧,生成参数压栈和清理堆栈的工作。JNA 3.0 之前,实现运行时构造栈帧的逻辑的对应代码 dispatch_i386.cdispatch_ppc.cdispatch_sparc.s,分别实现 Intel x86、PowerPC 和 Sparc 三种 CPU 架构。

+

运行时函数调用,这个问题其实是一个一般性的通用问题。早在 1996 年 10 月,Cygnus Solutions 的工程师 Anthony Green 等人就开发了 libffi(home, wiki, github, doc),解决的正是这个问题。目前,libffi 几乎支持全部常见的 CPU 架构。于是,从 JNA 3.0 开始,摒弃了原先手动构造栈帧的做法,把 libffi 集成进了 JNA。

+

直接映射(Direct Mapping)
+https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#RegisterNatives
+http://www.chiark.greenend.org.uk/doc/libffi-dev/html/The-Closure-API.html

+

JNR 源码简析

+

JNR 底层同样也是依赖 libffi,参见 jffi。但 JNR 相比 JNA 性能更好,做了很有优化。比较重要的点是,JNA 使用动态代理生成实现类,而 JNR 使用 ASM 字节码操作库生成直接实现类,去除了每次调用本地方法时额外的动态代理的逻辑。使用 ASM 生成实现类,对应的代码为 AsmLibraryLoader.java。其他细节,限于文档不全,本人精力有限,不再展开。

+

Java 9 的 getpid 实现

+

Java 9 以前 JDK 获取进程 id 没有简洁的方法,最新发布的 Java 9 中的 JEP 102(Process API Updates)增强了进程 API。进程 id 可以使用以下方式 [ javadoc ]

+
1
long pid = ProcessHandle.current().pid();
+

翻阅实现源码,可以看到对应的实现就是 JNI 调用:

+

jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl [ src ]

+
1
2
3
4
5
6
/**
* Return the pid of the current process.
*
* @return the pid of the current process
*/
private static native long getCurrentPid0();
+

*nix 平台下实现为:

+

jdk/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c [ src ]

+
1
2
3
4
5
6
7
8
9
10
/*
* Class: java_lang_ProcessHandleImpl
* Method: getCurrentPid0
* Signature: ()J
*/
JNIEXPORT jlong JNICALL
Java_java_lang_ProcessHandleImpl_getCurrentPid0(JNIEnv *env, jclass clazz) {
pid_t pid = getpid();
return (jlong) pid;
}
+

Windows 平台下实现为:

+

jdk/src/java.base/windows/native/libjava/ProcessHandleImpl_win.c [ src ]

+
1
2
3
4
5
6
7
8
9
10
11
12
/*
* Returns the pid of the caller.
*
* Class: java_lang_ProcessHandleImpl
* Method: getCurrentPid0
* Signature: ()J
*/
JNIEXPORT jlong JNICALL
Java_java_lang_ProcessHandleImpl_getCurrentPid0(JNIEnv *env, jclass clazz) {
DWORD pid = GetCurrentProcessId();
return (jlong)pid;
}
+

参考资料

+
    +
  1. Changing the current working directory in Java? https://stackoverflow.com/q/840190
  2. +
  3. How can a Java program get its own process ID? http://stackoverflow.com/q/35842
  4. +
  5. Java核心技术,卷II:高级特性,第9版2013:第12章 本地方法,豆瓣
  6. +
  7. Java Native Interface: Programmer's Guide and Specification, Sheng Liang (wikilinkedinmsa), 1999,豆瓣:作者梁胜,中国科技大学少年班83级,并拥有耶鲁大学计算机博士学位(1990-1996),目前 Rancher Labs 创始人兼 CEO [ ref ]
  8. +
  9. 2013-07 Charles Nutter: Java Native Runtime http://www.oracle.com/technetwork/java/jvmls2013nutter-2013526.pdf
  10. +
  11. JEP 191: Foreign Function Interface http://openjdk.java.net/jeps/191 作者是Charles Nutter
  12. +
  13. 2014-03 Java 外部函数接口 http://www.infoq.com/cn/news/2014/03/java-foreign-function-interface
  14. +
  15. 2005-08 Brian Goetz:用动态代理进行修饰 https://www.ibm.com/developerworks/cn/java/j-jtp08305.html
  16. +
+ +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2018/01/stack-frame-calling-convention/index.html b/2018/01/stack-frame-calling-convention/index.html new file mode 100644 index 00000000..3a9900d1 --- /dev/null +++ b/2018/01/stack-frame-calling-convention/index.html @@ -0,0 +1,694 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 栈帧与调用惯例 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ 栈帧与调用惯例 +

+ + +
+ + + + +
+ + +

栈与栈帧

+

要想知道函数是怎么被调用的,需要了解栈帧和调用惯例相关知识。俞甲子2009 的“第10章 内存: 栈与堆”对相关概念有很好的介绍。本文是对相关知识的学习笔记。

+ +栈与栈帧布局 +

附注,栈帧之间的划分边界,其实有两种不一样说法。在有些资料中 [ wikipedia; 俞甲子2009 ],callee 参数被划分在 callee 栈帧,但在 Intel 官方一些权威文档中 [ Intel ASDM, Vol.1, Ch.6; Intel X86-psABI ],callee 参数被划分在 caller 栈帧。

+

调用惯例

+

调用惯例,规定以下内容:(1) 函数参数的传递顺序和方式;(2) 栈的清理方式;(3) 名称修饰(name mangling)。常见的 x86 调用惯例列表有:cdecl(C 语言默认)、stdcall(Win32 API 标准)、fastcall、pascal。这些调用惯例如下下表所示(更加全面的列表参见 wikipedia):

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
调用惯例栈帧清理参数传递名称修饰
cdel调用者 caller从右至左入栈 RTL下划线+函数名,如 _sum
stdcall被调用者 callee从右至左入栈 RTL下划线+函数名+@+参数字节数,如 _sum@8
fastcall被调用者 callee头两参数存入寄存器 ECX 和 EDX,其余参数从右至左入栈 RTL@+函数名+@+参数字节数,如 @sum@8
pascal被调用者 callee从左至右入栈 LTR较为复杂,参见 pascal 文档
+

下面举例说明,cdecl 和 stdcall 两种调用惯例。

+

cdecl 调用惯例

+

cdecl,调用者负责清理堆栈(caller clean-up),参数从右至左(Right-to-Left,RTL)压入栈。举例说明 [ ref1 ref2 ]:

+
1
2
3
4
5
6
// cdecl 调用惯例
int __cdecl sum(int a, int b) {
return a + b;
}
// 调用
int c = sum(2, 3);
+

编译器生成的等价汇编代码:

+
1
2
3
4
5
; 调用者清理堆栈(caller clean-up),参数 RTL 入栈
push 3
push 2
call _sum ; 将返回地址压入栈, 同时 sum 的地址装入 eip
add esp, 8 ; 清理堆栈, 两个参数占用 8 字节
+
1
2
3
4
5
6
7
8
9
10
11
; sum 函数等价汇编代码
; // function prolog
push ebp
mov ebp, esp
; // return a + b;
mov eax, [ebp + 12]
add eax, [ebp + 8] ; 返回值规定保存在 eax
; // function epilog
mov esp, ebp ; 设置栈顶 esp
pop ebp ; 恢复 old ebp
ret ; 将栈中保存的返回地址装入 eip
+

stdcall 调用惯例

+

stdcall,被调用者负责清理堆栈(callee clean-up),参数从右至左(Right-to-Left,RTL)压入栈。举例说明:

+
1
2
3
4
5
6
// stdcall 调用惯例
int __stdcall sum(int a, int b) {
return a + b;
}
// 调用
int c = sum(2, 3);
+

编译器生成的等价汇编代码:

+
1
2
3
4
; 被调用者清理堆栈(callee clean-up),参数 RTL 入栈
push 3
push 2
call _sum@8 ; 将返回地址压入栈, 同时 sum 的地址装入 eip
+
1
2
3
4
5
6
7
8
9
10
11
; sum 函数等价汇编代码
; // function prolog
push ebp
mov ebp, esp
; // return a + b;
mov eax, [ebp + 12]
add eax, [ebp + 8] ; 返回值规定保存在 eax
; // function epilog
mov esp, ebp ; 设置栈顶 esp
pop ebp ; 恢复 old ebp
ret 8 ; 清理堆栈,并将栈中保存的返回地址装入 eip
+

gcc 汇编代码

+

hello1.c 文件内容如下:

+
1
2
3
4
5
6
7
8
9
int __cdecl sum(int a, int b) {
return a + b;
}

int main() {
sum(1, 2);
sum(3, 4);
return 0;
}
+

生成汇编代码:

+
1
2
3
4
$ gcc -m32 -S -masm=intel hello1.c -o hello1.s
$ gcc -m32 hello1.s -o hello
$ ./hello || echo $?
0
+

生成的 hello1.s,内容如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
  .section  __TEXT,__text,regular,pure_instructions
.macosx_version_min 10, 12
.intel_syntax noprefix
.globl _sum
.p2align 4, 0x90
_sum: ## @sum
## BB#0:
push ebp
mov ebp, esp
sub esp, 8 ; 预先分配 8 字节栈空间,保存 2 个布局变量
mov eax, dword ptr [ebp + 12] ; 堆栈中读取参数 2
mov ecx, dword ptr [ebp + 8] ; 堆栈中读取参数 1
mov dword ptr [ebp - 4], ecx ; 布局变量 1
mov dword ptr [ebp - 8], eax ; 布局变量 2
mov eax, dword ptr [ebp - 4]
add eax, dword ptr [ebp - 8]
add esp, 8 ; 清理 8 字节栈空间
pop ebp
ret

.globl _main
.p2align 4, 0x90
_main: ## @main
## BB#0:
push ebp
mov ebp, esp
sub esp, 40 ; 预先分配 40 字节栈空间
mov eax, 1
mov ecx, 2
mov dword ptr [ebp - 4], 0
mov dword ptr [esp], 1
mov dword ptr [esp + 4], 2
mov dword ptr [ebp - 8], eax ## 4-byte Spill
mov dword ptr [ebp - 12], ecx ## 4-byte Spill
call _sum
mov ecx, 3
mov edx, 4
mov dword ptr [esp], 3
mov dword ptr [esp + 4], 4
mov dword ptr [ebp - 16], eax ## 4-byte Spill
mov dword ptr [ebp - 20], ecx ## 4-byte Spill
mov dword ptr [ebp - 24], edx ## 4-byte Spill
call _sum
xor ecx, ecx
mov dword ptr [ebp - 28], eax ## 4-byte Spill
mov eax, ecx
add esp, 40 ; 清理 40 字节栈空间
pop ebp
ret

.subsections_via_symbols
+

GCC 生成的汇编代码并没有使用 push 而是通过 sub esp, 40 直接预先分配栈空间,然后使用 mov 指令将参数写进栈中,清理栈使用 add esp, 40。逻辑上,还是符合 cdecl 调用惯例,调用者负责清理堆栈(caller clean-up),参数从右至左(Right-to-Left,RTL)压入栈。这样做的好处是,如果同时多次调用 sum,清理栈空间的指令,只需要最后的时候调用一次就可以了。统一使用 sub espadd esp 去操作 esp 值,避免 push 指令操作 esp。

+

现在再来看看,stdcall 调用惯例下,GCC 生成的汇编代码。把 sum 函数改为 __stdcall,运行下面的命令:

+
1
2
$ gcc -m32 -S -masm=intel hello2.c -o hello2.s
$ diff -C1 hello1.s hello2.s
+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
*** hello1.s    Thu Feb 05 22:43:59 2018
--- hello2.s Thu Feb 05 22:45:24 2018
***************
*** 18,20 ****
pop ebp
! ret

--- 18,20 ----
pop ebp
! ret 8

***************
*** 35,36 ****
--- 35,37 ----
call _sum
+ sub esp, 8
mov ecx, 3
***************
*** 43,44 ****
--- 44,46 ----
call _sum
+ sub esp, 8
xor ecx, ecx
+

反汇编代码

+

反汇编 objdumpgdb/lldb,或者商业工具使用,IDA Pro 或者 Hopper Disassembler [ wiki ]

+

objdump 反汇编

+
1
2
$ gobjdump -d -Mintel hello1                # 使用 GNU objdump
$ objdump -d -x86-asm-syntax=intel hello1 # 使用 llvm-objdump
+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
hello1:	file format Mach-O 32-bit i386

Disassembly of section __TEXT,__text:
__text:
1f30: 55 push ebp
1f31: 89 e5 mov ebp, esp
1f33: 83 ec 08 sub esp, 8
1f36: 8b 45 0c mov eax, dword ptr [ebp + 12]
1f39: 8b 4d 08 mov ecx, dword ptr [ebp + 8]
1f3c: 89 4d fc mov dword ptr [ebp - 4], ecx
1f3f: 89 45 f8 mov dword ptr [ebp - 8], eax
1f42: 8b 45 fc mov eax, dword ptr [ebp - 4]
1f45: 03 45 f8 add eax, dword ptr [ebp - 8]
1f48: 83 c4 08 add esp, 8
1f4b: 5d pop ebp
1f4c: c3 ret
1f4d: 0f 1f 00 nop dword ptr [eax]
1f50: 55 push ebp
1f51: 89 e5 mov ebp, esp
1f53: 83 ec 28 sub esp, 40
1f56: b8 01 00 00 00 mov eax, 1
1f5b: b9 02 00 00 00 mov ecx, 2
1f60: c7 45 fc 00 00 00 00 mov dword ptr [ebp - 4], 0
1f67: c7 04 24 01 00 00 00 mov dword ptr [esp], 1
1f6e: c7 44 24 04 02 00 00 00 mov dword ptr [esp + 4], 2
1f76: 89 45 f8 mov dword ptr [ebp - 8], eax
1f79: 89 4d f4 mov dword ptr [ebp - 12], ecx
1f7c: e8 af ff ff ff call -81 <_sum>
1f81: b9 03 00 00 00 mov ecx, 3
1f86: ba 04 00 00 00 mov edx, 4
1f8b: c7 04 24 03 00 00 00 mov dword ptr [esp], 3
1f92: c7 44 24 04 04 00 00 00 mov dword ptr [esp + 4], 4
1f9a: 89 45 f0 mov dword ptr [ebp - 16], eax
1f9d: 89 4d ec mov dword ptr [ebp - 20], ecx
1fa0: 89 55 e8 mov dword ptr [ebp - 24], edx
1fa3: e8 88 ff ff ff call -120 <_sum>
1fa8: 31 c9 xor ecx, ecx
1faa: 89 45 e4 mov dword ptr [ebp - 28], eax
1fad: 89 c8 mov eax, ecx
1faf: 83 c4 28 add esp, 40
1fb2: 5d pop ebp
1fb3: c3 ret

_sum:
1f30: 55 push ebp
1f31: 89 e5 mov ebp, esp
1f33: 83 ec 08 sub esp, 8
1f36: 8b 45 0c mov eax, dword ptr [ebp + 12]
1f39: 8b 4d 08 mov ecx, dword ptr [ebp + 8]
1f3c: 89 4d fc mov dword ptr [ebp - 4], ecx
1f3f: 89 45 f8 mov dword ptr [ebp - 8], eax
1f42: 8b 45 fc mov eax, dword ptr [ebp - 4]
1f45: 03 45 f8 add eax, dword ptr [ebp - 8]
1f48: 83 c4 08 add esp, 8
1f4b: 5d pop ebp
1f4c: c3 ret
1f4d: 0f 1f 00 nop dword ptr [eax]

_main:
1f50: 55 push ebp
1f51: 89 e5 mov ebp, esp
1f53: 83 ec 28 sub esp, 40
1f56: b8 01 00 00 00 mov eax, 1
1f5b: b9 02 00 00 00 mov ecx, 2
1f60: c7 45 fc 00 00 00 00 mov dword ptr [ebp - 4], 0
1f67: c7 04 24 01 00 00 00 mov dword ptr [esp], 1
1f6e: c7 44 24 04 02 00 00 00 mov dword ptr [esp + 4], 2
1f76: 89 45 f8 mov dword ptr [ebp - 8], eax
1f79: 89 4d f4 mov dword ptr [ebp - 12], ecx
1f7c: e8 af ff ff ff call -81 <_sum>
1f81: b9 03 00 00 00 mov ecx, 3
1f86: ba 04 00 00 00 mov edx, 4
1f8b: c7 04 24 03 00 00 00 mov dword ptr [esp], 3
1f92: c7 44 24 04 04 00 00 00 mov dword ptr [esp + 4], 4
1f9a: 89 45 f0 mov dword ptr [ebp - 16], eax
1f9d: 89 4d ec mov dword ptr [ebp - 20], ecx
1fa0: 89 55 e8 mov dword ptr [ebp - 24], edx
1fa3: e8 88 ff ff ff call -120 <_sum>
1fa8: 31 c9 xor ecx, ecx
1faa: 89 45 e4 mov dword ptr [ebp - 28], eax
1fad: 89 c8 mov eax, ecx
1faf: 83 c4 28 add esp, 40
1fb2: 5d pop ebp
1fb3: c3 ret
+

lldb 反汇编

+

使用 lldb 反汇编:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
$ lldb hello1
(lldb) target create "hello1"
Current executable set to 'hello1' (i386).
(lldb) settings set target.x86-disassembly-flavor intel
(lldb) disassemble --name main
hello1`main:
hello1[0x1f50] <+0>: push ebp
hello1[0x1f51] <+1>: mov ebp, esp
hello1[0x1f53] <+3>: sub esp, 0x28
hello1[0x1f56] <+6>: mov eax, 0x1
hello1[0x1f5b] <+11>: mov ecx, 0x2
hello1[0x1f60] <+16>: mov dword ptr [ebp - 0x4], 0x0
hello1[0x1f67] <+23>: mov dword ptr [esp], 0x1
hello1[0x1f6e] <+30>: mov dword ptr [esp + 0x4], 0x2
hello1[0x1f76] <+38>: mov dword ptr [ebp - 0x8], eax
hello1[0x1f79] <+41>: mov dword ptr [ebp - 0xc], ecx
hello1[0x1f7c] <+44>: call 0x1f30 ; sum
hello1[0x1f81] <+49>: mov ecx, 0x3
hello1[0x1f86] <+54>: mov edx, 0x4
hello1[0x1f8b] <+59>: mov dword ptr [esp], 0x3
hello1[0x1f92] <+66>: mov dword ptr [esp + 0x4], 0x4
hello1[0x1f9a] <+74>: mov dword ptr [ebp - 0x10], eax
hello1[0x1f9d] <+77>: mov dword ptr [ebp - 0x14], ecx
hello1[0x1fa0] <+80>: mov dword ptr [ebp - 0x18], edx
hello1[0x1fa3] <+83>: call 0x1f30 ; sum
hello1[0x1fa8] <+88>: xor ecx, ecx
hello1[0x1faa] <+90>: mov dword ptr [ebp - 0x1c], eax
hello1[0x1fad] <+93>: mov eax, ecx
hello1[0x1faf] <+95>: add esp, 0x28
hello1[0x1fb2] <+98>: pop ebp
hello1[0x1fb3] <+99>: ret

(lldb) disassemble --name sum
hello1`sum:
hello1[0x1f30] <+0>: push ebp
hello1[0x1f31] <+1>: mov ebp, esp
hello1[0x1f33] <+3>: sub esp, 0x8
hello1[0x1f36] <+6>: mov eax, dword ptr [ebp + 0xc]
hello1[0x1f39] <+9>: mov ecx, dword ptr [ebp + 0x8]
hello1[0x1f3c] <+12>: mov dword ptr [ebp - 0x4], ecx
hello1[0x1f3f] <+15>: mov dword ptr [ebp - 0x8], eax
hello1[0x1f42] <+18>: mov eax, dword ptr [ebp - 0x4]
hello1[0x1f45] <+21>: add eax, dword ptr [ebp - 0x8]
hello1[0x1f48] <+24>: add esp, 0x8
hello1[0x1f4b] <+27>: pop ebp
hello1[0x1f4c] <+28>: ret
hello1[0x1f4d] <+29>: nop dword ptr [eax]

+

参考资料

+
    +
  1. 链接、装载与库,俞甲子,2009:第10章 内存: 栈与堆,豆瓣
  2. +
  3. IDA Pro权威指南,Eagle,第2版2011:6.2.1 调用约定,豆瓣
  4. +
  5. 2001-09 Calling Conventions Demystified https://www.codeproject.com/Articles/1388/Calling-Conventions-Demystified
  6. +
  7. Calling Conventions https://en.wikibooks.org/wiki/X86_Disassembly/Calling_Conventions
  8. +
  9. https://en.wikipedia.org/wiki/X86_calling_conventions
  10. +
+ +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2018/06/mysql-binlog/index.html b/2018/06/mysql-binlog/index.html new file mode 100644 index 00000000..e9de3105 --- /dev/null +++ b/2018/06/mysql-binlog/index.html @@ -0,0 +1,666 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MySQL binlog:格式、增量恢复、闪回、Java 解析 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ MySQL binlog:格式、增量恢复、闪回、Java 解析 +

+ + +
+ + + + +
+ + +

MySQL 的 binlog 日志文件,记录了数据库表的全部修改操作。本文简单整理 MySQL binlog 相关知识,以及如何使用 binlog 恢复或闪回数据库数据。

+

STATEMENT 格式的 binlog

+

要想开启 binlog,需要在启动 MySQL 时传入 --log-bin 参数。或者也可以在 MySQL 配置文件 /etc/my.cnf,设置 log_bin 开启 binlog。MySQL 5.7 开始,开启 binlog 后,--server-id 参数也必须指定,否则 MySQL 服务器会启动失败。

+ +

binlog_format 支持 STATEMENT, ROW, MIXED 三种格式,MySQL 5.5 和 5.6 默认为 STATEMENT,MySQL 5.7.7 开始默认为 ROW。若 SQL 使用 UUID(), RAND(), VERSION() 等函数,或者使用存储过程、自定义函数,基于 STATEMENT 的主从复时,是不安全的(很多人可能会认为 NOW(), CURRENT_TIMESTAMP 这些函数也是不安全的,事实上是安全的)[ doc1, doc2 ]。基于 ROW 的主从复制,是最安全的复制方式。

+

现在先来看下 STATEMENT 格式的 binlog,/etc/my.cnf 文件修改的内容如下:

+
1
2
3
4
server_id = 1
log_bin = mysql-bin
binlog_format = STATEMENT
binlog_row_image=FULL
+

重启 MySQL 后,在数据目录 datadir 下,比如 /var/lib/mysql/,将会生成相应的 binlog 文件,mysql-bin.indexmysql-bin.000001.index 后缀的文件保存全部 binlog 文件名。mysql-bin.000001 文件记录 binlog 内容。每次 MySQL 启动或者 flush 日志,都将按序号创建一个新的日志文件。另外,当日志文件大小超过 max_binlog_size 时,也会创建一个新的日志文件。

+

现在来试一试 binlog 功能。假设在 testdb 库在有 hello 表,并对其中某行做修改操作:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> select * from hello;
+----+-------+
| id | name |
+----+-------+
| 1 | Andy |
| 2 | Bill |
| 3 | Candy |
+----+-------+
4 rows in set (0.00 sec)

mysql> update hello set name = 'Will' where id = 3;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0
+

binlog 为二进制文件,需要使用 mysqlbinlogdoc, man)命令查看:

+
1
2
$ sudo mysqlbinlog /var/lib/mysql/mysql-bin.000001  # 直接在 mysql 服务器上读取 binlog 文件
$ mysqlbinlog -R -h192.168.2.107 -uroot -p123456 mysql-bin.000001 # 或者,远程读取 binlog 文件
+

执行 update 后相应新增的 binlog 文件内容:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# at 154
#180617 22:47:49 server id 1 end_log_pos 219 CRC32 0x4bd9d69b Anonymous_GTID last_committed=0 sequence_number=1 rbr_only=no
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 219
#180617 22:47:49 server id 1 end_log_pos 302 CRC32 0x476fafc9 Query thread_id=2 exec_time=0 error_code=0
SET TIMESTAMP=1529246869/*!*/;
SET @@session.pseudo_thread_id=2/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1075838976/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;
# at 302
#180617 22:47:49 server id 1 end_log_pos 423 CRC32 0x7f2c2c7a Query thread_id=2 exec_time=0 error_code=0
use `testdb`/*!*/;
SET TIMESTAMP=1529246869/*!*/;
update hello set name = 'Will' where id = 3
/*!*/;
# at 423
#180617 22:47:49 server id 1 end_log_pos 454 CRC32 0x68da744a Xid = 12
COMMIT/*!*/;
+

ROW 格式的 binlog

+

修改 /etc/my.cnfbinlog_formatROW,再重启 MySQL。格式修改后,会生成一个新的 binlog 文件 mysql-bin.000002

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
mysql> show create table hello;
+-------+-------------------------------------------------------------------------+
| Table | Create Table
+-------+-------------------------------------------------------------------------+
| hello | CREATE TABLE `hello` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 |
+-------+-------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select * from hello where id;
+----+------+
| id | name |
+----+------+
| 1 | Andy |
| 2 | Lily |
| 3 | Will |
+----+------+
1 row in set (0.00 sec)

mysql> update hello set name = 'David' where id = 3;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0
+

查看 ROW 格式的 binlog,需要使用 sudo mysqlbinlog -v --base64-output=DECODE-ROWS /var/lib/mysql/mysql-bin.000002 命令。执行 update 后相应新增的 binlog 内容:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# at 154
#180617 22:54:13 server id 1 end_log_pos 219 CRC32 0x2ce70d4d Anonymous_GTID last_committed=0 sequence_number=1 rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 219
#180617 22:54:13 server id 1 end_log_pos 293 CRC32 0x8183fddf Query thread_id=2 exec_time=0 error_code=0
SET TIMESTAMP=1529247253/*!*/;
SET @@session.pseudo_thread_id=2/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1075838976/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;
# at 293
#180617 22:54:13 server id 1 end_log_pos 346 CRC32 0x0fc7e1a4 Table_map: `testdb`.`hello` mapped to number 110
# at 346
#180617 22:54:13 server id 1 end_log_pos 411 CRC32 0xb58e729d Update_rows: table id 110 flags: STMT_END_F
### UPDATE `testdb`.`hello`
### WHERE
### @1=3
### @2='Will'
### SET
### @1=3
### @2='David'
# at 411
#180617 22:54:13 server id 1 end_log_pos 442 CRC32 0xef964db8 Xid = 13
COMMIT/*!*/;
+

若执行如下 SQL:

+
1
2
mysql> insert hello (name) values ('Frank');
Query OK, 1 row affected (0.02 sec)
+

相应生成的 binlog 内容:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# at 442
#180617 22:55:47 server id 1 end_log_pos 507 CRC32 0x79de08a7 Anonymous_GTID last_committed=1 sequence_number=2 rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 507
#180617 22:55:47 server id 1 end_log_pos 581 CRC32 0x56f9eb6a Query thread_id=2 exec_time=0 error_code=0
SET TIMESTAMP=1529247347/*!*/;
BEGIN
/*!*/;
# at 581
#180617 22:55:47 server id 1 end_log_pos 634 CRC32 0xedb73620 Table_map: `testdb`.`hello` mapped to number 110
# at 634
#180617 22:55:47 server id 1 end_log_pos 684 CRC32 0x525a6a70 Write_rows: table id 110 flags: STMT_END_F
### INSERT INTO `testdb`.`hello`
### SET
### @1=4
### @2='Frank'
# at 684
#180617 22:55:47 server id 1 end_log_pos 715 CRC32 0x09a0d4de Xid = 14
COMMIT/*!*/;
+

若执行如下 SQL:

+
1
2
mysql> delete from hello where id = 2;
Query OK, 1 row affected (0.02 sec)
+

相应生成的 binlog 内容:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# at 715
#180617 22:56:44 server id 1 end_log_pos 780 CRC32 0x9f52450e Anonymous_GTID last_committed=2 sequence_number=3 rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 780
#180617 22:56:44 server id 1 end_log_pos 854 CRC32 0x0959bc8d Query thread_id=2 exec_time=0 error_code=0
SET TIMESTAMP=1529247404/*!*/;
BEGIN
/*!*/;
# at 854
#180617 22:56:44 server id 1 end_log_pos 907 CRC32 0x2945260f Table_map: `testdb`.`hello` mapped to number 110
# at 907
#180617 22:56:44 server id 1 end_log_pos 956 CRC32 0xc70df255 Delete_rows: table id 110 flags: STMT_END_F
### DELETE FROM `testdb`.`hello`
### WHERE
### @1=2
### @2='Bill'
# at 956
#180617 22:56:44 server id 1 end_log_pos 987 CRC32 0x0c98f18e Xid = 15
COMMIT/*!*/;
+

使用 binlog 增量恢复

+

MySQL 逻辑备份通常会结合全量备份增量备份,使用 mysqldump 定期全量备份数据库,然后利用 binlog 保存增量数据。恢复数据时,就是用 mysqldump 备份的数据恢复到备份的时间点。数据库在备份时间点到当前时间的增量修改,则通过 mysqlbinlog 将 binlog 中的增量数据恢复到数据库。现在假设已经使用 mysqldump 将数据库还原到:

+
1
2
3
4
5
6
7
8
9
mysql> select * from hello;
+----+------+
| id | name |
+----+------+
| 1 | Andy |
| 2 | Lily |
| 3 | Will |
+----+------+
3 rows in set (0.00 sec)
+

之后执行的 SQL:

+
1
2
3
update hello set name = 'David' where id = 3;
insert hello (name) values ('Frank');
delete from hello where id = 2;
+

不管是使用 STATEMENT 还是 ROWmysqlbinlog 命令都可以将 binlog 增量恢复到数据库 [ doc ]。

+

观察 binlog 可以看到,从最开始的 update hello set name = 'David' where id = 3; 到最终的 delete from hello where id = 2;,时间上从 "2018-06-17 22:54:13" 到 "2018-06-17 22:56:44",所以基于时间点恢复,命令如下:

+
1
$ sudo mysqlbinlog --start-datetime="2018-06-17 22:54:13" --stop-datetime="2018-06-17 22:56:44" mysql-bin.000002 | mysql -uroot -p123456
+

binlog 的事件位置号是从 "154" 到 "956",但需要注意的是 用 --start-position--stop-position 指定位置点范围,逻辑上对应的是 start <= position < stop,所以基于时间点恢复,命令如下:

+
1
$ sudo mysqlbinlog --start-position=154 --stop-position=957 mysql-bin.000002 | mysql -uroot -p123456
+

两种方式任意执行,都能将数据恢复到:

+
1
2
3
4
5
6
7
8
9
mysql> select * from hello;
+----+-------+
| id | name |
+----+-------+
| 1 | Andy |
| 3 | David |
| 4 | Frank |
+----+-------+
3 rows in set (0.00 sec)
+

使用 binlog2sql 闪回

+

binlog2sql,作者为曹单锋,大众点评 DBA。binlog2sql,从 MySQL binlog 解析出你要的 SQL。根据不同选项,你可以得到原始 SQL、回滚 SQL、去除主键的 INSERT SQL 等。binlog2sql,底层实现依赖 python-mysql-replication,由该库完成 MySQL 复制协议和 binlog 格式的解析。

+
1
2
3
4
$ python binlog2sql/binlog2sql.py -h192.168.2.107 -uroot -p123456 --start-position=154 --stop-position=957 --start-file='mysql-bin.000002'
UPDATE `testdb`.`hello` SET `id`=3, `name`='David' WHERE `id`=3 AND `name`='Will' LIMIT 1; #start 4 end 411 time 2018-06-17 22:54:13
INSERT INTO `testdb`.`hello`(`id`, `name`) VALUES (4, 'Frank'); #start 442 end 684 time 2018-06-17 22:55:47
DELETE FROM `testdb`.`hello` WHERE `id`=2 AND `name`='Bill' LIMIT 1; #start 715 end 956 time 2018-06-17 22:56:44
+

生成回滚 sql:

+
1
2
3
4
$ python binlog2sql/binlog2sql.py --flashback -h192.168.2.107 -uroot -p123456 --start-position=154 --stop-position=956 --start-file='mysql-bin.000002'
INSERT INTO `testdb`.`hello`(`id`, `name`) VALUES (2, 'Bill'); #start 715 end 956 time 2018-06-17 22:56:44
DELETE FROM `testdb`.`hello` WHERE `id`=4 AND `name`='Frank' LIMIT 1; #start 442 end 684 time 2018-06-17 22:55:47
UPDATE `testdb`.`hello` SET `id`=3, `name`='Will' WHERE `id`=3 AND `name`='David' LIMIT 1; #start 154 end 411 time 2018-06-17 22:54:13
+

闪回的现实原理很简单,先通过 MySQL 复制协议com-binlog-dump 命令 dump 出 binlog,然后按照 binlog 的格式规范解析 binlog,将 binlog 转换成 SQL,再将这些 SQL 转换反向逻辑的 SQL,最后再倒序执行。具体可以看,binlog2sql 作者的文章 [ ref ]。

+

Java 解析 binlog

+

上文中的 binlog2sql 其实底层依赖 python-mysql-replication 库,这是 Python 库。如果想使用 Java 解析 binlog 可以使用 mysql-binlog-connector-javagithub)库。目前开源的 CDC 工具,如 Zendesk maxwell、Redhat debezium、LinkedIn Databus 等都底层依赖 mysql-binlog-connector-java 或者其前身 open-replicator。使用 mysql-binlog-connector-java 的示例代码如下:

+
1
2
3
4
5
6
7
8
BinaryLogClient client = new BinaryLogClient("192.168.2.107", 3306, "root", "123456");
client.setBinlogFilename("mysql-bin.000001");
client.setBinlogPosition(4);
client.setBlocking(false);
client.registerEventListener(event -> {
System.out.println(event);
});
client.connect();
+

输出(省略部分内容):

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
Event{header=EventHeaderV4{timestamp=1529247253000, eventType=TABLE_MAP, serverId=1, headerLength=19, dataLength=34, nextPosition=346, flags=0}, data=TableMapEventData{tableId=110, database='testdb', table='hello', columnTypes=8, 15, columnMetadata=0, 40, columnNullability={1}}}
Event{header=EventHeaderV4{timestamp=1529247253000, eventType=EXT_UPDATE_ROWS, serverId=1, headerLength=19, dataLength=46, nextPosition=411, flags=0}, data=UpdateRowsEventData{tableId=110, includedColumnsBeforeUpdate={0, 1}, includedColumns={0, 1}, rows=[
{before=[3, Will], after=[3, David]}
]}}
...
Event{header=EventHeaderV4{timestamp=1529247347000, eventType=TABLE_MAP, serverId=1, headerLength=19, dataLength=34, nextPosition=634, flags=0}, data=TableMapEventData{tableId=110, database='testdb', table='hello', columnTypes=8, 15, columnMetadata=0, 40, columnNullability={1}}}
Event{header=EventHeaderV4{timestamp=1529247347000, eventType=EXT_WRITE_ROWS, serverId=1, headerLength=19, dataLength=31, nextPosition=684, flags=0}, data=WriteRowsEventData{tableId=110, includedColumns={0, 1}, rows=[
[4, Frank]
]}}
...
Event{header=EventHeaderV4{timestamp=1529247404000, eventType=TABLE_MAP, serverId=1, headerLength=19, dataLength=34, nextPosition=907, flags=0}, data=TableMapEventData{tableId=110, database='testdb', table='hello', columnTypes=8, 15, columnMetadata=0, 40, columnNullability={1}}}
Event{header=EventHeaderV4{timestamp=1529247404000, eventType=EXT_DELETE_ROWS, serverId=1, headerLength=19, dataLength=30, nextPosition=956, flags=0}, data=DeleteRowsEventData{tableId=110, includedColumns={0, 1}, rows=[
[2, Bill]
]}}
+

参考资料

+
    +
  1. MySQL Replication: 5.1.1 Advantages and Disadvantages of Statement-Based and Row-Based Replication https://dev.mysql.com/doc/mysql-replication-excerpt/5.7/en/replication-sbr-rbr.html
  2. +
  3. Unsafe Statements for Statement-based Replication https://mariadb.com/kb/en/library/unsafe-statements-for-statement-based-replication/
  4. +
  5. MySQL 5.7 Reference Manual: 4.6.7 mysqlbinlog https://dev.mysql.com/doc/refman/5.7/en/mysqlbinlog.html
  6. +
  7. MySQL Internals Manual: 14.9 Replication Protocol https://dev.mysql.com/doc/internals/en/replication-protocol.html
  8. +
  9. MySQL Internals Manual: 20 The Binary Log https://dev.mysql.com/doc/internals/en/binary-log.html
  10. +
  11. MySQL闪回原理与实战 https://github.com/danfengcao/binlog2sql/blob/master/example/mysql-flashback-priciple-and-practice.md
  12. +
  13. https://dev.mysql.com/doc/dev/mysql-server/8.0.11/classbinary__log_1_1Table__map__event.html#details
  14. +
  15. https://dev.mysql.com/doc/dev/mysql-server/8.0.11/classbinary__log_1_1Rows__event.html#details
  16. +
+ +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2018/10/java-agent/index.html b/2018/10/java-agent/index.html new file mode 100644 index 00000000..aa2b4133 --- /dev/null +++ b/2018/10/java-agent/index.html @@ -0,0 +1,698 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Java Agent 学习笔记 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ Java Agent 学习笔记 +

+ + +
+ + + + +
+ + +

Java 从 1.5 开始提供了 java.lang.instrumentdoc)包,该包为检测(instrument) Java 程序提供 API,比如用于监控、收集性能信息、诊断问题。通过 java.lang.instrument 实现工具被称为 Java Agent。Java Agent 可以修改类文件的字节码,通常是,在字节码方法插入额外的字节码来完成检测。关于如何使用 java.lang.instrument 包,可以参考 javadoc 的包描述(en, zh)。

+ +

开发 Java Agent 的涉及的要点如下图所示 [ ref ]
+Java Agent

+

Java Agent 支持两种方式加载,启动时加载,即在 JVM 程序启动时在命令行指定一个选项来启动代理;启动后加载,这种方式使用从 JDK 1.6 开始提供的 Attach API 来动态加载代理。

+

启动时加载 agent

+

最简单的例子

+

现在创建命名为 proj-demo 的 gradle 项目,目录布局如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
$ tree proj-demo
proj-demo
├── build.gradle
└── src
├── main
│   └── java
│   └── com
│   └── demo
│   └── App.java
└── test
└── java

7 directories, 2 files
+

com.demo.App 类的实现:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
public class App {

public static void main(String[] args) throws InterruptedException {
while (true) {
System.out.println(getGreeting());
Thread.sleep(1000L);
}
}

public static String getGreeting() {
return "hello world";
}
}
+

运行 com.demo.App,每隔 1 秒输出 hello world

+
1
2
3
4
$ gradle build
$ java -cp "target/classes/java/main" com.demo.App
hello world
hello world
+

现在创建名称为 proj-premain 的 gradle 项目,com.demo.MyPremain 类实现 premain 方法:

+
1
2
3
4
5
6
7
package com.demo;

public class MyPremain {
public static void premain(String agentArgs, Instrumentation inst) {
System.out.println(agentArgs);
}
}
+

META-INF/MANIFEST.MF 文件指定 Premain-Class 属性:

+
1
2
3
4
5
6
7
8
jar {
manifest {
attributes 'Premain-Class': 'com.demo.MyPremain'
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
+

打包生成 proj-premain.jar,这个 jar 包就是 javaagent 代理。现在来试试运行 com.demo.App 时,启动这个 javaagent 代理。根据 javadoc 的描述,可以将以下选项添加到命令行来启动代理:

+
1
-javaagent:jarpath[=options] 
+

指定 -javaagent:"proj-premain.jar=hello agent",传入的 agentArgshello agent,再次运行 com.demo.App

+
1
2
3
4
$ java -javaagent:"proj-premain.jar=hello agent" -cp "target/classes/java/main" com.demo.App
hello agent
hello world
hello world
+

可以看到,在运行 main 之前,运行了 premain 方法,即先输出 hello agent,每隔 1 秒输出 hello world

+

修改字节码

+

在实现 premain 时,除了能获取 agentArgs 参数,还能获取 Instrumentation 实例。Instrumentation 类提供 addTransformer 方法,用于注册提供的转换器 ClassFileTransformer

+
1
2
// 注册提供的转换器
void addTransformer(ClassFileTransformer transformer)
+

ClassFileTransformer 是抽象接口,唯一需要实现的是 transform 方法。在转换器使用 addTransformer 注册之后,每次定义新类时(调用 ClassLoader.defineClass)都将调用该转换器的 transform 方法。该方法签名如下:

+
1
2
3
4
5
6
7
// 此方法的实现可以转换提供的类文件,并返回一个新的替换类文件
byte[] transform(ClassLoader loader,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer)
throws IllegalClassFormatException
+

操作字节码可以使用 ASM、Apache BCEL、Javassist、cglib、Byte Buddy 等库。下面示例代码,使用 BCEL 库实现名为 GreetingTransformer 转换器。该转换器实现的逻辑就是,将 com.demo.App.getGreeting() 方法输出的 hello world,替换为输出 premain 方法的传入的参数 agentArgs

+
1
2
3
4
5
public class MyPremain {
public static void premain(String agentArgs, Instrumentation inst) {
inst.addTransformer(new GreetingTransformer(agentArgs));
}
}
+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import org.apache.bcel.*;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;

public class GreetingTransformer implements ClassFileTransformer {
private String agentArgs;

public GreetingTransformer(String agentArgs) {
this.agentArgs = agentArgs;
}

@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, byte[] classfileBuffer) {
if (!className.equals("com/demo/App")) {
return classfileBuffer;
}
try {
JavaClass clazz = Repository.lookupClass(className);
ClassGen cg = new ClassGen(clazz);
ConstantPoolGen cp = cg.getConstantPool();
for (Method method : clazz.getMethods()) {
if (method.getName().equals("getGreeting")) {
MethodGen mg = new MethodGen(method, cg.getClassName(), cp);
InstructionList il = new InstructionList();
il.append(new PUSH(cp, this.agentArgs));
il.append(InstructionFactory.createReturn(Type.STRING));
mg.setInstructionList(il);
mg.setMaxStack();
mg.setMaxLocals();
cg.replaceMethod(method, mg.getMethod());
}
}
return cg.getJavaClass().getBytes();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
+

启动后加载 agent

+

最早 JDK 1.5发布 java.lang.instrument 包时,agent 是必须在 JVM 启动时,通过命令行选项附着(attach)上去。但在 JVM 正常运行时,加载 agent 没有意义,只有出现问题,需要诊断才需要附着 agent。JDK 1.6 实现了 attach-on-demand(按需附着)[ JDK-4882798 ],可以使用 Attach API 动态加载 agent [ oracle blog, javadoc ]。这个 Attach API 在 tools.jar 中。JVM 启动时默认不加载这个 jar 包,需要在 classpath 中额外指定。使用 Attach API 动态加载 agent 的示例代码如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;

public class AgentLoader {

public static void main(String[] args) throws Exception {
if (args.length < 2) {
System.err.println("Usage: java -cp .:$JAVA_HOME/lib/tools.jar"
+ " com.demo.AgentLoader <pid/name> <agent> [options]");
System.exit(0);
}

String jvmPid = args[0];
String agentJar = args[1];
String options = args.length > 2 ? args[2] : null;
for (VirtualMachineDescriptor jvm : VirtualMachine.list()) {
if (jvm.displayName().contains(args[0])) {
jvmPid = jvm.id();
break;
}
}

VirtualMachine jvm = VirtualMachine.attach(jvmPid);
jvm.loadAgent(agentJar, options);
jvm.detach();
}
}
+

启动时加载 agent,-javaagent 传入的 jar 包需要在 MANIFEST.MF 中包含 Premain-Class 属性,此属性的值是 代理类 的名称,并且这个 代理类 要实现 premain 静态方法。启动后加载 agent 也是类似,通过 Agent-Class 属性指定 代理类代理类 要实现 agentemain 静态方法。agent 被加载后,JVM 将尝试调用 agentmain 方法。

+

上文提到每次定义新类(调用 ClassLoader.defineClass)时,都将调用该转换器的 transform 方法。对于已经定义加载的类,需要使用重定义类(调用 Instrumentation.redefineClass)或重转换类(调用 Instrumentation.retransformClass)。

+
1
2
3
4
5
6
7
8
// 注册提供的转换器。如果 canRetransform 为 true,那么重转换类时也将调用该转换器
void addTransformer(ClassFileTransformer transformer, boolean canRetransform)
// 使用提供的类文件重定义提供的类集。新的类文件字节,通过 ClassDefinition 传入
void redefineClasses(ClassDefinition... definitions)
throws ClassNotFoundException, UnmodifiableClassException
// 重转换提供的类集。对于每个添加时 canRetransform 设为 true 的转换器,在这些转换器中调用 transform 方法
void retransformClasses(Class<?>... classes)
throws UnmodifiableClassException
+

重定义类(redefineClass)从 JDK 1.5 开始支持,而重转换类(retransformClass)是 JDK 1.6 引入。相对来说,重转换类能力更强,当存在多个转换器时,重转换将由 transform 调用链组成,而重定义类无法组成调用链。重定义类能实现的逻辑,重转换类同样能完成,所以保留重定义类方法(Instrumentation.redefineClass)可能只是为了向后兼容 [ stackoverflow ]。

+

实现 agentmain 的示例代码如下,其中 GreetingTransformer 转换器的类定义和上文一样。

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyAgentMain {

public static void agentmain(String agentArgs, Instrumentation inst) {
inst.addTransformer(new GreetingTransformer(agentArgs), true);
try {
Class clazz = Class.forName("com.demo.App");
if (inst.isModifiableClass(clazz)) {
inst.retransformClasses(clazz);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
+

MANIFEST.MF 文件配置:

+
1
2
3
4
5
6
7
8
9
10
jar {
manifest {
attributes 'Agent-Class': 'com.demo.MyAgentMain'
attributes 'Can-Redefine-Classes' : true
attributes 'Can-Retransform-Classes' : true
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
+

需要注意的是,和定义新类不同,重定义类和重转换类,可能会更改方法体、常量池和属性,但不得添加、移除、重命名字段或方法;不得更改方法签名、继承关系 [ javadoc ]。这个限制将来可能会通过 “JEP 159: Enhanced Class Redefinition” 移除 [ ref ]。

+

使用 Byte Buddy

+

Byte Buddy(home, github, javadoc),运行时的代码生成和操作库,2015 年获得 Oracle 官方 Duke's Choice award,提供高级别的创建和修改 Java 类文件的 API,使用这个库时,不需要了解字节码。另外,对 Java Agent 的开发 Byte Buddy 也有很好的支持,可以参考 Byte Buddy 作者 Rafael Winterhalter 写的介绍文章 [ ref1, ref2 ]。

+

上文使用 BCEL 实现的 GreetingTransformer,现在改用 Byte Buddy,会变得非常简单。实现 premain 示例代码:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void premain(String agentArgs, Instrumentation inst) {
new AgentBuilder.Default()
.type(ElementMatchers.named("com.demo.App"))
.transform(new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
TypeDescription typeDescription,
ClassLoader classLoader,
JavaModule module) {
return builder.method(ElementMatchers.named("getGreeting"))
.intercept(FixedValue.value(agentArgs));
}
}).installOn(inst);
}
+

实现 agentmain

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void agentmain(String agentArgs, Instrumentation inst) {
new AgentBuilder.Default()
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.disableClassFormatChanges()
.type(ElementMatchers.named("com.demo.App"))
.transform(new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
TypeDescription typeDescription,
ClassLoader classLoader,
JavaModule module) {
return builder.method(ElementMatchers.named("getGreeting"))
.intercept(FixedValue.value(agentArgs));
}
}).installOn(inst);
}
+

另外,Byte Buddy 对 Attach API 作了封装,屏蔽了对 tools.jar 的加载,可以直接使用 ByteBuddyAgent 类:

+
1
ByteBuddyAgent.attach(new File(agentJar), jvmPid, options);
+

上文中的 AgentLoader,可以使用这个 API 简化,实现的完整示例参见 AgentLoader2

+

实现性能计时器

+

Byte Buddy 的 github 的 README 文档提供了一个性能计时拦截器的代码示例,能对某个方法的运行耗时做统计。现在我们来看下是如何实现的。假设 com.demo.App2 类如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class App2 {

public static void main(String[] args) {
while (true) {
System.out.println(getGreeting());
}
}

public static String getGreeting() {
try {
Thread.sleep((long) (1000 * Math.random()));
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello world";
}
}
+

使用 Byte Buddy 实现计时拦截器的 agent,如下:

+
1
2
3
4
5
6
7
8
9
10
11
public class TimerAgent {

public static void premain(String agentArgs, Instrumentation inst) {
new AgentBuilder.Default()
.type(ElementMatchers.any())
.transform((builder, type, classLoader, module) ->
builder.method(ElementMatchers.nameMatches(agentArgs))
.intercept(MethodDelegation.to(TimingInterceptor.class)))
.installOn(inst);
}
}
+
1
2
3
4
5
6
7
8
9
10
11
12
public class TimingInterceptor {

@RuntimeType
public static Object intercept(@Origin Method method, @SuperCall Callable<?> callable) throws Exception {
long start = System.currentTimeMillis();
try {
return callable.call();
} finally {
System.out.println(method + " took " + (System.currentTimeMillis() - start) + "ms");
}
}
}
+

getGreeting 方法进行性能剖析,运行结果如下:

+
1
2
3
4
5
$ java -javaagent:"proj-byte-buddy.jar=get.*" -cp "target/classes/java/main" com.demo.App2
public static java.lang.String com.demo.App2.getGreeting() took 694ms
hello world
public static java.lang.String com.demo.App2.getGreeting() took 507ms
hello world
+

示例代码中的 premain 参数 agentArgs 用于指定需要剖析性能的方法名,支持正则表达式。当实际参数传入 get.* 时,匹配到 getGreeting 方法。上面的示例,使用的是 Byte Buddy 的方法委托 Method Delegation API [ javadoc ]。Delegation API 实现原理就是,将被拦截的方法委托到另一个办法上,如下左图所示(图片来自 Rafael Winterhalter 的 slides)。这种写法会修改被代理类的类定义格式,只能用在启动时加载 agent,即 premain 方式代理。

+

若要通过 Byte Buddy 实现启动后动态加载 agent,官方提供了 Advice API [ javadoc ]。Advice API 实现原理上是,在被拦截方法内部的开始和结尾添加代码,如下右图所示。这样只更改了方法体,不更改方法签名,也没添加额外的方法,符合重定义类(redefineClass)和重转换类(retransformClass)的限制。

+delegation vs. advice +

现在来看下使用 Advice API 实现性能定时器的代码示例:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
public class TimingAdvice {

@Advice.OnMethodEnter
public static long enter() {
return System.currentTimeMillis();
}

@Advice.OnMethodExit
public static void exit(@Advice.Origin Method method, @Advice.Enter long start) {
long duration = System.currentTimeMillis() - start;
System.out.println(method + " took " + duration + "ms");
}
}
+
1
2
3
4
5
6
7
8
9
10
11
public static void agentmain(String agentArgs, Instrumentation inst) {
new AgentBuilder.Default()
.disableClassFormatChanges()
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
// .with(AgentBuilder.Listener.StreamWriting.toSystemOut())
.type(ElementMatchers.any())
.transform((builder, type, classLoader, module) ->
builder.visit(Advice.to(TimingAdvice.class)
.on(ElementMatchers.nameMatches(agentArgs))))
.installOn(inst);
}
+

若对 com.demo.App 类,动态加载这个 Advice API 实现的 agent,getGreeting() 方法将会被重定义为(真正的实现可能稍有不同,但原理一致):

+
1
2
3
4
5
6
7
public static String getGreeting() {
long $start = System.nanoTime();
String $result = "hello world";
long $duration = System.nanoTime() – $start;
System.out.println("App.getGreeting()" + " took " + $duration + "ms");
return $result;
}
+

实际应用案例

+

Java Agent 的实际应用案例很多,举些笔者实际工作中使用到的开源软件的应用案例。

+

微服务是目前流行的互联网架构,实施微服务架构其中用于观察分布式服务的 APM (应用性能管理)系统是必不可缺的一环。典型的 APM 系统,如 PinpointSkyWalking,为了减少的 Java 服务应用代码的入侵,底层实现上都采用 Java Agent 技术,在 Java 服务应用启动时加载 agent,进行字节码增强技术,实现分布式追踪、服务性能监控等特性。具体可参见 Pinpoint 文档和 SkyWalking 文档

+

Alibaba Java 诊断利器 Arthas,实现上使用了动态 Attach API,相关源代码参见 github。Arthas 4.0 开始支持 premain 方式启动时加载 agent,参见 issue #550

+
+

**附注:**本文中提到的代码,可以在 github 上访问得到,javaagent-demo

+

参考资料

+ + +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2019/01/elastic-stack/index.html b/2019/01/elastic-stack/index.html new file mode 100644 index 00000000..65f4226d --- /dev/null +++ b/2019/01/elastic-stack/index.html @@ -0,0 +1,798 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Elastic Stack 日志分析平台搭建笔记 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ Elastic Stack 日志分析平台搭建笔记 +

+ + +
+ + + + +
+ + +

Elastic Stack(旧称 ELK Stack)是最受欢迎的开源日志平台 [ ref ]。Elastic Stack 由 Elasticsearch、Logstash、Kibana 和 Beats 四个组件组成:

+
    +
  • Beats,是轻量型采集器的平台,从边缘机器向 Logstash 和 Elasticsearch 发送数据。
  • +
  • Logstash,集中、转换和存储数据,是动态数据收集管道,拥有可扩展的插件生态系统,能够与 Elasticsearch 产生强大的协同作用。
  • +
  • Elasticsearch,搜索、分析和存储您的数据,是基于 JSON 的分布式搜索和分析引擎,专为实现水平扩展、高可靠性和管理便捷性而设计。
  • +
  • Kibana,实现数据可视化,导览 Elastic Stack。能够以图表的形式呈现数据,并且具有可扩展的用户界面,供您全方位配置和管理 Elastic Stack。
  • +
+ +

Elastic Stack 是逐步发展而来的,一开始只有 Elasticsearch,专注做搜索引擎,2013 年 1 月 Kibana 及其作者 Rashid Khan 加入 Elasticsearch 公司,同年 8 月 Logstash 及作者 Jordan Sissel 也加入,原本的非官方的 ELK Stack,正式成为官方用语。2015 年 3 月,旧金山举行的第 1 届 Elastic{ON} 大会上,Elasticsearch 公司改名为 Elastic。两个月后,Packetbeat 项目也加入 Elastic,Packetbeat 和 Filebeat(之前叫做 Logstash-forwarder,由 Logstash 作者 Jordan Sissel 开发)项目被整合改造为 Beats。加上 Beats 以后,官方不知道如何将 “B” 和 E-L-K 组合在一起(用过 ELKB 或 BELK),ELK Stack 于是改名为 Elastic Stack,并在 2016 年 10 月正式发布 Elastic Stack 5.0 [ ref1, ref2, ref3 ]。

+

使用 Logstash

+

Logstash(home, github)最初是来自 Dreamhost 运维工程师 Jordan Sissel 的开源项目,是管理事件和日志的工具,能够用于采集数据,转换数据,然后将数据发送到您最喜欢的“存储库”中(比如 Elasticsearch)。Logstash 使用 JRuby 开发,2011 年 5 月发布 1.0 版本。2013 年 8 月 Jordan Sissel 带着 Logstash 加入 Elasticsearch 公司,Logstash 成为 Elastic Stack 一员。

+

在 Ubuntu 下安装启动 Logstash 可以使用下面命令:

+
1
2
3
4
5
6
$ sudo apt-get install logstash                # 安装 logstash
$ sudo systemctl start logstash.service # 系统服务方式启动 logstash
$ /usr/share/logstash/bin/logstash --version # 查看 logstash 版本
logstash 6.5.4
$ sudo vim /etc/logstash/logstash.yml # 查看默认 logstash.yml
$ sudo vim /etc/logstash/logstash-sample.conf # 查看示例 logstash-sample.conf
+

安装完成后,二进制文件在 /usr/share/logstash/bin 目录下,配置文件位于 /etc/logstash 目录,日志输出位于 /var/log/logstash 目录,其他详细的目录位置的分布情况,可以阅读官方文档

+

最简单的示例

+

Logstash 管道(pipeline)由 inputfilteroutput 三个元素组成,其中 inputoutput 必须设置,而 filter 可选。input 插件从数据源中消费数据,filter 插件按指定方式修改数据,output 插件将数据写入特定目标中 [ doc ]。

+Logstash 管道 +

现在来试试 Logstash 下 Hello Wolrd 级别的示例,运行下面命令:

+
1
$ sudo /usr/share/logstash/bin/logstash -e 'input { stdin { } } output { stdout {} }'
+

-e 选项能够使 Logstash 直接在命令行中设置管道配置。示例中 input 插件为 stdin (标准输入),output 插件是 stdout (标准输出)。若在控制台输入 hello world,相应的控制台将输出:

+
1
2
3
4
5
6
{
"@version" => "1",
"host" => "ubuntu109",
"@timestamp" => 2019-01-12T05:52:56.291Z,
"message" => "hello world"
}
+

值得注意的是,输出内容编码格式默认为 rubydebug,使用 Ruby 的 "awesome_print" 库打印。另外,响应输出 @timestamp 字段的值为 2019-01-12T05:52:56.291Z,这是 ISO 8601 时间格式,时区是 0(zero),和北京时间相差 8 个小时。

+

输出内容编码格式,可以通过 codec 指令指定。除了默认的 rubydebug 外,官方还支持其他 20 多种编码格式,参见 doc。若把编码格式改为 json,即 stdout { codec => json },输出结果将变成:

+
1
{"message":"hello world","@version":"1","@timestamp":"2019-01-12T05:52:56.291Z","host":"ubuntu109"}
+

管道配置也可以保存到文件中,以 *.conf 作为文件后缀,比如保存为 test-stdin-stdout.conf

+
1
2
3
4
5
6
input {
stdin { }
}
output {
stdout { }
}
+

启动 logstash 时,-f 选项用于指定管道配置文件的路径:

+
1
$ sudo /usr/share/logstash/bin/logstash -f ~/test-stdin-stdout.conf
+

默认情况下,在启动 logstash 后,若再修改管道配置文件,新的修改需要重启 logstash 才能加载生效。在开发调试时,不太方便。解决这个问题,可以使用 -r 命令行选项。开启这个选项后,只要确定配置文件已经发生变更,便会自动重新加载配置文件。

+

file 输入插件

+

上文日志是控制台输入的,但真实情况日志在日志文件中,要想使用 Logstash 读取日志文件,官方提供了 file 输入插件。管道配置文件示例 test-file-stdout.conf,如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
input {
file {
path => ["/home/yulewei/test.log"]
sincedb_path => "/dev/null"
start_position => "beginning"
}
}
filter {
}
output {
stdout {
codec => rubydebug
}
}
+

启动 Logstash:

+
1
$ sudo /usr/share/logstash/bin/logstash -r -f ~/test-file-stdout.conf
+

配置文件中的 path 指令用于指定日志文件的路径。start_position 指令设置 Logstash 启动时读取日志文件的位置,可以设置为 beginning 或者 end,默认是 end,即文件末尾。

+

为了跟踪每个输入文件中已处理了哪些数据,Logstash 文件输入插件会使用名为 sincedb 的文件来记录现有位置。由于我们的配置用于开发,所以我们希望能够重复读取文件,并进而希望禁用 sincedb 文件。在 Linux 系统上,将 sincedb_path 指令设置为 “/dev/null” 即可禁用。若没有禁用,默认保存的 sincedb 文件将在 /usr/share/logstash/data/plugins/inputs/file/ 目录下。

+

grok 过滤插件

+

上文的例子,做的核心事情就是把日志行转换到 message 字段,并附加某些元数据,如 @timestamp。如果要想解析自己的日志,把非结构化日志转换结构换日志,有两个过滤器特别常用:dissect 会根据分界符来解析日志,而 grok 则会根据正则表达式匹配来运行。

+

如果数据结构定义非常完善,dissect 过滤插件的运行效果非常好,而且运行速度非常快捷高效。同时,其也更加容易上手,对于不熟悉正则表达式的用户而言,更是如此。通常而言,grok 的功能更加强大,而且可以处理各种各样的数据。然而,正则表达式匹配会耗费更多资源,而且速度也会慢一些,如果未能正确进行优化的话,尤为如此。

+

现在先来看下 grok 过滤插件。grok 模式的基本语法是 %{SYNTAX:SEMANTIC}SYNTAX 是用于匹配数据的模式(或正则表达式)名称,SEMANTIC 是标识符或字段名称。Logstash 提供了超过 120 种默认的 grok 模式,全部预定义的模式可以在 github 上找到。典型的预定义模式(非完整列表)[ github ]:

+
    +
  • WORD - 匹配单个词汇的模式
  • +
  • NUMBER - 匹配整数或浮点数(正值或负值均可)的模式
  • +
  • POSINT - 匹配正整数的模式
  • +
  • EMAILADDRESS - 邮箱地址
  • +
  • IP - 匹配 IPv4 或 IPv6 IP 地址的模式
  • +
  • URI - URI 地址
  • +
  • TIMESTAMP_ISO8601 - ISO8601 格式的时间
  • +
  • NOTSPACE - 匹配非空格的任何内容的格式
  • +
  • SPACE - 匹配任何数量的连续空格的模式
  • +
  • DATA - 匹配任何数据类型的限定数量的模式
  • +
  • GREEDYDATA - 匹配剩余所有数据的格式
  • +
+

比如,3.44 可以使用 NUMBER 模式进行匹配,192.168.2.104 可以使用 IP 模式。%{NUMBER:num} %{IP:client} 模式,将会用 NUMBER 模式把 3.44 识别为 num 字段,用 IP 模式把 192.168.2.104 识别为 client 字段。默认情况识别获得的字段值是字符串类型,grok 插件支持把类型转换为 intfloat。要想把 3.44 转换为浮点数,可以使用 %{NUMBER:num:float}

+

假设有如下日志内容:

+
1
Will, yulewei@gmail.com, 42, 1024, 3.14
+

grok 匹配表达式可以写成这样:

+
1
%{WORD:name}, %{EMAILADDRESS:email}, %{NUMBER:num1}, %{NUMBER:num2:int}, %{NUMBER:pi:float}
+

即,在这一行日志中依次提取出,nameemailnum1num2pi 字段。完整的 filter 过滤器配置的写法:

+
1
2
3
4
5
filter {
grok {
match => { "message" => "%{WORD:name}, %{EMAILADDRESS:email}, %{NUMBER:num1}, %{NUMBER:num2:int}, %{NUMBER:pi:float}" }
}
}
+

启动 logstash:

+
1
$ sudo /usr/share/logstash/bin/logstash -r -f ~/test-file-grok-stdout.conf
+

控制台将输出:

+
1
2
3
4
5
6
7
8
9
10
11
12
{
"@version" => "1",
"message" => "Will, yulewei@gmail.com, 42, 1024, 3.14",
"num1" => "42",
"pi" => 3.14,
"@timestamp" => 2019-01-12T08:12:49.581Z,
"path" => "/home/yulewei/test-grok.log",
"host" => "ubuntu109",
"email" => "yulewei@gmail.com",
"name" => "Will",
"num2" => 1024
}
+

Logstash 提供了超过 120 种默认的 grok 模式,基本上满足大多数使用场景。若没有符合要求的预定义的模式,可以使用 Oniguruma 语法指定正则表达式:

+
1
(?<field_name>the pattern here)
+

上文中的 %{WORD:name}%{EMAILADDRESS:email},等价的正则表达式的写法如下 [ ref1, ref2 ]:

+
1
2
(?<name>\w+)
(?<email>[a-zA-Z][a-zA-Z0-9_.+-=:]+@[0-9A-Za-z][0-9A-Za-z-]{0,62}\.[0-9A-Za-z][0-9A-Za-z-]{0,62})
+

调试 grok 匹配表达式容易出错,官方提供可视化的 Grok Debugger 工具,提高调试效率。

+Grok Debugger +

解析 http 服务器日志

+

现在来看下,真实的日志解析案例,使用 grok 过滤插件解析 http 服务器日志。通用日志格式(Common Log Format),是 http 服务器的标准的日志格式。对通用日志格式扩展,加上额外的 referer 和 user-agent 字段,称为组合日志格式(Combined Log Format)。两种日志格式包含的字段如下:

+
1
2
3
4
# 通用日志格式
%remote-host %ident %authuser %timestamp "%request" %status %bytes
# 组合日志格式
%remote-host %ident %authuser %timestamp "%request" %status %bytes "%referer" "%user-agent"
+

ApacheNginx 服务器默认的日志格式,采用的就是通用日志格式或者组合日志格式。解析这两种日志格式,Logstash 提供预定义模式 COMMONAPACHELOGCOMBINEDAPACHELOG

+

典型的 nginx 日志例子:

+
1
192.168.2.104 - - [13/Jan/2019:02:01:15 +0800] "GET /images/avatar.png HTTP/1.1" 200 266975 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:64.0) Gecko/20100101 Firefox/64.0"
+

管道配置文件示例 test-file-grokhttp-stdout.conf,如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
input {
file {
path => ["/var/log/nginx/access.log"]
sincedb_path => "/dev/null"
start_position => "beginning"
}
}
filter {
grok {
match => { "message" => "%{COMBINEDAPACHELOG}" }
remove_field => ["message"]
}
}
output {
stdout { }
}
+

示例中使用了 grok 的预定义模式 COMBINEDAPACHELOG。另外,remove_field 指令用于把输出事件中某字段删除,示例中是 message 字段。

+

启动 logstash:

+
1
$ sudo /usr/share/logstash/bin/logstash -r -f ~/test-file-grokhttp-stdout.conf
+

解析获得的结构化数据,如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"auth" => "-",
"host" => "ubuntu109",
"verb" => "GET",
"clientip" => "192.168.2.104",
"@version" => "1",
"httpversion" => "1.1",
"@timestamp" => 2019-01-13T13:35:52.983Z,
"bytes" => "266975",
"timestamp" => "13/Jan/2019:02:01:15 +0800",
"request" => "/images/avatar.png",
"response" => "200",
"referrer" => "\"-\"",
"path" => "/var/log/nginx/access.log",
"agent" => "\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:64.0) Gecko/20100101 Firefox/64.0\"",
"ident" => "-"
}
+

dissect 过滤插件

+

和 grok 过滤插件使用正则表达式提取字段不同,dissect 过滤插件使用分界符切割来提取字段。由于没有使用正则表达式,运行速度相对 grok 快很多。使用 dissect 过滤插件时,需要指明提取字段的顺序,还要指明这些字段之间的分界符。过滤插件会对数据进行单次传输,并匹配模式中的分界符。同时,过滤插件还会将分界符之间的数据分配至指定字段。过滤插件不会对所提取数据的格式进行验证。

+

现在看下示例,test-dissect.log 文件内容如下:

+
1
Will, yulewei@gmail.com, 42, 1024, 3.14
+

dissect 匹配规则可以写成这样:

+
1
%{name}, %{email}, %{num1}, %{num2}, %{num3}
+

完整的配置文件,test-file-dissect-stdout.conf

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
input {
file {
path => ["/home/yulewei/test-dissect.log"]
sincedb_path => "/dev/null"
start_position => "beginning"
}
}
filter {
dissect {
mapping => {
"message" => "%{name}, %{email}, %{num1}, %{num2}, %{num3}"
}
convert_datatype => {
"num2" => "int"
"num3" => "float"
}
}
}
output {
stdout { }
}
+

和 grok 插件一样,默认提取的字段是字符串类型。配置文件中的 convert_datatype 指令用于将类型转为 intfloat

+

启动 logstash:

+
1
$ sudo /usr/share/logstash/bin/logstash -r -f ~/test-file-dissect-stdout.conf
+

输出结果:

+
1
2
3
4
5
6
7
8
9
10
11
12
{
"host" => "ubuntu109",
"num1" => "42",
"message" => "Will, yulewei@gmail.com, 42, 1024, 3.14",
"@version" => "1",
"name" => "Will",
"num2" => 1024,
"@timestamp" => 2019-01-13T13:32:10.900Z,
"path" => "/home/yulewei/test-dissect.log",
"email" => "yulewei@gmail.com",
"num3" => 3.14
}
+

输出到 Elasticsearch

+

上文举的例子全部都是,输出控制台,使用 stdout 输出插件,没有实用价值。Elastic Stack 的核心其实是 Elasticsearch,使用Elasticsearch 搜索和分析日志。想要将数据发送到 Elasticsearch,可以使用 elasticsearch 输出插件。

+

安装 Elasticsearch

+

如果没有安装 Elasticsearch,参考官方文档按步骤安装。唯一要注意的是,在执行 apt install 命令前,必须先添加 elastic 的软件源地址,否则无法正常启动。核心命令如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ sudo apt-get install elasticsearch           # 安装 elasticsearch
$ sudo systemctl start elasticsearch.service # 系统服务方式启动 elasticsearch
$ curl http://localhost:9200/ # 用 rest 接口查看 elasticsearch
{
"name" : "1t9JXt5",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "yQgVsvupSqGCGQbwqnanIg",
"version" : {
"number" : "6.5.4",
"build_flavor" : "default",
"build_type" : "deb",
"build_hash" : "d2ef93d",
"build_date" : "2018-12-17T21:17:40.758843Z",
"build_snapshot" : false,
"lucene_version" : "7.5.0",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}
+

默认情况下 elasticsearch 服务器绑定的 ip 地址是回环地址 127.0.0.1,若想绑定特定 ip 地址,可以修改 /etc/elasticsearch/elasticsearch.yml 配置文件中的 network.host 选项:

+
1
network.host: 192.168.2.109
+

修改完成并重启后,elasticsearch 服务器访问地址从 http://localhost:9200/ 变成 http://192.168.2.109:9200/

+

输出到 Elasticsearch

+

现在来看下 elasticsearch 输出插件。示例,test-file-elasticsearch.conf

+
1
2
3
4
5
6
7
8
9
10
11
12
13
input {
file {
path => ["/home/yulewei/test.log"]
sincedb_path => "/dev/null"
start_position => "beginning"
}
}
output {
elasticsearch {
hosts => ["http://192.168.2.109:9200"]
index => "logstash-%{+YYYY.MM.dd}"
}
}
+

示例的 elasticsearch 输出插件使用了 hostsindex 指令。hosts 指令,用于指定 elasticsearch 服务器的地址。而 index 指令,用于指定 elasticsearch 索引的名称模式,该指令默认值为 logstash-%{+YYYY.MM.dd}。在字符串内部的 %{...},是 Logstash 字符串插值语法,官方称之为 sprintf format [ doc ]。+YYYY.MM.dd,用于指定 @timestamp 的格式化的格式。logstash-%{+YYYY.MM.dd},格式化后最终生成的值可能将是 logstash-2019.01.13

+

启动 logstash:

+
1
$ sudo /usr/share/logstash/bin/logstash -r -f ~/test-file-elasticsearch.conf
+

查看在 elasticsearch 上新创建的 logstash-* 索引以及从 logstash 同步过来的日志数据:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$ curl http://192.168.2.109:9200/_cat/indices
yellow open logstash-2019.01.13 tFjc5xL_QYeNw4oqe4odeg 5 1 3 0 15.5kb 15.5kb
$ curl 'http://192.168.2.109:9200/logstash-*/_search?pretty' -H 'Content-Type: application/json' -d'{"size": 1}'
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 3,
"max_score" : 1.0,
"hits" : [
{
"_index" : "logstash-2019.01.13",
"_type" : "doc",
"_id" : "RUHNRWgBLIBntI4FV8Rf",
"_score" : 1.0,
"_source" : {
"path" : "/home/yulewei/test.log",
"@timestamp" : "2019-01-13T06:01:51.303Z",
"@version" : "1",
"host" : "ubuntu109",
"message" : "hello world"
}
}
]
}
}
+

可以看到,新的索引名为 logstash-2019.01.13。同步过来的日志记录全部有 5 条,第 1 条日志的 message 内容是 hello world

+

使用 Kibana

+

Kibana,能够对 Elasticsearch 中的数据进行可视化,是 Elastic Stack 的窗口。在 Ubuntu 下安装 Kibana 可以使用下面命令:

+
1
2
$ sudo apt-get install kibana          # 安装 kibana,当前最新版为 6.5.4
$ sudo systemctl start kibana.service # 系统服务方式启动 kibana
+

默认配置下,kibana 服务访问地址是 http://localhost:5601/,连接的 elasticsearch 地址是 http://localhost:9200,这两个配置分别由 server.hostelasticsearch.url 控制 [ doc ]。上文尝试过把 elasticsearch 服务 ip 地址绑定到 192.168.2.109。现在来试下绑定 ip 地址到 kibana,编辑配置文件 /etc/kibana/kibana.yml,修改为:

+
1
2
server.host: "192.168.2.109"
elasticsearch.url: "http://192.168.2.109:9200"
+

使用 sudo systemctl restart kibana.service 重启后,kibana 服务访问地址变成 http://192.168.2.109:5601/

+

elasticsearch 服务器上存在索引 logstash-2019.01.13,要想把这个索引导入到 kibana,参考官方教程即可。点击 Management 菜单,然后创建索引模式(index pattern)。索引模式可以直接为 logstash-2019.01.13,这样匹配单个索引。若要匹配多个时间的 logstash 索引,可以使用通配符 *,比如 logstash-*。如果要匹配全部 2019 年 01 月的索引,可以写成 logstash-2019.01*。完成索引模式定义后,便可以在 Discover 菜单下查看索引,如图:

+Kibana +

使用 Filebeat

+

Filebeat,轻量型日志采集器 [ home ]。其前身是由 Logstash 作者 Jordan Sissel 开发的 Logstash Forwarder。Logstash Forwarder 项目因为和收购过来的 Packetbeat 项目功能相近,并且都是 Go 语言开发,就一起被整合改造为 Beats [ ref ]。

+

我们知道,Logstash 使用 JRuby 开发,运行依赖 JVM,会消耗较多的系统资源。为了减少系统资源(CPU、内存和网络)的使用,Logstash Forwarder 改用 Go 语言开发。另外,在功能上也做了精简,只做单一的数据传输,不像 Logstash 有数据过滤能力。Logstash 类似于功能多样的“瑞士军刀”,能提供从多个数据源加载数据的功能,使用各种强大的插件来处理日志,并提供将多个来源的输出数据进行存储的功能。简而言之,Logstash 提供数据 ETL(数据的提取、变换和加载)的功能;而 Beats 是轻量级的数据传输工具,能将数据传输到 Logstash 或 Elasticsearch 中,其间没有对数据进行任何转换 [ Gupta2017 ]。Filebeat 和 Logstash 的关系如下图所示 [ logz.io ]:

+Filebeat 和 Logstash 的关系 +

安装 filebeat 很简单,参考官方文档即可,核心命令如下:

+
1
2
3
4
$ sudo apt-get install filebeat           # 安装 filebeat
$ filebeat version # 查看 filebeat 版本
filebeat version 6.5.4 (amd64), libbeat 6.5.4 [bd8922f1c7e93d12b07e0b3f7d349e17107f7826 built 2018-12-17 20:22:29 +0000 UTC]
$ sudo systemctl start filebeat.service # 系统服务方式启动 filebeat
+

输出到 Elasticsearch

+

修改 filebeat 配置文件 /etc/filebeat/filebeat.yml,示例如下:

+
1
2
3
4
5
6
7
filebeat.inputs:
- type: log
paths:
- /home/yulewei/test.log

output.elasticsearch:
hosts: ["192.168.2.109:9200"]
+

filebeat.inputs 选项用于配置日志的输入方式。子选项 type 支持 logstdinredisudptcp 等,示例中使用了 log,表明从日志文件输入。

+

output 选项用于配置日志的输出方式,配置支持 elasticsearch、logstash、kafka、redis、file、console 等,一次只能选择配置其中某一个。示例配置了 output.elasticsearch.hosts,指定日志输出目标 elasticsearch 的主机地址。output.elasticsearch.index 可以用来指定索引 index 名称模式,默认是 filebeat-%{[beat.version]}-%{+yyyy.MM.dd}(比如 filebeat-6.5.4-2019.01.12)[ doc ]。

+

完成 filebeat.yml 修改后,重启 filebeat,将可以看到,在 elasticsearch 上新创建的 filebeat-* 索引:

+
1
2
$ curl http://192.168.2.109:9200/_cat/indices
yellow open filebeat-6.5.4-2019.01.12 B4JbQDnZQuK5XvsQ77uedA 3 1 11043 0 1.7mb 1.7mb
+

输出到 Logstash

+

上文的示例直接把 Filebeat 采集的日志传输到 Elasticsearch,日志数据并没有被解析或者转换。若想解析和转换日志,需要在Filebeat 和 Elasticsearch 中间引入 Logstash。现在看下把日志输出到 Logstash 的示例配置文件,filebeat.yml 示例:

+
1
2
3
4
5
6
7
filebeat.inputs:
- type: log
paths:
- /home/yulewei/test.log

output.logstash:
hosts: ["localhost:5044"]
+

filebeat.inputs 和上文的示例一样。不同的是,把 output.elasticsearch.hosts 改成了 output.logstash.hosts,指定日志输出目标 Logstash 的主机地址。5044 这个端口是 Logstash 用于监听 Filebeat 的端口。

+

现在来看下 Logstash 的管道配置文件,示例 test-beats-stdout.conf

+
1
2
3
4
5
6
7
8
9
10
input {
beats {
port => 5044
}
}
output {
stdout {
codec => rubydebug
}
}
+

示例中,使用了 beats 输入插件,配置的端口就 filebeat.yml 中指定的 5044。输出插件为 stdout,即把 Logstash 采集到日志输出到控制台。

+

重启 filebeat 和 logstash:

+
1
2
3
4
$ cat test.log                              # 查看日志文件内容
hello world
$ sudo systemctl restart filebeat.service # 重启 filebeat
$ sudo /usr/share/logstash/bin/logstash -r -f ~/test-beats-stdout.conf
+

控制台输出:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
"tags" => [
[0] "beats_input_codec_plain_applied"
],
"source" => "/home/yulewei/test.log",
"input" => {
"type" => "log"
},
"message" => "hello world",
"@timestamp" => 2019-01-12T13:32:05.131Z,
"@version" => "1",
"prospector" => {
"type" => "log"
},
"beat" => {
"hostname" => "ubuntu109",
"version" => "6.5.4",
"name" => "ubuntu109"
},
"offset" => 0,
"host" => {
"os" => {
"version" => "16.04.4 LTS (Xenial Xerus)",
"platform" => "ubuntu",
"codename" => "xenial",
"family" => "debian"
},
"architecture" => "x86_64",
"id" => "29b1bf39547d4ca9ae26c3b7656ff9e3",
"containerized" => false,
"name" => "ubuntu109"
}
}
+

集成 Filebeat, Logstash, Elasticsearch, Kibana

+

真实场景下,日志文件可能分布在多台服务器上,同一台服务器上也可能分布着不同来源类型的日志。现在我们来尝试下,使用 Filebeat 把两个日志文件各自采集到两个不同的 Elasticsearch 索引中,并用 Kibana 可视化。有两个日志文件 test-beats1.logtest-beats2.log,内容如下:

+
1
2
3
4
5
$ cat test-beats1.log
hello world1
hello world1
$ cat test-beats2.log
hello world2
+

filebeat.yml 配置示例:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
filebeat.inputs:
- type: log
paths:
- /home/yulewei/test-beats1.log
fields:
log_type: test1
- type: log
paths:
- /home/yulewei/test-beats2.log
fields:
log_type: test2

output.logstash:
hosts: ["localhost:5044"]
+

示例配置文件使用了 filebeat.inputs.fields 选项,fields 选项用于在日志事件输出中添加字段。添加的字段名可以任意指定,示例中名为 log_type。因为现在在 filebeat 配置中同时导入两个日志文件,输出到同一个 logstash 中。使用这个额外字段是为了区分日志是来自 test-beats1.log 还是 test-beats2.log。示例中,第 1 个日志事件输出的 log_type 字段值配置为 test1, 第 2 个日志配置为 test2

+

管道配置文件示例,test-beats-elasticsearch.conf

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
input {
beats {
port => 5044
}
}
output {
elasticsearch {
hosts => ["http://192.168.2.109:9200"]
index => "filebeat-%{[fields][log_type]}-%{+YYYY.MM.dd}"
}
stdout {
codec => rubydebug
}
}
+

输出插件同时使用了 elasticsearchstdout。配置文件中的 elasticsearch 输出插件的 index 指令被设置为 filebeat-%{[fields][log_type]}-%{+YYYY.MM.dd}[fields][log_type] 引用的是在 filebeat.ymlfilebeat.inputs.fields 选项添加的 log_type 字段(关于在配置文件引用字段的语法,可以参考官方文档)。根据 log_type 字段不同,把日志将输出到不同的索引中。因为 filebeat.yml 配置文件中设置的 log_type 字段是 test1 或者 test2,所以最终生成的索引名是 filebeat-test1-* 或者 filebeat-test1-*filebeat-test1-* 索引中全部日志数据来自 test-beats1.log 日志文件,filebeat-test2-* 索引数据来自 test-beats2.log

+

启动 filebeat 和 logstash:

+
1
2
$ sudo systemctl restart filebeat.service
$ sudo /usr/share/logstash/bin/logstash -r -f ~/test-beats-elasticsearch.conf
+

控制台输出:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
...
{
"@version" => "1",
"host" => {
"name" => "ubuntu109"
},
"message" => "hello world2",
"prospector" => {
"type" => "log"
},
"fields" => {
"log_type" => "test2"
},
"offset" => 0,
"tags" => [
[0] "beats_input_codec_plain_applied"
],
"beat" => {
"name" => "ubuntu109",
"version" => "6.5.4",
"hostname" => "ubuntu109"
},
"@timestamp" => 2019-01-13T09:32:11.845Z,
"source" => "/home/yulewei/test-beats2.log",
"input" => {
"type" => "log"
}
}
...
+

查看在 elasticsearch 上新创建的 filebeat-test1-*filebeat-test1-* 索引:

+
1
2
3
$ curl http://192.168.2.109:9200/_cat/indices/filebeat-*
yellow open filebeat-test1-2019.01.13 NLVfFJl5TQ-7I1r9KoVLaQ 5 1 5 0 31.8kb 31.8kb
yellow open filebeat-test2-2019.01.13 NnsBp3P9Q3-mLc8chE-Tiw 5 1 3 0 24.1kb 24.1kb
+

在 kibana 上查看收集的日志:

+Kibana +

整体架构上,如下图所示 [ doc ]:

+Deploying Logstash +
+

附注:本文中提到的配置文件,可以在 github 上访问得到,elastic-stack-conf

+

参考资料

+ + +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2019/06/mysql-5.7-json/index.html b/2019/06/mysql-5.7-json/index.html new file mode 100644 index 00000000..475aab3a --- /dev/null +++ b/2019/06/mysql-5.7-json/index.html @@ -0,0 +1,973 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MySQL 5.7 的 JSON 类型 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ MySQL 5.7 的 JSON 类型 +

+ + +
+ + + + +
+ + +

2015 年 8 月,MySQL 5.7.8 开始提供对 JSON 的原生支持[1][2]。MySQL 对 JSON 的支持可以说是千呼万唤始出来。2009 年开始 NoSQL 逐渐流行起来,相继出现了键值对数据库、文档数据库、列族数据库、图数据库等各类 NoSQL,解决经典关系型数据库无法解决的痛点。其中,对灵活存储半结构化数据的需求,使得类似 MongoDB 这类文档数据库涌现出来。各大主流关系型数据库也在响应趋势,开始支持半结构化数据。早在 2012 年,PostgreSQL 9.2 就已经添加了 JSON 数据类型[3]。Oracle 也在 2014 年 7 月发布 12c Release 1 后开始支持 JSON[4][5]。Facebook 在 MySQL 5.7 没发布之前,对 5.6 版本的 MySQL 添加了存储 JSON 功能,这个特性被 Facebook 命名为 DocStore (Document Database for MySQL at Facebook)[6][7]。另外,SQL 标准组织行动也很快,在 2014 年 3 月已经完成了 SQL/JSON 标准草案(SQL/JSON Proposals)[8][9][10]。完整的草案在 2016 年 12 月正式被采纳为标准,即 SQL:2016。

+ +

浏览 SQL/JSON 标准草案可以发现,全部作者共有 9 人,这些作者来自两个公司,Oracle 和 IBM,而排前面的作者如 Jim Melton, Fred Zemke, Beda Hammerschmidt 都 Oracle 的专家(有兴趣可以看下他们的 LinkedIn)。正因为 SQL:2016 主要就是 Oracle 参与制定的,目前,Oracle 数据库对 SQL:2016 的支持也是最全的[11]

+

MySQL 对 JSON 的支持,设计文档主要是 WL#7909: Server side JSON functions[12],另外还有 WL#8132: JSON datatype and binary storage format[13]、WL#8249: JSON comparator[14]、WL#8607: Inline JSON path expressions in SQL[15] 等。在 MySQL 开始 WL#7909 之时,SQL/JSON 标准草案已经公开,WL#7909 中也提及了这份标准,但是如果拿 MySQL 提供 JSON 的功能与 SQL:2016 比较,可以发现 MySQL 虽然融入了部分的设计,但并没有完全参考标准,定义的 JSON 函数多数有区别。

+

回到正题,下面来看下 MySQL 5.7 的 JSON 的用法。

+

JSON 函数列表

+

MySQL 官方列出 JSON 相关的函数,完整列表如下[16]

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
分类函数描述
json 创建函数json_array()创建 json 数组
json_object()创建 json 对象
json_quote()用双引号包裹 json 文档
json 查询函数json_contains()判断是否包含某个 json 值
json_contains_path()判断某个路径下是否包 json 值
json_extract()提取 json 值
column->pathjson_extract() 的简洁写法,5.7.9 开始支持
column->>pathjson_unquote(json_extract()) 的简洁写法,5.7.13 开始支持
json_keys()把 json 对象的顶层的全部键提取为 json 数组
json_search()按给定字符串关键字搜索 json,返回匹配的路径
json 修改函数json_append()5.7.9 废弃,改名为 json_array_append()
json_array_append()在 josn 文档末尾添加数组元素
json_array_insert()在 josn 数组中插入元素
json_insert()插入值(只插入新值,不替换旧值)
json_merge()5.7.22 废弃,与 json_merge_preserve() 同义
json_merge_patch()合并 json 文档,重复键的值将被替换掉
json_merge_preserve()合并 json 文档,保留重复键
json_remove()删除 json 文档中的数据
json_replace()替换值(只替换旧值,不插入新值)
json_set()设置值(替换旧值,或插入新值)
json_unquote()移除 json 值的双引号包裹
json 属性函数json_depth()返回 json 文档的最大深度
json_length()返回 json 文档的长度
json_type()返回 json 值的类型
json_valid()判断是否为合法 json 文档
json 工具函数json_pretty()美化输出 json 文档,5.7.22 新增
json_storage_size()返回 json 文档占用的存储空间,5.7.22 新增
+

官方文档对全部函数都作了充分解释并提供一定的示例代码。另外,官方博客也有极佳的相关介绍文章[17][18]。下文挑选了部分函数,演示它们的使用方法。

+

创建与插入 JSON

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
-- 创建 tbl 表,字段 data 为 json 类型
mysql> create table tbl (data JSON);
Query OK, 0 rows affected (0.17 sec)

-- 插入 json 对象
mysql> insert into tbl values ('{"id": 1, "name": "Will"}');
Query OK, 1 row affected (0.04 sec)

-- 插入 json 数组
mysql> insert into tbl values ('[1, 42, 1024]');
Query OK, 1 row affected (0.01 sec)

-- 使用 json_object() 创建 json 对象
mysql> insert into tbl values (json_object('id', 2, 'name', 'Joe'));
Query OK, 1 row affected (0.02 sec)

-- 使用 json_array() 创建 json 数组
mysql> insert into tbl values (json_array(1, "abc", null, true, curtime()));
Query OK, 1 row affected (0.02 sec)

-- 查询 tbl 表数据
mysql> select * from tbl;
+-------------------------------------------+
| data |
+-------------------------------------------+
| {"id": 1, "name": "Will"} |
| [1, 42, 1024] |
| {"id": 2, "name": "Andy"} |
| [1, "abc", null, true, "20:27:41.000000"] |
+-------------------------------------------+
4 rows in set (0.00 sec)
+

上面的 SQL 示例简单验演示了创建 JSON 列以及写入并查询 JSON 数据,比较简单,就不做解释了。

+

查询 JSON

+

json_extract() 与 -> 操作符

+

如果要查询 JSON 文档中内容,提取 JSON 中的值,可以使用 json_extract() 函数。函数定义如下:

+
1
json_extract(json_doc, path[, path] ...)
+

先来看下 SQL 示例:

+
1
2
3
4
5
6
7
8
-- 使用 json_extract() 函数查询 json 对象
mysql> select json_extract('{"id": 1, "name": "Will"}', '$.name');
+-------------------------------------------------------+
| json_extract('{"id": 1, "name": "Will"}', '$.name') |
|-------------------------------------------------------|
| "Will" |
+-------------------------------------------------------+
1 row in set (0.01 sec)
+

示例中的 $.name,使用的是 JSON 路径语法,用来提取 JSON 文档的内容。JSON 路径语法,源自 Stefan Goessner 的 JsonPath[19],不过 MySQL 作了简化。路径语法使用 $ 开头来表示整个 JSON 文档。如果要提取部分 JSON 文档,可以在路径后面添加选择符:

+
    +
  • 在路径 path 后上追加对象的键名称,可以获取这个键下成员。如果加键名称后,路径表达式非法,需要对键名称用双引号包裹(比如,键名称中包含空格的情况)
  • +
  • 在路径 path 后加上追加 [N],用于选择数组的第 N 个元素。数组索引从 0 开始。如果 path 下并不是数组,path[0] 获取结果就是 path 本身。
  • +
  • 路径可以包含 *** 通配符: +
      +
    • .[*] 用于获取 JSON 对象的全部成员。
    • +
    • [*] 用于获取 JSON 数组的全部元素。
    • +
    • prefix**suffix 表示全部以 prefix 开始,以 suffix 结尾的路径。
    • +
    +
  • +
  • 如果路径在 JSON 文档中不存在数据,将返回 NULL
  • +
+

假设 $ 引用的是如下 JSON 数组:

+
1
[3, {"a": [5, 6], "b": 10}, [99, 100]]
+

$[0] 获取到的值为 3,$[1] 获取到 {"a": [5, 6], "b": 10}$[2] 获取到 [99, 100]$[3] 获取到 NULL(因为不存在第 4 个元素)。

+

因为 $[1]$[2] 获取的并非纯量(nonscalar),它们可以进一步使用路径访问到内嵌的值,比如:$[1].a 获取到 [5, 6]$[1].a[1] 获取到 6$[1].b 获取到 10$[2][0] 获取到 99

+

上文提到,如果追加键值名后,路径表达式非法,需要对键名称用双引号包裹。假设 $ 引用的是如下 JSON 对象:

+
1
{"name 1": "Will", "name 2": "Andy"}
+

两个键都包含空格,需要加上双引号,才能使用路径表达式访问。$."name 1" 将获取到 Will,而 $."name 2" 将获取到 Andy

+

现在来看下通配符的示例,假设 JSON 对象如下:

+
1
{"a": {"b": 1}, "c": {"b": 2}, "d": [3, 4, 5]}
+

使用 $.* 将获取到 [{"b": 1}, {"b": 2}, [3, 4, 5]]
+使用 $.d[*] 将获取到 [3, 4, 5]
+使用 $**.b(对应 $.a.b$.c.b)将获取到 [1, 2]

+

MySQL 5.7.9 开始,官方支持 json_extract(column, path) 的简洁写法,内联 JSON 路径表达式 column->path(WL#8607)。示例如下:

+
1
2
3
4
5
6
7
8
-- 使用内联 json 路径表达式,查询 json 对象
mysql> select * from tbl where data -> '$.id' = 2;
+---------------------------+
| data |
+---------------------------+
| {"id": 2, "name": "Andy"} |
+---------------------------+
1 row in set (0.00 sec)
+

本质上,这种写法是语法糖,column->path 等价于 json_extract(column, path),内联 JSON 路径表达式会在语法解析阶段被转换为 json_extract() 调用。另外,column->path,存在以下限制[20]

+

限制

+

即,1. 数据源必须是表字段,2. 路径表达式必须为字符串,3. SQL 语句中最多只支持一个。

+

现在来试验下这个限制,如果使用内联 JSON 路径表达式查询 MySQL 变量,将会报语法错误:

+
1
2
3
4
5
mysql> set @j = '["a", "b"]';

-- 语法错误
mysql> select @j -> '$[0]';
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-> '$[0]'' at line 1
+

json_unquote() 与 ->> 操作符

+

假设数据如下:

+
1
2
3
4
5
6
7
8
mysql> select * from tbl;
+-----------------------------------------------+
| data |
+-----------------------------------------------+
| {"id": 1, "name": "Will"} |
| {"id": 2, "name": "printf(\"hello world\");"} |
+-----------------------------------------------+
2 rows in set (0.00 sec)
+

来看下使用 -> 提取获得 JSON 值:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
mysql> select data -> '$.id', data -> '$.name', substr(data -> '$.name', 1, 1) from tbl;
+----------------+----------------------------+--------------------------------+
| data -> '$.id' | data -> '$.name' | substr(data -> '$.name', 1, 1) |
+----------------+----------------------------+--------------------------------+
| 1 | "Will" | " |
| 2 | "printf(\"hello world\");" | " |
+----------------+----------------------------+--------------------------------+
2 rows in set (0.00 sec)

mysql> create table tmp (id int, name varchar(50));
mysql> insert tmp select data -> '$.id', data -> '$.name' from tbl;
mysql> select *, substr(name, 1, 1) from tmp;
+------+----------------------------+--------------------+
| id | name | substr(name, 1, 1) |
+------+----------------------------+--------------------+
| 1 | "Will" | " |
| 2 | "printf(\"hello world\");" | " |
+------+----------------------------+--------------------+
2 rows in set (0.01 sec)
+

可以看到,对于 string 类型的 JSON 值,使用 json_extract()-> 获取的都是被双引号包裹的字符串。MySQL 提供 json_unquote() 函数,用于去掉双引号包裹。另外,MySQL 支持 column->>path 语法,通过 ->> 操作符获取纯量(scalar)。column->>path 写法等价于 json_unquote( json_extract(column, path) ) 或者 json_unquote(column -> path)。来看下 SQL 示例:

+
1
2
3
4
5
6
7
8
9
mysql> select data ->> '$.id' as id, data -> '$.name' as name,
-> data ->> '$.name' as name, json_unquote(data -> '$.name') as name from tbl;
+------+----------------------------+------------------------+------------------------+
| id | name | name | name |
+------+----------------------------+------------------------+------------------------+
| 1 | "Will" | Will | Will |
| 2 | "printf(\"hello world\");" | printf("hello world"); | printf("hello world"); |
+------+----------------------------+------------------------+------------------------+
2 rows in set (0.00 sec)
+

MySQL 这种区分 ->->> 的写法,怀疑是源自 Postgres。因为 Postgres 也分别提供了 ->->> 操作符,-> 也是保留双引号(get JSON object field by key),而 ->> 才能获取实际的字符串值(get JSON object field as text)[21][22]

+

在笔者看来,这种需要通过 json_unquote() 才能获取实际字符串值的写法完全没有必要,因为很难想到有需要保留双引号的使用场景,而就获取实际的字符串值才是多数情况。实际上,SQLite 的开发者也持有相同的想法。2015 年 10 月,SQLite 3.9 发布,开始支持 JSON 类型[23][24]。简单对比下,可以发现 SQLite 提供的 JSON 函数和 MySQL 极其相似,很多函数同名并且同语义。SQLite 也提供了 json_extract() 函数,与 MySQL 不同,SQLite 返回的是移除双引号后的字符串(the dequoted text for a JSON string value)。看下示例:

+
1
2
3
4
sqlite> select json_extract('{"id": 1, "name": "Will"}', '$.name');
Will
sqlite> select json_extract('{"code": "printf(\"hello world\");"}', '$.code');
printf("hello world");
+

对于提取 JSON 文档中的纯量(scalar),SQL 标准定义了的 json_value() 函数,MySQL 没有支持,但 Oracle、MariaDB、MSSQL 都有支持。MariaDB 在兼容 MySQL 的同时也支持 SQL 标准,json_extract() 和 json_value() 在 MariaDB 下都可用。来看下 SQL 示例:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
MariaDB [testdb]> select * from tbl;
+-----------------------------------------------+
| data |
+-----------------------------------------------+
| {"id": 1, "name": "Will"} |
| {"id": 2, "name": "printf(\"hello world\");"} |
+-----------------------------------------------+
2 rows in set (0.00 sec)

-- 使用 json_extract() 提取 JSON 值,string 类型的值保留双引号
MariaDB [testdb]> select json_extract(data, '$.id'), json_extract(data, '$.name') from tbl;
+----------------------------+------------------------------+
| json_extract(data, '$.id') | json_extract(data, '$.name') |
+----------------------------+------------------------------+
| 1 | "Will" |
| 2 | "printf(\"hello world\");" |
+----------------------------+------------------------------+
2 rows in set (0.00 sec)

-- 使用 json_value() 提取 JSON 值,string 类型的值自动移除双引号
MariaDB [testdb]> select json_value(data, '$.id'), json_value(data, '$.name') from tbl;
+--------------------------+----------------------------+
| json_value(data, '$.id') | json_value(data, '$.name') |
+--------------------------+----------------------------+
| 1 | Will |
| 2 | printf("hello world"); |
+--------------------------+----------------------------+
2 rows in set (0.00 sec)
+

其他查询函数

+

除了上文的 json_extract() 函数,查询 JSON 文档相关的还有其他函数,如 json_contains()、json_contains_path()、json_keys()、json_search()。示例如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
mysql> set @j = '{"a": 1, "b": 2, "c": {"d": 4}}';
Query OK, 0 rows affected (0.00 sec)

-- 使用 json_contains() 函数判断是否存在某 JSON 值
mysql> select json_contains(@j, '{"a": 1}');
+-------------------------------+
| json_contains(@j, '{"a": 1}') |
+-------------------------------+
| 1 |
+-------------------------------+
1 row in set (0.00 sec)

-- 使用 json_contains_path() 函数判断是否存在某 JSON 路径
mysql> select json_contains_path(@j, 'one', '$.a', '$.e');
+-----------------------------------------------+
| json_contains_path(@j, 'one', '$.a', '$.e') |
|-----------------------------------------------|
| 1 |
+-----------------------------------------------+
1 row in set (0.00 sec)

-- 使用 json_contains_path() 函数判断是否存在某 JSON 路径
mysql> select json_contains_path(@j, 'all', '$.a', '$.e');
+-----------------------------------------------+
| json_contains_path(@j, 'all', '$.a', '$.e') |
|-----------------------------------------------|
| 0 |
+-----------------------------------------------+
1 row in set (0.00 sec)
+

函数的完整定义和用法可以参考官方文档,本文不再一一举例说明。

+

修改 JSON

+

对于 MySQL 的 JSON 类型的数据,若要修改数据,可以使用类似如下的 SQL:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mysql> select * from tbl where data->'$.id' = 2;
+---------------------------+
| data |
+---------------------------+
| {"id": 2, "name": "Will"} |
+---------------------------+
1 row in set (0.00 sec)

-- 对 data 整个字段修改
mysql> update tbl set data = '{"id": 2, "name": "Andy"}' where data->'$.id' = 2;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 0

mysql> select * from tbl where data->'$.id'= 2;
+---------------------------+
| data |
+---------------------------+
| {"id": 2, "name": "Andy"} |
+---------------------------+
1 row in set (0.00 sec)
+

如果要修改 JSON 内部数据,是否可以通过 JSON 路径表达式直接赋值呢?答案是,不行,MySQL 不支持。

+
1
2
3
-- 语法错误,不支持通过 JSON 路径表达式赋值,修改 JSON 数据
mysql> update tbl set data->'$.name' = 'Andy' where data->'$.id' = 2;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '->'$.name' = 'Andy' where data->'$.id' = 2' at line 1
+

MySQL 提供了数个函数来修改 JSON 数据。我们先来看看 json_replace()、json_set() 和 json_insert() 这三个函数:

+
    +
  • json_replace():替换值。替换旧值,但不插入新值
  • +
  • json_set():设置值。替换旧值,或插入新值
  • +
  • json_insert():插入值。只插入新值,不替换旧值
  • +
+

json_insert() 只能插入数据, json_replace() 只能更新数据,json_set() 能更新或插入数据。

+

替换值,json_replace() 示例:

+
1
2
3
4
5
6
7
8
-- 使用 json_replace() 函数
-- 把 {"id": 2, "name": "Will"} 修改为 {"id": 2, "name": "Andy"}
-- 路径 $.name 指向的值存在,旧值被替换为新值
mysql> update tbl
-> set data = json_replace(data, '$.name', 'Andy')
-> where data->'$.id' = 2;
Query OK, 1 row affected (0.03 sec)
Rows matched: 1 Changed: 1 Warnings: 0
+

设置值,json_set() 示例:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-- 使用 json_set() 函数
-- 把 {"id": 2, "name": "Will"} 修改为 {"id": 2, "city": "北京", "name": "Bill"}
-- 路径 $.name 指向的值存在,旧值被替换为新值;路径 $.city 指向的值不存在,将插入新值
mysql> update tbl
-> set data = json_set(data, '$.name', 'Bill', '$.city', '北京')
-> where data->'$.id'= 2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> select * from tbl where data->'$.id'= 2;
+---------------------------------------------+
| data |
+---------------------------------------------+
| {"id": 2, "city": "北京", "name": "Bill"} |
+---------------------------------------------+
1 row in set (0.00 sec)
+

插入值,json_insert() 示例:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-- 使用 json_set() 函数
-- 把 {"id": 2, "name": "Will"} 修改为 {"id": 2, "address": "故宫"}
-- 路径 $.name 指向的值存在,将不替换这个旧值;路径 $.address 指向的值不存在,将插入新值
mysql> update tbl
-> set data = json_insert(data, '$.name', 'Bill', '$.address', '故宫')
-> where data->'$.id'= 2;
Query OK, 1 row affected (0.04 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> select * from tbl where data->'$.id'= 2;
+---------------------------------------------------------------------+
| data |
+---------------------------------------------------------------------+
| {"id": 2, "name": "Will", "address": "故宫"} |
+---------------------------------------------------------------------+
1 row in set (0.00 sec)
+

现在,我们来看下修改 JSON 数组的两个函数,json_array_insert() 和 json_array_append(),函数定义如下:

+
1
2
json_array_insert(json_doc, path, val[, path, val] ...)
json_array_append(json_doc, path, val[, path, val] ...)
+

json_array_insert(),参数 path 必须指向 JSON 数组某个位置的元素,若该位置存在值,将会把 val 插入该位置,然后其他元素向右移动;若该位置超出数组大小范围,将会把 val 插入到数组末尾。SQL 示例如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
mysql> set @j = '["a", {"b": [1, 2]}, [3, 4]]';

-- 在数组的索引 1 的位置上插入值 5,原本索引 1 位置上的 {"b": [1, 2]} 被挤到后边
mysql> select json_array_insert(@j, '$[1]', 5);
+------------------------------------+
| json_array_insert(@j, '$[1]', 5) |
|------------------------------------|
| ["a", 5, {"b": [1, 2]}, [3, 4]] |
+------------------------------------+
1 row in set (0.00 sec)

-- 插入位置超出数组大小范围,将会把值插入到数组末尾
mysql> select json_array_insert(@j, '$[100]', 5);
+--------------------------------------+
| json_array_insert(@j, '$[100]', 5) |
|--------------------------------------|
| ["a", {"b": [1, 2]}, [3, 4], 5] |
+--------------------------------------+
1 row in set (0.00 sec)

-- path 指向不是 JSON 数组的元素,SQL 执行报错
mysql> select json_array_insert(@j, '$[1].b', 5);
(3165, 'A path expression is not a path to a cell in an array.')
+

json_array_append(),如果参数 path 指向的 JSON 是数组,将在数组末尾添加元素;如果参数 path 指向的 JSON 是值或对象,该值或对象将被包裹为数组,然后在这个数组末尾添加元素。

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
mysql> set @j = '["a", {"b": [1, 2]}, [3, 4]]';

-- path 指向的 JSON 是数组,将在数组末尾添加元素
mysql> select json_array_append(@j, '$', 5);
+---------------------------------+
| json_array_append(@j, '$', 5) |
+---------------------------------+
| ["a", {"b": [1, 2]}, [3, 4], 5] |
+---------------------------------+
1 row in set (0.00 sec)

-- path 指向的 JSON 是值或对象,该值或对象将被包裹为数组,然后在这个数组末尾添加元素
mysql> select json_array_append(@j, '$[1]', 5);
+-----------------------------------+
| json_array_append(@j, '$[1]', 5) |
+-----------------------------------+
| ["a", [{"b": [1, 2]}, 5], [3, 4]] |
+-----------------------------------+
1 row in set (0.00 sec)
+

除了上文提到的函数,还有 json_merge_patch()、json_merge_preserve()、json_remove() 这个些函数,可以参考官方文档的介绍,本文不再一一举例说明。

+

索引 JSON:生成列

+

现在来看下根据 JSON 列查询表数据的执行计划,如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mysql> explain select * from tbl where data -> "$.id" = 1 \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: tbl
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 2
filtered: 100.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)
+

可以看到,因为没有加索引,访问类型是全表扫描 type: ALL。来试下在 JSON 类型的 data 列上添加索引,会提示如下错误:

+
1
2
mysql> alter table tbl add index (data);
ERROR 3152 (42000): JSON column 'data' cannot be used in key specification.
+

对于索引 JSON 类型列问题,MySQL 文档有如下阐述[2:1]

+
+

JSON columns, like columns of other binary types, are not indexed directly; instead, you can create an index on a generated column that extracts a scalar value from the JSON column. See Indexing a Generated Column to Provide a JSON Column Index, for a detailed example.

+
+

就是说,不能直接在 JSON 列上创建索引;替代方式是,先创建提取 JSON 纯量的生成列(generated column),然后在这个生成列上创建索引。回过头来,ERROR 3152,这个报错提示信息其实让人有点困惑,对没仔细阅读文档的人来说,可能会误以为 MySQL 不支持索引 JSON 列(Bug #81364[25])。于是,在 MySQL 8.0 错误提示信息优化为:

+
+

ERROR 3152 (42000): JSON column '%s' supports indexing only via generated columns on a specified JSON path.

+
+

生成列以及在生成列上创建索引,是 MySQL 5.7 开始支持的新特性。但其实,在 SQL:2003 标准中,生成列就早已经被定义为可选特性,“Optional Features of SQL/Foundation:2003, T175 Generated columns”。这个特性在其他 DBMS 中很早就有支持。2007 年 9 月发布的 Oracle Database 11g 开始支持生成列,不过它们称之为称之为虚拟列(virtual column)。2008 年 8 月发布的 SQL Server 2008 开始支持计算列(computed column),实现的就是 SQL 标准中的生成列。在相近的时间点,MySQL 创建了WL#411: Computed virtual columns as MS SQL server has[26]。之后,MySQL 的社区贡献者 Andrey Zhakov 实现了 WL#411 描述的特性,并发布了实现的代码补丁[27][28][29]。可惜的是 MySQL 官方很长一段时间都没把这个补丁合并进来,直到 2015 年的 MySQL 5.7(7年后)才官方实现 WL#411[30],同时 WL#411 的标题也被更新为符合 SQL 标准术语的 “Generated columns”。与之相对比的是,2010 年 4 月发布的 MariaDB 5.2 就开始支持虚拟列[31],实现上同样也是基于 Andrey Zhakov 贡献的代码。关于生成列或虚拟列,Wikipedia 的 Virtual column 词条[32]总结了各大 DBMS 的支持情况,可以参阅。总结下,标准 SQL 定义生成列的语法和 SQL Server 2008、Oracle 11g、MariaDB、MySQL 的区别[30:1][33]

+
1
2
3
4
5
6
7
8
9
Standard             MSSQL 2008      Oracle 11g           MariaDB 10.1           MySQL 5.7               
-------- ----------- ---------- ------------ ---------
column_name column_name column_name column_name column_name
[data type] [data type] data_type data type
GENERATED ALWAYS AS AS GENERATED ALWAYS AS [GENERATED ALWAYS] AS [GENERATED ALWAYS] AS
(expression) (expression) (expression) (expression) (expression)
[PERSISTENT] [VIRTUAL] [VIRTUAL | PERSISTENT] [VIRTUAL | STORED]
[constraints] [constraints] [constraints] [constraints] [constraints]
[COMMENT 'string'] [COMMENT 'string']
+

回到正题,我们现在来试试 MySQL 的生成列:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
-- 添加生成列
mysql> alter table tbl add id int as (data -> "$.id");
Query OK, 0 rows affected (0.15 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> select * from tbl;
+-----------------------------------------------+------+
| data | id |
+-----------------------------------------------+------+
| {"id": 1, "name": "Will"} | 1 |
| {"id": 2, "name": "printf(\"hello world\");"} | 2 |
+-----------------------------------------------+------+
2 rows in set (0.00 sec)
+

上面的示例,创建生成列 id,生成列对应的表达式是 data -> "$.id"。现在再试试在生成列 id 上,创建索引:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
-- 在生成列上创建索引 idx_id
mysql> create index idx_id on tbl (id);
Query OK, 0 rows affected (0.05 sec)
Records: 0 Duplicates: 0 Warnings: 0

-- 执行计划
mysql> explain select * from tbl where id = 1 \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: tbl
partitions: NULL
type: ref
possible_keys: idx_id
key: idx_id
key_len: 5
ref: const
rows: 1
filtered: 100.00
Extra: NULL
1 row in set, 1 warning (0.00 sec)

-- 执行计划
mysql> explain select * from tbl where data -> "$.id" = 1 \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: tbl
partitions: NULL
type: ref
possible_keys: idx_id
key: idx_id
key_len: 5
ref: const
rows: 1
filtered: 100.00
Extra: NULL
1 row in set, 1 warning (0.00 sec)
+

从上面的执行计划可以看到,查询条件用 id 或者 data -> "$.id" 都能使用索引 idx_id

+

JSON 二进制格式

+

内部实现上,保存到数据库的 JSON 数据并非以 JSON 文本存储,而是二进制格式,具体可以参见,WL#8132: JSON datatype and binary storage format,当然也可以直接阅读源码 json_binary.h[34]、json_binary.cc[35]或 doxygen[36]

+

MySQL 的 JSON 二进制格式,其中有一点比较值得注意,WL#8132 提到:

+
+

The keys are sorted, so that lookup can use binary search to locate the key quickly.

+
+

就是,为了能利用二分搜索快速定位键,存入数据库的JSON 对象的键是被排序过的。来看下下面的 SQL:

+
1
2
3
4
5
6
7
8
9
10
11
mysql> truncate tbl;
mysql> insert into tbl values ('{"b": "c", "a": {"y": 1, "x": 2}}');
Query OK, 1 row affected (0.02 sec)

mysql> select * from tbl;
+-----------------------------------+
| data |
+-----------------------------------+
| {"a": {"x": 2, "y": 1}, "b": "c"} |
+-----------------------------------+
1 row in set (0.00 sec)
+

上面的 SQL 可以看到,insert 写入时键并没有按次序排列,而用 select 将 JSON 数据反序列化读出,发现实际保存的键是有序的。排序规则是,先按字符串长度排序,若长度相同按字母排序。同样的,键关联的值,按键排序后的次序排列。对键排序,显然只能针对 JSON 对象,若要存储 JSON 数组,值按索引位置排序。

+

MySQL 5.7.22 新增 json_storage_size() 函数,用于返回 json 文档二进制表示占用的存储空间。先来看下 SQL 示例:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
mysql> select json_storage_size('"abc"');
+----------------------------+
| json_storage_size('"abc"') |
+----------------------------+
| 5 |
+----------------------------+
1 row in set (0.00 sec)

mysql> select json_storage_size('[42, "xy", "abc"]');
+----------------------------------------+
| json_storage_size('[42, "xy", "abc"]') |
+----------------------------------------+
| 21 |
+----------------------------------------+
1 row in set (0.00 sec)

mysql> select json_storage_size('{"b": 42, "a": "xy"}');
+-------------------------------------------+
| json_storage_size('{"b": 42, "a": "xy"}') |
+-------------------------------------------+
| 24 |
+-------------------------------------------+
1 row in set (0.00 sec)
+

WL#8132 给出了 JSON 二进制格式的 BNF 语法描述。参考这个语法描述,可以推算出上文示例中的 "abc"[42, "xy", "abc"]{"b": 42, "a": "xy"} 对应的二进制表示。先来看下 "abc" 纯量,语法推导过程如下:

+
1
2
3
4
5
6
7
doc
=> type value // 使用产生式 doc ::= type value
=> 0x0c value // 使用产生式 type ::= 0x0c (utf8mb4 string 类型)
=> 0x0c string // 使用产生式 value ::= string
=> 0x0c data-length utf8mb4-data // 使用产生式 string ::= data-length utf8mb4-data
=> 0x0c 0x03 utf8mb4-data // 使用产生式 data-length ::= uint8*
=> 0x0c 0x03 0x61 0x62 0x63
+

对应的二进制值,共 5 个字节,依次为 0x0c 0x03 0x61 0x62 0x63,其中 0x61 0x62 0x63,就是 16 进制表示的字符串 abc。占用 5个字节,与 json_storage_size() 函数返回的结果一致。相应的语法树如下:

+

mysql-jsonb-syntax-tree-w350

+

从二进制的角度看,纯量 "abc" 的 JSON 二进制表示如下:

+

mysql-jsonb-scalar-w350

+

[42, "xy", "abc"] 的推导过程,如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
doc 
=> type value // 使用产生式 doc ::= type value
=> 0x02 array // 使用产生式 type ::= 0x02 (small JSON array 类型)
=> 0x02 element-count size value-entry* value* // 使用产生式 array ::= element-count size value-entry* value*
=> 0x02 0x03 0x00 size value-entry* value* // 使用产生式 element-count ::= uint16 (使用 little-endian)
=> 0x02 0x03 0x00 0x14 0x00 value-entry* value* // 使用产生式 size ::= uint16 (使用 little-endian)
=> 0x02 0x03 0x00 0x14 0x00 type offset-or-inlined-value value-entry* value* // 使用产生式 value-entry ::= type offset-or-inlined-value
=> 0x02 0x03 0x00 0x14 0x00 0x06 offset-or-inlined-value value-entry* value* // 使用产生式 type ::= 0x06 (uint16 类型)
=> 0x02 0x03 0x00 0x14 0x00 0x06 0x2a 0x00 value-entry* value* // 使用产生式 offset-or-inlined-value ::= uint16
... 省略
=> 0x02 0x03 0x00 0x14 0x00 0x06 0x2a 0x00 0x0c 0x0d 0x00 0x0c 0x10 0x00 value*
=> 0x02 0x03 0x00 0x14 0x00 0x06 0x2a 0x00 0x0c 0x0d 0x00 0x0c 0x10 0x00 string value // 使用产生式 value ::= string
=> 0x02 0x03 0x00 0x14 0x00 0x06 0x2a 0x00 0x0c 0x0d 0x00 0x0c 0x10 0x00 data-length utf8mb4-data value // 使用产生式 string ::= data-length utf8mb4-data
=> 0x02 0x03 0x00 0x14 0x00 0x06 0x2a 0x00 0x0c 0x0d 0x00 0x0c 0x10 0x00 0x02 utf8mb4-data value // 使用产生式 data-length ::= uint8*
=> 0x02 0x03 0x00 0x14 0x00 0x06 0x2a 0x00 0x0c 0x0d 0x00 0x0c 0x10 0x00 0x02 0x78 0x78 value
... 省略
=> 0x02 0x03 0x00 0x14 0x00 0x06 0x2a 0x00 0x0c 0x0d 0x00 0x0c 0x10 0x00 0x02 0x78 0x79 0x03 0x61 0x62 0x63
+

[42, "xy", "abc"] 对应的二进制表示,共 21 个字节,依次为 0x02 0x03 0x00 0x14 0x00 0x06 0x2a 0x00 0x0c 0x0d 0x00 0x0c 0x10 0x00 0x02 0x78 0x79 0x03 0x61 0x62 0x63。如下图:

+

mysql-jsonb-array

+

相对来说,产生式 array ::= element-count size value-entry* value*,是整个JSON 数组二进制表示语法的核心。element-count,表示元素个数。上图中,第 4、5 个字节是 size 字段,十进制值为 20(0x14),是完整二进制表示去掉开头 type 字段后的大小(文档没有明确这个字段的含义,不过通过源码推断出来)。另外,value-entrytypeoffset-or-inlined-value 字段组成。type 很好理解,不做解释。offset-or-inlined-value 字段,官方文档给出了含义,含义如下:

+
1
2
3
4
5
6
// This field holds either the offset to where the value is stored,
// or the value itself if it is small enough to be inlined (that is,
// if it is a JSON literal or a small enough [u]int).
offset-or-inlined-value ::=
uint16 | // if used in small JSON object/array
uint32 // if used in large JSON object/array
+

就是说,如果实际要保存的值足够小,将直接内联在这个字段中,否则将保存偏移量(offset),也就是指向实际值的指针。在示例中,保存 xy 对应的 offset 值为 13(0x0d),指向的相对地址是 14。因为这里的 offset 并不是以相对地址 0 为基准地址,是以相对地址 1 为基准地址(图中箭头 B 指向的位置),所以偏移量是 13 而不是 14(这个字段的明确含义也是从源码推断而来)。类似的,保存 abc 对应的 offset 值为 16(0x10),指向的相对地址是 17。

+

阅读文档容易发现,element-countsizeoffset 字段占用的字节大小是固定的,小 JSON(64KB 以内)是 2 字节,大 JSON 是 4 字节。所以,若要查找 JSON 数组的第 pos 个元素的 value-entry 的偏移量,可以使用下面的式子快速定位:

+
1
entry_offset = offset_size * 2 + (1 + offset_size) * pos
+

JSON 数组二进制表示的其他字段比较容易理解,文档都有解释,就不展开阐述了。

+

现在来看下,JSON 对象 {"b": 42, "a": "xy"} 的二进制表示,如下图:

+

mysql-jsonb-object

+

对于 JSON 对象二进制表示的语法,核心的产生式是 object ::= element-count size key-entry* value-entry* key* value*element-countsizevalue-entry 字段,在 JSON 数组中也有,不再赘述。而 key-entry 字段,类似于 value-entrykey-entry 中的 key-offset 保存的是偏移量,是指向键的指针。另外,正如上文提到的 MySQL 会对 JSON 键排序,所以上图示例的第 20 和 21 个字节值分别是 0x610x62,即 ab,而非 ba。同样的,键关联的值,按键排序后的次序排列,依次是 "xy"42

+

参考资料

+
+
+
    +
  1. MySQL 5.7 Reference Manual, What Is New in MySQL 5.7 https://dev.mysql.com/doc/refman/5.7/en/mysql-nutshell.html ↩︎

    +
  2. +
  3. MySQL 5.7 Reference Manual, 12 Data Types, 12.6 The JSON Data Type http://dev.mysql.com/doc/refman/5.7/en/json.html ↩︎ ↩︎

    +
  4. +
  5. 2012-09 PostgreSQL 9.2 released https://www.postgresql.org/about/news/postgresql-92-released-1415/ ↩︎

    +
  6. +
  7. JSON Support in Oracle Database 12c Release 1 (12.1.0.2) https://oracle-base.com/articles/12c/json-support-in-oracle-database-12cr1 ↩︎

    +
  8. +
  9. Oracle Database 12c Release 1 (12.1.0.2) New Features, 1.9 JSON Support https://docs.oracle.com/database/121/NEWFT/chapter12102.htm#NEWFT505 ↩︎

    +
  10. +
  11. Facebook DocStore: Document column type [Deprecated] https://github.com/facebook/mysql-5.6/wiki/Document-column-type-[Deprecated] ↩︎

    +
  12. +
  13. 2015-04 DocStore: Document Database for MySQL at Facebook (slides) https://web.archive.org/web/20161022061349/https://www.percona.com/live/mysql-conference-2015/sites/default/files/slides/Facebook DocStore Percona 2015.pdf ↩︎

    +
  14. +
  15. 2014-03 SQL/JSON Proposals, Part 1 https://www.wiscorp.com/pub/DM32.2-2014-00024R1_JSON-SQL-Proposal-1.pdf ↩︎

    +
  16. +
  17. 2014-03 SQL/JSON Proposals, Part 2 https://www.wiscorp.com/pub/DM32.2-2014-00025r1-sql-json-part-2.pdf ↩︎

    +
  18. +
  19. 2014-03 SQL Support for JSON (slides) https://web.archive.org/web/20150919002536/http://jtc1bigdatasg.nist.gov/_workshop/08_SQL_Support_for_JSON_abstract.pdf ↩︎

    +
  20. +
  21. 2017-06 What’s New in SQL:2016 https://modern-sql.com/blog/2017-06/whats-new-in-sql-2016 ↩︎

    +
  22. +
  23. WL#7909: Server side JSON functions https://dev.mysql.com/worklog/task/?id=7909 ↩︎

    +
  24. +
  25. WL#8132: JSON datatype and binary storage format https://dev.mysql.com/worklog/task/?id=8132 ↩︎

    +
  26. +
  27. WL#8249: JSON comparator https://dev.mysql.com/worklog/task/?id=8249 ↩︎

    +
  28. +
  29. WL#8607: Inline JSON path expressions in SQL https://dev.mysql.com/worklog/task/?id=8607 ↩︎

    +
  30. +
  31. MySQL 5.7 Reference Manual, 13 Functions and Operators, 13.16 JSON Functions https://dev.mysql.com/doc/refman/5.7/en/json-functions.html ↩︎

    +
  32. +
  33. 2015-04 JSON Labs Release: JSON Functions, Part 1 — Manipulation JSON Data http://mysqlserverteam.com/json-labs-release-json-functions-part-1-manipulation-json-data/ ↩︎

    +
  34. +
  35. 2015-04 JSON Labs Release: JSON Functions, Part 2 — Querying JSON Data http://mysqlserverteam.com/mysql-5-7-lab-release-json-functions-part-2-querying-json-data/ ↩︎

    +
  36. +
  37. JSONPath - XPath for JSON https://goessner.net/articles/JsonPath/ ↩︎

    +
  38. +
  39. 2015-10 Inline JSON Path Expressions in MySQL 5.7 http://mysqlserverteam.com/inline-json-path-expressions-in-mysql-5-7/ ↩︎

    +
  40. +
  41. PostgreSQL 11.10 Documentation, 9.15. JSON Functions and Operators https://www.postgresql.org/docs/11/functions-json.html ↩︎

    +
  42. +
  43. What is the difference between ->> and -> in Postgres SQL? https://stackoverflow.com/a/47270495 ↩︎

    +
  44. +
  45. 2015-10 SQLite Release 3.9.0 https://sqlite.org/releaselog/3_9_0.html ↩︎

    +
  46. +
  47. SQLite: The JSON1 Extension https://www.sqlite.org/json1.html ↩︎

    +
  48. +
  49. Bug #81364: Indexing JSON column should suggest generated columns https://bugs.mysql.com/bug.php?id=81364 ↩︎

    +
  50. +
  51. WL#411: Computed virtual columns as MS SQL server has https://web.archive.org/web/20080917094638/http://forge.mysql.com/worklog/task.php?id=411 ↩︎

    +
  52. +
  53. Bug #46491: Patch: Virtual columns (WL#411) https://bugs.mysql.com/bug.php?id=46491 ↩︎

    +
  54. +
  55. 2008-09 MySQL virtual columns https://datacharmer.blogspot.com/2008/09/mysql-virtual-columns.html ↩︎

    +
  56. +
  57. MySQL virtual columns preview https://web.archive.org/web/20120629093123/http://forge.mysql.com/wiki/MySQL_virtual_columns_preview ↩︎

    +
  58. +
  59. WL#411: Generated columns https://dev.mysql.com/worklog/task/?id=411 ↩︎ ↩︎

    +
  60. +
  61. MariaDB: Generated (Virtual and Persistent/Stored) Columns https://mariadb.com/kb/en/generated-columns/ ↩︎

    +
  62. +
  63. Virtual column https://en.wikipedia.org/wiki/Virtual_column ↩︎

    +
  64. +
  65. 2016-02 Generated columns in MariaDB and MySQL https://planet.mysql.com/entry/?id=5994068 ↩︎

    +
  66. +
  67. MySQL 5.7 Source Code: sql/json_binary.h https://github.com/mysql/mysql-server/blob/5.7/sql/json_binary.h ↩︎

    +
  68. +
  69. MySQL 5.7 Source Code: sql/json_binary.cc https://github.com/mysql/mysql-server/blob/5.7/sql/json_binary.cc ↩︎

    +
  70. +
  71. MySQL 8.0 Source Code Documentation: json_binary.h File Reference (doxygen) https://dev.mysql.com/doc/dev/mysql-server/8.0.16/json__binary_8h.html#details ↩︎

    +
  72. +
+
+ +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2020/05/kong-gateway/index.html b/2020/05/kong-gateway/index.html new file mode 100644 index 00000000..4ff4d235 --- /dev/null +++ b/2020/05/kong-gateway/index.html @@ -0,0 +1,759 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 微服务 API 网关 Kong 实践 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ 微服务 API 网关 Kong 实践 +

+ + +
+ + + + +
+ + +

Kong 简介

+

Kong 是云原生、高效、可扩展、分布式的微服务抽象层,被称为 API 网关,或者 API 中间件。Kong 在 2015 年 4 月由 Mashape 公司开源,基于 OpenResty 和 Apache Cassandra/PostgreSQL 构建,提供易于使用的 RESTful API 来操作和配置 API 系统[1][2]

+ +

Mashape 是 API 集市,是为应用开发者与 API 提供者服务的 API 交易市场,Mashape 让发者能够方便地查找与购买 API,而 API 提供商则能轻松地销售与管理 API[3]。随着 Mashape 市场上的 API 越来越多,原先基于 Node.js 实现的 API 代理不再适用,不能处理大流量尖峰,无法快速扩容。于是,寻找处理大流量的方案,同时需要保证可靠性和安全性,成为 Mashape 亟待解决的问题。2013 年,在 CloudFlare(当时 OpenResty 背后的公司)的工程师的建议下,Mashape 开始在 OpenResty 基础上开发 Kong 项目[4]。Mashape 公司的名字,MashAPE,有人猿猩猩的含义,公司 logo 也是相应动物。类似的,Kong,对应的是,King Kong,就是电影里的金刚[4:1]。在 Mashape 开启 Kong 项目两年后,2015 年 4 月,Mashape 公司开源了 Kong[2:1]

+

2017 年 5月,Mashape 和 RapidAPI 合并,组成全球最大的 API 集市[5][6]。5 个月后,Mashape, Inc. 改名为 Kong Inc.,新的公司以 Kong 项目为聚焦,把全部工程师投入到 Kong 开发中,并且于此同时他们发布了 Kong 企业版[7]

+

Kong,作为微服务的请求的网关,能通过插件提供负载均衡、日志记录、鉴权、限流、转换以及其他等功能。相对与旧的、没有使用网关的方式,Kong 把这些通用功能中心化,让微服务更加专注于业务本身。

+The Old way vs. The Kong Way +

Kong 的整体架构,如下图所示[1:1]

+
    +
  • 管理 API:通过 RESTful API 管理 Kong;能自动化集成;管理 API 能通过插件扩展
  • +
  • 插件:使用 Lua 脚本创建 Plugins;实现强力的定制化;与第三方服务集成
  • +
  • 集群和数据存储:数据存储可选择 PostgreSQL 或 Cassandra;能从单节点扩展为集群;使用内存缓存提高性能
  • +
  • OpenResty:拦截请求/响应生命周期;基于 NGINX 扩展;Lua 脚本化
  • +
  • NGINX:验证过的高性能基础组件;HTTP 和反向代理服务器;处理底层操作
  • +
+Kong Architecture +

Kong 安装

+

目前最新的 Kong 版本是 2.0.x,2.0 发布时间是 2020 年 1 月,而 1.0 发布时间是 2018 年 12 月[8][9]。笔者公司使用的 Kong 版本是 0.14.1,暂时未升级自最新版,所以下文阐述的 Kong 版本主要以 0.14.1 为准,并同时会提及其他版本的特性。

+

安装 Kong 很简单,参见官方文档即可。在 Ubuntu 18.04 下安装 Kong 0.14.1,可以执行下面的命令:

+
1
2
3
4
5
6
7
# kong 安装
$ sudo apt update
$ sudo apt install openssl libpcre3 procps perl
$ wget -O kong-community-edition-0.14.1.trusty.all.deb https://bintray.com/kong/kong-community-edition-deb/download_file?file_path=dists/kong-community-edition-0.14.1.trusty.all.deb
$ sudo dpkg -i kong-community-edition-0.14.1.trusty.all.deb
$ kong version
0.14.1
+

Kong 依赖数据库,Postgres 或者 Cassandra,默认依赖 Postgres(kong 1.1 开始支持无数据库声明式配置[10])。我们预先安装 Postgres:

+
1
2
3
4
5
# 安装 postgresql
$ sudo apt install postgresql
$ sudo service postgresql start
$ psql --version
psql (PostgreSQL) 10.12 (Ubuntu 10.12-0ubuntu0.18.04.1)
+

在 Postgres 下添加 Kong 需要的的数据库实例和用户。下面的示例,创建数据库 kong,用户名 kong,密码为 kong

+
1
2
3
4
$ sudo -u postgres psql
postgres=# CREATE USER kong; CREATE DATABASE kong OWNER kong;
postgres=# ALTER USER kong WITH PASSWORD 'kong';
postgres=# \q
+

执行完成后,即可使用用户名为 kong 的用户连接 Postgres,psql -h localhost -U kong -d kong

+

Kong 安装完成后,默认会创建配置文件 /etc/kong/kong.conf.default,这份配置文件在 GitHub 上也能找到,被注释掉的配置项,就是默认设置。

+

在启动 Kong 网关服务器前,我们参考 kong.conf.default,创建自己的 kong.conf 配置文件。我们把配置文件放在 /home/yulewei/kong 目录下,同时也把这目录当作为 Kong 的 prefix 目录。修改这配置 kong.conf,文件末尾添加:

+
1
2
3
4
prefix = /home/yulewei/kong/
pg_user=kong
pg_password=kong
pg_database = kong
+

使用 kong 命令,启动 Kong 网关服务器:

+
1
2
3
4
# 初始化或迁移数据库数据
$ kong migrations up -c /home/yulewei/kong/kong.conf
# 启动 kong
$ kong start -c /home/yulewei/kong/kong.conf
+

Kong 默认绑定 4 个端口:

+
    +
  • :8000 用来接收来自客户端的 HTTP 流量的请求,并转发到上游服务
  • +
  • :8443 用来接收来自客户端的 HTTPS 流量的请求,并转发到上游服务
  • +
  • :8001 用来接收访问 Admin API 的 HTTP 流量的请求
  • +
  • :8444 用来接收访问 Admin API 的 HTTPS 流量的请求
  • +
+

所以,可以执行下面的命令,来确认 Kong 是否正常运行:

+
1
2
3
# 确认 Kong 是否正常运行
$ curl -i http://localhost:8000/
$ curl -i http://localhost:8001/
+

Kong 底层依赖 OpenResty,启动 Kong 后,可以看到 nginx 进程:

+
1
2
3
4
5
# 查看 nginx 进程
$ ps -ef | grep nginx
yulewei 19090 1 0 16:05 ? 00:00:00 nginx: master process /usr/local/openresty/nginx/sbin/nginx -p /home/yulewei/kong -c nginx.conf
yulewei 19091 19090 0 16:05 ? 00:00:00 nginx: worker process
yulewei 19092 19090 0 16:05 ? 00:00:00 nginx: worker process
+

安装 Kong 0.14.1,自动安装的 OpenResty 版本是 1.13.6.2,OpenResty 捆绑的安装了 LuaJIT。

+
1
2
3
4
5
6
7
8
9
10
11
12
13
$ /usr/local/openresty/nginx/sbin/nginx -v
nginx version: openresty/1.13.6.2

$ /usr/local/openresty/bin/resty -V
resty 0.21
nginx version: openresty/1.13.6.2
built by gcc 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.4)
built with OpenSSL 1.0.2n 7 Dec 2017
TLS SNI support enabled
configure arguments: ... 省略 ...

$ /usr/local/openresty/luajit/bin/luajit -v
LuaJIT 2.1.0-beta3 -- Copyright (C) 2005-2017 Mike Pall. http://luajit.org/
+

另外,同时也安装了 LuaRocks,LuaRocks 关联的是 OpenResty 捆绑的 LuaJIT。事实上,Kong 就是一个 LuaRocks 的 rock 包,在Kong 项目的 GitHub 上可以看到 rockspec 文件。Kong 的安装,底层实现上,是通过 luarocks 命令完成的,类似这样的命令,luarocks install kong 0.14.1-0[11][12]。可以使用 luarocks show 命令查看这个 Kong 的 rcok 包:

+
1
2
3
4
5
6
7
8
9
10
11
$ luarocks show kong
kong 0.14.1-0 - Kong is a scalable and customizable API Management Layer built on top of Nginx.

License: MIT
Homepage: http://getkong.org
Installed in: /usr/local

Modules:
kong (/usr/local/share/lua/5.1/kong/init.lua)
kong.api (/usr/local/share/lua/5.1/kong/api/init.lua)
... 省略 ...
+

有个小细节值得注意,通过 luarocks 看到,Kong 采用的协议是 MIT。但事实上,Kong 0.5.0 开始协议从 MIT 改成了 Apache 2.0。此处是一个小 bug,Kong 的 rockspec 文件没有及时更新,这个问题后来修复了,参见 #4125

+

GUI 管理工具

+

管理 Kong 可以直接使用 Admin API,当然也有基于 Admin API 实现 GUI 管理工具。

+

Kong 官方的企业版提供了 GUI 管理工具,Kong Manager(Kong EE 0.34 之前称为 Admin GUI),Kong 社区版没有提供 GUI 管理工具。

+

第三方的开源 GUI 工具,比较活跃的就是 Konga,值得推荐,如下图。

+konga +

另外,还有其他的 GUI 工具,比如 Kong Dashboard,也可以了解下。

+

Kong 使用

+

Kong 核心概念:

+
    +
  • Service:对应位于 Kong 后方的自身的 Upstream API 或微服务。
  • +
  • Route:Kong 的入口点,定义了如何把请求发送到特定 Service 的规则。一个 Service 可以有多个Route
  • +
  • Plugin:插件提供了模块化系统,用来修改或控制 Kong。插件提供了大量功能,比如访问控制、缓存、限流、日志记录等。
  • +
  • Consumer:消费者,表示使用 API 的用户,能用来对用户进行访问控制、跟踪等。
  • +
+

Kong 网关的请求响应工作流,如下图所示:

+Kong Overview +

反向代理

+

Kong 的核心功能就是对现有的上游服务的 API 作反向代理。反向代理,官方的完整的文档参见[13]。现在我们来试验下 Kong 的反向代理功能,执行下面的命令:

+
1
2
3
4
5
6
7
8
9
# 添加 service
$ curl -XPOST -H 'Content-Type: application/json' \
-d '{"name":"example.service","url":"http://httpbin.org"}' \
http://localhost:8001/services/

# 在 service 上添加 route
$ curl -XPOST -H 'Content-Type: application/json' \
-d '{"paths":["/base64"],"strip_path":false}' \
http://localhost:8001/services/example.service/routes
+

上面的第一条命令,通过调用 Kong 提供的 Admin API,让 Kong 创建了名为 example.serviceserviceservice 指向的上游服务是 http://httpbin.org。第二条命令,在 example.service 上添加 route 规则,规则是让请求路径前缀为 /base64 的请求转发到这个 service。来验证下,刚刚的 Kong 的配置:

+
1
2
3
4
5
# 验证 Kong 配置结果
$ curl http://httpbin.org/base64/aGVsbG8ga29uZw==
hello kong
$ curl http://localhost:8000/base64/aGVsbG8ga29uZw==
hello kong
+

上文的 Kong 配置,等价的 nginx.conf 配置文件的写法是:

+
1
2
3
4
5
6
server {
listen 8000;
location /base64 {
proxy_pass http://httpbin.org/base64;
}
}
+

除了前缀外,route 规则的 paths 字段也支持 PCRE 正则表达式,来看下示例:

+
1
2
3
curl -XPOST -H 'Content-Type: application/json' \
-d '{"paths":["/status/\\d+"],"strip_path":false}' \
http://localhost:8001/services/example.service/routes
+

上面的命令,添加 route 规则,设置的 paths 字段值为 /status/\d+,让只有请求路径的中包含数字才能匹配。

+
1
2
3
4
5
6
7
8
9
# 验证 Kong 配置结果
$ curl -sI http://httpbin.org/status/418 | head -n1
HTTP/1.1 418 I'M A TEAPOT
$ curl -sI http://localhost:8000/status/418 | head -n1
HTTP/1.1 418 I'M A TEAPOT
$ curl -sI http://localhost:8000/status/200 | head -n1
HTTP/1.1 200 OK
$ curl http://localhost:8000/status/abc
{"message":"no route and no API found with those values"}
+

负载均衡

+

上文的反向代理指向的是单台的上游服务器,如果要指向多台上游服务器,实现负载均衡,要如何配置呢?负载均衡,Nginx 可以通过 upstream 指令实现,而类似的,Kong 通过创建 upstream 对象实现。

+

假设在服务器 192.168.2.100:80192.168.2.101:80 上运行着本地版的 httpbin.org 的 REST API 服务(通过 docker run -p 80:80 kennethreitz/httpbin)。执行下面的命令:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 添加 upstream
curl -XPOST -H 'Content-Type: application/json' \
-d '{"name":"example.upstream"}' \
http://localhost:8001/upstreams/

# 在 upstream 上添加 target
curl -XPOST -H 'Content-Type: application/json' \
-d '{"target":"192.168.2.100:80"}' \
http://localhost:8001/upstreams/example.upstream/targets

# 在 upstream 上添加 target
curl -XPOST -H 'Content-Type: application/json' \
-d '{"target":"192.168.2.101:80"}' \
http://localhost:8001/upstreams/example.upstream/targets

# 添加 service
curl -XPOST -H 'Content-Type: application/json' \
-d '{"name":"example.service","host":"example.upstream"}' \
http://localhost:8001/services/

# 在 service 上添加 route
curl -XPOST -H 'Content-Type: application/json' \
-d '{"paths":["/base64"],"strip_path":false}' \
http://localhost:8001/services/example.service/routes
+

上面的命令,先创建了 upstream 对象,虚拟主机名(virtual hostname)为 example.upstream 。然后在这个 upstream 上添加 target192.168.2.100:80192.168.2.101:80。再然后把 service 对象的 host 字段值设置为 example.upstream。这样全部发送到这个 service 的请求都会被转发到 example.upstream 这个 upstreamupstream 再执行负载均衡算法,把请求转发到最终的上游服务器。和 Nginx 一样,默认的负载均衡算法为加权轮询算法(weighted-round-robin)。

+
1
2
3
# 验证 Kong 配置结果
$ curl http://localhost:8000/base64/aGVsbG8ga29uZw==
hello kong
+

上文的 Kong 配置,等价的 nginx.conf 配置文件的写法是:

+
1
2
3
4
5
6
7
8
9
10
upstream example.upstream {
server 192.168.2.100:80;
server 192.168.2.101:80;
}
server {
listen 8000;
location /base64 {
proxy_pass http://example.upstream/base64;
}
}
+

关于 Kong 负载均衡的更多介绍,可以阅读官方文档[14],本文不再展开。

+

开启插件

+

Kong 提供了很多插件,官方整理维护的全部插件列表,可以在官网上看到。全部插件分 8 大类:身份认证类插件(Authentication)、安全控制类插件(Security)、流量控制类插件(Traffic Control)、无服务器计算类插件(Serverless)、分析与监控类插件(Analytics & Monitoring)、协议转换类插件(Transformations)、日志记录类插件(Logging)、部署类插件(Deployment)。Kong 0.14.1 社区版默认绑定的预定义插件,全部 31 个,调用下面的 Admin API 可以查看:

+
1
2
3
# Kong 社区版全部默认绑定的插件,共 31 个
$ curl http://localhost:8001/plugins/enabled
{"enabled_plugins":["response-transformer","oauth2","acl","correlation-id","pre-function","jwt","cors","ip-restriction","basic-auth","key-auth","rate-limiting","request-transformer","http-log","file-log","hmac-auth","ldap-auth","datadog","tcp-log","zipkin","post-function","request-size-limiting","bot-detection","syslog","loggly","azure-functions","udp-log","response-ratelimiting","aws-lambda","statsd","prometheus","request-termination"]}
+

现在我们来试下 Kong 的 basic-auth 插件,用来实现 HTTP Basic 认证(RFC 7617)。执行下面的命令,在上文的 example.serviceservice 上开启 basic-auth 插件:

+
1
2
3
# 在 service 上开启 basic-auth 插件
$ curl -XPOST --data "name=basic-auth" \
http://localhost:8001/services/example.service/plugins
+

这样全部到 example.service 的请求都需要进行 Basic 认证。再次请求之前的 /base64 接口,返回状态码 401 Unauthorized

+
1
2
3
4
5
6
# 接口 HTTP 状态码返回 401
$ curl -i http://localhost:8000/base64/aGVsbG8ga29uZw==
HTTP/1.1 401 Unauthorized
... 省略 ...

{"message":"Unauthorized"}
+

添加身份认证的凭证,添加 username/password:

+
1
2
3
4
5
6
# 添加 consumer
$ curl -XPOST --data "username=Jason" \
http://localhost:8001/consumers/
# 在 consumer 上添加 basic-auth 插件的凭证 username/password
$ curl -XPOST --data "username=test&password=123456" \
http://localhost:8001/consumers/Jason/basic-auth
+

现在请求头上带上凭证,重新请求 /base64 接口,响应正常:

+
1
2
$ curl -u 'test:123456' http://localhost:8000/base64/aGVsbG8ga29uZw==
hello kong
+

Kong 插件,除了绑定到 service 上外,也可以绑定在 routeconsumer 上。如果开启插件时,servicerouteconsumer 全部都不关联,就是全局范围开启插件,插件会在全部请求上运行。全局范围上开启 basic-auth 插件,命令如下:

+
1
2
3
# 全局范围上开启 basic-auth 插件
$ curl -XPOST --data "name=basic-auth" \
http://localhost:8001/plugins
+

关于 Kong 插件的更多介绍,可以阅读官方文档,本文不再展开。

+

Kong 插件开发

+

Kong 基于 OpenResty,OpenResty 通过 ngx_http_lua_module 模块实现了在 Nginx 中内嵌 Lua 脚本的能力。Kong 插件,使用 Lua 脚本实现,全部默认加载的预定义插件对应的 Lua 源码(包括上文提到的 basic-auth 插件),可以在 Kong 项目仓库的 kong/plugins 目录下看到。

+

除了能使用 Kong 预定义插件,我们可以根据 Kong 插件开发文档[15],开发自定义插件。

+

如何开发插件,文本不展开。Kong 官方提供了自定义插件的模板代码,源码参见项目 kong-plugin[16]。另外,有兴趣也可以参考笔者提供的 Kong 自定义插件示例,源码参见 kong-plugin-demo[17]

+

值得注意的是,Kong 使用 Lua 的 rxi/classic 模块来模拟 Lua 中的类,自定义 Kong 的插件时,实现 handler 需要继承 BasePlugin class,目前最新的文档还是采用这种写法。不过,Kong 1.2 开始,Kong 内部的预定义实现的插件,废弃了继承 BasePlugin class 的写法,参见 Pull Request #4590,“plugins handlers do not have to inherit from BasePlugin anymore #4590”。去掉对 BasePlugin class 的继承后,在开启单个插件(key-auth)的场景下,压测 Kong 性能提升 6%,开启多个插件的场景,性能提升更高。

+

参考资料

+
+
+
    +
  1. What is Kong? https://konghq.com/about-kong/ ↩︎ ↩︎

    +
  2. +
  3. 2015-04 Mashape 开源 API 网关——Kong https://www.infoq.cn/article/2015/04/kong/ ↩︎ ↩︎

    +
  4. +
  5. 2012-07 打造大集市:API交易网站Mashape正式推出 https://www.csdn.net/article/2012-07-31/2807936 ↩︎

    +
  6. +
  7. 2015-10 How Mashape Manages Over 15,000 APIs & Microservices https://stackshare.io/kong/how-mashape-manages-over-15000-apis-and-microservices ↩︎ ↩︎

    +
  8. +
  9. 2017-05 Mashape 和 RapidAPI 合并,组成全球最大的应用编程接口(API)集市! https://www.sohu.com/a/144114294_465914 ↩︎

    +
  10. +
  11. 2017-05 The API Marketplace Joins RapidAPI https://konghq.com/blog/the-api-marketplace-joins-rapidapi/ ↩︎

    +
  12. +
  13. 2017-10 Welcome Kong Inc. A New Name, a New Product, a New Era. https://konghq.com/blog/introducing-kong-inc/ ↩︎

    +
  14. +
  15. 2018-12 Kong 1.0 GA https://konghq.com/blog/kong-1-0-ga/ ↩︎

    +
  16. +
  17. 2020-01 Kong Gateway 2.0 GA https://konghq.com/blog/kong-gateway-2-0-0-released/ ↩︎

    +
  18. +
  19. Documentation for Kong: DB-less and Declarative Configuration https://docs.konghq.com/1.1.x/db-less-and-declarative-config/ ↩︎

    +
  20. +
  21. Kong Installation: Compile Source https://docs.konghq.com/install/source/ ↩︎

    +
  22. +
  23. Build tools to package and release Kong https://github.com/Kong/kong-build-tools ↩︎

    +
  24. +
  25. Documentation for Kong: Proxy Reference https://docs.konghq.com/0.14.x/proxy/ ↩︎

    +
  26. +
  27. Documentation for Kong: Load Balancing Reference https://docs.konghq.com/0.14.x/loadbalancing/ ↩︎

    +
  28. +
  29. Documentation for Kong: Plugin Development https://docs.konghq.com/0.14.x/plugin-development/ ↩︎

    +
  30. +
  31. Kong 官方自定义插件的模板代码 https://github.com/Kong/kong-plugin ↩︎

    +
  32. +
  33. Kong 自定义插件示例 https://github.com/yulewei/kong-plugin-demo ↩︎

    +
  34. +
+
+ +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2023/07/innodb-locking/index.html b/2023/07/innodb-locking/index.html new file mode 100644 index 00000000..461876ee --- /dev/null +++ b/2023/07/innodb-locking/index.html @@ -0,0 +1,1303 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + InnoDB 的并发控制:锁与 MVCC | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ InnoDB 的并发控制:锁与 MVCC +

+ + +
+ + + + +
+ + +

目前主流数据库事务的并发控制实现,如 MySQL InnoDB、PostgreSQL、Oracle,都使用两阶段封锁 2PLMVCC 技术,但具体实现细节上存在差异。InnoDB 是在以封锁技术为主体的情况下,用 MVCC 技术辅助实现读-写、写-读操作的并发。PostgreSQL 的并发控制技术是以 MVCC 技术为主,封锁技术为辅。本文主要关注 InnoDB 事务的并发控制实现。

+ + +

背景知识

+

并发控制,是数据库系统的 ACID 特性中的隔离性(Isolation)的保障。所谓隔离性,就是事务的执行不应受到其他并发执行事务的干扰,事务的执行看上去应与其他事务是隔离的。被隔离的执行,等价于事务的某种串行执行,或者说,它等价于一个没有并发的执行。保证串行性可能只允许极小的并发度,采用较弱隔离性,能带来更高的并发度,是并发事务的正确性和性能之间的妥协。

+

早期各大数据库厂商实现并发控制时多采用基于封锁的并发控制技术,所以在基于封锁的技术背景下,才在 ANSI SQL-92 标准中提出了四种隔离级别:未提交读(Read Uncommitted)、己提交读(Read Committed)、可重复读(Repeatable Read)、可串行化(Serializable)(附注:为了书写简便本文将各个隔离级别依次缩写为 RU、RC、RR、SER)。ANSI SQL-92 标准的四种隔离级别,是根据三种读异常现象(phenomena)定义的,隔离级别和异常现象的关系如下:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
隔离级别P1 脏读P2 不可重复读P4 幻读
Read Uncommitted可能可能可能
Read Committed避免可能可能
Repeatable Read避免避免可能
Serializable避免避免避免
+

ANSI SQL-92 标准文档对三种读异常现象的定义原文如下 [ref]:

+
+

The isolation level specifies the kind of phenomena that can occur during the execution of concurrent SQL-transactions. The following phenomena are possible:
+1) P1 ("Dirty read"): SQL-transaction T1 modifies a row. SQL-transaction T2 then reads that row before T1 performs a COMMIT. If T1 then performs a ROLLBACK, T2 will have read a row that was never committed and that may thus be considered to have never existed.
+2) P2 ("Non-repeatable read"): SQL-transaction T1 reads a row. SQL-transaction T2 then modifies or deletes that row and performs a COMMIT. If T1 then attempts to reread the row, it may receive the modified value or discover that the row has been deleted.
+3) P3 ("Phantom"): SQL-transaction T1 reads the set of rows N that satisfy some . SQL-transaction T2 then executes SQL-statements that generate one or more rows that satisfy the used by SQL-transaction T1. If SQL-transaction T1 then repeats the initial read with the same , it obtains a different collection of rows.

+
+

除了脏读、不可重复读和幻读这 3 种读数据异常外,还有写数据异常,即脏写和丢失更新。各个异常的含义如下:

+
    +
  • P0 脏写(Dirty Write):事务 T1 写某数据项,并且未提交或回滚,事务 T2 也写该数据项,然后事务 T1 或事务 T2 回滚,回滚导致另外一个事务的修改被连带回滚。脏写异常会导致事务无法回滚,原子性无法得到保障,所以全部隔离级别下都应该避免。脏写也可以叫回滚丢失。
  • +
  • P1 脏读(Dirty Read):读到了其他事务还未提交的数据。
  • +
  • P2 不可重复读(Non-Repeatable):事务 T1 读取某数据项,事务 T2 修改 update 或删除 delete 该数据项,事务 T1 再次读取该数据项,结果不同。
  • +
  • P3 幻读(Phantom):事务 T1 读取满足某条件的数据项集合,事务 T2 生成新的满足该条件的数据项,事务 T2 再次读取满足该条件的数据项集合,结果不同。
  • +
  • P4 丢失更新(Lost Update):事务 T1 读取某数据项,事务 T2 更新该数据项并提交,事务 T1 忽略事务 T2 的更新,直接基于最初的读取数据项做更新并提交,导致事务 T2 的更新丢失。丢失更新也可以叫覆盖丢失。
  • +
+

各个异常的读写操作序列的简化符号表示如下 [Berenson 1995]:

+
1
2
3
4
5
P0: w1[x]...w2[x]...(c1 or a1)                 事务 T2 脏写
A1: w1[x]...r2[x]...(a1 and c2 in any order) 事务 T2 脏读,r2[x] 为脏读
A2: r1[x]...w2[x]...c2...r1[x]...c1 事务 T1 不可重复读,两次 r1[x] 结果不同
A3: r1[P]...w2[y in P]...c2...r1[P]...c1 事务 T1 幻读,两次 r1[P] 结果不同
P4: r1[x]...w2[x]...w1[x]...c1 事务 T2 更新丢失,c1 导致 w2[x] 丢失
+

其中 w1[x] 表示事务 T1 写入记录 x,r1[x] 表示事务 T1 读取记录 x,c1 表示事务 T1 提交,a1 表示事务 T1 回滚,r1[P] 表示事务 T1 按照谓词 P 的条件读取若干条记录,w1[y in P] 表示事务 T1 写入记录 y 满足谓词 P 的条件。

+

Berenson 的论文评判了 ANSI SQL-92 标准的异常定义。ANSI SQL-92 标准的异常的定义存在歧义,可以严格解释,也可以宽松解释,A1、A2 和 A3 的符号表示为严格解释,按严格解释,某些特殊的异常无法囊括,所以推荐宽松解释。按照标准的定义,容易引起误解的是,在排除 P1 脏读、P2 不可重复、P3 幻读这三种读异常后就会得到可串行化隔离级别,但是事实并非如此。标准没有定义 P0 脏写和 P4 更新丢失异常。另外,基于 MVCC 技术实现的快照隔离(Snapshot Isolation),能避免标准定义的 P1 脏读、P2 不可重复、P3 幻读,并且避免 P0 脏写和 P4 更新丢失,但还存在写偏序(Write Skew)异常。

+

不可重复读和幻读的区别:

+
    +
  • 不可重复读对于事务 T2 的写操作是更新或删除操作,而幻读对于事务 T2 的写操作是插入(插入的新数据满足条件)或更新(使不满足条件的数据在更新后满足条件)操作。
  • +
  • 对于幻读现象中事务 T2 的操作,如果操作是对现有数据的更新或删除操作,则表明这样的操作等同于不可重复读,即是在多个行数据上进行更新或删除,即在多个行数据上批量化重演了不可重复读现象
  • +
  • 不可重复读和幻象最大的区别就是前者只需要“锁住”(考虑)已经读过的数据,而幻读需要对“还不存在的数据“做出预防。不可重复读现象中事务 T2 着眼于对现有数据进行操作;而幻读现象中事务 T2 着眼于对新增(或不在锁定范围内已经存在的数据上做更新后而得的数据满足了谓词条件)数据
  • +
+

异常由并发冲突引起,对应关系如下:

+
    +
  • 写写冲突:P0 脏写、P4 丢失更新
  • +
  • 写读冲突:P1 脏读
  • +
  • 读写冲突:P2 不可重复读、P3 幻读
  • +
+

早期各大数据库厂商实现并发控制时多采用基于封锁的并发控制技术,所以在基于封锁的技术背景下,才在ANSI SQL 标准中提出了四种隔离级别。基于锁的并发控制技术的加锁方式与隔离级别的关系表 [Berenson 1995]:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
隔离级别写锁数据项的读锁谓词的读锁
Read Uncommitted长写锁无锁要求无锁要求
Read Commited长写锁短读锁短谓词锁
Repeatable Read长写锁长读锁短谓词锁
Serializable长写锁长读锁长谓词锁
+

说明:

+
    +
  • 短锁(short duration lock),当前正在执行的语句持有锁,语句执行完毕锁被释放。长锁(long duration lock),当锁被持有后,直到事务提交之后才被释放。
  • +
  • RU 隔离级别,阻止 P0,长写锁
  • +
  • RC 隔离级别,阻止 P0、P1,长写锁 + 短读锁 + 短谓词锁
  • +
  • RR 隔离级别,阻止 P0、P1、P4、P2,长写锁 + 长写锁 + 短谓词锁
  • +
  • SER 隔离级别,阻止 P0、P1、P4、P2、P3,长写锁 + 长写锁 + 长谓词锁
  • +
+

基于锁的并发控制下,隔离级别和异常现象的关系:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
隔离级别P0 脏写P1 脏读P4 丢失更新P2 不可重复读P4 幻读
Read Uncommitted避免可能可能可能可能
Read Committed避免避免可能可能可能
Repeatable Read避免避免避免避免可能
Serializable避免避免避免避免避免
+

各个隔离级别在基于锁的并发控制技术下的具体的实现说明(参考自腾讯李海翔的《数据库事务处理的艺术》第 2 章):

+基于锁的并发控制 +

基于锁的并发控制,读-读操作可以并发执行,但读-写、写-读、写-写操作无法并发执行,阻塞等待。MVCC 结合封锁技术,使得读-写、写-读操作互不阻塞,即只有写-写操作不能并发,并发度被提高到 75%,这就是 MVCC 被广为使用的原因。

+

InnoDB 的并发控制以封锁技术为主,MVCC 技术为辅助。让我们先看下 InnoDB 的封锁技术。

+

共享锁与排他锁

+

InnoDB 存储引擎实现两种标准的行级锁模式,共享锁(读锁)和排他锁(写锁)[doc]:

+
    +
  • 共享锁(shared lock,S):允许事务读一行数据。
  • +
  • 排他锁(exclusive Lock,X):允许事务删除或更新一行数据。
  • +
+

如果事务 T1 持有行 r 上的共享锁(S),则来自某个不同事务 T2 的对行 r 上的锁的请求将按如下方式处理:

+
    +
  • T2 对 S 锁的请求可以立即被授予。因此,T1 和 T2 持有 r 上的锁。
  • +
  • T2 对 X 锁的请求不能立即被授予。
  • +
+

如果事务 T1 持有行 r 上的排他锁(X),则某个不同事务 T2 对 r 上任一类型的锁的请求无法立即被授予。相反,事务 T2 必须等待事务 T1 释放其对行 r 的锁定。

+

共享锁和排他锁的兼容性:

+ + + + + + + + + + + + + + + + + + + + +
待申请 \ 已持有共享锁 S排他锁 X
共享锁 S兼容冲突
排他锁 X冲突冲突
+

区分共享锁(读锁)和排它锁(写锁)后,读锁与读锁的并发可被允许进行,并发能力得以提高。

+

对于 updatedeleteinsert 语句,InnoDB 会自动给涉及数据集加排他锁(X);对于普通 select 语句,InnoDB 不会加任何锁(SERIALIZABLE隔离级别下除外);事务可以通过以下语句显式给查询 select 显式加共享锁或排他锁:

+
    +
  • 共享锁(S):select ... for share
  • +
  • 排他锁(X):select ... for update
  • +
+

现在让我们来试验下共享锁和排他锁。创建 tbl 表,并添加表数据:

+
1
2
3
4
5
6
7
create table tbl 
(a int, b int, c int, d int, primary key(a), unique key(b), key(c));
insert into tbl values
(10, 10, 10, 10), (20, 20, 20, 20), (30, 30, 30, 30),
(40, 40, 40, 40), (50, 50, 50, 50), (60, 60, 60, 60),
(70, 70, 70, 70), (80, 80, 80, 80), (90, 90, 90, 90),
(100, 100, 100, 100);
+

InnoDB 的排它锁示例,如下:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
事务1事务2
mysql> begin;mysql> begin;
-- 在 a = 10 的索引记录上添加排他锁
mysql> select * from tbl where a = 10 for update;
-- 阻塞,获取 a = 10 的排他锁超时
mysql> update tbl set b = 42 where a = 10;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
-- 阻塞,获取 a = 10 的排他锁超时
mysql> update tbl set b = 42 where a >= 10;
-- 阻塞,获取 a = 10 的排他锁超时
mysql> delete from tbl where a = 10;
-- 阻塞,获取 a = 10 的排他锁超时
mysql> select * from tbl where a = 10 for update;
-- 更新成功,可以获得其他记录的排他锁
mysql> update tbl set b = 42 where a = 20;
mysql> commit;
-- 更新成功,在事务 1 释放锁后,其他事务可以获取排他锁
mysql> update tbl set b = 42 where a = 10;
+

InnoDB的共享锁示例,如下:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
事务1事务2
mysql> begin;mysql> begin;
-- 在 a = 10 的索引记录上添加共享锁
mysql> select * from tbl where a = 10 for share;
-- 获取 a = 10 的共享锁成功
mysql> select * from tbl where a = 10 for share;
-- 阻塞,获取 a = 10 的排他锁超时
mysql> update tbl set b = 42 where a = 10;
mysql> commit;
-- 更新成功,在事务 1 释放锁后,其他事务可以获取排他锁
mysql> update tbl set b = 42 where a = 10;
+

多粒度与意向锁

+

InnoDB 存储引擎支持多粒度锁定(multiple granularity locking),这种锁定允许事务在行级上的锁和表级上的锁同时存在。为了支持在不同粒度上进行加锁操作,InnoDB 存储引擎支持一种额外的锁方式,称之为意向锁(Intention Lock)。意向锁是将锁定的对象分为多个层次,意向锁意味着事务希望在更细粒度上进行加锁。

+

若将上锁的对象看成一棵树,那么对最下层的对象上锁,也就是对最细粒度的对象进行上锁,那么首先需要对粗粒度的对象上锁。如果需要对页上的记录 r 进行上 X 锁,那么分别需要对数据库 A、表、页上意向锁 IX,最后对记录 r 上 X 锁。若其中任何一个部分导致等待,那么该操作需要等待粗粒度锁的完成。

+

在一个对象加锁之前,该对象的全部祖先节点均加上了意向锁。希望给某个记录加锁的事务必须遍历从根到记录的路径。在遍历树的过程中,该事务给各节点加上意向锁。

+粒度层次图 +

举例来说,假设在表 1 的记录 r 上持有 X 锁,表 1 上必定持有 IX 锁。如果其他事务想在表 1 上加 S 表锁或 X 表锁,但与已有 IX 锁不兼容,所以该事务需要等待。再举例,假设表 1 持有 S 锁,如果其他事务想在表 1 的记录 r 上加 X 锁,需要先获得表 1 的 IX 锁,但与已有 S 锁不兼容,所以该事务需要等待。有了意向锁之后,就能快速判断行锁和表锁之间是否兼容。

+

InnoDB 存储引擎支持意向锁设计比较简练,其意向锁即为表级别的锁,两种意向锁 [doc]:

+
    +
  • 意向共享锁(IS):事务打算给数据行加行共享锁(S),事务在给一个数据行加共享锁(S)前必须先取得该表的 IS 锁。
  • +
  • 意向排他锁(IX):事务打算给数据行加行排他锁(X),事务在给一个数据行加排他锁(X)前必须先取得该表的 IX 锁。
  • +
+

IS、IX、S、X 锁的兼容性:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
待申请 \ 已持有ISIXSX
IS兼容兼容兼容冲突
IX兼容兼容冲突冲突
S兼容冲突兼容冲突
X冲突冲突冲突冲突
+

兼容关系:各种意向锁(IS、IX)之间全部兼容,意向共享锁 IS 和共享锁 S 兼容,共享锁 S 和共享锁 S 兼容,其他冲突。

+

SQL 语句可以分为数据定义语言(DDL)、数据控制语言(DCL)、数据查询语言(DQL)、数据操纵语言(DML)四种类型的语句,前两种语句,涉及的对象在数据之上,所以加锁的范围,通常是表级,对应表级锁。后两种语句操作的对象是数据,加锁的范围,通常是数据级,这就对应行级锁。

+

三种行锁:记录锁、间隙锁和 next-key 锁

+

InnoDB 行锁分为 3 种类型 [doc]:

+
    +
  • 记录锁(record lock):对索引记录项加锁。
  • +
  • 间隙锁(gap lock):间隙锁,对索引记录项之间的“间隙”、笫一条记录前的“间隙”或最后一条记录后的“间隙“加锁。锁定一个范围,但不包含索引记录本身。
  • +
  • next-key 锁(next-key Lock):前两种锁的组合,记录锁 + 间隙锁,锁定一个范围,并且锁定索引记录本身。(中文世界有时将 next-key lock 翻译为“临键锁”)
  • +
+

如果索引上包含 10, 20, 30, 40, 50 这些记录,那么可能的 next-key 锁的锁区间(interval),如下:

+
1
2
3
4
5
6
(-无穷, 10]     即,间隙锁 (-无穷, 10) + 记录锁 10。区间为,左开右闭区间
(10, 20] 即,间隙锁 (10, 20) + 记录锁 20
(20, 30] 即,间隙锁 (20, 30) + 记录锁 30
(30, 40] 即,间隙锁 (30, 40) + 记录锁 40
(40, 50] 即,间隙锁 (40, 50) + 记录锁 50
(50, +无穷] 即,间隙锁 (50, +无穷)
+

最后一个锁区间 (50, +无穷],对应的是上界伪记录(supremum pseudo-record),不是真实存在的记录。这个锁区间用于防止在最大值 50 之后插入记录。

+

记录锁总是会去锁住索引记录,如果 InnoDB 存储引擎表在建立的时候没有设置任何一个索引,那么这时 InnoDB 存储引擎会使用隐式的主键来进行锁定。

+

MySQL 默认的事务隔离级别是可重复读(REPEATABLE-READ),如果把事务隔离级别改成已提交读(READ-COMMITTED),间隙锁会被禁用。禁用间隙锁后,幻读异常会出现,因为其他事务可以在间隙中插入新行。InnoDB 的间隙锁,就是为了解决幻读异常而引入的。关于幻读异常,参见官方文档 doc

+

RR 隔离级别下,InnoDB 的锁通常使用 next-key 锁。但是,在唯一索引(和主键索引)上的等值查询next-key 锁退化为记录锁,间隙锁并不需要,即仅锁住索引本身,而不是范围。如果在唯一索引(和主键索引)上做范围查询,间隙锁依然需要。官方文档描述如下 [doc]:

+
+

Gap locking is not needed for statements that lock rows using a unique index to search for a unique row. (This does not include the case that the search condition includes only some columns of a multiple-column unique index; in that case, gap locking does occur.)

+
+

间隙锁是“纯抑制性的”,间隙锁唯一的作用就是为了防止其他事务的插入到间隙中。间隙锁和间隙锁之间是互不冲突的,所以间隙共享 S 锁和间隙排他 X 锁没有任何区别。

+

另外,还有一种锁叫插入意向锁(insert intention lock),基于间隙锁,专门用于 insert 操作。在执行 insert 操作时,需要先申请获取插入意向锁,也就是说,需要先检查当前插入位置上的下一条记录上是否持有间隙锁,如果被间隙锁锁住,则锁冲突,插入被阻塞。多个事务做 insert 操作,被相同的间隙锁阻塞,如果插入的值各不相同,这些事务的 insert 操作之间不阻塞。

+

所以,间隙锁与插入意向锁的兼容关系是,已持有的间隙锁与待申请的插入意向锁冲突,而插入意向锁之间兼容,在一个间隙锁锁上可以有多个意向锁等待。

+

IS、IX、X、S 锁和记录锁、间隙锁、next-key 锁的关系:

+
    +
  • IS、IX、S、X 是锁模式(lock mode)(源码层面上对应 lock_mode 枚举)。
  • +
  • 记录锁、间隙锁、next-key 锁、插入意向锁是行锁类型(record lock type)。
  • +
  • 每一种行锁类型,都包含 IS、IX、S、X 锁模式,如共享的记录锁、排他的记录锁、共享的间隙录锁、排他的间隙锁等。
  • +
+

锁监控:data_locks 和 data_lock_waits 表

+

MySQL 8.0 之前,information_schema 库提供 innodb_trxinnodb_locksinnodb_lock_waits 三张表,用来监控事务和诊断潜在的锁问题,具体介绍可以参见官方 5.7 文档 doc

+
    +
  • innodb_trx:当前事务表
  • +
  • innodb_locks:锁等待中的锁信息表
  • +
  • innodb_lock_waits:锁等待中的事务表
  • +
+

在 MySQL 8.0 之前,要想获得当前已持有的锁信息,需要开启参数 innodb_status_output_locks 并且执行命令 show engine innodb status,具体介绍可以参见官方文档“15.17 InnoDB Monitors”,doc

+

MySQL 8.0 开始,innodb_locks 表和 innodb_lock_waits 表,被 performance_schema 库的 data_locks 表和 data_lock_waits 表替代。其中值得注意的不同点是,新的 data_locks 表,同时包含了已持有的锁和请求中的锁的信息,这样查看当前已持有的锁信息更加方便。相关 SQL 示例:

+
1
2
3
4
5
6
7
8
9
10
11
-- 查询全部锁信息
select * from performance_schema.data_locks \G
-- 查询全部记录锁的锁信息
select * from performance_schema.data_locks where LOCK_TYPE = 'RECORD' \G
-- 查询等待中的锁信息
select * from performance_schema.data_locks where LOCK_STATUS = 'WAITING' \G
-- 查询锁等待中的事务
select * from performance_schema.data_lock_waits \G
-- 使用 sys 库的 innodb_lock_waits 视图
-- 查询锁等待中的事务
select * from sys.innodb_lock_waits \G
+

命令 show engine innodb status 的输出和 data_locks 表的对应关系,可以参考文章 link

+

行锁加锁案例分析

+

RR 隔离级别

+

本文的全部案例采用的 MySQL 版本为 8.0.30。MySQL 的默认事务隔离级别是 REPEATABLE-READ(可重复读),事务隔离级别可以通过系统变量 transaction_isolation 控制。

+
1
2
3
4
5
6
7
8
-- 事务隔离级别,默认为可重复读(Repeatable Read)
mysql> select @@global.transaction_isolation, @@transaction_isolation;
+--------------------------------+-------------------------+
| @@global.transaction_isolation | @@transaction_isolation |
+--------------------------------+-------------------------+
| REPEATABLE-READ | REPEATABLE-READ |
+--------------------------------+-------------------------+
1 row in set (0.00 sec)
+

tbl 表的数据如下:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mysql> select * from tbl;
+-----+------+------+------+
| a | b | c | d |
+-----+------+------+------+
| 10 | 10 | 10 | 10 |
| 20 | 20 | 20 | 20 |
| 30 | 30 | 30 | 30 |
| 40 | 40 | 40 | 40 |
| 50 | 50 | 50 | 50 |
| 60 | 60 | 60 | 60 |
| 70 | 70 | 70 | 70 |
| 80 | 80 | 80 | 80 |
| 90 | 90 | 90 | 90 |
| 100 | 100 | 100 | 100 |
+-----+------+------+------+
10 rows in set (0.00 sec)
+

(a1) 主键索引上的等值查询

+

SQL 语句:

+
1
select * from tbl where a = 10 for update;
+

data_locks 表中的行锁数据:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
mysql> select * from performance_schema.data_locks where LOCK_TYPE = 'RECORD' \G
*************************** 1. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 4816436360:185:4:3:140408965390368
ENGINE_TRANSACTION_ID: 56664
THREAD_ID: 367
EVENT_ID: 22
OBJECT_SCHEMA: testdb
OBJECT_NAME: tbl
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: PRIMARY
OBJECT_INSTANCE_BEGIN: 140408965390368
LOCK_TYPE: RECORD
LOCK_MODE: X,REC_NOT_GAP
LOCK_STATUS: GRANTED
LOCK_DATA: 10
+

加锁情况:

+
    +
  • 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
  • +
+

其他 SQL 语句的加锁情况(通过查 data_locks 表确认):

+
1
2
3
4
5
6
7
8
-- 在 a = 10 的索引记录上添加共享记录锁(S,REC_NOT_GAP)
select * from tbl where a = 10 for share;

-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
update tbl set b = 42 where a = 10;

-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
delete from tbl where a = 10;
+

加锁与锁冲突 SQL 演示:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
事务1事务2
mysql> begin;mysql> begin;
-- 在 a = 10 的索引记录上添加排他记录锁
mysql> select * from tbl where a = 10 for update;
-- 阻塞,因为 a = 10 上存在排他记录锁
mysql> select * from tbl where a = 10 for update;
-- 阻塞,因为 a = 10 上存在排他记录锁
mysql> insert into tbl (a) values (10);
-- 插入成功
mysql> insert into tbl (a) values (9);
-- 插入成功
mysql> insert into tbl (a) values (11);
mysql> rollback;mysql> rollback;
+

(a2) 唯一索引上的等值查询

+

SQL 语句的加锁情况(通过查 data_locks 表确认):

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
-- 在 b = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
select * from tbl where b = 10 for update;

-- 在 b = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 覆盖索引,但系统会认为接下来要更新数据,因此会顺便给主键索引上满足条件的行加上行锁
select a from tbl where b = 10 for update;

-- 在 b = 10 的索引记录上添加共享记录锁(S,REC_NOT_GAP)
-- 在 a = 10 的索引记录上添加共享记录锁(S,REC_NOT_GAP)
select * from tbl where b = 10 for share;

-- 在 b = 10 的索引记录上添加共享记录锁(S,REC_NOT_GAP)
-- 覆盖索引,所以只在字段 b 上加锁
select a from tbl where b = 10 for share;

-- 在 b = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
update tbl set b = 42 where b = 10;

-- 在 b = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
delete from tbl where b = 10;
+

上面的全部 SQL,除了走覆盖索引的 select for share 外,其他的加锁范围都相同。

+

(a3) 非唯一索引上的等值查询

+

SQL 语句的加锁情况(通过查 data_locks 表确认):

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
-- 在 c = 10 的索引记录上添加排他 next-key 锁,区间为 (-无穷, 10](X)
-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 c = 20 的索引记录上添加排他间隙锁,区间为 (10, 20)(X,GAP)
select * from tbl where c = 10 for update;

-- 在 c = 10 的索引记录上添加共享 next-key 锁,区间为 (-无穷, 10](S)
-- 在 a = 10 的索引记录上添加共享记录锁(S,REC_NOT_GAP)
-- 在 c = 20 的索引记录上添加共享间隙锁,区间为 (10, 20)(S,GAP)
select * from tbl where c = 10 for share;

-- 在 c = 10 的索引记录上添加共享 next-key 锁,区间为 (-无穷, 10](S)
-- 在 c = 20 的索引记录上添加共享间隙锁,区间为 (10, 20)(S,GAP)
-- 覆盖索引,所以只在字段 c 上加锁
select a from tbl where c = 10 for share;

-- 在 c = 10 的索引记录上添加排他 next-key 锁,区间为 (-无穷, 10](X)
-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 c = 20 的索引记录上添加排他间隙锁,区间为 (10, 20)(X,GAP)
update tbl set c = 42 where c = 10;

-- 在 c = 10 的索引记录上添加排他 next-key 锁,区间为 (-无穷, 10](X)
-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 c = 20 的索引记录上添加排他间隙锁,区间为 (10, 20)(X,GAP)
delete from tbl where c = 10;
+

上面的全部 SQL,除了走覆盖索引的 select for share 外,其他的加锁范围都相同。

+

加锁与锁冲突 SQL 演示:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
事务1事务2
mysql> begin;mysql> begin;
-- 在 c = 10 的索引记录上添加排他 next-key 锁,区间为 (-无穷, 10]
-- 在 a = 10 的索引记录上添加排他记录锁
-- 在 c = 20 的索引记录上添加排他间隙锁,区间为 (10, 20)
mysql> select * from tbl where c = 10 for update;
-- 阻塞,因为 c = 10 上存在排他 next-key 锁
mysql> select * from tbl where c = 10 for update;
-- 阻塞,因为 a = 10 上存在排他记录锁
mysql> select * from tbl where a = 10 for update;
-- 阻塞,因为 c = 10 上存在排他 next-key 锁,区间为 (-无穷, 10]
mysql> insert into tbl (a, c) values (1, 9);
-- 阻塞,因为 c = 10 上存在排他 next-key 锁,区间为 (-无穷, 10]
mysql> insert into tbl (a, c) values (1, 10);
-- 阻塞,因为 c = (10, 20) 区间存在间隙锁
mysql> insert into tbl (a, c) values (1, 11);
-- 插入成功
mysql> insert into tbl (a, c) values (1, 21);
mysql> rollback;mysql> rollback;
+

(a4) 无索引的等值查询

+

SQL 语句的加锁情况(通过查 data_locks 表确认):

+
1
2
-- 在 a 主键的全部索引记录上添加排他 next-key 锁
select * from tbl where d = 10 for update;
+

因为字段 d 上没有索引,这个 SQL 语句,只能在聚簇索引上全表扫描。加锁情况,在 a 主键的全部索引记录上添加排他 next-key 锁。表 tbl 共 10 条记录,全部的持有的 next-key 锁的锁区间,如下:

+
1
2
3
4
5
6
7
8
9
10
11
(-无穷, 10]
(10, 20]
(20, 30]
(30, 40]
(40, 50]
(50, 60]
(60, 70]
(70, 80]
(80, 90]
(90, 100]
(100, +无穷]
+

(a5) 值不存在的等值查询

+

SQL 语句的加锁情况(通过查 data_locks 表确认):

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
---- 主键索引上的值不存在的等值查询
-- 在 a = 100 的索引记录上添加排他间隙锁,区间为 (90, 100)(X,GAP)
select * from tbl where a = 95 for update;
-- 在 a 的索引记录上添加排他 next-key 锁,区间为 (100, +无穷](X)
select * from tbl where a = 105 for update;

---- 唯一索引上的值不存在的等值查询
-- 在 b = 100 的索引记录上添加间隙锁,区间为 (90, 100)(X,GAP)
select * from tbl where b = 95 for update;
-- 在 b 的索引记录上添加排他 next-key 锁,区间为 (100, +无穷](X)
select * from tbl where b = 105 for update;

---- 非唯一索引上的值不存在的等值查询
-- 在 c = 100 的索引记录上添加间隙锁,区间为 (90, 100)
select * from tbl where c = 95 for update;
-- 在 c 的索引记录上添加排他 next-key 锁,区间为 (100, +无穷](X)
select * from tbl where c = 105 for update;
+

(b1) 主键索引上的范围查询

+

SQL 语句的加锁情况(通过查 data_locks 表确认):

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)
-- 在 a 的索引记录上添加排他 next-key 锁,区间为 (100, +无穷](X)
select * from tbl where a >= 90 for update;

-- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a 的索引记录上添加排他 next-key 锁,区间为 (100, +无穷](X)
select * from tbl where a >= 100 for update;

-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 100 的索引记录上添加排他间隙锁,区间为 (90, 100)(X,GAP)
-- 附注:与主键上的等值查询 `a = 90` 的加锁范围的区别是额外加了区间为 (90, 100) 间隙锁
select * from tbl where a >= 90 and a < 91 for update;

-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 100 的索引记录上添加排他间隙锁,区间为 (90, 100)(X,GAP)
-- 附注:与相同查询条件的 `select for update`,加锁范围相同
update tbl set d = 42 where a >= 90 and a < 91;

-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 100 的索引记录上添加排他间隙锁,区间为 (90, 100)(X,GAP)
-- 附注:与相同查询条件的 `select for update` 的 SQL,加锁范围相同
delete from tbl where a >= 90 and a < 91;
+

(b2) 唯一索引上的范围查询

+

SQL 语句的加锁情况(通过查 data_locks 表确认):

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
-- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)
-- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 b 的索引记录上添加排他 next-key 锁,区间为 (100, +无穷](X)
select * from tbl where b >= 90 for update;

-- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)(不必要的记录锁)
select * from tbl where b >= 90 and b < 91 for update;

-- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)(不必要的记录锁)
-- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)(不必要的记录锁)
update tbl set d = 42 where b >= 90 and b < 91;

-- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)(不必要的记录锁)
-- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)(不必要的记录锁)
delete from tbl where b >= 90 and b < 91;
+

加锁与锁冲突 SQL 演示:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
事务1事务2
mysql> begin;mysql> begin;
-- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90]
-- 在 a = 90 的索引记录上添加排他记录锁
-- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100]
mysql> select * from tbl where b >= 90 and b < 91 for update;
-- 阻塞,因为 b = 90 上存在排他 next-key 锁
mysql> select * from tbl where b = 90 for update;
-- 阻塞,因为 b = 100 上存在排他 next-key 锁(不必要的记录锁)
mysql> select * from tbl where b = 100 for update;
-- 阻塞,因为 a = 90 上存在排他记录锁
mysql> select * from tbl where a = 90 for update;
mysql> rollback;mysql> rollback;
+

(b3) 非唯一索引上的范围查询

+

SQL 语句的加锁情况(通过查 data_locks 表确认):

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
-- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)
-- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 b 的索引记录上添加排他 next-key 锁,区间为 (100, +无穷](X)
select * from tbl where c >= 90 for update;

-- 在 c = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 c = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)(不必要的记录锁)
select * from tbl where c >= 90 and c < 91 for update;

-- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)(不必要的记录锁)
-- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)(不必要的记录锁)
update tbl set d = 42 where c >= 90 and c < 91;

-- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)(不必要的记录锁)
-- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)(不必要的记录锁)
delete from tbl where c >= 90 and c < 91;
+

对比,唯一索引上的范围查询的加锁情况,容易得出结论,唯一索引和普通索引上的范围查询的加锁规则相同

+

RC 隔离级别

+

把事务隔离级别修改为已提交读(Read Committed):

+
1
2
-- 事务隔离级别,修改为已提交读(Read Committed)
mysql> set @@transaction_isolation = 'READ-COMMITTED';
+

(a1) 主键索引上的等值查询

+

SQL 语句的加锁情况(通过查 data_locks 表确认):

+
1
2
3
4
5
6
7
8
9
10
11
-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
select * from tbl where a = 10 for update;

-- 在 a = 10 的索引记录上添加共享记录锁(S,REC_NOT_GAP)
select * from tbl where a = 10 for share;

-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
update tbl set b = 42 where a = 10;

-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
delete from tbl where a = 10;
+

结论:因为主键索引上的等值查询不涉及间隙锁,所以 RR 和 RC 隔离级别下的加锁规则相同。

+

(a2) 唯一索引上的等值查询

+

同样的,因为唯一索引上的等值查询不涉及间隙锁,所以 RR 和 RC 隔离级别下的加锁规则相同。

+

(a3) 非唯一索引上的等值查询

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
-- 在 c = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
select * from tbl where c = 10 for update;

-- 在 c = 10 的索引记录上添加排他记录锁(S,REC_NOT_GAP)
-- 在 a = 10 的索引记录上添加排他记录锁(S,REC_NOT_GAP)
select * from tbl where c = 10 for share;

-- 在 c = 10 的索引记录上添加排他记录锁(S,REC_NOT_GAP)
-- 覆盖索引,所以只在字段 b 上加锁
select a from tbl where c = 10 for share;

-- 在 c = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
update tbl set c = 42 where c = 10;

-- 在 c = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
delete from tbl where c = 10;
+

(a4) 无索引的等值查询

+
1
2
-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
select * from tbl where d = 10 for update;
+

(a5) 值不存在的等值查询

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
---- 主键索引上的值不存在的等值查询
-- 无锁
select * from tbl where a = 95 for update;
-- 无锁
select * from tbl where a = 105 for update;

---- 唯一索引上的值不存在的等值查询
-- 无锁
select * from tbl where b = 95 for update;
-- 无锁
select * from tbl where b = 105 for update;

---- 非唯一索引上的值不存在的等值查询
-- 无锁
select * from tbl where c = 95 for update;
-- 无锁
select * from tbl where c = 105 for update;
+

(b1) 主键索引上的范围查询

+
1
2
3
4
5
6
7
8
9
10
11
12
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
select * from tbl where a >= 90 for update;

-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
select * from tbl where a >= 90 and a < 91 for update;

-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
update tbl set d = 42 where a >= 90 and a < 91;

-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
delete from tbl where a >= 90 and a < 91;
+

(b2) 唯一索引上的范围查询

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-- 在 b = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 b = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
select * from tbl where b >= 90 for update;

-- 在 b = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
select * from tbl where b >= 90 and b < 91 for update;

-- 在 b = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
update tbl set d = 42 where b >= 90 and b < 91;

-- 在 b = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
delete from tbl where b >= 90 and b < 91;
+

(b3) 非唯一索引上的范围查询

+

加锁情况,和 RC 隔离级别的唯一索引上的范围查询完全相同。

+

行锁加锁规则总结

+

RC 隔离级别时的加锁规则:

+
    +
  • 间隙锁被禁用,只有记录锁,没有间隙锁和 next-key 锁。
  • +
  • 对全部满足查询条件的索引记录加记录锁。如果查询条件满足覆盖索引,就只对辅助索引加记录锁。如果需要回表,对辅助索引记录和聚簇索引记录引同时加锁。
  • +
  • 如果不存在满足查询条件的索引记录,就不加锁。
  • +
+

RR 隔离级别时的加锁规则:

+
    +
  • 加锁的基本单位是 next-key 锁。
  • +
  • 对全部满足查询条件的索引记录加 next-key 锁。如果查询条件满足覆盖索引,就只对辅助索引加记录锁。如果需要回表,对辅助索引记录和聚簇索引记录引同时加锁。
  • +
  • 范围查询时,或值不存在的等值查询时,在从右扫描到的最后的不满足查询条件的记录上加间隙锁。如果索引的最大记录值,满足查询条件,则在上界伪记录(supremum pseudo-record)上加 next-key 锁(相当于间隙锁)。
  • +
  • 等值查询时,在主键索引和唯一索引上加锁,next-key 锁退化为记录锁。
  • +
+

范围查询时的不必要加锁 bug

+

注意,RR 隔离级别时,在主键索引上的范围查询时,确实是按上文的规则加间隙锁。但实际验证发现,在辅助索引(包括唯一索引和普通索引)上的范围查询时,在最后的不满足查询条件的记录上实际加的是 next-key 锁。这样加锁的问题是,会在不满足查询条件的记录上记录锁,这个记录锁其实是不必要的,是一个 bug。

+

其实,这个不必要的记录锁 bug,在 MySQL 8.0.18 之前,主键索引的场景下也存在,MySQL 8.0.18 修复了,但只修复了主键索引的场景,辅助索引的场景未修复。修复对应 bug 为“Bug #29508068 UNNECESSARY NEXT-KEY LOCK TAKEN”,修复提交记录见 github

+

在 MySQL 8.0.19 版本上,有人再次提了 bug,“Bug #98639 Redundant row-level locking for secondary index”。不过 MySQL 官方认为“Not a Bug”。然后,提 bug 的人,也只好妥协认为这个是“performance issue”。

+

对比下面这 3 个 SQL 的加锁情况,可以发现后 2 个 SQL 存在不必要的加锁问题。

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-- 主键索引上的范围查询
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 100 的索引记录上添加排他间隙锁,区间为 (90, 100)(X,GAP)
select * from tbl where a >= 90 and a < 91 for update;

-- 唯一索引上的范围查询
-- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)(不必要的记录锁)
select * from tbl where b >= 90 and b < 91 for update;

-- 非唯一索引上的范围查询
-- 在 c = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 c = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)(不必要的记录锁)
select * from tbl where c >= 90 and c < 91 for update;
+

隔离级别的实现

+

上文提到,PostgreSQL 的并发控制技术是以 MVCC 技术为主,封锁技术为辅。先看下 PostgreSQL 对隔离级别的实现 [doc]:

+
    +
  • PostgreSQL 支持 SQL 标准的 4 种隔离级别,默认的隔离级别是 RC。但 PostgreSQL 内部只实现 3 种隔离级别 RC、RR 和 SER。若选择 RU 隔离,实际上是 RC。
  • +
  • PostgreSQL 的 RR 隔离级别,底层是基于 MVCC 技术实现的快照隔离(SI,Snapshot Isolation)。快照隔离下,能避免 SQL-92 定义的三种异常,脏读、不可重复读和幻读异常,但是可能会出现写偏序(Write Skew)异常。
  • +
  • PostgreSQL 的 SER 隔离,底层是可串行化的快照隔离(SSI,Serializable Snapshot Isolation)。
  • +
+

InnoDB 的并发控制以封锁技术为主,MVCC 技术辅助,各个隔离级别的具体实现是:

+
    +
  • RC 隔离级别:快照读 + 写长锁 +
      +
    • 快照读,能避免脏读
    • +
    +
  • +
  • RR 隔离级别:快照读 + 写长锁 + 间隙锁(没有实现真正的快照隔离 SI) +
      +
    • 快照读,能一定程度避免不可重复读和幻读异常,但因为 InnoDB 的刷新快照的特殊实现,不能完全避免
    • +
    • 间隙锁,能避免幻读异常,只有锁定读时才会申请获取间隙锁
    • +
    +
  • +
  • 可串行化隔离级别:读长锁 + 写长锁 + 间隙锁 +
      +
    • 完全基于锁实现串行化,并发度很低,性能不好
    • +
    +
  • +
+

InnoDB 实现的 MVCC 技术,能让事务以快照读的方式执行查询。快照读snapshot read),或者叫一致性非锁定读(consistent nonlocking read),或者一致性读(consistent read),即使用多版本技术实现的读取数据在某个时间点的快照的查询。在 RR 和 RC 隔离级别下,一致性读是普通的 select 语句的默认模式。快照读避免加锁,从而提高并发度。在 RR 和 RC 隔离级别下快照读的区别:

+
    +
  • RR 隔离级别时,事务中的所有一致性读都会读取该事务中第一次此类读取建立的快照。
  • +
  • RC 隔离级别时,事务中的每个一致性读都会设置并读取其自己的最新快照,快照是最新已提交的数据。
  • +
+

如果事务在查询数据后,要对该数据做修改操作,快照读无法提供足够的保护,因为其他事务可以对这些数据做修改操作。为了提供额外的保护,InnoDB 提供锁定读locking read),即同时执行锁定操作的 select 语句,锁持有直到事务结束。锁定读分两种:

+
    +
  • select ... for share 是加共享锁的查询数据
  • +
  • select ... for update 是加排他锁的查询数据
  • +
+

RR 隔离级别下的不可重复读和幻读异常

+

上文提到,“快照读,能一定程度避免不可重复读和幻读异常,但因为 InnoDB 的刷新快照的特殊实现,不能完全避免”。现在来看下 RR 隔离级别下的不可重复读异常的示例:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
事务1事务2
mysql> begin;mysql> begin;
-- 返回值为 10,快照读
mysql> select b from tbl where a = 10;
-- 把 b 值修改为 0
mysql> update tbl set b = 0 where a = 10;
mysql> commit;
-- 返回值为 10,没有出现不可重复读异常
mysql> select b from tbl where a = 10;
-- update 会读取 a = 10 的已提交的最新值
-- 同时 a = 10 记录的快照会被刷新
mysql> update tbl set b = b + 1 where a = 10;
-- 返回值为 1,出现不可重复读异常
mysql> select b from tbl where a = 10;
+

这个问题在 MySQL 的 Bug 系统中可以找到,参见:Bug #57973、Bug #63870 等。官方认为,这不是 Bug,InnoDB 就是按这种方式设计。Bug #57973 下 MySQL 工程师 Kevin Lewis 对这个问题的解答 [ref]:

+
+

[16 Aug 2013 19:23] Kevin Lewis
+Rejecting this bug because InnoDB is working as designed for the following reason;
+...
+But when InnoDB Repeatable Read transactions modify the database, it is possible to get phantom reads added into the static view of the database, just as the ANSI description allows. Moreover, InnoDB relaxes the ANSI description for Repeatable Read isolation in that it will also allow non-repeatable reads during an UPDATE or DELETE. Specifically, it will write to newly committed records within its read view. And because of gap locking, it will actually wait on other transactions that have pending records that may become committed within its read view. So not only is an UPDATE or DELETE affected by pending or newly committed records that satisfy the predicate, but also 'SELECT … LOCK IN SHARE MODE' and 'SELECT … FOR UPDATE'.
+This WRITE COMMITTED implementation of REPEATABLE READ is not typical of any other database that I am aware of. But it has some real advantages over a standard 'Snapshot' isolation. When an update conflict would occur in other database engines that implement a snapshot isolation for Repeatable Read, an error message would typically say that you need to restart your transaction in order to see the current data. So the normal activity would be to restart the entire transaction and do the same changes over again. But InnoDB allows you to just keep going with the current transaction by waiting on other records which might join your view of the data and including them on the fly when the UPDATE or DELETE is done. This WRITE COMMITTED implementation combined with implicit record and gap locking actually adds a serializable component to Repeatable Read isolation.

+
+

就是说,InnoDB 实现的 RR 隔离级别,放松了 SQL 标准对 RR 隔离级别的要求。事务 T1 在快照读后,如果其他事务 T2 修改了快照对应的记录并提交,之后事务 T1 执行涉及快照的 DML 语句(update、delete、insert)或锁定读,会触发快照刷新,事务 T2 最新提交的修改会刷新进快照。最终导致事务 T1 再次执行相同条件的快照读,读取结果不同,出现不可重复读或幻读异常。简单概括就是,在快照失效后,又刷新快照,导致两次读到的快照不同。另外,如果实现上选择不刷新快照,并且事务 T1 正常执行,会出现 P4 丢失更新异常。

+

不可重复读异常的避免(一定程度上避免,但没有完全避免):

+
    +
  • 如果事务重复的两次读都是快照读(普通 select 语句),并且中间没有执行涉及快照的 DML 或锁定读,这样两次读到的是相同的快照读,所以不会出现不可重复读异常。
  • +
  • 如果事务重复的两次读都是当前读(select for update/share),因为第一次加锁,其他事务无法更新该记录,所以也不会出现不可重复读异常。
  • +
  • 如果事务重复的两次读都是快照读,但是中间执行涉及快照的 DML 或锁定读,触发了快照刷新,如果快照被更新,就会出现不可重复读异常。
  • +
+

幻读异常的避免(一定程度上避免,但没有完全避免):

+
    +
  • 如果事务重复的两次读都是快照读(普通 select 语句),并且中间没有执行涉及快照的 DML 或锁定读,这样两次读到的是相同的快照读,所以不会出现幻读异常。
  • +
  • 如果事务重复的两次读都是当前读(select for update/share),因为第一次当前读加间隙锁,其他事务无法插入,被阻塞,所以也不会出现幻读异常。
  • +
  • 如果事务重复的两次读都是快照读,但是中间执行涉及快照的 DML 或锁定读,触发了快照刷新,如果快照被更新,就会出现幻读异常。
  • +
+

上述的快照失效的场景,PostgreSQL 的处理方式是,事务会被回滚并报错提示,应用程序收到这个报错,可以尝试重试,重试的事务读到的快照是最新的,这样即避免丢失更新异常,也避免了幻读和不可重复读异常(参见官方文档 doc)。

+

参考资料

+

MySQL 8.0 Reference Manual

+ +

其他参考资料:

+ + +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2023/07/io-multiplexing-network-server/index.html b/2023/07/io-multiplexing-network-server/index.html new file mode 100644 index 00000000..f816f319 --- /dev/null +++ b/2023/07/io-multiplexing-network-server/index.html @@ -0,0 +1,902 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + I/O 多路复用与网络服务器并发策略 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ I/O 多路复用与网络服务器并发策略 +

+ + +
+ + + + +
+ + +

目前主流的网络服务器,网络 I/O 相关的底层最核心的技术都是 I/O 多路复用(I/O Multiplexing),比如 Apache HTTP Server、Nginx、Redis 等。本文尝试解释各种 I/O 模型,包括解释什么是 I/O 多路复用,同时也总结 I/O 多路复用底层的系统调用 select、poll、kqueue 和 epoll 的演进和区别,并编写了使用这些函数的示例代码。另外,本文还总结了各种基于 I/O 多路复用实现的网络服务器的并发策略的三种模式,包括对 Apache HTTP Server、Nginx 和 Redis 等网络服务器的并发策略的具体案例的解析。

+ +

I/O 模型与多路复用

+

类 Unix 系统下的 I/O 操作,默认是阻塞 I/O(Blocking I/O,缩写为 BIO)。比如,当一个进程发出了读操作请求,但没有可访问的数据时,该进程通常会阻塞在内核中,直到出现可以访问的数据为止。然而,进程有时要处理对多个描述符的 I/O 操作,需要在多个文件描述符上阻塞,典型的场景是终端 I/O 和网络 I/O。

+

例如,有一个远程登录程序,它要从键盘读入数据然后把这些数据通过套接字发送到一个远程的计算机上。这个程序还需要从和远程终端相连接的套接字上读取数据,并将数据显示于屏幕上。如果进程在读键盘数据时阻塞,它就不能读那些从远程终端发送到屏幕上的数据。这样一来,在来自远程终端的更多数据到达之前,用户就不知道该通过键盘输入些什么,于是,死锁便产生了。相反的,如果进程在读从远程终端送来的数据时阻塞,它将不能读来自键盘终端的数据。

+

历史上,Unix 系统通过使用多个进程让应用能同时处理多个文件描述符,这些进程间可以通过管道或者是其他的进程间通信方法进行通信。然而,如果处理上下文切换的代价比处理输入的代价更大,那么这种方法就会导致巨大的系统开销,因为它要求在进程间进行频繁的上下文切换。并且,在一个进程内实现这种应用会显得比较直观。由于上述原因,BSD 提供了三种机制,允许对描述符进行多路 I/O 访问,非阻塞式 I/O、 I/O 多路复用和信号驱动 I/O[1]

+
    +
  • 非阻塞 I/O(Nonblocking I/O,缩写为 NIO):进程对描述符尝试 I/O 操作,如果描述符未就绪(ready),系统不把本进程投入睡眠,而是返回一个错误(EAGAINEWOULDBLOCK)。进程收到错误后,要么放弃,要么不停地轮询(polling),直至发现有描述符可以进行 I/O 操作为止。这种轮询的方法的问题在于,进程必须连续不断地运行,检查描述符是否就绪,很浪费 CPU 时间。
  • +
  • I/O 多路复用(I/O Multiplexing):让系统提供一种方法在多个感兴趣的描述符中查找哪个描述符可以进行 I/O 操作,如果没有这样的描述符,系统会让进程处于睡眠状态,直到出现这样的描述符为止。这种方法的缺点是对于每个操作,进程要完成两个系统调用,一个用来查找就绪描述符,另一个是 I/O 操作本身。非阻塞 I/O 是在用户空间轮询查找就绪描述符,而 I/O 多路复用是执行特殊的系统调用在内核空间查找就绪描述符。
  • +
  • 信号驱动 I/O(Signal-Driven I/O):当可以进行 I/O 操作时,使所有描述符发信号。进程只用等待这些信号就可以知道是否可以进行 I/O 操作。这种方法的缺点在于捕获这些信号的开销是巨大的,所以此方法对于那些涉及大量 I/O 操作的应用并不实用。
  • +
+

类 Unix 系统下,默认的 I/O 操作都是阻塞 I/O。有两种方法可以将描述符设置非阻塞 I/O:(1) 如果是调用 open() 获得描述符,则可以在调用时设置 O_NONBLOCK 标志;(2) 对于已经打开的一个描述符,则可调用 fcntl(),由该函数为描述符设置 O_NONBLOCK 标志。另外,对于网络套接字的描述符,如果想在获得描述符时直接指定为非阻塞 I/O,可以在调用 socket() 或 accept() 时传入 SOCK_NONBLOCK 标志,当然也可以在获得描述符后,再调用 fcntl()修改。

+

I/O 多路复用,最早是在 4.2BSD(1983.08)中由 select() 系统调用提供的。虽然该系统调用主要用于终端 I/O 和网络 I/O,但它对其他描述符同样是起作用的。poll() 是另外一个实现 I/O 多路复用的系统调用,和 select() 功能几乎相同。SVR3(1987)在增加 STREAMS 机制时增加了 poll() 系统调用。但在 SVR4 (1988)之前,poll() 只对 STREAMS 设备起作用。SVR4 开始支持对任意描述符起作用的 poll()select()poll() 系统调用,都是在 POSIX.1-2001 开始标准化定义,然而从可移植性角度考虑,支持 select() 的系统比支持 poll() 的系统要多,所以在应用的实现上,相比于 poll() 基于 select() 实现更多。另外 POSIX 还定义了 pselect(),它是能够处理信号阻塞并提供了更高时间分辨率的 select() 的增强版本。

+

在 Linux 系统下,poll() 系统调用从 2.1.23 版本(1997.01)开始提供,而 poll() 库函数由 libc 5.4.28(1997.05)开始提供。早期 Linux 内核未提供 poll() 系统调用,glibc 使用 select() 来模拟实现 poll()。另外,Linux 还提供特有的 I/O 多路复用解决方案,即 epoll,详细介绍参见下文。

+

为了能持续不断的监听 I/O 操作就绪事件,应用实现上需要循环调用 select()poll()。为了方便使用,封装各个不同的 I/O 多路复用函数的第三方库,通常会把这样的循环调用被抽象为事件循环(event loop),然后把 I/O 就绪事件的处理抽象成回调函数(callback)。最早的提供事件循环(event loop)抽象的典型的第三方库是 libevent 库(最早在 2002.04 发布)。

+

信号驱动 I/O,在描述符就绪时内核会发送 SIGIO 信号。但是信号驱动 I/O 对于 TCP 套接字近乎无用,问题在于 SIGIO 信号产生得过于频繁,并且它的出现并没有告诉我们发生了什么事件,无法区分触发信号的各种情况。在 UDP 上使用信号驱动式 I/O 没有上述问题。关于信号驱动 I/O 的详细阐述,可以参阅《UNIX网络编程 卷1》的第 25 章[2]

+

描述符就绪条件

+

select()poll() 系统调用是在多个文件描述符中查找就绪(ready)的描述符。就绪条件具体指是什么呢?select()man 文档,有如下描述(poll() 的就绪条件类似,不展开讨论):

+
+

A file descriptor is considered ready if it is possible to perform a corresponding I/O operation (e.g., read(2), or a sufficiently small write(2)) without blocking.
+...
+A file descriptor is ready for reading if a read operation will not block; in particular, a file descriptor is also ready on end-of-file.
+A file descriptor is ready for writing if a write operation will not block. However, even if a file descriptor indicates as writable, a large write may still block.

+
+

针对网络套接字描述符的就绪条件,《UNIX网络编程 卷1》如下总结:

+套接字描述的就绪条件小结 +

表中的“有数据可读”含义是,该套接字接收缓冲区中的数据字节数大于等于套接字接收缓冲区低水位标记的当前大小。对这样的套接字执行读操作不会阻塞并将返回一个大于 0 的值(也就是返回准备好读入的数据)。接收低水位标记,可以通过调用 setsockopt() 的 SO_RCVLOWAT 选项来设置,默认值为 1。

+

表中的“有可用于写的空间”含义是,该套接字发送缓冲区中的可用空间字节数大于等于套接字发送缓冲区低水位标记的当前大小,并且或者该套接字已连接,或者该套接字不需要连接(如UDP套接字)。发送低水位标记,可以通过调用 setsockopt() 的 SO_SNDLOWAT 选项来设置,默认值为 1024。

+

表中的“关闭连接的读一半”和“关闭连接的写一半”含义是,套接字的 TCP 连接接收了关闭 FIN,此时会收到读就绪事件和写就绪事件。对这样的套接字做读操作将不阻塞并返回 0(也就是返回 EOF);对这样的套接字做写操作将产生 SIGPIPE 信号(Broken pipe: write to pipe with no readers)。

+

I/O 模型的比较

+

上文阐述的就是 Unix 系统的 4 种 I/O 模型,阻塞 I/O、非阻塞 I/O、I/O 多路复用和信号驱动式 I/O。另外,还有一种 I/O 模型是,异步 I/O(Asynchronous I/O,缩写为 AIO)。异步 I/O,由 POSIX 规范定义,工作机制是,告知内核启动某个操作,并让内核在整个操作(包括将数据从内核复制到我们自己的缓冲区)完成后通知进程。这种模型与信号驱动模型的主要区别在于:信号驱动 I/O 是由内核通知我们何时可以启动一个 I/O 操作,而异步 I/O 模型是由内核通知我们 I/O 操作何时完成。POSIX 定义的异步 I/O 的函数为,aio_write()aio_read() 等。

+

关于 POSIX 异步 IO,Linux 的 aio 的 man 文档,有如下说明:

+
+

The current Linux POSIX AIO implementation is provided in user space by glibc. This has a number of limitations, most notably that maintaining multiple threads to perform I/O operations is expensive and scales poorly. Work has been in progress for some time on a kernel state-machine-based implementation of asynchronous I/O (see io_submit(2), io_setup(2), io_cancel(2), io_destroy(2), io_getevents(2)), but this implementation hasn't yet matured to the point where the POSIX AIO implementation can be completely reimplemented using the kernel system calls.

+
+

本质上,Linux 下的 POSIX AIO 是在用户空间下用线程模拟实现的 AIO,并非真正的 AIO,性能很差,所以很少被使用。

+

Linux 内核实现的 AIO 是 io_submitio_setupio_getevents 等系统调用,也被成为“Linux Native AIO”,或者缩写为 KAIO(kernel AIO),从 Linux 2.5 开始支持(2001.11),这些系统调用对应的库函数由 libaio 库提供。但是 Linux Native AIO 几乎不可用,只适合以 O_DIRECT 方式做直接 IO(无缓存的 I/O)。如果真的实现了异步 AIO,io_submit 系统调用不应该阻塞,但是对缓存 I/O、网络访问、管道等,io_submit 会发生阻塞,整个操作将在 io_submit 系统调用期间执行,并且通过调用 io_getevents,I/O 操作完成结果可以立即访问,这样也就破坏了异步 I/O 的目的[3]

+

最新的内核实现的 AIO 是 io_uring,已经被 Linux 5.1(2019.05)采纳。很多开源项目,比如 libeventlibuvNginxRedis 等,都有打算支持或甚至已经支持 io_uring。io_uring 的杂类资料整理,可以参考“Awesome io_uring”[4]。本文主要关注 I/O 多路复用,io_uring 不再展开讨论。

+

《UNIX网络编程 卷1》对这 5 种 I/O 模型做了对比[2:1]

+5 种 I/O 模型的比较 +

可以看出,前 4 种模型的主要区别在于第一阶段(等待描述符就绪),因为它们的第二阶段是一样的:在数据从内核复制到调用者的缓冲区期间,进程阻塞于 recvfrom 调用。相反,异步 I/O 模型在这两个阶段都要处理,从而不同于其他 4 种模型。

+

各个 I/O 模型,用户空间的应用与内核空间的交互过程如下图所示(信号驱动 I/O 实际场景较少使用,所以忽略)[5]

+ + + + + + + + + + + + + +
阻塞式 I/O非阻塞式 I/O
非阻塞式 I/O + I/O 多路复用异步 I/O
+

通常对“I/O 多路复用”术语的理解,其实就是特指,由 select() 、poll() 或类似的系统调用实现的在多个文件描述符中查找就绪状态描述符的技术。不过,根据 McKusick 书籍的描述[1:1]I/O 多路复用也可以泛指为,单个进程同时处理多个文件描述符的技术,与之相对立的技术是早期的由多个进程同时处理多个描述符的解决方案。广义理解的话,I/O 多路复用包括非阻塞 I/O、狭义的 I/O 多路复用、信号驱动式 I/O、异步 IO 等技术

+

单独的“多路复用(multiplexing)”术语,维基百科的解释是,一个通信和计算机网络领域的专业术语,多路复用通常表示在一个信道上传输多路信号或数据流的过程和技术。

+

阻塞、非阻塞与同步、异步的区别

+

在概念上,阻塞 I/O 和非阻塞 I/O,是根据系统是否会阻塞进程的执行而区分的:

+
    +
  • 阻塞 I/O,在执行 I/O 操作后,如果 I/O 操作的描述符未就绪,系统会让进程进入睡眠状态,直到描述符就绪为止。
  • +
  • 非阻塞 I/O,在执行 I/O 操作后,不会阻塞当前进程,可以继续执行其他的任务。
  • +
+

另外,POSIX 定义了同步 I/O(Synchronous I/O)和异步 I/O(Asynchronous I/O)两个术语[2:2]

+
    +
  • 同步 I/O 操作,导致请求进程阻塞,直到 I/O 操作完成
  • +
  • 异步 I/O 操作,不导致请求进程阻塞。
  • +
+
+

A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes.
+An asynchronous I/O operation does not cause the requesting process to be blocked.

+
+

按照这个定义,阻塞 I/O、非阻塞 I/O、I/O 多路复用和信号驱动 I/O 都是同步 I/O,因为其中真正的 I/O 操作将阻塞进程(第二阶段,将数据从内核复制到用户空间的缓冲区阶段)。只有异步 I/O 模型与 POSIX 定义的异步 I/O 相匹配。

+

不过,对于 I/O 多路复用是属于同步 I/O 还是异步 I/O 存在争议,不同视角下存在不同的理解。I/O 多路复用,单看等待 I/O 就绪阶段,其实是异步的。所以很多时候,I/O 多路复用,虽然没有实现真正的 POSIX 定义的异步 I/O,但也被归类为异步 I/O。比如,Jones 的文章[5:1]将 I/O 多路复用归类为阻塞的异步 I/O,将 POSIX AIO 归类为非阻塞的异步 I/O。类似的,封装各个不同的 I/O 多路复用函数的 libevent 库的官方文档[6]自称是“Asynchronous I/O”。Node.js 底层是基于 I/O 多路复用封装的 libuv 库,libuv 库也自称是“Asynchronous I/O”。另外,如果跳出 I/O 视角,从整体应用的执行流程角度看,基于 I/O 多路复用实现的应用,相对于在多个描述符列表上主轮询流程,在单个描述符上 I/O 事件的应用处理流程相对独立,可以认为是异步的。Node.js 文档对“异步”的解释如下[7]

+
+

Asynchronous means that things can happen independently of the main program flow.

+
+

严格意义上,典型的 I/O 多路复用的应用是单进程单线程执行的,本质上都是串行执行的,是假异步。

+

服务器并发策略与 C10K 问题

+

世界上第一个 HTTP 服务器,CERN httpd,早期实现采用的 I/O 模型是阻塞 I/O,然后为了能同时处理多个客户端连接,会为每个客户端连接创建一个新的处理请求的子进程(process-per-connection),这种并发模式被称为 fork 模式,这也是传统的 Unix 服务器采用的并发模式。之后的版本,改为基于 select() 的 I/O 多路复用 + fork 模式(参见源码 HTDaemon.c)。

+

NCSA HTTPd,是早期的第一个流行的 HTTP 服务器,在版本 1.3 以及之前版本,也是采用阻塞 I/O + fork 模式实现,会为每个客户端连接创建一个新的子进程(参见源码 httpd.c)。之后 NCSA HTTPd 的 1.4 版本,I/O 模型改造为基于 select() 的 I/O 多路复用,进程模型改为“pre-forking”模式,但这种模式本质上还是每个客户端连接对应单个子进程(process-per-connection),“pre-forking”的优点是在创建新客户端连接时有预先创建的子进程直接处理请求(类似进程池),避免在创建新连接的同时执行创建子进程这样的重型操作,具体可以参见 1996.03 的官方文档的对“pre-forking”模型的性能测试[8](相关的实现源码参见 httpd.c)。

+

Apache HTTP Server,最早在 1995.04 对外公开发布首个版本 0.6.2,这个版本的代码基于 NCSA httpd 1.3[9]。 之后在 5 月和 6 月,Apache 也开始实现“pre-forking”特性,在版本 0.8.0 开始正式支持[9:1][10]。一直到 Apache HTTP Server 2.2,prefork 模式依然是 Unix 系统下的默认模式[11]在 Apache 的 prefork 模式下,每个客户端连接由单独的子进程处理,这样的子进程被 Apache 称为 worker 进程,worker 进程数就是同时处理的客户端连接数。因为线程相对进程更加轻量,理论上每个客户端连接对应单个线程(thread-per-connection)更有优势。所以,在 2002.04,Apache 发布 2.0 的首个 GA 版本时,新增了 worker 模式,一种多进程和多线程混合的模式。在 Apache 的 worker 模式下,每个客户端连接由单独的子线程处理,这样的子线程也就是 worker 线程,worker 线程数就是同时处理的客户端连接数。

+

相对单线程,多进程或多线程的问题是,占用更多内存(每个线程都需要维护自己的线程栈),以及频繁的上下文切换。所以,有些 HTTP 服务器倾向于基于 select() 实现单进程单线程的网络服务器。这种模式实现的服务器一般会把循环调用 select() 的过程抽象为事件循环(event loop),把 I/O 操作就绪事件的处理抽象成回调函数(callback),所以也被称为事件驱动服务器(event-driven server)。多核 CPU 时,为了能充分使用 CPU 多核资源,事件驱动服务器的进程数(或线程数)通常为 CPU 核数。事件驱动模式,在软件架构中被也称为 Reactor 模式。基于事件并发和基于线程的并发的比较,可以阅读 John Ousterhout 的 1995 年的经典 slides:“Why Threads Are A Bad Idea (for most purposes)”[12]

+

早期的典型的基于 select() 实现的单线程 HTTP 服务器的例子,是由 ACME 实验室开发并开源的 thttpd(1995.11 对外发布 1.0 版)。thttpd 服务器作者 Jef Poskanzer 在文章“Web Server Comparisons”(1998.07)[13]中对比了各个 Web 服务器。根据文章的对比,容易发现基于 select() 实现的单线程服务器,在响应性能和最大并发连接数上都占优,thttpd 支持的最大的每秒请求数 QPS 是 720,thttpd 支持的最大并发连接数是 1000+。

+

虽然在实验条件下表现良好,但是在真实场景下,基于 select() 实现的 HTTP 单线程服务器,性能并没有优于传统的基于 fork 模式的服务器[14]。Banga 等人经过分析后得出的主要原因是,当服务器同时处理的客户端连接数超过几千后,系统调用 select()poll() 的性能很差,不具备可伸缩性。

+

最早的 HTTP 1.0 协议,在服务响应完成后连接会立即关闭,连接无法保持。HTTP 底层是 TCP 协议,建立 TCP 连接需要经过三次握手的过程。如果能复用 TCP 连接,同一个 HTTP 连接上的后续的 HTTP 请求就不用重新建立 TCP 连接,也就是能在同一个 HTTP 连接上支持多次 HTTP 请求和响应,这样 HTTP 性能也就得到了提高。于是,HTTP 1.1 协议(RFC 2068,1997.01)开始持久连接(persistent connection),默认让 HTTP 连接“keep-alive”。关于 HTTP 持久连接的详细介绍,可以参考 RFC 2068 的“8.1 Persistent Connections”。

+

HTTP 协议支持持久连接后,也带来了另外一个问题,就是出现大量的冷链接(cold connection)。浏览器如果未主动关闭连接,停留在网页上,并且如果连接未超时,此时的连接虽然不活跃但会保持一段时间,这样的连接就是冷链接。同时,随着互联网的快速发展,访问网站的用户量不断上升,Web 服务器需要维持的链接数也不断上升,如何让服务支持更多客户端连接问题也愈发尖锐。当时 Web 服务器支持的最大并发连接数大致是 1K,于是 Dan Kegel 在 1999 年提出了 C10k 问题,如何能让服务器支持 10K 的客户端连接,字母“C”代表的是“client connection”。在文章“The C10K problem”[15]中,Dan Kegel 对 C10K 问题的描述如下:

+
+

It's time for web servers to handle ten thousand clients simultaneously, don't you think? After all, the web is a big place now.

+
+

另外,值得一提的是,HTTP 1.0 和 HTTP 1.1 协议存在队头阻塞问题(HOL 阻塞,head of line blocking),为了避免队头阻塞,从而使网页能更快响应,大多数浏览器会为每个域名同时开启多个 HTTP 连接,通常是 6 个并发连接[16],结果导致 Web 服务器需要维持的链接数增加数倍。在发布 HTTP 1.1 协议的十几年后的 2012 年,HTTP 2.0 的首个草稿发布,而制定 HTTP/2 协议的最大的目标之一就是解决队头阻塞问题。

+

select 和 poll 性能问题

+

当 Web 服务器需要同时处理大量客户端连接时,服务器的性能表现差,原因就出在系统调用 select()poll() 的性能上,具体的问题有如下三点[17]

+
    +
  • 每次调用 select()poll(),内核都必须检查所有被指定的文件描述符,看它们是否处于就绪状态。随着待检查的文件描述符数量的增加,调用耗时也随之线性增加。若待检查的文件描述符数为 n,select()poll() 的时间复杂度为 O(n)。
  • +
  • 每次调用 select()poll(),程序都必须传递一个表示所有需要被检查的文件描述符的数据结构到内核,内核检查过描述符后,修改这个数据结构并返回给程序。(此外,对于 select() 来说,我们还必须在每次调用前初始化这个数据结构。)随着待检查的文件描述符数量的增加,传递给内核的数据结构大小也会随之增加。当检查大量文件描述符时,从用户空间到内核空间来回拷贝这个数据结构将占用大量的 CPU 时间。
  • +
  • select()poll() 调用完成后,程序必须检查返回的数据结构中的每个元素,以此查明哪个文件描述符处于就绪状态。
  • +
+

解决系统调用 select()poll() 的性能问题,让服务器能同时处理大量连接,比较典型的解决方案是,FreeBSD 4.1(2000.07 发布)开始支持的 kqueue 系统调用 ,以及 Linux 2.5.44(2002.10 发布)开始支持的 epoll 系统调用。

+

kqueue 和 epoll 系统调用

+

kqueue 相关的 API 主要涉及两个系统调用 kqueue()kevent()

+
    +
  • kqueue():用于在内核空间创建 kqueue 数据结构
  • +
  • kevent(): +
      +
    • 当传入其中的 changelist 等参数时,用于将感兴趣的 kevent 事件对象注册到 kqueuekevent 对象上记录感兴趣文件描述符和事件类型
    • +
    • 当传入其中的 eventlist 等参数时,用于查询就绪的 kevent 事件对象列表
    • +
    +
  • +
+

kqueue 的实现原理[18]:调用 kqueue() 创建由内核空间维护 kqueue 实例,kqueue 实例内包含链表,链表上保存全部监听的 kevent 事件对象,kevent 对象上感兴趣的记录文件描述符和事件类型。通过 kevent() 系统调用,可以在链表上注册、删除某 kevent 对象。当设备 I/O 事件触发时,设备与 kqueue 实例关联的钩子函数(hook)会被执行,钩子函数会判断事件是否与监听的事件相符合,如果符合就把事件添加到 kqueue 实例内下链表 active list 的末尾。查询就绪事件列表时,调用 kevent(),内核只需要检查链表 active list 是否有元素,若有就把就绪事件列表拷贝到用户空间。

+

epoll 相关的 API 主要涉及三个系统调用 epoll_create()epoll_ctl()epoll_wait()

+
    +
  • epoll_create():用于在内核空间创建 epoll 实例
  • +
  • epoll_ctl():用于添加感兴趣的 epoll_event 事件对象到 epoll 实例,epoll_event 对象上记录感兴趣文件描述符和事件类型
  • +
  • epoll_wait():用于查询就绪的 epoll_event 事件对象列表
  • +
+

epoll 的实现原理:调用 epoll_create() 创建由内核空间维护的 epoll 实例,epoll 实例内包含红黑树,红黑树上保存全部监听的 epoll_event 事件对象,epoll_event 对象上记录感兴趣的文件描述符和事件类型。通过 epoll_ctl() 系统调用,可以在红黑树上注册、删除某 epoll_event 对象。所有添加到红黑树中的事件都会与设备驱动程序建立回调关系,当 I/O 就绪事件触发时,会把事件添加到 epoll 实例内的链表 rdllist。查询就绪事件列表时,调用 epoll_wait(),内核只需要检查链表 rdllist 是否有元素,若有就把就绪事件列表拷贝到用户空间。

+

水平触发和边缘触发

+

epoll 系统调用的事件通知模式,区分水平触发(level-triggered,LT)和边缘触发(edge-triggered,ET),默认通知模式是水平触发 LT,EPOLLET 标志可以将通知模式改为边缘触发。poll()select() 所提供的通知模式是水平触发,不支持边缘触发。水平触发和边缘触发的通知模式的含义如下[17:1]

+
    +
  • 水平触发通知模式:如果文件描述符上可以非阻塞地执行 I/O 系统调用,此时认为它已经就绪。水平触发模式下,应用程序可以不立即处理该事件,当应用程序下一次调用 epoll_wait() 时,epoll_wait() 还会再次向应用程序通告此事件,直到该事件被处理。这种模式下 epoll 相当于一个效率较高的 poll。
  • +
  • 边缘触发通知模式:如果文件描述符自上次状态检查以来有了新的 I/O 事件,此时需要触发通知。也就是说,当 epoll_wait() 检测到某 I/O 事件发生并将此事件通知应用程序后,后续的 epoll_wait() 调用将不再向应用程序通知这一事件,只通知新的 I/O 事件。边缘触发模式在很大程度上降低了同一个 epoll 事件被重复触发的次数,因此效率要比水平触发模式高。但是相对水平触发,边缘触发模式下开发难度更大。
  • +
+

“水平触发”和“边缘触发”术语源于电子工程领域。水平触发是只要有状态发生就触发。边缘触发是只有在状态改变的时候才会发生。条件触发关心的是事件状态,边缘触发关心的是事件本身。

+

采用边缘触发通知的程序通常要按照如下规则来设计:

+
    +
  • 在接收到一个 I/O 事件通知后,程序在某个时刻应该在相应的文件描述符上尽可能多地执行 I/O(比如尽可能多地读取字节)。如果程序没这么做,那么就可能失去执行 I/O 的机会。
  • +
  • 如果尽可能多地执行 I/O,而文件描述符被设置为阻塞模式,那么最终当没有更多的 I/O 可执行时,I/O 系统调用就会阻塞。所以,每个被检查的文件描述符通常都应该设置为非阻塞模式。
  • +
+

另外,在边缘触发 ET 模式下,如果多个线程同时监听相同的描述符,只会有一个线程被唤醒用来处理 I/O 事件。epoll 的 man 文档对这个特性有如下描述,这个特性也避免了“惊群问题”(thundering herd problem)。

+
+

If multiple threads (or processes, if child processes have inherited the epoll file descriptor across fork(2)) are blocked in epoll_wait(2) waiting on the same epoll file descriptor and a file descriptor in the interest list that is marked for edge-triggered (EPOLLET) notification becomes ready, just one of the threads (or processes) is awoken from epoll_wait(2). This provides a useful optimization for avoiding "thundering herd" wake-ups in some scenarios.

+
+

因此,边缘触发通知模式其中一个适用的场景是,多核 CPU 上的多线程服务器,每个 CPU 核上运行一个线程,这些线程同时监听相同的描述符[19]

+

kqueue 文档没有使用水平触发和边缘触发术语。但接口效果上,默认是水平触发。开启EV_CLEAR标志可以达到类似边缘触发的效果。EV_CLEAR 标志的 man 文档描述:

+
+

After the event is retrieved by the user, its state is reset.

+
+

因为边缘触发通知模式效率更高,Nginx 服务器采用的就是边缘触发,参见源码 ngx_epoll_module.cngx_kqueue_module.c

+

select、poll、kqueue 和 epoll 的比较

+

selectpollkqueueepoll 系统调用的多个维度的对比总结,如下表:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
系统调用selectpollkqueueepoll
类 Unix 系统的支持情况POSIX 标准。最早 4.2BSD 提供(1983)POSIX 标准。最早 SVR3 提供(1987)BSD 专有。最早 FreeBSD 4.1 提供 (2000.08)Linux 专有。最早 Linux 2.5.44 提供(2002.10)
查询就绪描述符的时间复杂度O(n)O(n)O(1)O(1)
感兴趣描述符列表传递每次 select() 都全量拷贝到内核空间每次 poll() 都全量拷贝到内核空间由内核空间维护由内核空间维护
就绪描述符列表的返回只返回就绪描述符数量,需要检查感兴趣描述符列表来判断哪些是就绪描述符只返回就绪描述符数量,需要检查感兴趣描述符列表来判断哪些是就绪描述符返回就绪事件数量,并同时返回就绪事件列表返回就绪事件数量,并同时返回就绪事件列表
最大描述符数被常数 FD_SETSIZE 限制(值为 1024)无限制无限制无限制
触发通知模式水平水平水平和边缘水平和边缘
+

附注:查询就绪描述符的时间复杂度,selectpoll 都是 O(n),n 为感兴趣描述符的总数,因为内核实现上需要轮询全部感兴趣的描述符列表。kqueueepoll 都是 O(1),实际的查询耗时与就绪描述符总数线性有关,但真实场景下就绪描述符数量相对描述符总数很小,可以认为是常数,所以复杂度是 O(1)。

+

总体上,selectpoll 之间大同小异,而 kqueueepoll 之间也是大同小异。

+

libevent 库,对系统调用 selectpollkqueueepoll 做了性能基准测试,如下图所示(图片来源)。基准测试声明了大量连接(文件描述符),大多数连接是冷的,只有少数是活跃的。测试衡量的是,在不同的总连接数下,为 100 个活动连接提供服务所需的时间。可以看到,系统调用 selectpoll,随着文件描述符的增加,耗时也随之线性增加,2500 个文件描述符时耗时大约 20ms,5000 个文件描述符时耗时大约 40ms,10000 个文件描述符时耗时大约 80ms。而系统调用 kqueueepoll,耗时始终在 3ms ~ 5ms 之间。

+性能基准测试:select vs poll vs kqueue vs epoll +

echo 服务的简单示例代码

+

上文总结了 selectpollkqueueepoll 的接口特性和实现原理,但对具体应该如何使用这些函数没有切身感受。笔者使用 I/O 多路复用函数 select、poll、epoll 和 kqueue 以及 libevent 库,各自编写了 echo 服务的简单示例代码。所谓 echo 服务,即服务端接收到客户端的字符串输入,然后响应相同的字符串(为了方便区分响应字符串加了 > 前缀)。比如,如果客户端输入字符串 hello,服务端将响应字符串 > hello;如果客户端输入字符串 world,服务端将响应字符串 > world。完整的示例代码参见 io-multiplexing-demo

+

Nginx 服务器的并发策略解析

+

上文介绍了 NCSA HTTPd、Apache HTTP Server 和 thttpd 等 Web 服务器的并发策略。主要的并发策略有三种模式:单连接单进程模式、单连接单线程模式和单线程的事件驱动模式。

+

Nginx 最早是 2002 年开始开发的,2004.08 采用 BSD 协议对外开源首个版本 0.1.0,开发 Nginx 的目的是为了解决 C10k 问题[20]。2002 年,当时 FreeBSD 已经提供 kqueue 系统调用,而 Linux 的 epoll 即将正式发布,新的 kqueueepoll 系统调用让 Nginx 解决 C10k 问题成为可能。根据 w3techs 的统计,在 2013.07 Nginx 超越 Apache 成为 top 1000 网站使用最多的 Web 服务器[21]

+

Nginx 采用的是事件驱动架构,在单线程的进程上执行事件循环,以异步非阻塞的方式处理 I/O 操作事件,事件循环底层基于高效的 epollkqueue 实现的 I/O 多路复用[22]

+

Nginx 服务器,区分 Master 进程和 Worker 进程。Master 进程,用于加载配置文件、启动 Worker 进程和平滑升级等。Worker 进程,是单线程的进程,用于执行事件循环,并以非阻塞方式处理 I/O 操作,因此单个 Worker 进程就能并发处理大量连接。一个完整的请求完全由 Worker 进程来处理,而且只在一个 Worker 进程中处理。为了能充分利用多核 CPU 资源,通常生产环境配置的 Worker 进程数量等于 CPU 核心数。Nginx 的架构图如下[22:1]

+Nginx 架构图 +

Redis 服务器的并发策略解析

+

Redis 是内存数据库,处理网络请求也是采用单线程的事件驱动模式,底层基于高效的 epollkqueue 实现的 I/O 多路复用。事件循环处理的事件主要有,建立客户端新连接事件、客户端连接的缓冲区可读事件、客户端连接的缓冲区可写事件。Redis 的命令处理过程如下:

+
    +
  • 在收到建立客户端新连接事件后,会在新建立的客户端套接字上监听可读事件,用于等待客户端发起命令请求。客户端连接可能会一直保持,处理之后的多个客户端命令请求。
  • +
  • 如果监听到客户端连接的缓冲区可读事件,也就是收到客户端的命令请求,服务器会读取命令、解析命令,然后执行命令,最后把命令响应结果输出到内存缓冲区。值得注意的是,命令响应结果输出到内存缓冲区,但并未输出客户端连接的缓冲区。
  • +
  • 在等到开启新的事件循环时,Redis 会在等待接收新的 I/O 事件之前,统一将全部内存缓冲区的命令响应结果输出到各个客户端。当命令响应结果数据量非常大时,无法一次性将所有数据都发送给某客户端,这时就会监听该客户端缓冲区可写事件。
  • +
  • 如果监听到客户端连接的缓冲区可写事件,Redis 就会发送剩余部分的数据给客户端。
  • +
+

上述的命令处理过程,在源码层面上涉及的核心代码都在 networking.c 中:处理客户端新连接建立的事件的回调函数是 acceptTcpHandler,处理客户端命令请求事件的回调函数 readQueryFromClient,命令响应结果输出到各个客户端对应的函数是 handleClientsWithPendingWrites,处理客户端的可写事件的回调函数是 sendReplyToClient。更详细的实现原理解析,本文不再展开,可以自行深入阅读相关源代码或书籍资料。

+

Redis 与 Nginx 在并发策略上有不同的选择,Nginx 有多个 Worker 进程,每个 Worker 进程都运行自己的事件循环,而 Redis 整体上只有一个事件循环,采用的是单线程架构。这样的架构设计带来的问题就是 Redis 无法多核 CPU 并发。针对无法多核 CPU 并发问题,Redis 官方 FAQ 的推荐的解决方案是[23]:在多核 CPU 的单台机器上启动多个 Redis 实例。Redis 作者 antirez,解释了选择单线程而不选择多线程的原因,主要是:在 Redis 的数据结构上实现并发控制太复杂,多线程编程降低开发速度并且导致 bug 修复困难[24][25]。采用单线程的原因,概况成一句话就是[25:1]

+
+

There is less to gain, and a lot of complexity to add.

+
+

不过,随着 Redis 版本的演进,部分逻辑已经改成了多线程实现,Redis 新增的多线程特性有三处,Redis 2.4 新增的异步磁盘 IO、Redis 4.0 新增的“Lazy Freeing”和 Redis 6.0 新增的“Threaded I/O”。但整体设计上,还是可以认为 Redis 主要使用单线程设计,依然是单线程的事件循环,并以单线程的方式执行命令(绝大多数命令,“Lazy Freeing”相关的命令除外)[26][27]

+

参考资料

+
+
+
    +
  1. FreeBSD操作系统设计与实现,McKusick,2004:6.4.5 描述符上的多路I/O操作 ↩︎ ↩︎

    +
  2. +
  3. Unix网络编程 卷1:套接字联网API,Stevens,第3版2003 ↩︎ ↩︎ ↩︎

    +
  4. +
  5. 2014-04 AIO User Guide: A description of how to use AIO https://web.archive.org/web/0/http://code.google.com/p/kernel/wiki/AIOUserGuide ↩︎

    +
  6. +
  7. Awesome io_uring https://github.com/espoal/awesome-iouring ↩︎

    +
  8. +
  9. 2006-08 M. Jones: Boost application performance using asynchronous I/O https://developer.ibm.com/articles/l-async/ ↩︎ ↩︎

    +
  10. +
  11. Learning Libevent: A tiny introduction to asynchronous IO https://libevent.org/libevent-book/01_intro.html ↩︎

    +
  12. +
  13. Node.js: JavaScript Asynchronous Programming and Callbacks https://nodejs.dev/en/learn/javascript-asynchronous-programming-and-callbacks/ ↩︎

    +
  14. +
  15. 1995-04 NCSA httpd: Performance of Several HTTP Demons on an HP 735 Workstation https://web.archive.org/web/0/http://www.ncsa.uiuc.edu/InformationServers/Performance/V1.4/report.html ↩︎

    +
  16. +
  17. About the Apache HTTP Server Project https://httpd.apache.org/ABOUT_APACHE.html ↩︎ ↩︎

    +
  18. +
  19. Changes with Apache (12 Jun 1995: This release included modified versions of a lot of code from the Apache 0.6.4 public release, plus an early pre-forking patch codeveloped by Robert Thau and Rob Hartill.) https://github.com/apache/httpd/blob/1.3.x/src/CHANGES#L9427 ↩︎

    +
  20. +
  21. Apache HTTP Server Version 2.2: Multi-Processing Modules (MPMs) https://httpd.apache.org/docs/2.2/en/mpm.html#defaults ↩︎

    +
  22. +
  23. 1995 John Ousterhout: Why Threads Are A Bad Idea (for most purposes) (slides) http://www.cc.gatech.edu/classes/AY2010/cs4210_fall/papers/ousterhout-threads.pdf ↩︎

    +
  24. +
  25. 1998-07 Jef Poskanzer: Web Server Comparisons(thttpd 服务器作者) http://www.acme.com/software/thttpd/benchmarks.html ↩︎

    +
  26. +
  27. 1998 Gaurav Banga, Jeffrey C. Mogul: Scalable Kernel Performance for Internet Servers Under Realistic Loads. USENIX Annual Technical Conference 1998 dblp usenix.org ↩︎

    +
  28. +
  29. 1999-05 Dan Kegel: The C10K problem(最后更新时间 2011.07) http://www.kegel.com/c10k.html ↩︎

    +
  30. +
  31. 2014-02 详解浏览器最大并发连接数 https://web.archive.org/web/0/http://www.iefans.net/liulanqi-zuida-bingfa-lianjieshu ↩︎

    +
  32. +
  33. Linux Unix系统编程手册,Kerrisk 下册:第63章 其他备选的I/O模型 ↩︎ ↩︎

    +
  34. +
  35. 2001 Jonathan Lemon: Kqueue - A Generic and Scalable Event Notification Facility. USENIX Annual Technical Conference 2001 dblp usenix.org ↩︎

    +
  36. +
  37. What is the purpose of epoll's edge triggered option? https://stackoverflow.com/a/73540436/689699 ↩︎

    +
  38. +
  39. 2012-01 Interview with Igor Sysoev, author of Apache's competitor NGINX https://web.archive.org/web/0/http://www.freesoftwaremagazine.com/articles/interview_igor_sysoev_author_apaches_competitor_nginx ↩︎

    +
  40. +
  41. 2013-07 Nginx just became the most used web server among the top 1000 websites https://w3techs.com/blog/entry/nginx_just_became_the_most_used_web_server_among_the_top_1000_websites ↩︎

    +
  42. +
  43. 2012-03 AOSA Volume 2 - nginx (Andrew Alexeev) https://aosabook.org/en/v2/nginx.html ↩︎ ↩︎

    +
  44. +
  45. Redis FAQ: How can Redis use multiple CPUs or cores? https://redis.io/docs/getting-started/faq/#how-can-redis-use-multiple-cpus-or-cores ↩︎

    +
  46. +
  47. 2010-09 antirez: An update on the Memcached/Redis benchmark http://oldblog.antirez.com/post/update-on-memcached-redis-benchmark.html ↩︎

    +
  48. +
  49. 2019-02 antirez: An update about Redis developments in 2019 http://antirez.com/news/126 ↩︎ ↩︎

    +
  50. +
  51. Redis Doc: Diagnosing latency issues: Single threaded nature of Redis https://redis.io/docs/management/optimization/latency/#single-threaded-nature-of-redis ↩︎

    +
  52. +
  53. 2019-08 林添毅:正式支持多线程!Redis 6.0与老版性能对比评测 https://mp.weixin.qq.com/s/6WQNq5dNk-GuEhZXtVCo-A ↩︎

    +
  54. +
+
+ +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2023/11/amazon-architecture-evolution/index.html b/2023/11/amazon-architecture-evolution/index.html new file mode 100644 index 00000000..a1c631d2 --- /dev/null +++ b/2023/11/amazon-architecture-evolution/index.html @@ -0,0 +1,753 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 亚马逊网站架构演进 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ 亚马逊网站架构演进 +

+ + +
+ + + + +
+ + +

SOA 与微服务

+

Amazon,1994 年创立,早期网站是单服务、单数据库的单体架构的系统[1][2][3],全部代码由 C++ 编写,编译成单个二进制文件,整个代码仓库被命名为 Obidos。Obidos 是底层是一个 Web 页面渲染引擎,是一个框架,业务逻辑基于这个框架开发,Obidos 渲染引擎和业务逻辑共同组成整个代码仓库。随着时间的推移,Obidos 变得越来越复杂,编译 Obidos 整个代码库耗时 12 小时,开发调试效率低下[2:1]。另外,全部业务逻辑在单个二进制文件中,导致紧耦合,新功能特性无法快速发布上线。1995 年,Amazon 网站的技术架构,如下图所示[3:1]

+ +Amazon 网站技术架构(1995) +

到 2000 年,为了应对流量增长,解决网站的可扩展性问题,开始拆分 Obidos,向可扩展的 SOA 架构演进。拆分出的服务有,用户服务(customer service)、订单服务(order service)、商品服务(item service)等,并且每个服务都拥有各自独立的数据库。2005 年 1 月,Amazon 网站开始从 Obidos 引擎迁移到 Gurupa 引擎。Gurupa 是一个 Web 页面渲染引擎,同时也是一个 SOA 框架,Gurupa 被用于集成背后的数百个服务,使用 Perl 的 Mason 模板将各个服务响应的数据渲染成 Web 页面。到 2006 年完成了到 Gurupa 的全部迁移[4]

+

Amazon 网站技术架构演进过程,如下图所示[2:2]

+Amazon 网站技术架构演进 +

需要注意的是,图中认为从 2006 年开始 Amazon 网站架构从 SOA 演进为微服务,但是事实上,“微服务”这个术语诞生的时间是 2012 年。2006 年的架构实现与之前的 SOA 架构实现的不同点是,开始更细粒度的服务拆分。

+

本质上来看,微服务架构是一种特殊的 SOA 架构,在“微服务”术语诞生之前,亚马逊的 SOA 架构实现被认为是“SOA done right”(正确实现的 SOA)[5]。Netflix 的 SOA 架构实现也在“微服务”术语诞生之前,Netflix 认为自己实现架构的是“fine-grained SOA”(细粒度的 SOA)[6]。James Lewis 和 Martin Fowler 等人是“微服务”概念的早期提倡者,他们将亚马逊和 Netflix 的 SOA 架构实现归类为微服务的经典案例[7]。所以,SOA 和微服务的关系可以简单理解为,微服务是“fine-grained SOA”或“SOA done right”。

+

根据 Martin Fowler 的解释[8],SOA 与微服务的关系,如下图所示:

+SOA 与微服务的关系 +

在 SOA 架构的具体实践上,根据前亚马逊工程师 Steve Yegge 的 2011 年的文章[9][10],在 2002 年左右,亚马逊创始人兼 CEO Jeff Bezos 向全公司发布了一道指令(这个指令被外界称为“API Mandate”),具体内容如下:

+
+
    +
  1. 从今天起,所有的团队都要以服务接口的方式提供数据和各种功能。
  2. +
  3. 团队之间必须通过接口来通信。
  4. +
  5. 不允许任何其他形式的互操作:不允许直接链接,不允许直接读其他团队的数据,不允许共享内存,不允许任何形式的后门。唯一许可的通信方式就是通过网络调用服务。
  6. +
  7. 至于具体的技术则不做规定。HTTP、Corba、Pubsub、自定义协议都可以。贝索斯不关心这个。
  8. +
  9. 所有的服务接口,必须从一开始就要以可以公开为设计导向,没有例外。这就是说,团队必须在设计的时候就计划好,接口要可以对外面的开发人员开放。没有讨价还价的余地。
  10. +
  11. 不听话的人会被炒鱿鱼。
  12. +
+
+

技术栈演进

+

Amazon 网站的技术栈演进过程[2:3][4:1][11]

+
    +
  • 1995 ~ 2000:单体架构,Unix(Sun)、Obidos、Oracle、C++ +
      +
    • Obidos 是亚马逊内部 Web 动态页面渲染引擎,编程语言是 C++。
    • +
    +
  • +
  • 2000 ~ 2006:SOA 架构,Linux、Obidos、Oracle、C++ +
      +
    • 2000 年,将 Sun/Unix 服务器替换为 HP/Linux 服务器[12]
    • +
    • 2000 年,开始拆分应用服务,向 SOA 架构演进。
    • +
    • 2005 年初,开始将 Obidos 框架替换为 Gurupa 框架,Gurupa 是 Web 页面渲染引擎,同时也是 SOA 框架。Web 动态页面的编程语言从 C++ 替换为 Perl/Mason,同时应用服务开始被更细粒度的拆分。
    • +
    +
  • +
  • 2006 年开始:微服务架构,Linux、Gurupa、Oracle、Perl & Java & C++ +
      +
    • 2019.10,彻底去掉 Oracle 数据库,迁移到 Amazon RDS 和 NoSQL[13]
    • +
    +
  • +
+

当前 Amazon 网站的主要技术栈:

+
    +
  • 应用服务[4:2][11:1]: +
      +
    • 展示层:Perl/Mason[14]
    • +
    • 业务逻辑层:Java(主要)、C++ 等
    • +
    • RPC框架:Gurupa 框架(自研闭源) +
        +
      • 2006 年更早之前使用 Obidos 框架
      • +
      +
    • +
    • 消息队列MQAmazon SQS
    • +
    +
  • +
  • 数据存储[13:1]: +
      +
    • 关系数据库:Amazon RDS for PostgreSQL[15]、Amazon Aurora (PostgreSQL) +
        +
      • 2019 年 10 月彻底去掉 Oracle 数据库,迁移到 Amazon RDS 和 NoSQL。
      • +
      +
    • +
    • 键值存储Amazon DynamoDB
    • +
    • 缓存:Amazon ElastiCache for Redis[16]
    • +
    • Blob文件存储Amazon S3
    • +
    +
  • +
+

AWS 的诞生

+

Amazon 网站架构演进的过程,伴随着 AWS 云服务的诞生,促使 AWS 云服务诞生的因素主要有[17][18]

+
    +
  • 技术价值:Amazon 网站在向可扩展架构演进的过程中,其基础设施团队开始善于运营像计算、存储和数据库这样的基础设施,团队已经变得能非常熟练地运营可靠的、可扩展的、具有成本效益的数据中心,这些专业能力推动了亚马逊电商平台的发展。将维护可靠、可扩展的基础设施专业能力通过服务的方式对外交付,能有效节省第三方企业或初创公司的成本,当时亚马逊预计基础设施的成本可能会从 70% 降低至 30% 或更低[19]
  • +
  • 原始动机:Amazon 网站的流量有很强的季节性,每年 11 月和 12 月(尤其是在感恩节和圣诞节前后)流量都会飙升。为了应对购物季,不得不扩容,增加服务器资源。在购物季结束后,服务器资源被大量闲置。零售电商的利润很薄,却要面对数据中心基础设施不断扩展所带来的成本压力。所以,很多人(包括部分亚马逊员工)[20][21]认为推出 AWS 产品的一个重要原因是为了出租 SOA 网站在销售淡季时的过剩服务器容量。不过,出租过剩容量的故事是一个神话,因为不可能在每年购物季时把开发商从服务器里踢出去,而且实际上在推出 EC2 云服务后的 2 个月内,AWS 就已经烧掉了过剩的 Amazon 网站容量[19:1]
  • +
  • 商业理念Jeff Bezos,将亚马逊定位为一家技术公司,而不仅仅是一家在线零售商,所以在亚马逊的核心业务之外进行很多投资尝试,AWS 产品就是其中之一[17:1]
  • +
+

于是,在 2003 年亚马逊团队内部逐渐开始形成销售基础设施服务的设想。2003 年 9 月[22]Andy Jassy 写了 6 页纸的关于 AWS 的愿景文档(vision document)并提交给管理团队,愿景文档中提议了设想的 AWS 业务,并概述了 AWS 提供的初始的基础设施服务集,首批提供的服务包括存储、计算和数据库等。同年,Jassy 组建了由 57 人组成的 AWS 团队,AWS 团队的 CEO 由 Jassy 担任(Jassy 担任 AWS CEO 一直到 2021 年,2021 年 7 月开始任职亚马逊 CEO)。三年之后,2006 年 3 月 AWS 对外发布 S3 云存储,8 月对外发布 EC2 弹性云计算服务器,S3 和 EC2 是行业内最早的云服务产品。S3 发布的刚开始几个月,并没有引起太大的关注。EC2 发布后,大量开发商开始飞速涌入。在没有其他类似云服务产品最初几年,几乎每一家创业公司都在亚马逊的服务器上构建自己的系统。能吸引大量开发商的原因主要是,按需使用和收费的商业模式,以及亚马逊故意压力利润的价格策略[17:2]

+

迁移到 AWS

+

2011 年 11 月,Amazon 网站全部都迁移到了 AWS 云服务器上[23]。迁移到 AWS 上最大的动机是能利用 AWS 云服务器的弹性伸缩能力,从而节省成本。如果没有弹性伸缩能力,在淡季时,总体上服务器资源容量的利用率是 61%,无法有效利用的容量是 39%,到购物季的 11 月,无法有效利用的容量高到 76%。引入弹性伸缩技术后,可以按网站的实际流量负载情况,供应恰当的容量,避免资源浪费。Amazon 网站在淡季和购物季时的静态伸缩与弹性伸缩,如下图所示[23:1][24]

+Amazon 网站的典型的周流量分布 +Amazon 网站的静态伸缩 +Amazon 网站的弹性伸缩 +

参考资料

+
+
+
    +
  1. 2006-05 ACM Queue Interview: A Conversation with Amazon CTO Werner Vogels https://queue.acm.org/detail.cfm?id=1142065 ↩︎

    +
  2. +
  3. 2021-02 Amazon’s architecture evolution and AWS strategy (AWS re:Invent 2020) https://www.youtube.com/watch?v=HtWKZSLLYTE ↩︎ ↩︎ ↩︎ ↩︎

    +
  4. +
  5. 2022-11 Reliable scalability: How Amazon scales in the cloud (AWS re:Invent 2022) https://www.youtube.com/watch?v=_AhfV5LZmvo ↩︎ ↩︎

    +
  6. +
  7. 2011-04 Charlie Cheever: How did Google, Amazon, and the like initially develop and code their websites, databases, etc.? https://qr.ae/pKKyB0 ↩︎ ↩︎ ↩︎

    +
  8. +
  9. 2007-06 SOA done right: the Amazon strategy https://www.zdnet.com/article/soa-done-right-the-amazon-strategy/ ↩︎

    +
  10. +
  11. 2011-05 How the cloud helps Netflix (interview Adrian Cockcroft) http://radar.oreilly.com/2011/05/netflix-cloud.html ↩︎

    +
  12. +
  13. 2014-03 James Lewis & Martin Fowler: Microservices https://martinfowler.com/articles/microservices.html ↩︎

    +
  14. +
  15. 2014-11 Microservices • Martin Fowler • GOTO 2014 https://youtu.be/wgdBVIX9ifA?t=880 ↩︎

    +
  16. +
  17. 2011-10 Steve's Google Platform rant https://gist.github.com/chitchcock/1281611 ↩︎

    +
  18. +
  19. 2016-09 亚马逊如何变成 SOA(面向服务的架构)?(摘录自Steve Yegg的《程序员的呐喊》) https://www.ruanyifeng.com/blog/2016/09/how_amazon_take_soa.html ↩︎

    +
  20. +
  21. What programming languages are used at Amazon? https://qr.ae/pKFwnw ↩︎ ↩︎

    +
  22. +
  23. 2001-10 How Linux saved Amazon millions https://web.archive.org/web/0/http://news.com.com/2100-1001-275155.html ↩︎

    +
  24. +
  25. 2019-10 Migration Complete – Amazon’s Consumer Business Just Turned off its Final Oracle Database https://aws.Amazon/blogs/aws/migration-complete-amazons-consumer-business-just-turned-off-its-final-oracle-database/?nc1=h_ls ↩︎ ↩︎

    +
  26. +
  27. 2016-04 Is Amazon still using Perl Mason to render its content? https://qr.ae/pKFwFm ↩︎

    +
  28. +
  29. Amazon RDS for PostgreSQL customers https://aws.Amazon/rds/postgresql/customers/?nc1=h_ls ↩︎

    +
  30. +
  31. Amazon ElastiCache for Redis customers https://aws.Amazon/elasticache/redis/customers/?nc1=h_ls ↩︎

    +
  32. +
  33. 一网打尽:贝佐斯与亚马逊时代,Brad Stone,2013,豆瓣:第7章 一家技术公司,而非零售商 ↩︎ ↩︎ ↩︎

    +
  34. +
  35. 2016-07 AWS CEO Andy Jassy: How AWS came to be https://techcrunch.com/2016/07/02/andy-jassys-brief-history-of-the-genesis-of-aws/ ↩︎

    +
  36. +
  37. 2011-01 Amazon CTO Werner Vogels: How and why did Amazon get into the cloud computing business? https://qr.ae/pKscWd ↩︎ ↩︎

    +
  38. +
  39. 2016-07 前亚马逊员工在 Reddit 上对文章“How AWS came to be”的评论 https://www.reddit.com/r/programming/comments/4qxthq/comment/d4wrnk7/ ↩︎

    +
  40. +
  41. 2021-01 前亚马逊员工 Dan Rose:全球最大云厂商AWS是如何诞生的? https://mp.weixin.qq.com/s/C7Mqeh1hyT6k5BQOzpWL9w ↩︎

    +
  42. +
  43. 2013-11 Andy Jassy's Book Review of "The Everything Store" https://www.Amazon/review/R1Q4CQQV1ALSN0/ ↩︎

    +
  44. +
  45. 2011-07 2011 AWS Tour Australia, Closing Keynote: How Amazon migrated to AWS, by Jon Jenkins https://www.slideshare.net/AmazonWebServices/2011-aws-tour-australia-closing-keynote-how-amazoncom-migrated-to-aws-by-jon-jenkins ↩︎ ↩︎

    +
  46. +
  47. 2017-03 AWS: Elasticity and Management https://www.slideshare.net/AmazonWebServices/elasticity-and-management ↩︎

    +
  48. +
+
+ +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2023/11/reliability-engineering/index.html b/2023/11/reliability-engineering/index.html new file mode 100644 index 00000000..a61fe8e6 --- /dev/null +++ b/2023/11/reliability-engineering/index.html @@ -0,0 +1,849 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 可靠性工程概述 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ 可靠性工程概述 +

+ + +
+ + + + +
+ + +

为了应对负载的增长,目前大型网站普遍都采用分布式架构。相对于采用单体架构的系统,分布式系统中有大量的服务器及设备,各模块之间存在错综复杂的依赖关系,存在更多的不确定性。整个系统的故障率会随设备的增加而呈指数级增加,单一节点问题可能会被无限放大,日常运行过程中一定会伴随故障发生。所以,可靠性开始成为大型网站关注的最重要的质量属性之一,并因此发展出了站点可靠性工程(Site reliability engineering,SRE)。站点可靠性工程,是从可靠性工程发展而来的,从可靠性工程中借鉴了概念和成果。本文溯本求源,内容主要是总结概括,可靠性工程的历史演进和核心概念,软件可靠性工程的核心概念,以及可靠性设计的方法。

+ +

历史演进

+

可靠性工程起源于第二次世界大战[1]。“二战”期间,美国 60% 的机载电子设备运到远东后不能使用,50% 的电子设备在存储期间失效。经过分析,发现这些电子设备故障的主要原因是电子管的可靠性太差,为此美国在 1943 年成立电子管研究委员会,在 1952 年美国国防部成立一个由军方、工业部门及学术界组成的小组,名为“电子设备可靠性咨询小组”(AGREE,Advisory Group on the Reliability of Electronic Equipment)。1957 年 6 月,AGREE 小组出版报告《军用电子设备可靠性》(Reliability of Military Electronic Equipment),该报告是公认的可靠性工程的奠基性文件,研究报告提出一整套可靠性设计、试验和管理方法,确立了可靠性工程发展方向,标志着可靠性工程学科诞生。此后,它不断向工业和民用产品领域渗透,20 世纪 60 年代推广到核工业, 70 年代在化学工业普及,并陆续扩散到其他工程领域。

+

随着可靠性工程学科的发展演进,围绕故障展开,逐渐衍生出对产品的维修性(maintainability)、可用性(availability)、保障性(supportability)、测试性(testability)、安全性(safety)等质量特性的工程学研究。“维修性工程”和“安全性工程”是从“可靠性工程”中分离出来的,而“保障性工程”和“测试性工程”又是从“维修性工程”中独立出来的。新的 XX 性陆续分出,因为这些特性紧密相关,已经分出的 XX 性围绕可靠性又重新集成起来,在 20 世纪 80 年代呈现综合化发展趋势。可靠性的含义不断扩展,从狭义可靠性演变为广义可靠性,从狭义可靠性工程演变为广义可靠性工程。

+

1980 年代初期,为了避免因为扩展可靠性固有的含义引发的可靠性定性含义和可靠性的定量含义之间的理解混乱,Jean-Claude Laprie 选择“可信性”(dependability)作为术语,根据国际电工委员会标准,可信性的定义是,用以描述可用性及其影响因素(可靠性、维修性和维修保障性)的集合性术语,可信性仅用于非定量术语的一般描述。某些情况下,可信性还包含耐久性(durability)、安全性(safety)、安全保密性(security)等其他特性。可信性可以理解为广义可靠性

+

当今在国际上有两个比较完整的可靠性标准化体系,一个是美国军用标准(MIL-STD),另一个是国际电工委员会(IEC)标准。美国军用标准多年来一直扮演着研究开发可靠性相关标准文件的带头角色,也是最早制定可靠性标准的。最早的可靠性定义是由美国 AGREE 在 1957 年的报告中提出的,1966 年美国的 MIL-STD-721B 又给出了传统的或经典的可靠性定义,即产品在规定的条件下和规定的时间内完成规定功能的能力。最主要的可靠性国际标准组织是国际电工委员会的 TC56 技术委员会,TC56 的发展时间线[2]

+
    +
  • 1965,国际电工委员会 IEC 成立名为“电子元件和设备可靠性”(Reliability of Electronic Components and Equipment)的技术委员会,即 TC56。
  • +
  • 1973,TC56 更名为“可靠性与维修性”(Reliability and Maintainability)技术委员会。
  • +
  • 1985,TC56 技术委员会成立了软件可靠性工作组,开始制定软件可靠性和维修性标准。
  • +
  • 1989,TC56 更名为“可信性”(Dependability)技术委员会,此名称一直沿用至今。
  • +
  • 1990,TC56 在与国际标准化组织(ISO)协商后,工作范围应不再局限于电工技术领域,而是解决所有学科的通用可靠性问题,从而使 IEC/TC56 成为所谓的横向委员会。
  • +
+

我国与 IEC/TC56 对口的专业技术标准化组织是,TC24 全国电工电子产品可靠性与维修性标准化技术委员会(简称“可标委”),成立于 1982 年,挂靠在工业和信息化部电子第五研究所(又名中国电子产品可靠性与环境试验研究所)。

+

可信性与质量六性

+

除了上文的“可信性”集合性术语外,有些资料将广义可靠性解释为,“可用性 + 可靠性 + 维修性”,这三个质量特性也被缩写为 RAM。RAM 有时候会再加上安全性(Safety),被缩写为 RAMS。使用 RAMS 缩写的典型例子是国际电工委员会的 IEC 62278:2002 标准(等同的国家标准 GB/T 21562-2008)。

+

另外,常见的可靠性相关的缩写是 RMS 和 RMTSS。RMS 代表可靠性、维修性、保障性,或称“三性”。RMTSS 代表可靠性、维修性、测试性、保障性、安全性,或称“五性”。质量“三性”或“五性”,也是我国军用武器装备的军用标准要求的通用质量特性。我国武器装备的军用标准学习和借鉴的是美国军用标准,军用装备的质量特性分为专用质量特性和通用质量特性。专用质量特性,反映的是不同系统或者装备自身的特点和个性特征,主要指的是功能和性能,如某型飞机的最大(最小)飞行速度、巡航速度、飞行高度等指标。通用质量特性,则表征不同装备的共性特征。通用质量特性是逐渐演变的,从一开始的“二性”演变为“六性”[3][4],通用质量特性包含的特性如下:

+
    +
  • 二性:可靠性、维修性(也缩写为 R&M)
  • +
  • 三性:可靠性、维修性、保障性(也缩写为 RMS)
  • +
  • 五性:可靠性、维修性、测试性、保障性、安全性(也缩写为 RMTSS)
  • +
  • 六性:可靠性、维修性、保障性、测试性、安全性、环境适应性
  • +
+

通用质量特性与可信性的含义大体上相同。质量特性、可信性、可靠性的关系,如下图所示:

+质量特性、可信性、可靠性的关系 +

根据国际电工委员会 IEC 60050 (191):1990(等同的国家标准 GB/T 3187-1994 《可靠性、维修性术语》)、IEC 60050-192:2015(等同于 GB/T 2900.99-2016 《电工术语 可信性》)以及国家军用标准 GJB 451A-2005 《可靠性维修性保障性术语》(与美国军用标准 MIL-STD-721C 相似)等标准文档,相关特性的定义和度量指标如下:

+
    +
  • 可信性(dependability:用以描述可用性及其影响因索(可靠性、维修性和维修保障性)的集合性术语。可信性仅用于非定量术语的一般描述。
  • +
  • 可靠性(reliability:在给定的条件,给定的时间区间,能无故障地执行要求的能力。可靠性一般用可靠度(reliability)、平均故障间隔时间(MTBF)、使用寿命(useful life)等参数来度量。
  • +
  • 可用性(availability:在所要求的外部资源得到提供的情况下,产品在给定的条件下,在给定的时刻或时间区间内处于能完成要求的功能的状态的能力。此能力是产品的可靠性、维修性和维修保障性的综合反映。可用性的度量指标称为可用度(availability),表示为平均可用时间同平均可用时间与平均不可用时间的和之比。
  • +
  • 维修性(maintainability:在给定的条件下,使用所述的程序和资源实施维修时,产品在给定的使用条件下保持或恢复能完成要求的功能的状态的能力。维修性反映产品修理的难易程度,主要使用平均修复时间(MTTR)来度量。
  • +
  • 保障性(supportability:在规定的运行剖面和给定的后勤与维修资源下,保防能维待要求的可用性的能力。维修保障(maintenance support),是维修产品的资源的供给,资源包括人力资源、保障设备、材料和备件、维修设施、文档和信息以及维修信息系统。保障性一般用平均保障延误时间、资源满足率、资源利用率等参数来度量。
  • +
  • 测试性(testability):是指产品能及时并准确地确定其状态(可工作、不可工作或性能下降),并隔离其内部故障的能力。测试性反映产品是否易于测试、出现故障时是否易于检测和隔离,一般用检测时间、技术准备时间、故障检测率、故障隔离率等参数来度量。
  • +
  • 安全性(safety):是指产品所具有的不导致人员伤亡、系统毁坏、重大财产损失或不危及人员健康和环境的能力。安全性可理解为产品在任何情况下对人员、系统、财产和环境都不构成安全威胁。它可定义为产品在规定的条件下和规定的时间内,以可接受的风险执行规定功能的能力。安全性一般用事故概率、损失率、安全可靠度等参数来度量。
  • +
  • 环境适应性(environmental worthiness):是指产品在其寿命期内预计可能遇到的各种环境作用下能实现其所有预定功能、性能和(或)不被破坏的能力。它反映了产品对各种环境的适应能力,即在其可能遇到的各种环境下均能正常工作的能力,是可靠性的一种特殊情况。环境适应性鉴定试验通过的判定准则是,在所有试验条件下“零故障”。
  • +
+

通用质量特性的“六性”之间是紧密联系的[4:1][5]

+
    +
  • 维修性是对可靠性的补充,如果产品不发生故障就不需要修复性维修。
  • +
  • 可用性是产品的可靠性、维修性和维修保障性的综合反映。
  • +
  • 保障性为产品正常使用与维修提供外部资源的支持,提供使用保障和维修保障,可靠性和维修性依赖于保障性。
  • +
  • 测试性是维修性的基础,维修依赖于测试,产品要修理一定要先发现故障和隔离故障,所以测试性设计得好,维修时间就可大大缩短。
  • +
  • 安全性本是可靠性的一部分,是避免人员伤亡、健康损害、财产或环境损害风险的可靠性。可靠性是安全性的基础,很多安全性问题都是因为产品不可靠造成的,所以提高产品可靠性也能提高安全性,当然并非所有安全性问题都是不可靠引起的。
  • +
  • 环境适应性是可靠性的一种特殊情况,是可靠性研究的前提,研究可靠性首先要确定产品是否有足够的环境适应性。
  • +
+

通用质量特性的“六性”工作围绕故障(failure)而展开,也被人称为“故障六性”[6][4:2]。可靠性的目标是减少故障;维修性的目标是修复故障;测试性的目标是检测故障;保障性保证出现故障时可以快速供应维修资源;安全性旨在出现故障以后降低风险;环境适应性鉴定试验通过的判定准则是,在所有试验条件下“零故障”[5:1]

+故障六性 +

可靠性是产品质量特性之一,是一种面向时间的质量特性(time oriented quality characteristic)[7]。Lloyd Condra 在书中对可靠性和质量的关系的解释是,“可靠性是质量随着时间的变化(reliability is quality over time)”,“为了衡量产品的质量水平,我们对现在的产品进行评判,而为了度量产品的可靠性水平,则要对产品未来会是什么样子进行评判”。这里的讨论的质量其实指的是符合性质量,质量管理一开始是从符合性质量开始的,质量管理的主要工作是质量检验(Quality Inspection),检测产品是否符合规格,质量检验的结果即合格品率。质量管理的关注焦点是产品的合格品率,而可靠性关注焦点是产品在用户使用过程中合格水平随着时间的保持能力,如下图所示 [5:2]

+质量与可靠性关系示意图 +

故障与失效的区别

+

可靠性工程中有两个基本而重要的术语“fault”和“failure”。在我国的可靠性标准文档中,把“fault”翻译为“故障”,把“failure”翻译为“失效”或“故障”,也就是说,“失效”对应的英文只有“failure”;而“故障”对应的英文是“fault”或“failure”[8][9]

+

我国第一个定义可靠性相关的常用术语的国家标准是 GB 3187-1982 《可靠性基本名词术语及定义》,该标准对英文术语“failure”的中文翻译是“失效”或“故障”,并把“mean time between failures”翻译是“平均无故障时间”:[8:1]

+
+

2.2.1 失效(故障) failure:产品丧失规定的功能。对可修复产品通常也称故障。
+2.5.5 平均寿命(平均无故障时间) mean life (mean time between failures):寿命(无故障时间)的平均值。

+
+

替代 GB 3187-1982 的新国家标准是 GB/T 3187-1994 《可靠性、维修性术语》(等同于 IEC 60050-191:1991),该标准把“failure”仅翻译为“失效”,不再又称“故障”。完整的术语定义如下:

+
+

4.1.1 失效 failure
+产品终止完成规定功能的能力这样的事件。
+4.2.1 故障 fault
+产品不能执行规定功能的状态。预防性维修或共他计划性活动或缺乏外部资源的情况除外。故障通常是产品本身失效后的状态,但也可能在失效前就存在。

+
+

基于上述的定义,对于性能随时间逐渐退化的产品,故障(fault)与失效(failure)的区别,如下图所示[10]

+故障(fault)与失效(failure)的区别 +

国外历来都是将“fault”和“failure”的定义加以区分的,我国新的标准文档也区分翻译为“故障”和“失效”,但是实际上在我国的电工行业中的惯用情况是把“fault”和“failure”都翻译为“故障”,很多书籍资料也不严格区分。比如,中国质量协会的《可靠性工程师手册》(第 2 版 2017[5:3]),不严格区分“故障”与“失效”术语,统一都使用“故障”,书中的解释如下:

+
+

在我国的可靠性工程应用中,一般不对故障与失效进行严格的区分,如失效树分析也称为故障树分析,故障模式、影响分析也称为失效模式、影响分析。因此本书也不做严格区分,多数情况下故障一词也可用失效代替。

+
+

一般而言,故障是产品本身失效后的状态,此时产品处于故障状态,这时故障和失效是不需要严格加以区分。对无故障容忍能力的产品而言,故障即失效。然而,对有故障容忍能力的产品,产品可以出故障,但不会失效,这时我们就必须区分失效和故障的概念[9:1]。故障容忍(容错,fault tolerance),是在某些故障出现时继续运行的能力,只有当所有冗余的硬件同时有故障时,产品才失效。

+

可靠性的度量

+

可靠性的度量指标是可靠度reliability),根据国际电工委员会的标准文档,可靠度的定义是:在给定的条件下在时间区间 (t1, t2) 内按要求执行的概率。当 t1=0 和 t2=t,则 R(0,t) 可简化为 R(t),并称为产品的可靠度函数(reliability function)。

+

若在 t=0 时产品的总数为N0N_0,在 0 ~ t 的时间内累计的故障数为Nf(t)N_f(t),正常的产品数为Ns(t)N_s(t),则有:

+

N0=Nf(t)+Ns(t)N_0 = N_f(t) + N_s(t)

+

产品在 t 时刻的可靠度的估计值为:

+

R(t)^=Ns(t)N0\hat{R(t)}=\frac{N_s(t)}{N_0}

+

显然,当 t=0 时,R(0) = 1,当 t=∞ 时,R(∞) = 0。

+

可靠度的反面是不可靠度(unreliability),含义是:在规定的条件下,在规定的时间内,不能完成规定功能的概率。不可靠度函数通常记为F(t)F(t),不可靠度的估计值的计算公式为:

+

F(t)^=Nf(t)N0=N0Ns(t)N0=1R(t)^\hat{F(t)} = \frac{N_f(t)}{N_0} = \frac{N_0 - N_s(t)}{N_0} = 1 - \hat{R(t)}

+

示例:假设在 t=0,投入工作的 10000 只灯泡,以天作为度量时间的单位,在 t= 365 天时,发现有 300 只灯泡坏了,这时的可靠度和不可靠度的计算如下:

+

R(365)^=10003001000=0.97\hat{R(365)} = \frac{1000 - 300}{1000} = 0.97F(365)^=3001000=0.03\hat{F(365)} = \frac{300}{1000} = 0.03

+

对不可靠度函数求导,其导数称为故障概率密度函数,通常记为f(t)f(t)

+

f(t)=limΔt0F(t+Δt)F(t)Δtf(t) = \lim_{\Delta t \to 0} \frac{F(t + \Delta t) - F(t)} {\Delta t}

+

某时刻尚未发生故障的产品,在该时刻后单位时间内发生故障的概率,称为产品的故障率failure rate),记为记为λ(t)λ(t)。故障率的计算公式如下:

+

λ(t)^=Ns(t)Ns(t+Δt)Ns(t)Δt=间隔时间内的故障数间隔起点的存活数×时间间隔\hat{λ(t)} = \frac{N_s(t) - N_s(t + \Delta t)} {N_s(t) \Delta t} = \frac{间隔时间内的故障数}{间隔起点的存活数 × 时间间隔}

+

λ(t)=limΔt0Ns(t)Ns(t+Δt)Ns(t)Δt=limΔt0F(t+Δt)F(t)R(t)Δt=f(t)R(t)λ(t) = \lim_{\Delta t \to 0} \frac{N_s(t) - N_s(t + \Delta t)} {N_s(t) \Delta t} = \lim_{\Delta t \to 0} \frac{F(t + \Delta t) - F(t)}{R(t)\Delta t} = \frac{f(t)}{R(t)}

+

在长期的可靠性实践中,人们发现许多产品的故障率随时间的变化曲线形似浴盆,所以习惯性的将故障率曲线称为“浴盆曲线”(bathtub curve),如下图所示[5:4]。大多数电子产品的故障率曲线的形状就是浴盆曲线。

+产品典型的故障率曲线 +

故障率随时间的变化大致可以分为以下三个阶段:早期故障期(early failure period)、偶然故障期(random failure period)、耗损故障期(wear-out failure period)。三个阶段有时也被称为:早夭期(infant mortality period)、使用寿命期(useful life period)和耗损期(wear-out period)。故障率曲线与人类的死亡率曲线相似,曲线的三个阶段分别对应人类生命周期的婴幼儿时期、壮年期以及老年期。在偶然故障期,产品的故障率可降到一个较低的水平,且基本处于平稳状态,可以近似认为故障率为常数。

+

如果产品的故障率为常数,那么其故障的概率分布可以用指数分布(exponential distribution)描述,指数分布是唯一具有恒定故障率的连续概率分布。恒定故障率的特性也被称为“无记忆性”(memorylessness),该特性说明故障率在任何时刻都与系统已工作过的时间长短没有关系。服从指数分布的概率密度函数为:

+

f(t)=λeλtf(t) = {\lambda} e^{-\lambda t}

+

服从指数分布的可靠度函数、不可靠度函数和故障率函数依次为:

+

R(t)=eλtR(t) = e^{-\lambda t}F(t)=1eλtF(t) = 1 - e^{-\lambda t}λ(t)=λ\lambda(t) = \lambda

+

公式中的λ\lambda为常数。

+

上面提到的这些指标是概率相关的度量指标。另外,还有一些是时间相关的度量指标:

+
    +
  • 平均故障间隔时间(MTBF,mean time between failures):相邻两次故障间的持续时间的平均值。失效间隔时间(time between failures)包括可用时间和不可用时间。MTBF 只能用于可修复产品。
  • +
  • 平均故障间隔工作时间(MTBF /MOTBF,mean operating time between failures):相邻两次故障间的累计工作时间的平均值。MOTBF 只能用于可修复产品,该值也被成为可修复产品的平均寿命(mean life)。
  • +
  • 平均故障前工作时间MTTF,mean operating time to failure):故障前工作时间的平均值。等同于,平均失效前时间(MTTF,mean time to failure)。MTTF 可以用于不可修复产品和可修复产品。MTTF 值也被成为不可修复产品的平均寿命(mean life)。
  • +
  • 平均恢复时间MTTR,mean time to restoration):恢复时间的平均值。最新的国际电工委员会 IEV 标准文档,废弃了平均恢复时间(mean time to recovery)和平均修理时间(mean time to repair)。平均恢复时间是维修性的主要度量指标。
  • +
  • 可用性availability):或者翻译为“可用度”,可以表示为平均可用时间除以平均可用时间与平均不可用时间之和。可用性是反映可靠性和维修的综合性指标。
  • +
+

根据国际电工委员会标准文档 IEC 60050-192:2015(等同的国家标准文档是 GB/T 2900.99-2016《电工术语 可信性》),MTBF 和 MOTBF 缩写代表的都是平均故障间隔工作时间(mean operating time between failures),统计的值是故障间隔工作时间operating time between failures),即相邻两次故障间的累计工作时间;而故障间隔时间time between failures),包括可用时间和不可用时间。所以,平均故障间隔时间平均故障间隔工作时间的含义是不同的,前者同时统计包括工作时间(operating time)和非工作时间(non-operating time),而后者只统计工作时间(operating time)。但是在很多其他文档中,比如维基百科的词条“平均故障间隔时间”(Mean time between failures)词条,“平均失效间隔时间”的缩写也是 MTBF。也就说, MTBF 即是“平均故障间隔时间”的缩写,也是“平均故障间隔工作时间”的缩写,但两者含义却不同,需要读者自行辨别。本文使用 MTBF,统一都表示“平均故障间隔时间”。

+

MTBF 只能用于可修复产品,MTTF 用于不可修复产品和可修复产品。对于不可修复产品,MTTF 等同于 MTBF,对于可修复产品,MTTF 等同于 MOTBF。MTBF 是 MTTR 和 MTTF 的总和,即MTBF=MTTR+MTTFMTBF = MTTR + MTTF

+

产品的平均寿命(mean life)的理论值为故障概率密度函数的期望值,记为 θ。该期望值也是可修复产品的 MOTBF 的理论值,是不可修复产品的 MTTF 的理论值。平均寿命或 MTTF 的计算公式如下:

+

MTTF=θ=E(T)=0tf(t)dxMTTF = θ = E(T) = \int_{0}^\infty t f(t)\,\mathrm{d}x

+

如果概率密度函数服从指数分布,那么平均寿命或 MTTF 值为:

+

MTTF=θ=1/λMTTF = θ = 1/\lambda

+

对于服从指数分布的产品,当产品工作时间到达平均寿命时,可靠度的值 36.8%:

+

R(θ)=e1=36.8%R(θ) = e^{-1} = 36.8\%

+

假设某可修复产品的正常工作时间为{TFF1,TFF2...,TFFn}\left\{ {TFF}_1, {TFF}_2 ..., {TFF}_n \right\},故障时间为{TTR1,TTR2...,TTRn}\left\{ {TTR}_1, {TTR}_2 ..., {TTR}_n \right\},如下图所示:

+MTBF、MTTF 和 MTTR 示意图 +

MTBF、MTTF、MTTR 和可用性(availability)的估计值的计算公式如下:

+

MTBF=i=1nTBFin=total uptime + total downtimetotal number of failuresMTBF = \frac{\sum_{i=1}^n {TBF}_i}{n} = \frac{\text{total uptime + total downtime}}{\text{total number of failures}}

+

MTTF=i=1nTTFin=total uptimetotal number of failuresMTTF = \frac{\sum_{i=1}^n {TTF}_i}{n} = \frac{\text{total uptime}}{\text{total number of failures}}

+

MTTR=i=1nTTRin=total downtimetotal number of failuresMTTR = \frac{\sum_{i=1}^n {TTR}_i}{n} = \frac{\text{total downtime}}{\text{total number of failures}}

+

可用性=MTTFMTTF+MTTR=MTTFMTBF=total uptimetotal uptime+total downtime可用性 = \frac {MTTF} {MTTF + MTTR} = \frac {MTTF} {MTBF} = \frac{\text{total uptime}}{\text{total uptime} + \text{total downtime}}

+

对于电子设备,MTBF 近似常量,比如,典型的企业级固态硬盘 SSD 的 MTBF 值可能是 200 万小时[11],也就是 228 年,年故障率 AFR(Annualized Failure Rate) 为 0.44%(1/228)。

+

可以利用数学和统计方法对可靠性进行预计和度量,并分析可靠性数据。但是可靠性的量化涉及大量不确定性,由于可靠性经常关系到制造和使用产品的人,人的行为和表现不像植物对肥料的反应、气象模型对海洋温度的反应那样服从于数学分析和预测,而且产品可能在大范围变化的环境中工作,因此还会有其他不确定性因素被引入。数学和统计方法虽然在适当的场合是非常有价值的,但是由于涉及大量不确定性,在实际的可靠性工程中的作用有限,在实际的工程实践中优先需要确定的是故障的原因和解决方案[12]

+

软件可靠性工程

+

软件可靠性工程是从硬件可靠性工程发展而来的[13]。在软件工程学建立初期,一些软件工程专家利用和改造硬件可靠性工程学的成果,使之移植到软件领域,从而开创了软件可靠性学科。

+

类似的,起源于 Google 的“站点可靠性工程”(SRE, Site reliability engineering)也源自可靠性工程,区别是站点可靠性工程关注的是大型网站和网络服务这样的软件系统 [14][15]

+

术语与概念

+

国家标准 GB/T 11457-2006 《信息技术 软件工程术语》,对软件可靠性的定义如下:

+
+

2.1662 系统可靠性 system reliability
+包括全部硬件和软件子系统在内的某个系统,在规定的环境及时间里正确执行所要求的任务或使命的概率。
+2.1528 软件可靠性 software reliability
+a) 在规定条件下,在规定的时间内,软件不引起系统失效的概率。该概率是系统输人和系统使用的函数,也是软件中存在的缺陷的函数。系统输人将确定是否会遇到已存在的缺陷(如果有缺陷存在的话)。
+b) 在规定的时间周期内所述条件下程序执行所需要的功能的能力。

+
+

GB/T 11457-2006 吸收了 IEEE Std 610.12-1990 全部术语,包括术语“软件可靠性”,国标的术语定义只是对 IEEE 术语定义的中文翻译。IEEE 最早在标准文档中定义“软件可靠性”是在 IEEE Std 729-1983,这个标准之后被 IEEE Std 610.12-1990 替代。

+

IEEE 对“软件可靠性”术语给出两个定义,定义 a) 是定量的定义,也就是“可靠度”,定义 b) 是定性的定义。对比后容易发现,硬件可靠性和软件可靠性的定义是相同的。这种相容性,使这种可靠性定义能够用于既包括软件又包括硬件的系统。

+

故障相关的术语,国家标准 GB/T 11457-2006 《信息技术 软件工程术语》的定义是:

+
+

2.163 隐错 bug
+见:出错 error(2.561) 和故障 fault(2.609)。
+2.421 缺陷 defect
+见:故障 fault(2.609)。
+2.561 出错, 误差, 差错 error
+a) 计算的、观察的或测量的值或条件与实际的、规定的或理论上正确的值或条件的差别。例如,在计算的结果和正确的结果之间差30m;
+b) 不正确的步骤、过程或数据定义。例如,在计算机程序中的不正确的指定;
+c) 不正确的结果。例如,当正确的结果是10,而计算的结果是12;
+d) 产生不正确结果的人为动作。例如,在编程或操作的一部分上的不正确动作。
+注:当上述所有四种定义是公共使用时,一种区分赋给定义 a) 为字差错(error),定义 b) 为字过错(fault),定义 c) 为字失效(failure)和定义 d) 为字错误(mistake)。
+2.601 失效 failure
+系统或部件不能按规定的性能要求执行它所要求的功能。注:故障容忍在人们的动作(弄错-mistake)、它的显示(硬件或软件故障 fault)、故障的结果(失效 failure)和不正确(差错-error)结果的总数之间进行区分
+2.609 故障, 缺陷 fault
+a) 硬件设备或部件中的缺陷。例如,短路或断线。
+b) 在计算机程序中不正确的步骤、过程或数据定义。注:此定义最初由容错(fault tolerance)系统使用。在通常用法中,术语“差错(error)”和“隐错(bug)”表示同样含义。

+
+

基于 IEEE 的定义,容易发现术语“fault、“bug”和“defect”是同义词,术语“error”同时具有“mistake”、“fault”和“failure”的含义。这些术语之间的因果关系是,开发者在软件开发过程中产生人为失误(mistake),导致在软件中存在缺陷(fault, bug, defect),在软件运行时如果用户遭遇缺陷(fault, bug, defect),会引发失效(failure),如下图所示:

+软件故障的因果关系 +

失效(failure)是指系统或部件在特定约束下不能完成所要求的功能,用户在测试或实际使用中会观察到失效(failure)。失效(failure)是系统运行行为对用户要求的偏离,是一种面向用户的概念。故障(fault)是在系统运行时引起或可能潜在地引起失效(failure)的缺陷(defect),是一种面向开发者的概念。

+

可靠性的度量

+

早期的软件可靠性度量工作试图将硬件可靠性理论中的数学公式外推来进行软件可靠性的预测。大多数与硬件相关的可靠性模型依据的是由于“磨损”而导致的故障,而不是由于设计缺陷而导致的故障。在硬件中,由于物理磨损(如温度、腐蚀、振动的影响)导致的故障远比与设计缺陷有关的故障多。不幸的是,软件恰好相反。实际上,所有软件故障都可以追溯到设计或实现问题,磨损根本没有影响[16]

+

软件系统的故障主要是人为差错造成,涉及大量不确定性,利用数学和统计方法对可靠性进行预计和度量,在实际的工程实践中的作用有限。少数常用的与可靠性相关的度量指标是:MTBF、MTTR 和可用性。

+

MTBF 指标衡量的是系统无故障运行的能力,也就是可靠性。MTTR 指标衡量的是系统快速从故障中恢复的能力,这种能力在硬件产品下被称为“维修性”(maintainability),但在软件系统下通常为称“韧性”(resilience)。术语“maintainability”,在硬件上下文中通常被翻译为“维修性”,而在软件上下文中通常被翻译为“维护性”或“可维护性”,软件可维护性指的是软件可被修改的能力,修改可能包括修复缺陷、增加或完善功能等。

+

MTBF 反映的是硬件产品的寿命,是硬件产品质量的最重要的指标之一。与硬件不同,软件的 MTBF 不可控,而故障恢复的工作流程清晰,可干预程度高,研发团队可以对各环节展开精细化管理,轻松、高效地达成 MTTR 优化目标,所以软件系统的 MTTR 相对 MTBF 更加重要[17][18]

+

可用性是衡量可靠性和韧性的综合性指标。想要提高系统的可用性,需要做的是延长无故障时间(MTTF)和缩短故障恢复时间(MTTR)。

+

可靠性设计

+

Laprie 等人把提高系统可靠性的方法总结为四种

+
    +
  • 故障避免(fault avoidonce,简称“避错”):在系统的设计和实现过程中使用一些开发方法来减少故障发生,并在系统投入使用之前发现系统中的故障。
  • +
  • 故障排除(fault removal,简称“排错”):故障排除可以细分为两个子类别:开发期间的排除和使用期间的排除。在系统使用之前通过验证和确认(V&V)来发现和去除系统中的故障;如果系统已经投入使用,通过维护周期将其消除。
  • +
  • 故障容忍(fault tolerance,简称“容错”):容错是使系统在其某些组件中出现一个或多个故障时能够继续提供服务的能力,尽管该服务可能处于降级级别。容错技术主要是采用冗余redundancy)方法来消除故障的影响,冗余的含意是指当系统无故障时取消冗余资源不会影响系统正常运行。
  • +
  • 故障预报(fault forecasting):通过收集故障数据,建立可靠性建模,预测可能的故障。
  • +
+

针对软件可靠性设计,软件故障避免技术,包括采用优秀的软件设计方法、使用强类型的程序设计语言、全面的编译器检查等;软件故障排除技术,主要是代码评审和软件测试;故障预报,能提高硬件可靠性,但是很少应用于软件可靠性。

+

系统的资源包括硬件资源、软件资源、信息资源、时间资源,所以冗余区分 4 种方式:

+
    +
  • 硬件冗余(hardware redundancy):通过配置额外的硬件组件实现冗余
  • +
  • 软件冗余(software redundancy):通过配置额外的软件版本实现冗余,例如 N 版本编程(NVP
  • +
  • 信息冗余(information redundancy):通过对信息中外加一部分信息码或将信息存放在多个内存单元或将信息进行备份等实现冗余,例如循环冗余校验码、数据库备份等。
  • +
  • 时间冗余(time redundancy):多次执行相同的操作(重试)实现冗余,例如多次执行程序或传输数据的多个副本。
  • +
+

硬件冗余和软件冗余被合称为结构冗余(structural redundancy)。相对与时间冗余,硬件冗余、软件冗余、信息冗余被合称为空间冗余(space redundancy)。

+

在工程领域,利用冗余提高可靠性的例子很多,比如汽车的备胎、大货车的多个轮子、飞机的四台发动机或双台发动机、火箭的多台引擎和多台计算机等。《像火箭科学家一样思考》书中的“为什么冗余不是多余的”小节[19]中有这样一段阐述:

+
+

航天器上的计算机也使用冗余装置。在地球上,电脑往往免不了崩溃或死机,而在有压力的太空环境中,计算机发生故障的概率有增无减,因为计算机在太空中要经历无数振动、冲击、变化的电流和波动的温度。正因为如此,航天飞机的计算机是4倍冗余的,即飞机上有4台计算机在运行着同样的软件。这4台计算机会通过一个多数投票系统就下一步动作进行单独投票。如果其中一台计算机发生故障,开始乱输出数据,其他3台计算机就会投票将其排除在外(没错,伙计们,火箭科学比你想象的更民主)。
+冗余装置要正常工作,就必须独立运行。一架航天飞机配备4台计算机,这听起来非常棒,但由于它们运行着相同的软件,所以只要一个软件出现错误,4台计算机就会同时瘫痪。因此,航天飞机还配备了第5个备用飞行系统。该系统安装有一款不同的软件,而这款软件由不同于其他4款软件的分包商提供。如果某个一般性的软件错误使4台相同的主计算机瘫痪,则备用系统将启动,并会将航天飞机送回地球。

+
+

在航天飞机上配备 4 台计算机属于硬件冗余,第 5 个备用飞行系统属于软件冗余。

+

IDC 数据中心等级划分(data centre tiers)主要是根据线路、电源、冷却等核心组件的冗余程度而划分的,不同的等级代表不同的可靠性和可用性。按 Uptime Institute 和 TIA-942 标准的建议,数据中心由低到高划分为 T1、T2、T3、T4 共 4 个等级,T1 级为基本型、T2 级为冗余型、T3 级为可并行维护冗余型、T4 级为容错型。4 个等级的冗余程度分别是,T1 级无冗余,T2 级部分 N+1 冗余,T3 级全部 N+1 冗余,T4 级 2N 或 2N+1 冗余。按我国国家标准《GB 50174-2017 数据中心设计规范》,数据中心由高到低划分为 A、B、C 三级,A 级为容错型,B 级为冗余型,C 级为基本型。不同的数据中心等级的对比,如下表所示(表格参考自 [20]):

+数据中心等级划分 +

大多数商业数据中心都介于 T3 级和 T4 级之间,平衡了建设成本和可靠性。金融等行业的数据中心,如银行的数据中心,通常会同时遵循最高等级的国家标准 A 级和 Uptime Institute 的 Tier 4 级标准来建设。

+

在生物学中,冗余是生物体的一种重要特征。生物体中的冗余结构和功能可以提高生物体的适应性和生存能力。例如,人体的很多器官是冗余的,比如耳朵、眼睛、肾、肺。冗余的器官如果出现“故障”,虽然不会让人完全失去该器官的机能,但会导致机能降级。其中一个眼睛如果完全失去视力,不会让人失明,不过视觉上无法识别远近。其中一个耳朵如果完全没有听力,不会让人失聪,但无法透过耳朵识别声音的位置。

+

尽管冗余是一种很好的提高可靠性的措施,但额外的冗余增加到某种程度之后,就会无谓地增加设备的复杂性和成本,遵循边际效益递减规律。典型的例子是客机,随着发动机本身可靠性的提高,出于安全性和成本之间的权衡,之前的四发动机的客机越来越少见,逐渐被更省油、更低维护成本的双发动机的客机取代。

+

参考资料

+
+
+
    +
  1. 秦咏红,吕乃基:工程系统可靠性的演进,东北大学学报,2011年第4期295-299,cqvip ↩︎

    +
  2. +
  3. 可靠性概论,工信部电子第五研究所潘勇,2015,豆瓣:第11章 可靠性标准 ↩︎

    +
  4. +
  5. 2022-09 【标准解读】用标准语言解读装备“六性” https://mp.weixin.qq.com/s/FqfLL_ovGIZ-GO998HB4uw ↩︎

    +
  6. +
  7. 2021-07 张健:装备通用质量特性关系概述 https://mp.weixin.qq.com/s/nXmrTrz7c5EnEh4C_h4JEg ↩︎ ↩︎ ↩︎

    +
  8. +
  9. 可靠性工程师手册,中国质量协会,第2版 2017,豆瓣 ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

    +
  10. +
  11. 2018-01 北航康锐:可靠性的历史与今世 | 可靠性系统工程三部曲(上) https://mp.weixin.qq.com/s/275pk9Z-V4T3lntI-ZzYCA ↩︎

    +
  12. +
  13. 可靠性工程(Reliability Engineering),Kapur & Pecht,2014,豆瓣:第1章 21世纪的可靠性工程 ↩︎

    +
  14. +
  15. 2002-03 褚善元:failure和fault的定名问题 http://www.term.org.cn/CN/abstract/abstract10076.shtml ↩︎ ↩︎

    +
  16. +
  17. 2002-03 朱美娴:关于failure和fault定义的研讨 http://www.term.org.cn/CN/abstract/abstract10081.shtml ↩︎ ↩︎

    +
  18. +
  19. System Reliability Theory, Rausand, etc., 3rd 2020,豆瓣:3 Failures and Faults, Figure 3.3 Illustration of the difference between failure and fault for a degrading item. ↩︎

    +
  20. +
  21. 2021-09 揭秘:SSD 的“可靠性”到底可不可靠 https://memblaze.com/innovate/technical-articles/169.html ↩︎

    +
  22. +
  23. 实用可靠性工程(Practical Reliability Engineering),O'Connor, etc.,第5版2012,豆瓣 ↩︎

    +
  24. +
  25. 陈光宇,黄锡滋:软件可靠性学科发展现状及展望,电子科技大学学报社科版,2002年第3期99-102,cqvip ↩︎

    +
  26. +
  27. SRE:Google运维解密,Beyer, etc. 2016,豆瓣:序言 ↩︎

    +
  28. +
  29. SRE原理与实践:构建高可靠性互联网应用,张观石,2022,豆瓣:第1章 互联网软件可靠性概论 ↩︎

    +
  30. +
  31. 软件工程:实践者的研究方法,Pressman,第8版2014,豆瓣:第21章 软件质量保证,21.7 软件可靠性 ↩︎

    +
  32. +
  33. 2010-07 John Allspaw: Thoughts on systems safety, software operations, and sociotechnical systems https://www.kitchensoap.com/2010/11/07/mttr-mtbf-for-most-types-of-f/ ↩︎

    +
  34. +
  35. 2023-07 LigaAI:研发质量指标大 PK:MTTR vs MTBF,谁是靠谱王? https://segmentfault.com/a/1190000043971564 ↩︎

    +
  36. +
  37. 像火箭科学家一样思考,Ozan Varol,2020,豆瓣:第1章 与不确定性共舞,为什么冗余不是多余的 ↩︎

    +
  38. +
  39. 2020-12 艾瑞咨询:2020年中国数据中心行业研究报告 https://report.iresearch.cn/report/202012/3699.shtml ↩︎

    +
  40. +
+
+ +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2023/12/popular-websites-tech-stack/index.html b/2023/12/popular-websites-tech-stack/index.html new file mode 100644 index 00000000..2ec00dcc --- /dev/null +++ b/2023/12/popular-websites-tech-stack/index.html @@ -0,0 +1,1351 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 流行互联网网站技术栈整理 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+ + + + + +
+

+ 流行互联网网站技术栈整理 +

+ + +
+ + + + +
+ + +

技术栈是构建应用的技术集合,由编程语言、框架、库、服务器、数据库、工具等组合而成。组成技术栈的技术是与具体业务无关的基础软件。互联网公司选择的技术栈,倾向于使用开源软件,相对于专有软件,开源软件具有高质量、免费、开放、灵活等优势。互联网的早期开拓者 Yahoo 的技术栈选择是经典案例,受开源运动的影响,在 2000 左右 Yahoo 从最初基于自定义的专属软件迁移了到 LAMP 技术栈。

+ +

在“开源”(open source)一词出现之前,技术社区的黑客选择使用“自由软件”(free software)这个词。但是“自由软件”这个词与对知识产权的敌意、共产主义和其它观点相联系,几乎不受管理者和投资者的欢迎,于是 1998 年 2 月 3 日在由 Eric Raymond 等人参加的会议上“开源”一词诞生,2 月下旬开源软件促进会成立 OSI,Eric Raymond 担任主席。自由软件和开源软件被合称为 FOSS。缩写“LAMP”代表的是 Linux-Apache-MySQL-PHP,这些软件都是自由软件或开源软件。

+

案例汇总与解析

+

技术发展时间线

+

在互联网诞生早期,开源技术栈、开源社区尚未成熟,互联网公司不得不自研专有软件,随着开源软件的成熟,技术栈的选择开始从专有软件逐渐转向开源软件。先来看下,主要 Web 技术和服务端技术的发展时间线:

+
    +
  • 1994.03,Linux 1.0 对外发布,源码采用 GPL 协议。
  • +
  • 1994.10,网景公司的 Web 浏览器 Netscape 首次对外发布。
  • +
  • 1995.04,Apache HTTP Server 首次对外开源发布,版本为 0.6.2,源码采用 Apache 协议
  • +
  • 1995.12,JavaScript 语言诞生,创造者为来自网景公司的 Brendan Eich。
  • +
  • 1995.05,Java 语言诞生,创造者为 Sun 公司。Java 平台早期并不真正开源,虽然 1998 年 JDK 1.2 开始以 SCSL 协议开放源代码,但 SCSL 协议限制太大,饱受批评,直到 2006.11 才以 GPL 协议真正开源。
  • +
  • 1995.06,PHP 语言诞生,源码采用 PHP 协议(BSD 风格的协议)。
  • +
  • 1995.12,HTML 标准规范首次发布,版本为 HTML 2.0
  • +
  • 1996.05,Sun 公司首次对外发布 Java Servlet API。
  • +
  • 1996.10,MySQL 首次公开对外发布,最初的公开发行版仅提供了 Solaris 的二进制发行版,一个月后,源代码和 Linux 二进制文件发布,源码采用的是专有协议“MySQL Free Public License”,到 2000.06 改为 GPL 协议。
  • +
  • 1996.10,PostgreSQL 的诞生日是在 10 月 22 日,在这一天 PostgreSQL.org 网站上线。PostgreSQL 之前的项目名为 Postgres,之所以改名是为了反映其对 SQL 的支持。源码采用 PostgreSQL 协议(类似 BSD 或 MIT 协议)。
  • +
  • 1996.12,微软发布 ASP 技术,到 2002 年 ASP 被 ASP.NET 替代。
  • +
  • 1998.12,缩写“LAMP”诞生,代表 Linux-Apache-MySQL-PHP。
  • +
  • 1999.12,Sun 公司首次对外发布 J2EE,版本为 1.2,包括 Servlet、JSP、EJB 等技术。
  • +
  • 2002.08,Nginx 首次对外发布,源码采用 BSD 协议。最初,研发 Nginx 目的是为了解决 C10k 问题。之后,Nginx 逐渐替代 Apache HTTP Server,LAMP 技术栈改为 LNMP 技术栈。
  • +
  • 2003.06,Java 的 Spring 框架首次对外发布,版本为 0.9,源码采用 Apache 协议。
  • +
  • 2004.08,Ruby on Rails 框架首次对外发布,源码采用 MIT 协议。
  • +
  • 2005.02,“Ajax”术语诞生,早期使用 Ajax 技术的经典案例是 Google 在 2004 发布的 Gmail 和 2005 发布的 Google Maps。
  • +
  • 2005.07,Python 的 Django 框架首次对外发布,源码采用 BSD 协议。
  • +
  • 2007.02,HBase 宣布在 Hadoop 项目中成立,成为 Hadoop 的子项目。HBase 是 Google 的 BigTable(OSDI'2006)论文的开源实现。
  • +
  • 2007.01,iPhone 手机首次对外发布,同年 6 月 iPhone 正式发售,11 月 Android 系统首次对外公布,移到互联网开始大爆发。
  • +
  • 2008.07,Facebook 对外开源 Cassandra 项目,项目受 Amazon 的 Dynamo(SOSP'2007)论文和 Google 的 BigTable(OSDI'2006)论文的。
  • +
  • 2009.06,“NoSQL”术语诞生。“NoSQL”术语诞生于在旧金山举行的一场关于“开源、分布式、非关系数据库”的技术聚会,该技术聚会被命名为“NoSQL meetup”。NoSQL 的两大起源是 BigTable 和 Dynamo。
  • +
  • 2009.11,Google 对外公开 Go 语言,BSD 协议开源。
  • +
  • 2011.04,451 Group 咨询公司的分析师 Matthew Aslett 创造“NewSQL”术语,是对用于 OLTP 的分布式关系型数据库的统称。最具代表性的 NewSQL 是 Google 的 Spanner(OSDI'2012)和 Amazon 的 Aurora(2014.10 发布的云原生数据库产品)。
  • +
+

技术栈案例汇总

+

按编程语言区别,主要流行的互联网产品的创建时间和早期的技术栈选择(也可以参见 wiki):

+
    +
  • C/C++ 技术栈: +
      +
    • Yahoo!(1994,2002 转向 PHP)、Amazon(1994,之后转向以 Java 为主)、eBay(1995,2002 全面转向 Java)、Google 搜索(1998)[1][2]新浪网(1998,之后转 PHP,2008 年 PHP 占据 90% 以上的 Web 开发)[3]腾讯 QQ(1999)、QQ 空间(2005)、微信(2011)[4]百度搜索(2000)、Yandex 搜索(2000)[5]
    • +
    +
  • +
  • PHP(LAMP 或 LNMP)技术栈: +
      +
    • Wikipedia(2001)[6]Facebook(2004,2006 核心服务转向 C++)、Flickr(2004)[7]Etsy(2005)[8]WordPress(2005)、新浪博客(2005)[9]百度百科(2006,2006 开始百科、知道、文库、贴吧等产品以 PHP 为主实现)[10]Tumblr(2007,2011 转向 Scala)[11]哔哩哔哩(2009,2017 转向 Golang)[12]新浪微博(2009,2011 转向 Java)[13]腾讯微博(2010)[14]美团(2010,2011 转向 Java)[15]滴滴(2012,2017 业务系统转向 Golang)[16]
    • +
    +
  • +
  • Ruby on Rails 技术栈: +
      +
    • Twitter(2006,2009 核心服务转向 Scala 和 Java)、Shopify(2006)[17]SoundCloud(2007,2012 业务转向多种 JVM 语言和基础设施转向 Golang)[18][19][20]Heroku(2007)[21]GitHub(2008)[22]Airbnb(2008,2016 开始服务化并部分转向 Java)[23][24]
    • +
    +
  • +
  • Python 技术栈: +
      +
    • Reddit(2005,少部分高性逻辑用 C 语言)[25]YouTube(2005)[26]豆瓣(2005)[27]Disqus(2007)[28]Dropbox(2007,2013 基础设施转向 Golang)[29][30][31]Quora(2009,高性能服务用 C++)[32]Pinterest(2009,部分服务转向 Java)[33][34]Instagram(2010,少部分高性逻辑用 C++)[35][36][37]Uber(2010,2015 转向 Golang 和 Java 等)[38]知乎(2011,2018 核心业务转向 Golang)[39]字节跳动(2012,今日头条、抖音等,2014 开始引入 Golang,2016 业务大规模转向 Golang)[40][41]
    • +
    +
  • +
  • Java 技术栈: +
      +
    • 淘宝(2003,2004 PHP 全面转向 Java)、LinkedIn(2003)、Google Gmail(2004)[42]Google Docs(2006)、Google+(2011)[43]人人网(2005)[44]Netflix(2007)[45]
    • +
    +
  • +
  • .NET 技术栈 +
      +
    • 携程(1999,2017 全面转向 Java)[46]京东(2004,2012 全面转向 Java)[47]Stack Overflow(2008)、Bing 搜索(2009)等
    • +
    +
  • +
+

值得一提的是,PHP 之父 Rasmus Lerdorf,在 2002 年至 2009 年期间为供职于 Yahoo!,2011 年起至今供职于 Etsy。Python 之父 Guido van Rossum,在 2005 年至 2012 年期间供职于 Google,在 2013 年至 2019 年期间供职于 Dropbox。国内最有影响力的 PHP 技术专家是惠新宸,是加入 PHP 语言官方开发组的首位国人,曾先后供职于雅虎中国、百度、新浪微博、链家网等公司。

+

编程语言选择

+

2000 年前创建的网站,因为开源技术栈尚未成熟,编程语言基本上都是选择 C++ 开发。在开源技术栈成熟后,多数网站会选择拥抱开源。具体选择哪个编程语言,PHP、Ruby、Python、Java 等,主要由技术负责人的技术偏好决定。根据 w3techs 统计,历年网站使用的服务端编程语言统计占比,2012 年至今 10 多年,PHP 占比稳居榜首,每年都是 75% 以上。大型网站通常都是公司内的技术团队研发的,技术栈由技术团队选择,而很多小型网站,很可能会直接使用开源的 CMS 系统搭建。根据 w3techs 统计,前 100 万网站中有 43.0% 使用 WordPress 构建。WordPress 的服务端编程语言就是 PHP,数据库是 MySQL。大型网站选择 PHP 越来越少,因为 PHP 是解释型脚本语言,相对编译型编程语言有性能劣势。另外,PHP 的优势是快速开发 Web 动态网页,但是随着前后端分离开发模式的流行,Web 页面从服务端渲染逐渐转向客户端渲染,PHP 的优势不再,后端工程师只需要向前端提供 REST API 接口,展示层的实现完全由前端工程师实现。

+

早期部分网站选择 .NET 技术栈,比如京东携程。但是,Java 平台生态更完善,有非常多的经验可以借鉴。另外,.NET 平台本身虽然不收费,但是 Windows 操作系统是收费的,开发工具也不便宜。于是京东在 2012 年从 .NET 迁移到 Java,携程在 2017 左右从 .NET 迁移到 Java。目前在国内,多数互联网大厂都选择 Java 技术栈,如淘宝、美团、京东、微博、携程等,Java 相对来说是主流选择。

+

编程语言的另外一个流行趋势是 Go 语言。Go 语言诞生于 Google,在 2009 年 11 月对外公开。在发明 Go 语言前,Google 内部主要使用的语言是 C++、Java 和 Python 等,但是 Go 发明者认为这些语言无法同时满足高效编译、高效执行和易于编程的特性诉求,所以创造了 Go 语言[48]。Go 比 C++ 能更高效编译和易于编程,比 Java 更易于编程,比 Python 能更高效执行。在 GoCon Tokyo 2014 会议上,Go 语言研发团队的 Brad Fitzpatrick 对各种编程语言在编程乐趣和执行速度(Fun vs. Fast)的对比[49],如下图所示:

+编程语言 Fun vs. Fast +

早期由 Go 语言实现的经典开源项目主要是基础设施软件,比如 YouTube 的 Vitess 数据库分片中间件(2012.02 对外开源)、Docker 容器(2013.03 对外开源)、Red Hat 的 CoreOS 团队的 Etcd 分布式配置服务(2013.07 对外开源,实现 Raft 共识协议)、前 Google 工程师创建的 CockroachDB 分布式数据库(2014.02 对外开源,受 Google Spanner 启发)、Google 的 Kubernetes 容器编排系统(2014.06 对外开源)、SoundCloud 的 Prometheus 监控工具(2015.01 对外开源)等。大规模使用 Go 语言的代表性的国外的互联网公司有 SoundCloud[19:1][20:1]Dropbox[30:1][31:1]Uber[38:1] 等,国内的有七牛云字节跳动[40:1][41:1]哔哩哔哩[12:1]滴滴[16:1]知乎[39:1]百度[50][51]腾讯[52]等,在这些互联网公司 Go 语言通常主要被用于构建基础设施软件(网关、数据存储、监控、视频处理等)或高性能要求的业务服务,部分公司的大量核心业务也从 Python、PHP 等迁移到 Go 语言。使用 Go 语言的公司的更加完整的列表,可以参见官方整理的“GoUsers”。

+

数据库选择

+

数据库方面,根据 DB-Engines Ranking 的统计,流行的关系数据库主要是 4 个,开源免费的 MySQL 和 PostgreSQL,专有收费的 Oracle 和 Microsoft SQL Server。多数互联网产品使用的数据库是 MySQL,部分是 PostgreSQL 或 Oracle。一些早期使用 Oracle 数据库的网站选择部分或完全从 Oracle 数据库中迁出,代表性的案例是,Amazon 从 Oracle 完全迁移到 Amazon RDS 和 NoSQL,淘宝从 Oracle 完全迁移到 MySQL。以 PostgreSQL 为主数据库的互联网应用有 Skype、Reddit、Spotify、Disqus、Heroku、Instagram 等[53]

+

MySQL 相对 PostgreSQL 更加流行的主要原因是[54][55],在早期 MySQL 入门槛更低。MySQL 就支持在 Windows 下安装,而 PostgreSQL 只能在 Cygwin 下安装,MySQL 对 Windows 平台的支持使得初学者更容易上手,并且 MySQL 更加易于管理,能够快速简单地启动和使用,而且 MySQL 拥有一个非常简洁、易于导航和用户友好的在线文档和支持社区。另外一个重要原因是,MySQL 很早就默认支持复制(replication),而 PostgreSQL 的复制是第三方的,而且极其难用。之后的几年即便 PostgreSQL 完善了不足,但错过了流行的时间窗口,MySQL 成为了主流选择,有更完善的生态。不过,受 MySQL 被 Oracle 公司收购的影响,近几年 PostgreSQL 开始越来越流行,根据 DB-Engines Ranking 的统计,最新的 PostgreSQL 的流行度分数是 10 年前的三倍,流行度与前三名越来越接近。

+

传统关系数据库,因为在面对大数据量和高负载量时的性能和可扩展性较差,以及对数据模型的支持有限,逐渐演变出了分布式非关系数据库 NoSQL 和分布式关系数据库 NewSQL。NoSQL 数据库的按数据模型分类包括:键值数据库(比如 Redis、DynamoDB 等)、列族数据库(比如 Cassandra、HBase 等)、文档数据库(比如 MongoDB)、图数据库(比如 Neo4j)等。Redis,是内存型键值数据库,是目前缓存场景的主流解决方案。

+

技术栈和架构演进

+

容易发现多数网站的技术栈的演进模式类似。在创建网站早期通常选择使用 PHP、Ruby、Python 脚本语言和框架来开发,这些脚本语言和框架具有更快的开发效率,能快速交付上线。随着网站流量的增长,面临性能和可扩展性问题,通常会将网站服务化,从单体架构向面向服务的 SOA 和微服务架构演进,一大部分网站在服务化过程中会选择将核心业务改由其他性能更佳的编译型编程语言来实现,如 Java、Scala、C++、Go,原先的脚本语言可能全部废弃,也可能仅用于前端展示层的 Web 动态页面渲染,比如 Facebook、Twitter 等。当然也有一部分网站,演进为 SOA 和微服务架构后,业务逻辑的实现一直以最初的脚本语言为主。

+

在架构微服务化后,很多网站实现的微服务之间采用基于 HTTP 协议的 REST 方式通信(或者使用的 RPC 框架支持跨语言 RPC 调用),各个微服务的实现在理论上编程语言不需要统一,可以根据该微服务的性能要求或负责该微服务的团队的技术偏好自由选择,所以真实世界的互联网公司内部各个业务子系统的技术栈可能不统一。但是内部技术栈不统一会带来额外的维护成本。另外,考虑技术栈的迁移重构成本,新的业务子系统使用新的技术栈,而有些旧的业务子系统很可能继续使用旧的技术栈。除了业务子系统外,很可能团队内部有自研的中间件、运维工具等,这些组件由中间件团队、运维团队研发,很可能会选择与业务系统不一样的技术栈。

+

注意,解决网站的可扩展性问题,不一定需要演进为服务化架构。架构服务化意味着将完整的单体服务按业务的功能领域做垂直拆分,而实际上在应用服务层可以通过部署多个相同副本的单体服务的方式实现系统的水平扩展,网站的可扩展性问题主要在数据存储层上。拆分应用服务的好处在于能实现组织团队的规模化。解决数据库的扩展性的策略有,数据复制(数据缓存、数据库主从读写分离)、数据垂直拆分、数据水平拆分(也叫数据分片,sharding)。数据库被拆分后,如果单个事务内的数据分散在多个节点就要解决分布式事务问题,但是实现分布式事务代价太大,通常的选择是牺牲一致性,仅满足最终一致性(BASE)。

+

没有拆分应用服务,始终采用单体架构的经典案例是 Instagram,2019 年 Instagram 在技术博客上有这样一段话[37:1]

+
+

Our server app is a monolith, one big codebase of several million lines and a few thousand Django endpoints, all loaded up and served together. A few services have been split out of the monolith, but we don’t have any plans to aggressively break it up.

+
+

Instagram 解决可扩展性问题,主要在数据存储层[35:1][36:1]。在 Instagram,PostgreSQL 被用于存储用户信息、媒体元数据、用户关系等数据,照片媒体数据存储在亚马逊 S3 服务上。Instagram 对 PostgreSQL 数据库做了主从读写分离、数据垂直拆分和数据水平分片。另外,Instagram 从 2012 年开始使用 Cassandra 数据库,Cassandra 被用于存储 Feed 流、活动等数据。类似的,Reddit 也是单体架构,在数据存储层做了可扩展性改造[25:1]。对 PostgreSQL 数据库做了主从读写分离和垂直拆分,拆分为四个主数据库,链接、帐户、子版块、评论、投票和杂项,每个主数据库都从数据库。另外,投票数据存储在 Cassandra 数据库。

+

Yahoo!(1994)

+

Yahoo!,1994 年创立,早期网站操作系统是 FreeBSD,Web 服务器是自研的 Filo Server,数据库是自研的 DBM 文件,Web 动态页面脚本是自研的 yScript,业务逻辑编程语言是 C++。1996 年 Web 服务器改用 Apache HTTP Server,1999 年部分数据库改用 MySQL(同时也使用 Oracle 数据库),2002 年编程语言从 yScript 和 C++ 改为 PHP,操作系统也从 FreeBSD 逐渐转向 Linux[56][57][58]。在 2002.10 的 PHPCon 2002 会议上,Yahoo! 工程师 Michael Radwin 介绍了 Yahoo! 从专有软件向开源软件转向的原因和演进过程,以及选择 PHP 而不选择 ASP、Perl、JSP 等其他技术的原因[56:1]。Yahoo! 转向开源软件的原因主要是,避免维护专有软件的成本,开源软件从早期的不成熟最终变得成熟,具有更好的性能,更容易与第三方软件集成,以及开源社区逐渐发展壮大。2005 年,Yahoo! 的技术架构如下图所示[57:1]

+Yahoo! 技术架构(2005) +

2000 年 ~ 2010 年,Yahoo! 是世界上流量最大的网站,虽然期间被 Google 短暂超越,但随后又反超,一直到到 2010 年后才被 Google 彻底超越。2000 年前后 Yahoo! 转向到 MySQL 和 PHP,并在技术上助力 LAMP 生态的发展壮大,对 LAMP 技术栈的流行起到巨大的推动作用。值得一提的是,知名 MySQL 专家 Jeremy Zawodny,《高性能MySQL》2004 年第 1 版(豆瓣)的作者,在 1999.12 ~ 2008.06 期间为 Yahoo! 工程师;PHP 之父 Rasmus Lerdorf 在 2002.09 ~ 2009.11 期间为 Yahoo! 工程师。

+

Amazon(1994)

+

Amazon,1994 年创立,早期是单服务、单数据库的单体架构,使用的编程语言是 C++,2000 年开始从单体架构向 SOA 和微服务架构演进,使用最多的语言变为 Java,C++ 被用在高性能要求的系统和底层基础设施组件。Amazon 架构演进过程如下图所示[59]

+Amazon 架构演进 +

Amazon.com 的技术栈演进过程:

+
    +
  • 1995 ~ 2000:Unix(Sun)、Obidos、Oracle、C++ +
      +
    • Obidos 是亚马逊内部 Web 动态页面渲染引擎,编程语言是 C++。
    • +
    +
  • +
  • 2000 ~ 2006:Linux、Obidos、Oracle、C++ +
      +
    • 2000 年,开始将 Sun 服务器替换为 HP/Linux 服务器,并同时开始拆分应用服务,向 SOA 架构演进。
    • +
    • 2005 年初,开始将 Obidos 框架替换为 Gurupa 框架,Gurupa 是 Web 页面渲染引擎,同时也是 SOA 框架。Web 动态页面的编程语言从 C++ 替换为 Perl/Mason,同时应用服务开始被更细粒度的拆分。
    • +
    +
  • +
  • 2006 年开始:Linux、Gurupa、Oracle、Perl & Java & C++ +
      +
    • 2019.10,彻底去掉 Oracle 数据库,迁移到 Amazon RDS 和 NoSQL。
    • +
    +
  • +
+

当前 Amazon.com 网站的主要技术栈[59:1][60][61][62]

+
    +
  • 应用服务: +
      +
    • 展示层:Perl/Mason
    • +
    • 业务逻辑层:Java(主要)、C++ 等
    • +
    • RPC框架:Gurupa 框架(自研闭源) +
        +
      • 2006 年更早之前使用 Obidos 框架
      • +
      +
    • +
    • 消息队列MQAmazon SQS
    • +
    +
  • +
  • 数据存储[63]: +
      +
    • 关系数据库:Amazon RDS for PostgreSQL[64]、Amazon Aurora (PostgreSQL) +
        +
      • 2019 年 10 月彻底去掉 Oracle 数据库,迁移到 Amazon RDS 和 NoSQL。
      • +
      +
    • +
    • 键值存储Amazon DynamoDB
    • +
    • 缓存:Amazon ElastiCache for Redis[65]
    • +
    • Blob文件存储Amazon S3
    • +
    +
  • +
  • 数据分析Amazon Kinesis、Amazon EMR、AWS LambdaAmazon Redshift
  • +
+

eBay(1995)

+

eBay,1995 年创立,早期使用的编程语言是 Perl,1997 年迁移到 C++,2002 年迁移到 Java。eBay 的技术栈演进过程[66][67]

+
    +
  • 1995 ~ 1997:FreeBSD、Apache、GDBM、Perl
  • +
  • 1997 ~ 2002:Windows、IIS、Oracle、C++ +
      +
    • 1999.02,开始应用服务器池化和水平扩展;数据库服务器垂直扩展(替换为高端服务器 Sun E10000)
    • +
    • 1999.11,开始数据库水平扩展,按功能垂直拆分、数据水平分片。
    • +
    +
  • +
  • 2002 ~ 2006:Windows、IBM WebSphere、Oracle、Java(J2EE) +
      +
    • 2002 年,开始将 C++ 替换为 Java,使用 J2EE 框架
    • +
    +
  • +
  • 2006 年开始:Ubuntu、Tomcat、Oracle、Java(Spring/Spring Boot) +
      +
    • 2007 年初,开始向 SOA 架构演进,再然后演进为微服务架构[68][69]
    • +
    +
  • +
+

2016 年,eBay 的技术架构如下图所示[69:1]

+eBay 技术架构(2016) +

当前 eBay 的主要技术栈[66:1][67:1][69:2][70]

+
    +
  • 应用服务: +
      +
    • 展示层:Java、Spring MVC
    • +
    • 业务逻辑层:Java、Spring、Spring Boot
    • +
    • RPC框架:Raptor、Raptor.io(自研闭源,基于 Spring、Spring Boot)
    • +
    • 消息队列MQ:BES (business event stream)(自研闭源)、BES2(自研闭源,基于 Kafka 实现,BES2 API 完全兼容 BES1)[71]
    • +
    +
  • +
  • 数据存储[72]: +
      +
    • 关系数据库:Oracle(主)、MySQL(次)
    • +
    • NoSQL:Apache Cassandra、MongoDB
    • +
    • 搜索引擎:Elasticsearch[73]
    • +
    +
  • +
  • 数据分析[74]:Apache Kafka、Apache Flink、Apache Kylin(自研开源,MOLAP 数仓)、ClickHouse(ROLAP 实时数仓) 等 +
      +
    • Apache Kylin,2014.10 对外开源,2014.11 成为 Apache 孵化器项目,2015.12 从 Apache 孵化器毕业。
    • +
    +
  • +
+

淘宝(2003)

+

淘宝技术架构[75][76][77][78][79],是从 LAMP 架构演变而来的。在 2003 年 5 月最早上线时,淘宝是对购买得到的采用 LAMP 架构网站源码进行二次开发的网站。为了应对网站流量的增长,2003 年底数据库从 MySQL 切换到 Oracle,2004 年初编程语言从 PHP 迁移到 Java,同时硬件演变为 IBM 小型机和 EMC 高端硬件存储,依赖的基础设施被统称为“IOE”(IBM 小型机、Oracle 数据库、EMC 存储设备),这个架构被称为 2.0 架构。

+

2007 年底开始拆分第一个业务中心是用户中心(UIC,User Information Center),在 2008 年初上线。2008 年初,启动“千岛湖”项目,拆分出了交易中心(TC,Trade Center)和类目属性中心(Forest)。2008 年 10 月,为了打通淘宝网和淘宝商城(后来的天猫)的数据,启动“五彩石”项目,拆分出了店铺中心(SC,Shop Center)、商品中心(IC,Item Center)、评价中心(RC,Rate Center)。到 2009 年初,“五彩石”项目结束,阿里电商架构也从之前的单体架构演进为了 SOA 服务化架构,被称为 3.0 架构,同时淘宝网和淘宝商城也完成了数据整合,并淘宝网和淘宝商城的共享业务沉淀到多个业务中心。在 2009 年,共享业务事业部成立,在组织架构上共享业务事业部和淘宝、天猫平级。在业务中心的上层业务服务有,交易管理(TM,Trade Manager)、商品管理(IM,Item Manager)、店铺系统(ShopSystem)、商品详情(Detail)、评价管理(RateManager)等。2009 年淘宝的服务化拆分如下图所示[77:1]

+淘宝的服务化拆分(2009) +

在各个应用服务拆分的同时,数据库也按业务功能做了垂直拆分,2008 年 Oracle 被拆分为商品、交易、用户、评价、收藏夹等 10 来套。当时的淘宝的分布式架构设计,包括 Java + Oracle 技术栈的选择,以及应用服务和数据库的拆分策略,很大程度上参考的是 eBay 的架构[75:1][78:1]。对照 eBay 架构师在 2006 年 11 月对外分享的 eBay 架构的 slides[66:2],容易发现两者大同小异。

+

因为使用 Oracle 成本太高,2008 年 8 月淘宝数据库设计了异构数据库读写分离架构,写库为集中式的 Oracle,读库使用分库分表的 MySQL,该数据库架构方案基于自研的数据库中间件 TDDL 实现[80]。之后的几年,数据库逐渐向 MySQL 迁移。2008 年 9 月前微软亚洲研究院常务副院长王坚博士加盟阿里巴巴集团,担任首席架构师,2009 年 11 月时任阿里 CTO 的王坚博士决策启动阿里“去IOE”工程。淘宝的“去IOE”工程的关键时点[81]

+
    +
  • 2009.07,王坚博士开始担任阿里首席技术官 CTO。
  • +
  • 2009.11,王坚博士决策启动阿里“去IOE”工程。
  • +
  • 2010.01,大淘宝核心系统“去IOE”工作启动。
  • +
  • 2010.07,淘宝商品库完成“去I”。
  • +
  • 2011.07,淘宝商品库从 Oracle 迁移到 MySQL,完成“去IOE”。
  • +
  • 2011.09,淘宝交易库从 Oracle 迁移到 MySQL,完成“去IOE”。
  • +
  • 2012.12,完成大淘宝“去IOE”。
  • +
+

值得注意的是,在 2011 年淘宝商品库和交易库“去IOE”的同时,为了满足数据库的性能要求,底层硬件从 HDD 机械硬盘改为 SSD 固态硬盘。而庆幸的是,当时的前几年正好是 SSD 大爆发的时间点[82]。在消费级 SSD 市场,2010 年苹果的 MacBook Air 开始全面改用 SSD,2012 年苹果的 MacBook Pro 开始全面改用 SSD。在数据库服务器层面,因为 SSD 在随机读写的性能具有巨大优势,2010 年开始机械硬盘改用 SSD 成为趋势,当时的 MySQL 新版代码也专门针对 SSD 做了性能优化[83]

+

2009 年初淘宝演变为 SOA 架构后,服务拆分粒度越来越细,到 2009 年底拆分出的总服务数达到 187 个,到 2010 年底达到 329 个[77:2]。因为系统依赖关系越来越复杂,当时最大问题是稳定性问题,系统的稳定性建设成为重点工作。到 2013 年阿里电商系统开始 4.0 架构改造,即异地多活架构改造,内部称为单元化项目。2013 年 8 月完成杭州同城双活,2014 年双 11 前的 10 月完成杭州和上海近距离两个单元的异地双活,2015 年双 11 完成三地四单元的异地多活[76:1][79:1],至此也完成了 3.0 到 4.0 架构的升级。在阿里电商系统迁移到阿里云公共云方面,2015 年阿里电商系统开始采用混合云弹性架构,当阿里本地保有云无法支撑时,就快速在公有云上扩建新的单元,当流量过去后,再还资源给公有云。2015 年 10% 的双 11 大促流量使用了阿里云的机器来支撑,2016 年 50% 以上的双 11 大促流量使用了阿里云的机器来支撑[76:2]。2019 年初,阿里电商开启了全面上公共云的改造,到 2019 年双 11,阿里电商系统实现了全部核心应用上公共云,2021 年双 11,阿里电商系统实现了 100% 上公共云。

+

当前阿里电商系统(淘宝、天猫等)的主要技术栈[78:2][79:2]

+
    +
  • 应用服务: +
      +
    • 展示层:Java
    • +
    • 业务逻辑:Java、Spring、Spring Boot 等
    • +
    • RPC框架:HSF(2008 自研闭源)、Apache Dubbo(2008 自研,2011.10 对外开源)
    • +
    • 消息队列MQApache RocketMQ(自研,2013.09 对外开源) +
        +
      • 2007 年自研 Notify;2011 年自研 MetaQ;2013.09,对外开源发布 RocketMQ 3.0。RocketMQ 3.0 和 MetaQ 3.0 等价,阿里内部使用的称为 MetaQ 3.0,外部开源称之为 RocketMQ 3.0。
      • +
      +
    • +
    • 链路追踪:鹰眼 EagleEye(2012 自研闭源) +
        +
      • 2012 年内部发布鹰眼 1.0,参考 Google 2010 年的 Dapper 论文
      • +
      +
    • +
    • 注册和配置服务:ConfigServer(2008 自研闭源)、Nacos(自研,2018.07 对外开源) +
        +
      • 2008 年,淘宝团队内部自研 ConfigServer 并发布 1.0,被用于 HSF 的服务发现。2018.07,Nacos 对外开源,是 ConfigServer 的开源实现,在阿里内部 Nacos 被用在钉钉、考拉、饿了么、优酷等业务线。
      • +
      +
    • +
    +
  • +
  • 数据存储: +
      +
    • 关系数据库:MySQL (阿里云 RDS,底层基于 MySQL 自研 AliSQL)、自研 TDDL 中间件、阿里云分布式式数据库 PolarDB-X、MySQL 的 X-Engine 存储引擎 +
        +
      • 2008 年,淘宝团队内部自研 TDDL 中间件,用于实现数据库的读写分离、分库分表。
      • +
      • 2014 年,淘宝 TDDL 团队和阿里云 RDS 团队合作,在阿里云上输出产品分布式数据库服务 DRDS,2014.06 DRDS 开始公测,2014.12 正式上线。DRDS 脱胎于阿里 B2B 团队开源的 Cobar 分布式数据库引擎(2012.06 对外开源),同时借鉴了淘宝 TDDL 丰富的分布式数据库实践经验。
      • +
      • 2020 年,阿里云发布分布式式数据库 PolarDB-X,融合了分布式 SQL 引擎 DRDS 与分布式自研存储 X-DB(X-Cluster)。
      • +
      • MySQL 的 X-Engine 存储引擎,早期代码源自 Facebook 的 RocksDB 4.8.1(2016.07 发布),被应用在阿里的交易历史库、钉钉历史库等核心系统。
      • +
      +
    • +
    • 缓存Tair(2009 自研,2010.06 对外开源,分布式键值存储,支持基于内存和文件的两种存储方式) +
        +
      • 2009.04,Tair 1.0 正式诞生,并被应用于淘宝核心系统、MDB缓存、用户中心等业务。
      • +
      • 2010.06,Tair 对外开源。
      • +
      • 2014.05,阿里云推出基于 Tair 的缓存产品 OCS。
      • +
      • 2019.11,阿里云发布 Redis 企业版,即 Tair 3.0,兼容 Redis 5.0。
      • +
      +
    • +
    • 列族数据库:Apache HBase,为淘宝推荐、手淘消息等提供支撑的数据库 +
        +
      • 早期淘宝交易订单的所有数据都存储在单独的 Oracle 数据库;2010 年拆分为在线库和历史库,三个月之前的历史订单迁移进单独的 Oracle 历史库;2011 年交易历史库整体迁移到 HBase;2018 年历史库迁移到基于 X-Engine 存储引擎的 PolarDB-X 集群[84]
      • +
      +
    • +
    • 搜索引擎:Havenask(自研,2022.12 对外开源) +
        +
      • 支持了淘宝、天猫、菜鸟、优酷、高德、饿了么等在内整个阿里的搜索业务。阿里云的 OpenSearch 产品底层基于 Havenask 实现。
      • +
      +
    • +
    • Blob文件存储:阿里云 OSS +
        +
      • 早期采用 NetApp 提供的 NAS 存储设备;2007.06 开始基于自研的 TFS(Taobao File System);2010.09 对外开源 TFS;2016 迁移到阿里云 OSS[85]
      • +
      +
    • +
    +
  • +
  • 数据分析:阿里云 Flink、阿里云 MaxCompute(离线数仓)、阿里云 Hologres(实时数仓)等 +
      +
    • 早期阿里内部三大实时计算引擎并存,Galaxy、JStorm、Blink(Apache Flink 的分支),2017 年开始统一到 Blink。2019.01,阿里收购 Apache Flink 母公司 Data Artisans,随后阿里的 Blink 正式开源,之后 Blink 和 Flink 完成合并。2021 年开始,阿里内部的实时计算使用的是 Blink 团队与 Flink 创始团队联合打造了 Flink 企业版平台,即 VVP(Ververica Platform)。
    • +
    +
  • +
+

2016 年,阿里产品专家倪超对外介绍的阿里电商技术架构,如下图所示[86]

+阿里电商技术架构(2016) +

类似的,阿里巴巴中间件首席架构师《企业IT架构转型之道》(豆瓣)作者钟华在 2017 年对外介绍的阿里电商技术架构图[87]

+阿里电商中台架构(2017) +

2017 年,阿里中间件技术部专家谢吉宝对外介绍的阿里中间件技术大图[79:3]

+阿里中间件技术大图(2017) +

阿里 HSF 与 Dubbo 的历史演进时间线:

+
    +
  • 2008 年,阿里淘宝团队自研 HSF 框架,5 月发布 HSF 1.1。
  • +
  • 2009 年初,由阿里 B2B 团队研发的 Dubbo 发布 1.0 版本。阿里内部淘系(淘宝、天猫、一淘等)主要使用的服务框架是 HSF,而阿里 B2B 使用的则是 Dubbo,二者独立,各行其道,彼此不通[88]
  • +
  • 2010.04,重构后发布 Dubbo 2.0 版本。
  • +
  • 2011.10,Dubbo 对外开源,版本为 2.0.7。因为在功能完善性、架构优雅性、使用简便性等方面有其相对独特的优势,开源后被国内很多互联网公司广泛使用[89],包括去哪儿,京东、当当网、网易考拉、有赞等。
  • +
  • 2012 年,阿里内部架构调整,开始统一技术基础设施,合并重复项目,决定把 Dubbo 合并到 HSF 里面去[90]。随后,HSF 发布 2.0 的版本,兼容 Dubbo 的协议,HSF 推出后很快就在阿里集团全面铺开[88:1]。Dubbo 项目在阿里内部被抛弃,在 2012.10 发布 2.5.3 版本之后就停止更新,2013 年和 2014 年更新了 2 次 Dubbo 2.4 的维护版本,然后停止了所有维护工作。
  • +
  • 2014.10,当当网开源 Dubbox,基于 Dubbo 2.5.3 的代码,为 Dubbo 新增了 REST 风格远程调用、Kryo/FST 序列化等特性。
  • +
  • 2016.01,阿里云互联网中间件产品 EDAS 正式商用,EDAS 所提供的分布式服务框架源自阿里的 HSF。
  • +
  • 2017.09,Dubbo 重启维护,对外发布恢复维护后的第一个版本是 2.5.4。之所以重启是因为阿里云上的客户大部分使用 Dubbo,阿里云想要将基于 Dubbo 的解决方案作为自己的一个产品,卖给这些客户[88:2][90:1]
  • +
  • 2018.01,Dubbo 2.6.0 发布,合并了当当网提供的 Dubbox 分支。
  • +
  • 2018.02,阿里宣布将 Dubbo 捐献给 Apache,进入 Apache 孵化器。
  • +
  • 2018.11,阿里云 EDAS 产品版本升级,新版本实现 SpringCloud 和 Dubbo 用户代码零侵入就能迁移至 EDAS。
  • +
  • 2018.12,Dubbo 3.0 正式进入开发阶段,Dubbo 3.0 是 HSF 与 Dubbo 的融合版本。
  • +
  • 2019.01,Dubbo 2.7.0 发布,包名切换到 org.apache,全面拥抱 Java 8。
  • +
  • 2019.05,Dubbo 从 Apache 毕业,成为 Apache 的顶级项目。
  • +
  • 2020 年,在双十一前在阿里内部率先由阿里考拉实现了 Dubbo 3.0 的全面部署。
  • +
  • 2021.06,Dubbo 3.0 正式发布。
  • +
  • 2022 年,阿里集团几乎所有的业务线(包括淘宝、天猫、饿了么、钉钉等)全面从 HSF2 迁移到 Dubbo3。阿里内部使用的是 HSF3,HSF3 与以往的 HSF2 完全不同,HSF3 完全就是基于标准 Dubbo3 的 SPI 扩展库[91][92]
  • +
+

阿里 RocketMQ 的历史演进时间线:

+
    +
  • 2007,自研 Notify,最早底层的消息存储采用本地文件存储,参考 ActiveMQ 实现了单机 kv 存储引擎,2008 年底层的消息存储改用 Oracle,2010 年从 Oracle 迁移到高可用 MySQL 存储集群[93]
  • +
  • 2011.01,基于 Kafka 的设计用 Java 完全重写并发布 MetaQ 1.0。
  • +
  • 2012.03,MetaQ 1.x 对外开源,项目名为 Metamorphosis
  • +
  • 2012.09,淘宝内部发布 MetaQ 2.0 版本,MetaQ 2.0 对架构进行了重新设计,对消息日志文件存储目录结构做了改造[94]。改造后的 MetaQ 架构与 Kafka 存在很大差异,这个版本的 MetaQ 可以认为是第一代的 RocketMQ。
  • +
  • 2013.07,淘宝内部发布 MetaQ 3.0 版本,增加了主从复制(replication)、延迟消息等特性。 +
      +
    • 值得注意的是,Kafka 的复制特性,直到 2013.12 发布的 0.8.0 版本才开始支持。MetaQ 实现的复制特性类似与 MySQL 的主从复制,而 Kafka 实现的复制是集群间的分区复制(Intra-cluster Replication),复制的单位是分区(partition),参见 KAFKA-50。分区,在其他系统中也被叫做分片(shard),含义相同。
    • +
    +
  • +
  • 2013.09,对外开源发布 RocketMQ 3.0。RocketMQ 3.0 和 MetaQ 3.0 等价,阿里内部使用的称为 MetaQ 3.0,外部开源称之为 RocketMQ 3.0[95]
  • +
  • 2014.10,阿里云消息队列 ONS(云开放消息服务,Open Notification Service)对外公测,ONS 是基于阿里消息中间件 MetaQ(RocketMQ)打造的云消息产品。
  • +
  • 2016.11,阿里巴巴将 RocketMQ 捐赠给 Apache,成为 Apache 孵化器项目。
  • +
  • 2017.09,RocketMQ 从孵化器毕业,正式成为 Apache 顶级项目。
  • +
+

LinkedIn(2003)

+

LinkedIn,2003 年创立,采用纯 Java 技术栈,早期是单体架构,到 2008 年演化为 SOA 架构[96]。到 2010 年拆分的服务数超过 150 个,到 2015 年拆分的服务数超过 750 个[97]

+

2008 年,LinkedIn 对外介绍的技术架构如下图所示[96:1]

+LinkedIn 技术架构(2008) +

2012 年,LinkedIn 对外介绍的关注在数据基础设施上的技术架构图[98]

+LinkedIn 数据基础设施架构(2012) +

当前 LinkedIn 的主要技术栈[96:2][97:1]

+
    +
  • 应用服务: +
      +
    • 展示层:Java、Spring MVC、
    • +
    • 业务逻辑层:Java、Spring
    • +
    • RPC框架: +
        +
      • Rest.li(自研开源),REST + JSON 框架。2023.04,对外宣布 Rest.li 项目不再活跃,为了提升性能,迁移到 Protobuf + gRPC。
      • +
      +
    • +
    • 消息队列MQ:ActiveMQ
    • +
    +
  • +
  • 数据存储[98:1][99][100]: +
      +
    • 关系数据库:Oracle(主)、MySQL(次)
    • +
    • 缓存:Memcached
    • +
    • 键值存储Voldemort(自研,2009.01 对外开源) +
        +
      • 2009.01 对外开源,设计受 Amazon Dynamo 论文影响。2018 年之后 LinkedIn 不在使用 Voldemort,数据迁移到 LinkedIn 的 Venice 数据库
      • +
      +
    • +
    • 文档数据库Espresso(自研闭源),分布式文档数据库 +
        +
      • 2011 年初开始计划和设计,2012.06 在生产环境部署,底层实现基于 MySQL、Lucene、ZooKeeper。
      • +
      +
    • +
    • 图数据库:LIquid(自研闭源)
    • +
    • 搜索引擎:基于 Lucene
    • +
    • Blob文件存储Ambry(自研,2016.05 对外开源)
    • +
    +
  • +
  • 数据分析[98:2][99:1][100:1]: +
      +
    • 数据采集: +
        +
      • Databus(自研,2013.02 对外开源) +
          +
        • 数据变更抓取 CDC 工具,支持 Oracle 和 MySQL,2012.10 在 SoCC 2012 会议上发表论文,2013.02 对外开源。
        • +
        +
      • +
      • Apache Kafka(自研,2011.01 对外开源) +
          +
        • 2011.07 成为 Apache 孵化器项目,2012.10 从 Apache 孵化器毕业
        • +
        +
      • +
      +
    • +
    • 计算引擎:Apache Hadoop、Apache Samza(自研开源)、Apache Spark、Apache Flink +
        +
      • Apache Samza,2013.09 对外开源,2015.01 从 Apache 孵化器毕业
      • +
      +
    • +
    • 数据仓库:Apache Hive、Presto、Venice
    • +
    +
  • +
+

Facebook(2004)

+

Facebook,2004 年创立,早期采用 LAMP 技术栈,为了应对负载增长开始服务化,将核心业务从 LAMP 中移出到新的服务,新的服务改用使用 C++、Java 等编写。为了解决 PHP 进程与非 PHP 进程的 RPC 通信问题,2006 年内部研发了跨语言的 RPC 库 Thrift,2007.04 对外开源。PHP 代码用于实现前端展示层的 Web 动态页面渲染,以及对服务层的数据聚合。

+

2010 年,Facebook 工程师 Aditya Agarwal 对外介绍的 Facebook 技术架构如下图所示[101]

+Facebook 技术架构(2010) +

Facebook 的技术栈图[102]

+Facebook 技术架构(2008) +

Facebook 的 NewsFeed 服务的架构图[102:1]

+Facebook NewsFeed 技术架构(2008) +

Facebook 的 Search 服务的架构图[102:2]

+Facebook Search 技术架构(2008) +

当前 Facebook 的主要技术栈[101:1][102:3][103]

+
    +
  • 应用服务: +
      +
    • 展示层:PHP(早期采用 LAMP 技术栈)、HHVM2011.12 对外开源)、Hack(2014.03 对外发布)
    • +
    • 业务逻辑层:Hack、C++(主要用于实现性能敏感服务,包括 Ads、News Feed、Search 等)、Rust、Java 等[104][105]
    • +
    • RPC框架Apache Thrift(自研开源) +
        +
      • 2005 年末开始研发;2007.04 对外开源;2008.05 成为 Apache 孵化器项目;2010.10 从 Apache 孵化器毕业。
      • +
      +
    • +
    • 消息队列MQ:Wormhole(自研闭源) +
        +
      • 2013.06 对外介绍;2015.05 在 NSDI 2015 会议上发表论文。Wormhole 是发布-订阅系统,消息发布者直接读取数据存储系统的写事务日志,投递给对消息感兴趣的订阅者,订阅者可能是 News Feed、Cache、Index Servers 等。
      • +
      +
    • +
    +
  • +
  • 数据存储: +
      +
    • 关系数据库:MySQL、MySQL 存储引擎 MyRocks(自研,2015.11 对外开源) +
        +
      • RocksDB 是 Facebook 在 2012.04 创建的内嵌的键值数据库,基于 Google 开源的 LevelDB 代码。
      • +
      • MyRocks 是 Facebook 基于 RocksDB 数据库实现的 MySQL 存储引擎,2014 年开始研究 RocksDB 和 MySQL 的集成,2015.11 对外开源,在 2016.04 在 Percona Live 2016 会议上最早对外介绍。
      • +
      • 2017.08,Facebook 将 UDB 数据库(User Database,存储社交活动数据)从 InnoDB 完全迁移到了 MyRocks,迁移后存储空间使用量减少了一半,而 CPU 和 IO 使用率没有明显变化。
      • +
      • 2018.06,Facebook 在博客上对外介绍已经将 Messenger 应用的数据从 HBase 迁移到了 MyRocks,迁移后存储空间使用量减少 90%,读取延迟比以前的系统低 50 倍。值得注意的是,Messenger 应用的数据最早存储在 Facebook 自研的 Cassandra 上,2010 年底发布新版的 Messenger 开始,改为存储在 HBase 上。
      • +
      +
    • +
    • 键值存储ZippyDB(自研闭源),基于 RocksDB 实现的分布式键值数据库,2013 年开始在 Facebook 部署使用
    • +
    • 缓存Mcrouter(自研开源),实现分布式扩展的 Memcached +
        +
      • Facebook 早在 2005.04 就已经开始使用 Memcached;2013.04NSDI 2013 会议上发表论文,描述对 Memcached 的分布式扩展性改造。
      • +
      +
    • +
    • 图数据库TAO(自研闭源),底层是 Memcache 和 MySQL
    • +
    • 搜索引擎Unicorn(自研闭源),基于标准的搜索引擎的概念,但增加了社交图谱搜索的特性。Facebook 搜索功能(包括 Facebook Graph Search 产品)底层实现基于 Unicorn。 +
        +
      • 2013.03 Facebook Graph Search 产品对外推出,2014.12 开始原始的图谱搜索公开可见度降低,2019.06 几乎完全弃用。
      • +
      • 2015 年初,Instagram 的搜索引擎从 Elasticsearch 迁移到 Unicorn[106]
      • +
      +
    • +
    • Blob文件存储:Haystack(自研闭源) +
        +
      • 2009.04 对外介绍;2010.10 在 OSDI 2010 会议上发表论文。基于 Haystack 论文的开源实现包括:SeaweedFS、bilibili 的 BFS 等。
      • +
      +
    • +
    +
  • +
  • 数据分析[107][108]: +
      +
    • 日志采集Scribe(自研,2008.10 对外开源)
    • +
    • 计算引擎:XStream(Puma、Stylus、Swift)
    • +
    • 数据仓库Apache Hive(自研,2008.08 对外开源)、Presto(自研,2013.11 对外开源)、Laser、Scuba
    • +
    +
  • +
+

Twitter(2006)

+

Twitter,2006 年创立,早期采用 Ruby on Rails 技术栈,数据库是 MySQL,2009 年开始服务化,将核心业务从 Ruby on Rails 中移出到新的服务,新的服务用 Scala、Java 编写[109][110]

+

2013 年,Twitter 工程师总结的 Twitter 从单体架构向分布式架构演进的过程,如下图所示[110:1]

+Twitter 单体架构 +Twitter 服务化架构(2013) +

当前 Twitter 的主要技术栈[109:1][110:2]

+
    +
  • 应用服务: +
      +
    • 展示层:Ruby on Rails
    • +
    • 业务逻辑层:Scala(主要)、Java
    • +
    • RPC框架Finagle(自研,2011.08 对外开源) +
        +
      • 使用 Finagle 框架的公司包括:Foursquare(2010 PHP 转向 Scala)、Pinterest(Python + Java)、SoundCloud(Ruby + JVM)、Tumblr(PHP + Scala) 等。
      • +
      +
    • +
    • 消息队列MQ:Kestrel(2008.11 对外开源) -> DistributedLog -> Kafka
    • +
    • 链路追踪Zipkin(自研开源) +
        +
      • 2012.06,对外开源,是 Google Dapper 链路追踪系统的开源实现。
      • +
      • 2015 年中,项目从 Twitter 转交到 OpenZipkin 开源组织。
      • +
      +
    • +
    +
  • +
  • 数据存储[111]: +
      +
    • 关系数据库:MySQL、Manhattan(自研闭源,基于 MySQL 的分布式数据库) +
        +
      • 最初所有数据都存储在 MySQL 上。
      • +
      • 2009 年底,计划从 MySQL 迁移到 Cassandra,打算用 Cassandra 存储推文 Tweets 数据,但最终改变了策略,继续使用 MySQL,Cassandra 仅被用于存储分析数据[112]
      • +
      • 2010.04,对外开源数据库分片框架 Gizzard,基于 Gizzard 的分布式数据库 T-bird 被用于存储推文 Tweets 数据[113]
      • +
      • 2014.04,对外介绍自研的基于 MySQL 的分布式数据库 Manhattan,被用于存储推文 Tweets 等主要数据,Cassandra 被废弃。
      • +
      • 2018 年中,开始将 Manhattan 底层使用的 MhBtree 存储引擎改为基于 RocksDB 存储引擎。
      • +
      +
    • +
    • 缓存和键值存储:Redis、Memcached
    • +
    • 图数据库FlockDB(自研开源)
    • +
    • 搜索引擎:Earlybird[114](自研闭源)、Elasticsearch[115],用于推文 Tweets、用户、消息等搜索 +
        +
      • 2010 年,自研基于 Lucene 实现的 Earlybird 搜索引擎,替代旧的基于 MySQL 实现的搜索[114:1]
      • +
      +
    • +
    • Blob文件存储:Blobstore(自研闭源) + +
    • +
    +
  • +
  • 数据分析[116]:Kafka、Cloud BigTable、Cloud BigQuery 等
  • +
+

参考资料

+
+
+
    +
  1. 2007 Jeff Dean: Software Engineering Advice from Building Large-Scale Distributed Systems (Stanford CS295 class lecture, Spring, 2007) https://research.google.com/people/jeff/stanford-295-talk.pdf ↩︎

    +
  2. +
  3. 2008-11 Google Architecture http://highscalability.com/blog/2008/11/22/google-architecture.html ↩︎

    +
  4. +
  5. 2008-06 新浪夏清然、徐继哲:自由软件和新浪网. 程序员 2008年第6期54-55 http://lib.cqvip.com/Qikan/Article/Detail?id=27523653 http://www.zeuux.com/blog/content/3620/ ↩︎

    +
  6. +
  7. 2016-01 微信张文瑞:从无到有:微信后台系统的演进之路 https://www.infoq.cn/article/the-road-of-the-growth-weixin-background ↩︎

    +
  8. +
  9. 2008-02 Yandex Architecture http://highscalability.com/yandex-architecture ↩︎

    +
  10. +
  11. 2007-08 Wikimedia architecture http://highscalability.com/wikimedia-architecture ↩︎

    +
  12. +
  13. 2007-11 Flickr Architecture http://highscalability.com/flickr-architecture ↩︎

    +
  14. +
  15. 2016-03 What does Etsy's architecture look like today? http://highscalability.com/blog/2016/3/23/what-does-etsys-architecture-look-like-today.html ↩︎

    +
  16. +
  17. 2011-05 新浪刘晓震:新浪博客应用架构分享 (PHPChina 2011) https://web.archive.org/web/0/http://www.phpchina.com/?action-viewnews-itemid-38418 https://www.modb.pro/doc/121035 ↩︎

    +
  18. +
  19. 2013-11 百度张东进:百度PHP基础设施构建思路 (QCon上海2013, slides, 30p) https://www.modb.pro/doc/121042 ↩︎

    +
  20. +
  21. 2013-05 The Tumblr Architecture Yahoo Bought for a Cool Billion Dollars http://highscalability.com/blog/2013/5/20/the-tumblr-architecture-yahoo-bought-for-a-cool-billion-doll.html ↩︎

    +
  22. +
  23. 2017-06 B站任伟:B站高性能微服务架构 https://zhuanlan.zhihu.com/p/33247332 ↩︎ ↩︎

    +
  24. +
  25. 2021-05 微博刘道儒:十年三次重大架构升级,微博应对“极端热点”的进阶之路 https://www.infoq.cn/article/qgwbh0wz5bvw9apjos2a ↩︎

    +
  26. +
  27. 2012-08 腾讯张松国:腾讯微博架构介绍 (ArchSummit深圳2012, slides, 59p) https://www.slideshare.net/dleyanlin/08-13994311 ↩︎

    +
  28. +
  29. 2016-02 美团夏华夏:从技术细节看美团架构 (ArchSummit北京2014) https://www.infoq.cn/article/see-meituan-architecture-from-technical-details http://bj2014.archsummit.com/node/596/ https://www.modb.pro/doc/8311 ↩︎

    +
  30. +
  31. 2019-06 滴滴杜欢:大型微服务框架设计实践 (Gopher China 2019) https://www.infoq.cn/article/EfOlY8_rubh4LfoXzF8B https://www.modb.pro/doc/35485 ↩︎ ↩︎

    +
  32. +
  33. 2018-08 E-Commerce at Scale: Inside Shopify's Tech Stack - Stackshare.io https://shopify.engineering/e-commerce-at-scale-inside-shopifys-tech-stack ↩︎

    +
  34. +
  35. 2013-03 Phil Calçado @ SoundCloud: From a monolithic Ruby on Rails app to the JVM (slides, 75p) https://www.slideshare.net/pcalcado/from-a-monolithic-ruby-on-rails-app-to-the-jvm ↩︎

    +
  36. +
  37. 2012-07 Go at SoundCloud https://developers.soundcloud.com/blog/go-at-soundcloud ↩︎ ↩︎

    +
  38. +
  39. 2014-04 Peter Bourgon @ SoundCloud: Go: Best Practices for Production Environments (GopherCon 2014) http://peter.bourgon.org/go-in-production/ ↩︎ ↩︎

    +
  40. +
  41. 2009-04 Heroku - Simultaneously Develop and Deploy Automatically Scalable Rails Applications in the Cloud http://highscalability.com/blog/2009/4/24/heroku-simultaneously-develop-and-deploy-automatically-scala.html ↩︎

    +
  42. +
  43. 2021-07 GitHub’s Journey from Monolith to Microservices https://www.infoq.com/articles/github-monolith-microservices/ ↩︎

    +
  44. +
  45. 2017-12 Building Services at Airbnb, Part 1 https://medium.com/airbnb-engineering/c4c1d8fa811b ↩︎

    +
  46. +
  47. 2020-11 Jessica Tai @ Airbnb: How to Tame Your Service APIs: Evolving Airbnb’s Architecture https://www.infoq.com/presentations/airbnb-api-architecture/ ↩︎

    +
  48. +
  49. 2013-08 Reddit: Lessons Learned from Mistakes Made Scaling to 1 Billion Pageviews a Month http://highscalability.com/blog/2013/8/26/reddit-lessons-learned-from-mistakes-made-scaling-to-1-billi.html ↩︎ ↩︎

    +
  50. +
  51. 2012-03 7 Years of YouTube Scalability Lessons in 30 Minutes http://highscalability.com/blog/2012/3/26/7-years-of-youtube-scalability-lessons-in-30-minutes.html ↩︎

    +
  52. +
  53. 2016-04 豆瓣田忠博:豆瓣的服务化体系改造 (QCon北京2016, slides, 37p) http://2016.qconbeijing.com/presentation/2834/ ↩︎

    +
  54. +
  55. 2010-09 Disqus: Scaling the World's Largest Django App (DjangoCon 2010, slides) https://www.slideshare.net/zeeg/djangocon-2010-scaling-disqus ↩︎

    +
  56. +
  57. 2021-05 Dropbox: Atlas: Our journey from a Python monolith to a managed platform https://dropbox.tech/infrastructure/atlas--our-journey-from-a-python-monolith-to-a-managed-platform ↩︎

    +
  58. +
  59. 2014-07 Dropbox: Open Sourcing Our Go Libraries https://dropbox.tech/infrastructure/open-sourcing-our-go-libraries ↩︎ ↩︎

    +
  60. +
  61. 2017-07 Tammy Butow @ Dropbox: Go Reliability and Durability at Dropbox https://about.sourcegraph.com/blog/go/go-reliability-and-durability-at-dropbox-tammy-butow ↩︎ ↩︎

    +
  62. +
  63. 2011-02 Adam D'Angelo: Why did Quora choose C++ over C for its high performance services? Does the Quora codebase use a limited subset of C++? https://qr.ae/pKwCE3 ↩︎

    +
  64. +
  65. 2012-02 A Short on the Pinterest Stack for Handling 3+ Million Users http://highscalability.com/blog/2012/2/16/a-short-on-the-pinterest-stack-for-handling-3-million-users.html ↩︎

    +
  66. +
  67. 2015-08 Finagle and Java Service Framework at Pinterest (slides) https://www.slideshare.net/yongshengwu/finaglecon2015pinterest ↩︎

    +
  68. +
  69. 2013-03 Instagram 5位传奇工程师背后的技术揭秘 https://web.archive.org/web/0/http://www.csdn.net/article/2013-03-28/2814698-The-technologie- behind-Instagram ↩︎ ↩︎

    +
  70. +
  71. 2017-03 Lisa Guo: Scaling Instagram Infrastructure(QCon London 2017, 87p) https://www.infoq.com/presentations/instagram-scale-infrastructure/ ↩︎ ↩︎

    +
  72. +
  73. 2019-08 Static Analysis at Scale: An Instagram Story https://instagram-engineering.com/8f498ab71a0c ↩︎ ↩︎

    +
  74. +
  75. 2016-07 The Uber Engineering Tech Stack, Part I: The Foundation https://web.archive.org/web/0/https://eng.uber.com/tech-stack-part-one/ ↩︎ ↩︎

    +
  76. +
  77. 2018-11 知乎社区核心业务 Golang 化实践 https://zhuanlan.zhihu.com/p/48039838 ↩︎ ↩︎

    +
  78. +
  79. 2022-10 字节马春辉:字节大规模微服务语言发展之路 https://www.infoq.cn/article/n5hkjwfx1gxklkh8iham ↩︎ ↩︎

    +
  80. +
  81. 2021-07 字节成国柱:字节跳动微服务架构体系演进 https://mp.weixin.qq.com/s/1dgCQXpeufgMTMq_32YKuQ ↩︎ ↩︎

    +
  82. +
  83. Why does Google use Java instead of Python for Gmail? https://qr.ae/pKkduC ↩︎

    +
  84. +
  85. 2011-07 揭秘Google+技术架构 http://www.infoq.com/cn/news/2011/07/Google-Plus ↩︎

    +
  86. +
  87. 2009-12 人人网架构师张洁:人人网使用的开源软件列表 https://web.archive.org/web/0/http://ugc.renren.com/2009/12/13/a-list-of-open-source-software-in-renren ↩︎

    +
  88. +
  89. 2018-12 Netflix OSS and Spring Boot — Coming Full Circle https://netflixtechblog.com/4855947713a0 ↩︎

    +
  90. +
  91. 携程为什么突然技术转型从 .NET 转 Java? https://www.zhihu.com/question/56259195 ↩︎

    +
  92. +
  93. 京东技术解密,2014,豆瓣:12 少年派的奇幻漂流——从.Net到Java ↩︎

    +
  94. +
  95. Golang Frequently Asked Questions: Why did you create a new language? https://go.dev/doc/faq#creating_a_new_language ↩︎

    +
  96. +
  97. 2014-05 Brad Fitzpatrick: Go: 90% Perfect, 100% of the time: Fun vs. Fast https://go.dev/talks/2014/gocon-tokyo.slide#28 ↩︎

    +
  98. +
  99. 2021-08 百度Geek说:短视频go研发框架实践 https://my.oschina.net/u/4939618/blog/5191598 ↩︎

    +
  100. +
  101. 2023-07 百度Geek说:从 php5.6 到 golang1.19 - 文库 App 性能跃迁之路 https://my.oschina.net/u/4939618/blog/10086661 ↩︎

    +
  102. +
  103. 2022-03 2021年,腾讯研发人员增长41%,Go首次超越C++成为最热门语言 https://mp.weixin.qq.com/s/zj-DhASG4S-3z56GTYjisg ↩︎

    +
  104. +
  105. 2020-05 Which Major Companies Use PostgreSQL? What Do They Use It for? https://learnsql.com/blog/companies-that-use-postgresql-in-business/ ↩︎

    +
  106. +
  107. 2009-05 Why is MySQL more popular than PostgreSQL? https://news.ycombinator.com/item?id=619871 ↩︎

    +
  108. +
  109. Why is MySQL more popular than PostgreSQL? https://qr.ae/pKPJcE ↩︎

    +
  110. +
  111. 2002-10 Michael Radwin: Making the Case for PHP at Yahoo! (PHPCon 2002, slides) https://web.archive.org/web/0/http://www.php-con.com/2002/view/session.php?s=1012 https://speakerdeck.com/yulewei/making-the-case-for-php-at-yahoo ↩︎ ↩︎

    +
  112. +
  113. 2005-10 Michael Radwin: PHP at Yahoo! (PHP Conference 2005, slides) https://speakerdeck.com/yulewei/php-at-yahoo-zend2005 ↩︎ ↩︎

    +
  114. +
  115. 2007-06 Federico Feroldi: PHP in Yahoo! (slides) https://www.slideshare.net/fullo/federico-feroldi-php-in-yahoo ↩︎

    +
  116. +
  117. 2021-02 AWS re:Invent 2020: Amazon.com’s architecture evolution and AWS strategy https://www.youtube.com/watch?v=HtWKZSLLYTE ↩︎ ↩︎

    +
  118. +
  119. What programming languages are used at Amazon? https://qr.ae/pKFwnw ↩︎

    +
  120. +
  121. 2011-04 Charlie Cheever: How did Google, Amazon, and the like initially develop and code their websites, databases, etc.? https://qr.ae/pKKyB0 ↩︎

    +
  122. +
  123. 2016-04 Is Amazon still using Perl Mason to render its content? https://qr.ae/pKFwFm ↩︎

    +
  124. +
  125. 2019-10 Migration Complete – Amazon’s Consumer Business Just Turned off its Final Oracle Database https://aws.amazon.com/blogs/aws/migration-complete-amazons-consumer-business-just-turned-off-its-final-oracle-database/?nc1=h_ls ↩︎

    +
  126. +
  127. Amazon RDS for PostgreSQL customers https://aws.amazon.com/rds/postgresql/customers/?nc1=h_ls ↩︎

    +
  128. +
  129. Amazon ElastiCache for Redis customers https://aws.amazon.com/elasticache/redis/customers/?nc1=h_ls ↩︎

    +
  130. +
  131. 2006-11 Randy Shoup & Dan Pritchett: The eBay Architecture (SDForum2006, slides, 37p) http://www.addsimplicity.com/downloads/eBaySDForum2006-11-29.pdf ↩︎ ↩︎ ↩︎

    +
  132. +
  133. 2007-05 eBay Architecture http://highscalability.com/blog/2008/5/27/ebay-architecture.html ↩︎ ↩︎

    +
  134. +
  135. 2011-10 Tony Ng: eBay Architecture (slides, 46p) https://www.slideshare.net/tcng3716/ebay-architecture ↩︎

    +
  136. +
  137. 2016-11 Ron Murphy: Microservices at eBay (slides, 20p) https://www.modb.pro/doc/120378 ↩︎ ↩︎ ↩︎

    +
  138. +
  139. 2020-09 High Efficiency Tool Platform for Framework Migration https://innovation.ebayinc.com/tech/engineering/high-efficiency-tool-platform-for-framework-migration/ ↩︎

    +
  140. +
  141. 2023-10 BES2:打造eBay下一代高可靠消息中间件 https://mp.weixin.qq.com/s/ThhkO1WM7ck1WO8RqjTCJA ↩︎

    +
  142. +
  143. 2013-06 Cassandra at eBay - Cassandra Summit 2013 (slides) https://www.slideshare.net/jaykumarpatel/cassandra-at-ebay-cassandra-summit-2013 ↩︎

    +
  144. +
  145. 2017-03 Sudeep Kumar: 'Elasticsearch as a Service' at eBay https://www.elastic.co/elasticon/conf/2017/sf/elasticsearch-as-a-service-at-ebay ↩︎

    +
  146. +
  147. 2016-08 How eBay Uses Apache Software to Reach Its Big Data Goals https://www.linux.com/news/how-ebay-uses-apache-software-reach-its-big-data-goals/ ↩︎

    +
  148. +
  149. 淘宝技术这十年,子柳,2013,豆瓣 ↩︎ ↩︎

    +
  150. +
  151. 尽在双11:阿里巴巴技术演进与超越,2017,豆瓣:第1章 阿里技术架构演进 ↩︎ ↩︎ ↩︎

    +
  152. +
  153. 2011-06 淘宝吴泽明范禹:淘宝业务发展及技术架构 (slides, 43p) https://www.modb.pro/doc/116697 ↩︎ ↩︎ ↩︎

    +
  154. +
  155. 2014-12 阿里云王宇德、张文生:淘宝迁云架构实践 https://web.archive.org/web/1/http://www.csdn.net/article/a/2014-12-09/15821474 ↩︎ ↩︎ ↩︎

    +
  156. +
  157. 2017-07 阿里谢吉宝唐三:阿里电商架构演变之路 (首届阿里巴巴中间件技术峰会, slides, 33p) https://www.modb.pro/doc/121185 ↩︎ ↩︎ ↩︎ ↩︎

    +
  158. +
  159. 2010-11 淘宝赵林丹臣:淘宝数据库架构演进历程 (iDataForum2010, slides, 38p) https://www.slideshare.net/ssuser1646de/ss-10163048 ↩︎

    +
  160. +
  161. 2019-10 阿里刘振飞:十年磨一剑:从2009启动“去IOE”工程到2019年OceanBase拿下TPC-C世界第一 https://mp.weixin.qq.com/s/7B6rp17XVhpAWZr1-6DHqQ https://developer.aliyun.com/article/722414 ↩︎

    +
  162. +
  163. 2016-02 SSD的30年发展史 https://mp.weixin.qq.com/s/JsHKFilB5fvLY9V9z_xsXw ↩︎

    +
  164. +
  165. 2010-04 Yoshinori Matsunobu: SSD Deployment Strategies for MySQL (slides, 52p) https://www.slideshare.net/matsunobu/ssd-deployment-strategies-for-mysql ↩︎

    +
  166. +
  167. 2020-04 阿里王剑英、和利:淘宝万亿级交易订单背后的存储引擎 https://mp.weixin.qq.com/s/MkX1Pr8tERrzK29XG9zMUQ https://help.aliyun.com/zh/rds/apsaradb-rds-for-mysql/storage-engine-that-processes-trillions-of-taobao-order-records ↩︎

    +
  168. +
  169. 2022-03 阿里云罗庆超:阿里巴巴集团上云之 TFS 迁移 OSS 技术白皮书 https://developer.aliyun.com/article/876301 ↩︎

    +
  170. +
  171. 2016-12 阿里倪超:阿里巴巴Aliware十年微服务架构演进历程中的挑战与实践 https://www.sohu.com/a/121588928_465959 ↩︎

    +
  172. +
  173. 2017-10 阿里钟华古谦:企业IT架构转型之道 (杭州云栖大会2017, slides, 18p) https://www.modb.pro/doc/121695 ↩︎

    +
  174. +
  175. 2021-09 阿里郭浩:Dubbo 和 HSF 在阿里巴巴的实践:携手走向下一代云原生微服务 https://mp.weixin.qq.com/s/_Ug3yEh9gz5mLE_ag1DjwA ↩︎ ↩︎ ↩︎

    +
  176. +
  177. 2012-11 阿里巴巴分布式服务框架 Dubbo 团队成员梁飞专访 http://www.iteye.com/magazines/103 ↩︎

    +
  178. +
  179. 2019-01 Dubbo 作者梁飞亲述:那些辉煌、沉寂与重生的故事 https://www.infoq.cn/article/3F3Giujjo-QwSw2wEz7u ↩︎ ↩︎

    +
  180. +
  181. Dubbo 用户案例:阿里巴巴升级 Dubbo3 全面取代 HSF2 https://cn.dubbo.apache.org/zh-cn/users/alibaba/ https://github.com/apache/dubbo-website/blob/ee727525aa61d68b397cc6ddedb322001f0ca4da/content/zh/users/alibaba.md ↩︎

    +
  182. +
  183. 2023-01 阿里巴巴升级 Dubbo3 全面取代 HSF2 https://cn.dubbo.apache.org/zh-cn/blog/2023/01/16/阿里巴巴升级-dubbo3-全面取代-hsf2/ ↩︎

    +
  184. +
  185. 2017-11 阿里林清山隆基:阿里消息中间件架构演进之路:notify和metaq https://zhuanlan.zhihu.com/p/302600352 ↩︎

    +
  186. +
  187. 2013-07 淘宝张乐伟韩彰:淘宝消息中间件技术演变:MetaQ 1.0、MetaQ 2.0、MetaQ 3.0(sildes, 30p)https://www.modb.pro/doc/109298 ↩︎

    +
  188. +
  189. 2017-03 阿里冯嘉鼬神:Apache RocketMQ背后的设计思路与最佳实践 https://developer.aliyun.com/article/71889 ↩︎

    +
  190. +
  191. 2008-05 LinkedIn - A Professional Network built with Java Technologies and Agile Practices (JavaOne2008, slides) https://www.slideshare.net/linkedin/linkedins-communication-architecture ↩︎ ↩︎ ↩︎

    +
  192. +
  193. 2015-07 Josh Clemm: A Brief History of Scaling LinkedIn https://engineering.linkedin.com/architecture/brief-history-scaling-linkedin https://www.slideshare.net/joshclemm/how-linkedin-scaled-a-brief-history ↩︎ ↩︎

    +
  194. +
  195. Aditya Auradkar, Chavdar Botev, etc.: Data Infrastructure at LinkedIn. ICDE 2012: 1370-1381,dblp, semanticscholar, slides ↩︎ ↩︎ ↩︎

    +
  196. +
  197. 2012-06 Sid Anand: LinkedIn Data Infrastructure Slides (Version 2) (slides) https://www.slideshare.net/r39132/linkedin-data-infrastructure-slides-version-2-13394853 ↩︎ ↩︎

    +
  198. +
  199. 2021-12 Evolving LinkedIn’s analytics tech stack https://engineering.linkedin.com/blog/2021/evolving-linkedin-s-analytics-tech-stack ↩︎ ↩︎

    +
  200. +
  201. 2010-05 Aditya Agarwal: Scale at Facebook (Qcon London 2010) https://www.infoq.com/presentations/Scale-at-Facebook/ ↩︎ ↩︎

    +
  202. +
  203. 2008-11 Aditya Agarwal: Facebook architecture (QCon SF 2008, slides, 34p) https://www.slideshare.net/mysqlops/facebook-architecture https://www.infoq.com/presentations/Facebook-Software-Stack/ ↩︎ ↩︎ ↩︎ ↩︎

    +
  204. +
  205. 2011-04 Michaël Figuière: What is Facebook's architecture? https://qr.ae/pKYg12 ↩︎

    +
  206. +
  207. 2013-10 Where does Facebook use C++? https://qr.ae/pKCIee ↩︎

    +
  208. +
  209. 2022-07 Programming languages endorsed for server-side use at Meta https://engineering.fb.com/2022/07/27/developer-tools/programming-languages-endorsed-for-server-side-use-at-meta/ ↩︎

    +
  210. +
  211. 2015-07 Instagram: Search Architecture https://instagram-engineering.com/eeb34a936d3a ↩︎

    +
  212. +
  213. Guoqiang Jerry Chen, Janet L. Wiener, etc.: Realtime Data Processing at Facebook. SIGMOD Conference 2016: 1087-1098,dblp, semanticscholar ↩︎

    +
  214. +
  215. 2021-10 XStream: stream processing platform at facebook (Flink Forward Global 2021, slides) https://www.slideshare.net/aniketmokashi/xstream-stream-processing-platform-at-facebook ↩︎

    +
  216. +
  217. 2013-01 Johan Oskarsson: The Twitter stack https://blog.oskarsson.nu/post/40196324612/the-twitter-stack ↩︎ ↩︎

    +
  218. +
  219. 2013-10 Chris Aniszczyk: Evolution of The Twitter Stack (slides) https://www.slideshare.net/caniszczyk/twitter-opensourcestacklinuxcon2013 ↩︎ ↩︎ ↩︎

    +
  220. +
  221. 2017-01 The Infrastructure Behind Twitter: Scale https://blog.twitter.com/engineering/en_us/topics/infrastructure/2017/the-infrastructure-behind-twitter-scale ↩︎

    +
  222. +
  223. 2010-07 Cassandra at Twitter Today https://blog.twitter.com/engineering/en_us/a/2010/cassandra-at-twitter-today ↩︎

    +
  224. +
  225. 2011-12 How Twitter Stores 250 Million Tweets a Day Using MySQL http://highscalability.com/blog/2011/12/19/how-twitter-stores-250-million-tweets-a-day-using-mysql.html ↩︎

    +
  226. +
  227. 2013-11 Michael Busch: Search at Twitter (Lucene Revolution 2013, slides) https://www.slideshare.net/lucenerevolution/twitter-search-lucenerevolutioneu2013-copy https://www.youtube.com/watch?v=AguWva8P_DI ↩︎ ↩︎

    +
  228. +
  229. 2022-10 Stability and scalability for search https://blog.twitter.com/engineering/en_us/topics/infrastructure/2022/stability-and-scalability-for-search ↩︎

    +
  230. +
  231. 2021-10 Processing billions of events in real time at Twitter https://blog.twitter.com/engineering/en_us/topics/infrastructure/2021/processing-billions-of-events-in-real-time-at-twitter- ↩︎

    +
  232. +
+
+ +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CNAME b/CNAME new file mode 100644 index 00000000..6b3092cd --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +nullwy.me diff --git a/about/index.html b/about/index.html new file mode 100644 index 00000000..d6e199e8 --- /dev/null +++ b/about/index.html @@ -0,0 +1,515 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + about | nullwy's blog + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + + + +
+ + + + + +
+
+ +

about +

+ + + +
+ + + + +
+

一个程序员,yulewei#gmail.com

+ + +
+ + + +
+ + + + + + + +
+ + +
+
+ +
+
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2016/11/index.html b/archives/2016/11/index.html new file mode 100644 index 00000000..66132233 --- /dev/null +++ b/archives/2016/11/index.html @@ -0,0 +1,548 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+ 嗯..! 目前共计 25 篇日志。 继续努力。 +
+ + +
+ 2016 +
+ + + + + + + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2016/12/index.html b/archives/2016/12/index.html new file mode 100644 index 00000000..145be437 --- /dev/null +++ b/archives/2016/12/index.html @@ -0,0 +1,548 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+ 嗯..! 目前共计 25 篇日志。 继续努力。 +
+ + +
+ 2016 +
+ + + + + + + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2016/index.html b/archives/2016/index.html new file mode 100644 index 00000000..08f921a0 --- /dev/null +++ b/archives/2016/index.html @@ -0,0 +1,628 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+ 嗯..! 目前共计 25 篇日志。 继续努力。 +
+ + +
+ 2016 +
+ + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2017/01/index.html b/archives/2017/01/index.html new file mode 100644 index 00000000..264e2fa8 --- /dev/null +++ b/archives/2017/01/index.html @@ -0,0 +1,488 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+ 嗯..! 目前共计 25 篇日志。 继续努力。 +
+ + +
+ 2017 +
+ + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2017/03/index.html b/archives/2017/03/index.html new file mode 100644 index 00000000..aa59eab5 --- /dev/null +++ b/archives/2017/03/index.html @@ -0,0 +1,488 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+ 嗯..! 目前共计 25 篇日志。 继续努力。 +
+ + +
+ 2017 +
+ + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2017/04/index.html b/archives/2017/04/index.html new file mode 100644 index 00000000..3e3cb67f --- /dev/null +++ b/archives/2017/04/index.html @@ -0,0 +1,488 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+ 嗯..! 目前共计 25 篇日志。 继续努力。 +
+ + +
+ 2017 +
+ + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2017/05/index.html b/archives/2017/05/index.html new file mode 100644 index 00000000..8c8dcc6f --- /dev/null +++ b/archives/2017/05/index.html @@ -0,0 +1,488 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+ 嗯..! 目前共计 25 篇日志。 继续努力。 +
+ + +
+ 2017 +
+ + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2017/11/index.html b/archives/2017/11/index.html new file mode 100644 index 00000000..12498a67 --- /dev/null +++ b/archives/2017/11/index.html @@ -0,0 +1,488 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+ 嗯..! 目前共计 25 篇日志。 继续努力。 +
+ + +
+ 2017 +
+ + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2017/index.html b/archives/2017/index.html new file mode 100644 index 00000000..c47581f5 --- /dev/null +++ b/archives/2017/index.html @@ -0,0 +1,568 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+ 嗯..! 目前共计 25 篇日志。 继续努力。 +
+ + +
+ 2017 +
+ + + + + + + + + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2018/01/index.html b/archives/2018/01/index.html new file mode 100644 index 00000000..b83d8998 --- /dev/null +++ b/archives/2018/01/index.html @@ -0,0 +1,508 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+ 嗯..! 目前共计 25 篇日志。 继续努力。 +
+ + +
+ 2018 +
+ + + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2018/06/index.html b/archives/2018/06/index.html new file mode 100644 index 00000000..f5f14165 --- /dev/null +++ b/archives/2018/06/index.html @@ -0,0 +1,488 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+ 嗯..! 目前共计 25 篇日志。 继续努力。 +
+ + +
+ 2018 +
+ + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2018/10/index.html b/archives/2018/10/index.html new file mode 100644 index 00000000..ceebe434 --- /dev/null +++ b/archives/2018/10/index.html @@ -0,0 +1,488 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+ 嗯..! 目前共计 25 篇日志。 继续努力。 +
+ + +
+ 2018 +
+ + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2018/index.html b/archives/2018/index.html new file mode 100644 index 00000000..f46a1206 --- /dev/null +++ b/archives/2018/index.html @@ -0,0 +1,548 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+ 嗯..! 目前共计 25 篇日志。 继续努力。 +
+ + +
+ 2018 +
+ + + + + + + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2019/01/index.html b/archives/2019/01/index.html new file mode 100644 index 00000000..8c044929 --- /dev/null +++ b/archives/2019/01/index.html @@ -0,0 +1,488 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+ 嗯..! 目前共计 25 篇日志。 继续努力。 +
+ + +
+ 2019 +
+ + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2019/06/index.html b/archives/2019/06/index.html new file mode 100644 index 00000000..c75cfd28 --- /dev/null +++ b/archives/2019/06/index.html @@ -0,0 +1,488 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+ 嗯..! 目前共计 25 篇日志。 继续努力。 +
+ + +
+ 2019 +
+ + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2019/index.html b/archives/2019/index.html new file mode 100644 index 00000000..7d3c3980 --- /dev/null +++ b/archives/2019/index.html @@ -0,0 +1,508 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+ 嗯..! 目前共计 25 篇日志。 继续努力。 +
+ + +
+ 2019 +
+ + + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2020/05/index.html b/archives/2020/05/index.html new file mode 100644 index 00000000..968e1e1e --- /dev/null +++ b/archives/2020/05/index.html @@ -0,0 +1,488 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+ 嗯..! 目前共计 25 篇日志。 继续努力。 +
+ + +
+ 2020 +
+ + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2020/index.html b/archives/2020/index.html new file mode 100644 index 00000000..6f91e31c --- /dev/null +++ b/archives/2020/index.html @@ -0,0 +1,488 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+ 嗯..! 目前共计 25 篇日志。 继续努力。 +
+ + +
+ 2020 +
+ + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2023/07/index.html b/archives/2023/07/index.html new file mode 100644 index 00000000..d9c199fa --- /dev/null +++ b/archives/2023/07/index.html @@ -0,0 +1,508 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+ 嗯..! 目前共计 25 篇日志。 继续努力。 +
+ + +
+ 2023 +
+ + + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2023/11/index.html b/archives/2023/11/index.html new file mode 100644 index 00000000..4c73d1bd --- /dev/null +++ b/archives/2023/11/index.html @@ -0,0 +1,508 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+ 嗯..! 目前共计 25 篇日志。 继续努力。 +
+ + +
+ 2023 +
+ + + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2023/12/index.html b/archives/2023/12/index.html new file mode 100644 index 00000000..c8584599 --- /dev/null +++ b/archives/2023/12/index.html @@ -0,0 +1,488 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+ 嗯..! 目前共计 25 篇日志。 继续努力。 +
+ + +
+ 2023 +
+ + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/2023/index.html b/archives/2023/index.html new file mode 100644 index 00000000..d5975827 --- /dev/null +++ b/archives/2023/index.html @@ -0,0 +1,568 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+ 嗯..! 目前共计 25 篇日志。 继续努力。 +
+ + +
+ 2023 +
+ + + + + + + + + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/index.html b/archives/index.html new file mode 100644 index 00000000..e8a4aa9e --- /dev/null +++ b/archives/index.html @@ -0,0 +1,886 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+ 嗯..! 目前共计 25 篇日志。 继续努力。 +
+ + +
+ 2023 +
+ + + + + + + + + + +
+ 2020 +
+ + +
+ 2019 +
+ + + + +
+ 2018 +
+ + + + + + + + +
+ 2017 +
+ + + + + + + + + + +
+ 2016 +
+ + + + + + + + +
+
+ + + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/archives/page/2/index.html b/archives/page/2/index.html new file mode 100644 index 00000000..f3a2d605 --- /dev/null +++ b/archives/page/2/index.html @@ -0,0 +1,571 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 归档 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+ 嗯..! 目前共计 25 篇日志。 继续努力。 +
+ + +
+ 2016 +
+ + + + + + + + + + + + +
+
+ + + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/atom.xml b/atom.xml new file mode 100644 index 00000000..7ebb23ed --- /dev/null +++ b/atom.xml @@ -0,0 +1,575 @@ + + + nullwy's blog + + + + + + 2023-12-06T12:43:00.105Z + https://nullwy.me/ + + + nullwy + + + + Hexo + + + 流行互联网网站技术栈整理 + + https://nullwy.me/2023/12/popular-websites-tech-stack/ + 2023-12-03T15:37:00.000Z + 2023-12-06T12:43:00.105Z + + 技术栈是构建应用的技术集合,由编程语言、框架、库、服务器、数据库、工具等组合而成。组成技术栈的技术是与具体业务无关的基础软件。互联网公司选择的技术栈,倾向于使用开源软件,相对于专有软件,开源软件具有高质量、免费、开放、灵活等优势。互联网的早期开拓者 Yahoo 的技术栈选择是经典案例,受开源运动的影响,在 2000 左右 Yahoo 从最初基于自定义的专属软件迁移了到 LAMP 技术栈。

在“开源”(open source)一词出现之前,技术社区的黑客选择使用“自由软件”(free software)这个词。但是“自由软件”这个词与对知识产权的敌意、共产主义和其它观点相联系,几乎不受管理者和投资者的欢迎,于是 1998 年 2 月 3 日在由 Eric Raymond 等人参加的会议上“开源”一词诞生,2 月下旬开源软件促进会成立 OSI,Eric Raymond 担任主席。自由软件和开源软件被合称为 FOSS。缩写“LAMP”代表的是 Linux-Apache-MySQL-PHP,这些软件都是自由软件或开源软件。

案例汇总与解析

技术发展时间线

在互联网诞生早期,开源技术栈、开源社区尚未成熟,互联网公司不得不自研专有软件,随着开源软件的成熟,技术栈的选择开始从专有软件逐渐转向开源软件。先来看下,主要 Web 技术和服务端技术的发展时间线:

  • 1994.03,Linux 1.0 对外发布,源码采用 GPL 协议。
  • 1994.10,网景公司的 Web 浏览器 Netscape 首次对外发布。
  • 1995.04,Apache HTTP Server 首次对外开源发布,版本为 0.6.2,源码采用 Apache 协议
  • 1995.12,JavaScript 语言诞生,创造者为来自网景公司的 Brendan Eich。
  • 1995.05,Java 语言诞生,创造者为 Sun 公司。Java 平台早期并不真正开源,虽然 1998 年 JDK 1.2 开始以 SCSL 协议开放源代码,但 SCSL 协议限制太大,饱受批评,直到 2006.11 才以 GPL 协议真正开源。
  • 1995.06,PHP 语言诞生,源码采用 PHP 协议(BSD 风格的协议)。
  • 1995.12,HTML 标准规范首次发布,版本为 HTML 2.0
  • 1996.05,Sun 公司首次对外发布 Java Servlet API。
  • 1996.10,MySQL 首次公开对外发布,最初的公开发行版仅提供了 Solaris 的二进制发行版,一个月后,源代码和 Linux 二进制文件发布,源码采用的是专有协议“MySQL Free Public License”,到 2000.06 改为 GPL 协议。
  • 1996.10,PostgreSQL 的诞生日是在 10 月 22 日,在这一天 PostgreSQL.org 网站上线。PostgreSQL 之前的项目名为 Postgres,之所以改名是为了反映其对 SQL 的支持。源码采用 PostgreSQL 协议(类似 BSD 或 MIT 协议)。
  • 1996.12,微软发布 ASP 技术,到 2002 年 ASP 被 ASP.NET 替代。
  • 1998.12,缩写“LAMP”诞生,代表 Linux-Apache-MySQL-PHP。
  • 1999.12,Sun 公司首次对外发布 J2EE,版本为 1.2,包括 Servlet、JSP、EJB 等技术。
  • 2002.08,Nginx 首次对外发布,源码采用 BSD 协议。最初,研发 Nginx 目的是为了解决 C10k 问题。之后,Nginx 逐渐替代 Apache HTTP Server,LAMP 技术栈改为 LNMP 技术栈。
  • 2003.06,Java 的 Spring 框架首次对外发布,版本为 0.9,源码采用 Apache 协议。
  • 2004.08,Ruby on Rails 框架首次对外发布,源码采用 MIT 协议。
  • 2005.02,“Ajax”术语诞生,早期使用 Ajax 技术的经典案例是 Google 在 2004 发布的 Gmail 和 2005 发布的 Google Maps。
  • 2005.07,Python 的 Django 框架首次对外发布,源码采用 BSD 协议。
  • 2007.02,HBase 宣布在 Hadoop 项目中成立,成为 Hadoop 的子项目。HBase 是 Google 的 BigTable(OSDI'2006)论文的开源实现。
  • 2007.01,iPhone 手机首次对外发布,同年 6 月 iPhone 正式发售,11 月 Android 系统首次对外公布,移到互联网开始大爆发。
  • 2008.07,Facebook 对外开源 Cassandra 项目,项目受 Amazon 的 Dynamo(SOSP'2007)论文和 Google 的 BigTable(OSDI'2006)论文的。
  • 2009.06,“NoSQL”术语诞生。“NoSQL”术语诞生于在旧金山举行的一场关于“开源、分布式、非关系数据库”的技术聚会,该技术聚会被命名为“NoSQL meetup”。NoSQL 的两大起源是 BigTable 和 Dynamo。
  • 2009.11,Google 对外公开 Go 语言,BSD 协议开源。
  • 2011.04,451 Group 咨询公司的分析师 Matthew Aslett 创造“NewSQL”术语,是对用于 OLTP 的分布式关系型数据库的统称。最具代表性的 NewSQL 是 Google 的 Spanner(OSDI'2012)和 Amazon 的 Aurora(2014.10 发布的云原生数据库产品)。

技术栈案例汇总

按编程语言区别,主要流行的互联网产品的创建时间和早期的技术栈选择(也可以参见 wiki):

  • C/C++ 技术栈
    • Yahoo!(1994,2002 转向 PHP)、Amazon(1994,之后转向以 Java 为主)、eBay(1995,2002 全面转向 Java)、Google 搜索(1998)[1][2]新浪网(1998,之后转 PHP,2008 年 PHP 占据 90% 以上的 Web 开发)[3]腾讯 QQ(1999)、QQ 空间(2005)、微信(2011)[4]百度搜索(2000)、Yandex 搜索(2000)[5]
  • PHP(LAMP 或 LNMP)技术栈
    • Wikipedia(2001)[6]Facebook(2004,2006 核心服务转向 C++)、Flickr(2004)[7]Etsy(2005)[8]WordPress(2005)、新浪博客(2005)[9]百度百科(2006,2006 开始百科、知道、文库、贴吧等产品以 PHP 为主实现)[10]Tumblr(2007,2011 转向 Scala)[11]哔哩哔哩(2009,2017 转向 Golang)[12]新浪微博(2009,2011 转向 Java)[13]腾讯微博(2010)[14]美团(2010,2011 转向 Java)[15]滴滴(2012,2017 业务系统转向 Golang)[16]
  • Ruby on Rails 技术栈
    • Twitter(2006,2009 核心服务转向 Scala 和 Java)、Shopify(2006)[17]SoundCloud(2007,2012 业务转向多种 JVM 语言和基础设施转向 Golang)[18][19][20]Heroku(2007)[21]GitHub(2008)[22]Airbnb(2008,2016 开始服务化并部分转向 Java)[23][24]
  • Python 技术栈
    • Reddit(2005,少部分高性逻辑用 C 语言)[25]YouTube(2005)[26]豆瓣(2005)[27]Disqus(2007)[28]Dropbox(2007,2013 基础设施转向 Golang)[29][30][31]Quora(2009,高性能服务用 C++)[32]Pinterest(2009,部分服务转向 Java)[33][34]Instagram(2010,少部分高性逻辑用 C++)[35][36][37]Uber(2010,2015 转向 Golang 和 Java 等)[38]知乎(2011,2018 核心业务转向 Golang)[39]字节跳动(2012,今日头条、抖音等,2014 开始引入 Golang,2016 业务大规模转向 Golang)[40][41]
  • Java 技术栈
    • 淘宝(2003,2004 PHP 全面转向 Java)、LinkedIn(2003)、Google Gmail(2004)[42]Google Docs(2006)、Google+(2011)[43]人人网(2005)[44]Netflix(2007)[45]
  • .NET 技术栈
    • 携程(1999,2017 全面转向 Java)[46]京东(2004,2012 全面转向 Java)[47]Stack Overflow(2008)、Bing 搜索(2009)等

值得一提的是,PHP 之父 Rasmus Lerdorf,在 2002 年至 2009 年期间为供职于 Yahoo!,2011 年起至今供职于 Etsy。Python 之父 Guido van Rossum,在 2005 年至 2012 年期间供职于 Google,在 2013 年至 2019 年期间供职于 Dropbox。国内最有影响力的 PHP 技术专家是惠新宸,是加入 PHP 语言官方开发组的首位国人,曾先后供职于雅虎中国、百度、新浪微博、链家网等公司。

编程语言选择

2000 年前创建的网站,因为开源技术栈尚未成熟,编程语言基本上都是选择 C++ 开发。在开源技术栈成熟后,多数网站会选择拥抱开源。具体选择哪个编程语言,PHP、Ruby、Python、Java 等,主要由技术负责人的技术偏好决定。根据 w3techs 统计,历年网站使用的服务端编程语言统计占比,2012 年至今 10 多年,PHP 占比稳居榜首,每年都是 75% 以上。大型网站通常都是公司内的技术团队研发的,技术栈由技术团队选择,而很多小型网站,很可能会直接使用开源的 CMS 系统搭建。根据 w3techs 统计,前 100 万网站中有 43.0% 使用 WordPress 构建。WordPress 的服务端编程语言就是 PHP,数据库是 MySQL。大型网站选择 PHP 越来越少,因为 PHP 是解释型脚本语言,相对编译型编程语言有性能劣势。另外,PHP 的优势是快速开发 Web 动态网页,但是随着前后端分离开发模式的流行,Web 页面从服务端渲染逐渐转向客户端渲染,PHP 的优势不再,后端工程师只需要向前端提供 REST API 接口,展示层的实现完全由前端工程师实现。

早期部分网站选择 .NET 技术栈,比如京东携程。但是,Java 平台生态更完善,有非常多的经验可以借鉴。另外,.NET 平台本身虽然不收费,但是 Windows 操作系统是收费的,开发工具也不便宜。于是京东在 2012 年从 .NET 迁移到 Java,携程在 2017 左右从 .NET 迁移到 Java。目前在国内,多数互联网大厂都选择 Java 技术栈,如淘宝、美团、京东、微博、携程等,Java 相对来说是主流选择。

编程语言的另外一个流行趋势是 Go 语言。Go 语言诞生于 Google,在 2009 年 11 月对外公开。在发明 Go 语言前,Google 内部主要使用的语言是 C++、Java 和 Python 等,但是 Go 发明者认为这些语言无法同时满足高效编译、高效执行和易于编程的特性诉求,所以创造了 Go 语言[48]。Go 比 C++ 能更高效编译和易于编程,比 Java 更易于编程,比 Python 能更高效执行。在 GoCon Tokyo 2014 会议上,Go 语言研发团队的 Brad Fitzpatrick 对各种编程语言在编程乐趣和执行速度(Fun vs. Fast)的对比[49],如下图所示:

编程语言 Fun vs. Fast

早期由 Go 语言实现的经典开源项目主要是基础设施软件,比如 YouTube 的 Vitess 数据库分片中间件(2012.02 对外开源)、Docker 容器(2013.03 对外开源)、Red Hat 的 CoreOS 团队的 Etcd 分布式配置服务(2013.07 对外开源,实现 Raft 共识协议)、前 Google 工程师创建的 CockroachDB 分布式数据库(2014.02 对外开源,受 Google Spanner 启发)、Google 的 Kubernetes 容器编排系统(2014.06 对外开源)、SoundCloud 的 Prometheus 监控工具(2015.01 对外开源)等。大规模使用 Go 语言的代表性的国外的互联网公司有 SoundCloud[19:1][20:1]Dropbox[30:1][31:1]Uber[38:1] 等,国内的有七牛云字节跳动[40:1][41:1]哔哩哔哩[12:1]滴滴[16:1]知乎[39:1]百度[50][51]腾讯[52]等,在这些互联网公司 Go 语言通常主要被用于构建基础设施软件(网关、数据存储、监控、视频处理等)或高性能要求的业务服务,部分公司的大量核心业务也从 Python、PHP 等迁移到 Go 语言。使用 Go 语言的公司的更加完整的列表,可以参见官方整理的“GoUsers”。

数据库选择

数据库方面,根据 DB-Engines Ranking 的统计,流行的关系数据库主要是 4 个,开源免费的 MySQL 和 PostgreSQL,专有收费的 Oracle 和 Microsoft SQL Server。多数互联网产品使用的数据库是 MySQL,部分是 PostgreSQL 或 Oracle。一些早期使用 Oracle 数据库的网站选择部分或完全从 Oracle 数据库中迁出,代表性的案例是,Amazon 从 Oracle 完全迁移到 Amazon RDS 和 NoSQL,淘宝从 Oracle 完全迁移到 MySQL。以 PostgreSQL 为主数据库的互联网应用有 Skype、Reddit、Spotify、Disqus、Heroku、Instagram 等[53]

MySQL 相对 PostgreSQL 更加流行的主要原因是[54][55],在早期 MySQL 入门槛更低。MySQL 就支持在 Windows 下安装,而 PostgreSQL 只能在 Cygwin 下安装,MySQL 对 Windows 平台的支持使得初学者更容易上手,并且 MySQL 更加易于管理,能够快速简单地启动和使用,而且 MySQL 拥有一个非常简洁、易于导航和用户友好的在线文档和支持社区。另外一个重要原因是,MySQL 很早就默认支持复制(replication),而 PostgreSQL 的复制是第三方的,而且极其难用。之后的几年即便 PostgreSQL 完善了不足,但错过了流行的时间窗口,MySQL 成为了主流选择,有更完善的生态。不过,受 MySQL 被 Oracle 公司收购的影响,近几年 PostgreSQL 开始越来越流行,根据 DB-Engines Ranking 的统计,最新的 PostgreSQL 的流行度分数是 10 年前的三倍,流行度与前三名越来越接近。

传统关系数据库,因为在面对大数据量和高负载量时的性能和可扩展性较差,以及对数据模型的支持有限,逐渐演变出了分布式非关系数据库 NoSQL 和分布式关系数据库 NewSQL。NoSQL 数据库的按数据模型分类包括:键值数据库(比如 Redis、DynamoDB 等)、列族数据库(比如 Cassandra、HBase 等)、文档数据库(比如 MongoDB)、图数据库(比如 Neo4j)等。Redis,是内存型键值数据库,是目前缓存场景的主流解决方案。

技术栈和架构演进

容易发现多数网站的技术栈的演进模式类似。在创建网站早期通常选择使用 PHP、Ruby、Python 脚本语言和框架来开发,这些脚本语言和框架具有更快的开发效率,能快速交付上线。随着网站流量的增长,面临性能和可扩展性问题,通常会将网站服务化,从单体架构向面向服务的 SOA 和微服务架构演进,一大部分网站在服务化过程中会选择将核心业务改由其他性能更佳的编译型编程语言来实现,如 Java、Scala、C++、Go,原先的脚本语言可能全部废弃,也可能仅用于前端展示层的 Web 动态页面渲染,比如 Facebook、Twitter 等。当然也有一部分网站,演进为 SOA 和微服务架构后,业务逻辑的实现一直以最初的脚本语言为主。

在架构微服务化后,很多网站实现的微服务之间采用基于 HTTP 协议的 REST 方式通信(或者使用的 RPC 框架支持跨语言 RPC 调用),各个微服务的实现在理论上编程语言不需要统一,可以根据该微服务的性能要求或负责该微服务的团队的技术偏好自由选择,所以真实世界的互联网公司内部各个业务子系统的技术栈可能不统一。但是内部技术栈不统一会带来额外的维护成本。另外,考虑技术栈的迁移重构成本,新的业务子系统使用新的技术栈,而有些旧的业务子系统很可能继续使用旧的技术栈。除了业务子系统外,很可能团队内部有自研的中间件、运维工具等,这些组件由中间件团队、运维团队研发,很可能会选择与业务系统不一样的技术栈。

注意,解决网站的可扩展性问题,不一定需要演进为服务化架构。架构服务化意味着将完整的单体服务按业务的功能领域做垂直拆分,而实际上在应用服务层可以通过部署多个相同副本的单体服务的方式实现系统的水平扩展,网站的可扩展性问题主要在数据存储层上。拆分应用服务的好处在于能实现组织团队的规模化。解决数据库的扩展性的策略有,数据复制(数据缓存、数据库主从读写分离)、数据垂直拆分、数据水平拆分(也叫数据分片,sharding)。数据库被拆分后,如果单个事务内的数据分散在多个节点就要解决分布式事务问题,但是实现分布式事务代价太大,通常的选择是牺牲一致性,仅满足最终一致性(BASE)。

没有拆分应用服务,始终采用单体架构的经典案例是 Instagram,2019 年 Instagram 在技术博客上有这样一段话[37:1]

Our server app is a monolith, one big codebase of several million lines and a few thousand Django endpoints, all loaded up and served together. A few services have been split out of the monolith, but we don’t have any plans to aggressively break it up.

Instagram 解决可扩展性问题,主要在数据存储层[35:1][36:1]。在 Instagram,PostgreSQL 被用于存储用户信息、媒体元数据、用户关系等数据,照片媒体数据存储在亚马逊 S3 服务上。Instagram 对 PostgreSQL 数据库做了主从读写分离、数据垂直拆分和数据水平分片。另外,Instagram 从 2012 年开始使用 Cassandra 数据库,Cassandra 被用于存储 Feed 流、活动等数据。类似的,Reddit 也是单体架构,在数据存储层做了可扩展性改造[25:1]。对 PostgreSQL 数据库做了主从读写分离和垂直拆分,拆分为四个主数据库,链接、帐户、子版块、评论、投票和杂项,每个主数据库都从数据库。另外,投票数据存储在 Cassandra 数据库。

Yahoo!(1994)

Yahoo!,1994 年创立,早期网站操作系统是 FreeBSD,Web 服务器是自研的 Filo Server,数据库是自研的 DBM 文件,Web 动态页面脚本是自研的 yScript,业务逻辑编程语言是 C++。1996 年 Web 服务器改用 Apache HTTP Server,1999 年部分数据库改用 MySQL(同时也使用 Oracle 数据库),2002 年编程语言从 yScript 和 C++ 改为 PHP,操作系统也从 FreeBSD 逐渐转向 Linux[56][57][58]。在 2002.10 的 PHPCon 2002 会议上,Yahoo! 工程师 Michael Radwin 介绍了 Yahoo! 从专有软件向开源软件转向的原因和演进过程,以及选择 PHP 而不选择 ASP、Perl、JSP 等其他技术的原因[56:1]。Yahoo! 转向开源软件的原因主要是,避免维护专有软件的成本,开源软件从早期的不成熟最终变得成熟,具有更好的性能,更容易与第三方软件集成,以及开源社区逐渐发展壮大。2005 年,Yahoo! 的技术架构如下图所示[57:1]

Yahoo! 技术架构(2005)

2000 年 ~ 2010 年,Yahoo! 是世界上流量最大的网站,虽然期间被 Google 短暂超越,但随后又反超,一直到到 2010 年后才被 Google 彻底超越。2000 年前后 Yahoo! 转向到 MySQL 和 PHP,并在技术上助力 LAMP 生态的发展壮大,对 LAMP 技术栈的流行起到巨大的推动作用。值得一提的是,知名 MySQL 专家 Jeremy Zawodny,《高性能MySQL》2004 年第 1 版(豆瓣)的作者,在 1999.12 ~ 2008.06 期间为 Yahoo! 工程师;PHP 之父 Rasmus Lerdorf 在 2002.09 ~ 2009.11 期间为 Yahoo! 工程师。

Amazon(1994)

Amazon,1994 年创立,早期是单服务、单数据库的单体架构,使用的编程语言是 C++,2000 年开始从单体架构向 SOA 和微服务架构演进,使用最多的语言变为 Java,C++ 被用在高性能要求的系统和底层基础设施组件。Amazon 架构演进过程如下图所示[59]

Amazon 架构演进

Amazon.com 的技术栈演进过程:

  • 1995 ~ 2000:Unix(Sun)、Obidos、Oracle、C++
    • Obidos 是亚马逊内部 Web 动态页面渲染引擎,编程语言是 C++。
  • 2000 ~ 2006:Linux、Obidos、Oracle、C++
    • 2000 年,开始将 Sun 服务器替换为 HP/Linux 服务器,并同时开始拆分应用服务,向 SOA 架构演进。
    • 2005 年初,开始将 Obidos 框架替换为 Gurupa 框架,Gurupa 是 Web 页面渲染引擎,同时也是 SOA 框架。Web 动态页面的编程语言从 C++ 替换为 Perl/Mason,同时应用服务开始被更细粒度的拆分。
  • 2006 年开始:Linux、Gurupa、Oracle、Perl & Java & C++
    • 2019.10,彻底去掉 Oracle 数据库,迁移到 Amazon RDS 和 NoSQL。

当前 Amazon.com 网站的主要技术栈[59:1][60][61][62]

  • 应用服务
    • 展示层:Perl/Mason
    • 业务逻辑层:Java(主要)、C++ 等
    • RPC框架:Gurupa 框架(自研闭源)
      • 2006 年更早之前使用 Obidos 框架
    • 消息队列MQAmazon SQS
  • 数据存储[63]
    • 关系数据库:Amazon RDS for PostgreSQL[64]、Amazon Aurora (PostgreSQL)
      • 2019 年 10 月彻底去掉 Oracle 数据库,迁移到 Amazon RDS 和 NoSQL。
    • 键值存储Amazon DynamoDB
    • 缓存:Amazon ElastiCache for Redis[65]
    • Blob文件存储Amazon S3
  • 数据分析Amazon Kinesis、Amazon EMR、AWS LambdaAmazon Redshift

eBay(1995)

eBay,1995 年创立,早期使用的编程语言是 Perl,1997 年迁移到 C++,2002 年迁移到 Java。eBay 的技术栈演进过程[66][67]

  • 1995 ~ 1997:FreeBSD、Apache、GDBM、Perl
  • 1997 ~ 2002:Windows、IIS、Oracle、C++
    • 1999.02,开始应用服务器池化和水平扩展;数据库服务器垂直扩展(替换为高端服务器 Sun E10000)
    • 1999.11,开始数据库水平扩展,按功能垂直拆分、数据水平分片。
  • 2002 ~ 2006:Windows、IBM WebSphere、Oracle、Java(J2EE)
    • 2002 年,开始将 C++ 替换为 Java,使用 J2EE 框架
  • 2006 年开始:Ubuntu、Tomcat、Oracle、Java(Spring/Spring Boot)
    • 2007 年初,开始向 SOA 架构演进,再然后演进为微服务架构[68][69]

2016 年,eBay 的技术架构如下图所示[69:1]

eBay 技术架构(2016)

当前 eBay 的主要技术栈[66:1][67:1][69:2][70]

  • 应用服务
    • 展示层:Java、Spring MVC
    • 业务逻辑层:Java、Spring、Spring Boot
    • RPC框架:Raptor、Raptor.io(自研闭源,基于 Spring、Spring Boot)
    • 消息队列MQ:BES (business event stream)(自研闭源)、BES2(自研闭源,基于 Kafka 实现,BES2 API 完全兼容 BES1)[71]
  • 数据存储[72]
    • 关系数据库:Oracle(主)、MySQL(次)
    • NoSQL:Apache Cassandra、MongoDB
    • 搜索引擎:Elasticsearch[73]
  • 数据分析[74]:Apache Kafka、Apache Flink、Apache Kylin(自研开源,MOLAP 数仓)、ClickHouse(ROLAP 实时数仓) 等
    • Apache Kylin,2014.10 对外开源,2014.11 成为 Apache 孵化器项目,2015.12 从 Apache 孵化器毕业。

淘宝(2003)

淘宝技术架构[75][76][77][78][79],是从 LAMP 架构演变而来的。在 2003 年 5 月最早上线时,淘宝是对购买得到的采用 LAMP 架构网站源码进行二次开发的网站。为了应对网站流量的增长,2003 年底数据库从 MySQL 切换到 Oracle,2004 年初编程语言从 PHP 迁移到 Java,同时硬件演变为 IBM 小型机和 EMC 高端硬件存储,依赖的基础设施被统称为“IOE”(IBM 小型机、Oracle 数据库、EMC 存储设备),这个架构被称为 2.0 架构。

2007 年底开始拆分第一个业务中心是用户中心(UIC,User Information Center),在 2008 年初上线。2008 年初,启动“千岛湖”项目,拆分出了交易中心(TC,Trade Center)和类目属性中心(Forest)。2008 年 10 月,为了打通淘宝网和淘宝商城(后来的天猫)的数据,启动“五彩石”项目,拆分出了店铺中心(SC,Shop Center)、商品中心(IC,Item Center)、评价中心(RC,Rate Center)。到 2009 年初,“五彩石”项目结束,阿里电商架构也从之前的单体架构演进为了 SOA 服务化架构,被称为 3.0 架构,同时淘宝网和淘宝商城也完成了数据整合,并淘宝网和淘宝商城的共享业务沉淀到多个业务中心。在 2009 年,共享业务事业部成立,在组织架构上共享业务事业部和淘宝、天猫平级。在业务中心的上层业务服务有,交易管理(TM,Trade Manager)、商品管理(IM,Item Manager)、店铺系统(ShopSystem)、商品详情(Detail)、评价管理(RateManager)等。2009 年淘宝的服务化拆分如下图所示[77:1]

淘宝的服务化拆分(2009)

在各个应用服务拆分的同时,数据库也按业务功能做了垂直拆分,2008 年 Oracle 被拆分为商品、交易、用户、评价、收藏夹等 10 来套。当时的淘宝的分布式架构设计,包括 Java + Oracle 技术栈的选择,以及应用服务和数据库的拆分策略,很大程度上参考的是 eBay 的架构[75:1][78:1]。对照 eBay 架构师在 2006 年 11 月对外分享的 eBay 架构的 slides[66:2],容易发现两者大同小异。

因为使用 Oracle 成本太高,2008 年 8 月淘宝数据库设计了异构数据库读写分离架构,写库为集中式的 Oracle,读库使用分库分表的 MySQL,该数据库架构方案基于自研的数据库中间件 TDDL 实现[80]。之后的几年,数据库逐渐向 MySQL 迁移。2008 年 9 月前微软亚洲研究院常务副院长王坚博士加盟阿里巴巴集团,担任首席架构师,2009 年 11 月时任阿里 CTO 的王坚博士决策启动阿里“去IOE”工程。淘宝的“去IOE”工程的关键时点[81]

  • 2009.07,王坚博士开始担任阿里首席技术官 CTO。
  • 2009.11,王坚博士决策启动阿里“去IOE”工程。
  • 2010.01,大淘宝核心系统“去IOE”工作启动。
  • 2010.07,淘宝商品库完成“去I”。
  • 2011.07,淘宝商品库从 Oracle 迁移到 MySQL,完成“去IOE”。
  • 2011.09,淘宝交易库从 Oracle 迁移到 MySQL,完成“去IOE”。
  • 2012.12,完成大淘宝“去IOE”。

值得注意的是,在 2011 年淘宝商品库和交易库“去IOE”的同时,为了满足数据库的性能要求,底层硬件从 HDD 机械硬盘改为 SSD 固态硬盘。而庆幸的是,当时的前几年正好是 SSD 大爆发的时间点[82]。在消费级 SSD 市场,2010 年苹果的 MacBook Air 开始全面改用 SSD,2012 年苹果的 MacBook Pro 开始全面改用 SSD。在数据库服务器层面,因为 SSD 在随机读写的性能具有巨大优势,2010 年开始机械硬盘改用 SSD 成为趋势,当时的 MySQL 新版代码也专门针对 SSD 做了性能优化[83]

2009 年初淘宝演变为 SOA 架构后,服务拆分粒度越来越细,到 2009 年底拆分出的总服务数达到 187 个,到 2010 年底达到 329 个[77:2]。因为系统依赖关系越来越复杂,当时最大问题是稳定性问题,系统的稳定性建设成为重点工作。到 2013 年阿里电商系统开始 4.0 架构改造,即异地多活架构改造,内部称为单元化项目。2013 年 8 月完成杭州同城双活,2014 年双 11 前的 10 月完成杭州和上海近距离两个单元的异地双活,2015 年双 11 完成三地四单元的异地多活[76:1][79:1],至此也完成了 3.0 到 4.0 架构的升级。在阿里电商系统迁移到阿里云公共云方面,2015 年阿里电商系统开始采用混合云弹性架构,当阿里本地保有云无法支撑时,就快速在公有云上扩建新的单元,当流量过去后,再还资源给公有云。2015 年 10% 的双 11 大促流量使用了阿里云的机器来支撑,2016 年 50% 以上的双 11 大促流量使用了阿里云的机器来支撑[76:2]。2019 年初,阿里电商开启了全面上公共云的改造,到 2019 年双 11,阿里电商系统实现了全部核心应用上公共云,2021 年双 11,阿里电商系统实现了 100% 上公共云。

当前阿里电商系统(淘宝、天猫等)的主要技术栈[78:2][79:2]

  • 应用服务
    • 展示层:Java
    • 业务逻辑:Java、Spring、Spring Boot 等
    • RPC框架:HSF(2008 自研闭源)、Apache Dubbo(2008 自研,2011.10 对外开源)
    • 消息队列MQApache RocketMQ(自研,2013.09 对外开源)
      • 2007 年自研 Notify;2011 年自研 MetaQ;2013.09,对外开源发布 RocketMQ 3.0。RocketMQ 3.0 和 MetaQ 3.0 等价,阿里内部使用的称为 MetaQ 3.0,外部开源称之为 RocketMQ 3.0。
    • 链路追踪:鹰眼 EagleEye(2012 自研闭源)
      • 2012 年内部发布鹰眼 1.0,参考 Google 2010 年的 Dapper 论文
    • 注册和配置服务:ConfigServer(2008 自研闭源)、Nacos(自研,2018.07 对外开源)
      • 2008 年,淘宝团队内部自研 ConfigServer 并发布 1.0,被用于 HSF 的服务发现。2018.07,Nacos 对外开源,是 ConfigServer 的开源实现,在阿里内部 Nacos 被用在钉钉、考拉、饿了么、优酷等业务线。
  • 数据存储
    • 关系数据库:MySQL (阿里云 RDS,底层基于 MySQL 自研 AliSQL)、自研 TDDL 中间件、阿里云分布式式数据库 PolarDB-X、MySQL 的 X-Engine 存储引擎
      • 2008 年,淘宝团队内部自研 TDDL 中间件,用于实现数据库的读写分离、分库分表。
      • 2014 年,淘宝 TDDL 团队和阿里云 RDS 团队合作,在阿里云上输出产品分布式数据库服务 DRDS,2014.06 DRDS 开始公测,2014.12 正式上线。DRDS 脱胎于阿里 B2B 团队开源的 Cobar 分布式数据库引擎(2012.06 对外开源),同时借鉴了淘宝 TDDL 丰富的分布式数据库实践经验。
      • 2020 年,阿里云发布分布式式数据库 PolarDB-X,融合了分布式 SQL 引擎 DRDS 与分布式自研存储 X-DB(X-Cluster)。
      • MySQL 的 X-Engine 存储引擎,早期代码源自 Facebook 的 RocksDB 4.8.1(2016.07 发布),被应用在阿里的交易历史库、钉钉历史库等核心系统。
    • 缓存Tair(2009 自研,2010.06 对外开源,分布式键值存储,支持基于内存和文件的两种存储方式)
      • 2009.04,Tair 1.0 正式诞生,并被应用于淘宝核心系统、MDB缓存、用户中心等业务。
      • 2010.06,Tair 对外开源。
      • 2014.05,阿里云推出基于 Tair 的缓存产品 OCS。
      • 2019.11,阿里云发布 Redis 企业版,即 Tair 3.0,兼容 Redis 5.0。
    • 列族数据库:Apache HBase,为淘宝推荐、手淘消息等提供支撑的数据库
      • 早期淘宝交易订单的所有数据都存储在单独的 Oracle 数据库;2010 年拆分为在线库和历史库,三个月之前的历史订单迁移进单独的 Oracle 历史库;2011 年交易历史库整体迁移到 HBase;2018 年历史库迁移到基于 X-Engine 存储引擎的 PolarDB-X 集群[84]
    • 搜索引擎:Havenask(自研,2022.12 对外开源)
      • 支持了淘宝、天猫、菜鸟、优酷、高德、饿了么等在内整个阿里的搜索业务。阿里云的 OpenSearch 产品底层基于 Havenask 实现。
    • Blob文件存储:阿里云 OSS
      • 早期采用 NetApp 提供的 NAS 存储设备;2007.06 开始基于自研的 TFS(Taobao File System);2010.09 对外开源 TFS;2016 迁移到阿里云 OSS[85]
  • 数据分析:阿里云 Flink、阿里云 MaxCompute(离线数仓)、阿里云 Hologres(实时数仓)等
    • 早期阿里内部三大实时计算引擎并存,Galaxy、JStorm、Blink(Apache Flink 的分支),2017 年开始统一到 Blink。2019.01,阿里收购 Apache Flink 母公司 Data Artisans,随后阿里的 Blink 正式开源,之后 Blink 和 Flink 完成合并。2021 年开始,阿里内部的实时计算使用的是 Blink 团队与 Flink 创始团队联合打造了 Flink 企业版平台,即 VVP(Ververica Platform)。

2016 年,阿里产品专家倪超对外介绍的阿里电商技术架构,如下图所示[86]

阿里电商技术架构(2016)

类似的,阿里巴巴中间件首席架构师《企业IT架构转型之道》(豆瓣)作者钟华在 2017 年对外介绍的阿里电商技术架构图[87]

阿里电商中台架构(2017)

2017 年,阿里中间件技术部专家谢吉宝对外介绍的阿里中间件技术大图[79:3]

阿里中间件技术大图(2017)

阿里 HSF 与 Dubbo 的历史演进时间线:

  • 2008 年,阿里淘宝团队自研 HSF 框架,5 月发布 HSF 1.1。
  • 2009 年初,由阿里 B2B 团队研发的 Dubbo 发布 1.0 版本。阿里内部淘系(淘宝、天猫、一淘等)主要使用的服务框架是 HSF,而阿里 B2B 使用的则是 Dubbo,二者独立,各行其道,彼此不通[88]
  • 2010.04,重构后发布 Dubbo 2.0 版本。
  • 2011.10,Dubbo 对外开源,版本为 2.0.7。因为在功能完善性、架构优雅性、使用简便性等方面有其相对独特的优势,开源后被国内很多互联网公司广泛使用[89],包括去哪儿,京东、当当网、网易考拉、有赞等。
  • 2012 年,阿里内部架构调整,开始统一技术基础设施,合并重复项目,决定把 Dubbo 合并到 HSF 里面去[90]。随后,HSF 发布 2.0 的版本,兼容 Dubbo 的协议,HSF 推出后很快就在阿里集团全面铺开[88:1]。Dubbo 项目在阿里内部被抛弃,在 2012.10 发布 2.5.3 版本之后就停止更新,2013 年和 2014 年更新了 2 次 Dubbo 2.4 的维护版本,然后停止了所有维护工作。
  • 2014.10,当当网开源 Dubbox,基于 Dubbo 2.5.3 的代码,为 Dubbo 新增了 REST 风格远程调用、Kryo/FST 序列化等特性。
  • 2016.01,阿里云互联网中间件产品 EDAS 正式商用,EDAS 所提供的分布式服务框架源自阿里的 HSF。
  • 2017.09,Dubbo 重启维护,对外发布恢复维护后的第一个版本是 2.5.4。之所以重启是因为阿里云上的客户大部分使用 Dubbo,阿里云想要将基于 Dubbo 的解决方案作为自己的一个产品,卖给这些客户[88:2][90:1]
  • 2018.01,Dubbo 2.6.0 发布,合并了当当网提供的 Dubbox 分支。
  • 2018.02,阿里宣布将 Dubbo 捐献给 Apache,进入 Apache 孵化器。
  • 2018.11,阿里云 EDAS 产品版本升级,新版本实现 SpringCloud 和 Dubbo 用户代码零侵入就能迁移至 EDAS。
  • 2018.12,Dubbo 3.0 正式进入开发阶段,Dubbo 3.0 是 HSF 与 Dubbo 的融合版本。
  • 2019.01,Dubbo 2.7.0 发布,包名切换到 org.apache,全面拥抱 Java 8。
  • 2019.05,Dubbo 从 Apache 毕业,成为 Apache 的顶级项目。
  • 2020 年,在双十一前在阿里内部率先由阿里考拉实现了 Dubbo 3.0 的全面部署。
  • 2021.06,Dubbo 3.0 正式发布。
  • 2022 年,阿里集团几乎所有的业务线(包括淘宝、天猫、饿了么、钉钉等)全面从 HSF2 迁移到 Dubbo3。阿里内部使用的是 HSF3,HSF3 与以往的 HSF2 完全不同,HSF3 完全就是基于标准 Dubbo3 的 SPI 扩展库[91][92]

阿里 RocketMQ 的历史演进时间线:

  • 2007,自研 Notify,最早底层的消息存储采用本地文件存储,参考 ActiveMQ 实现了单机 kv 存储引擎,2008 年底层的消息存储改用 Oracle,2010 年从 Oracle 迁移到高可用 MySQL 存储集群[93]
  • 2011.01,基于 Kafka 的设计用 Java 完全重写并发布 MetaQ 1.0。
  • 2012.03,MetaQ 1.x 对外开源,项目名为 Metamorphosis
  • 2012.09,淘宝内部发布 MetaQ 2.0 版本,MetaQ 2.0 对架构进行了重新设计,对消息日志文件存储目录结构做了改造[94]。改造后的 MetaQ 架构与 Kafka 存在很大差异,这个版本的 MetaQ 可以认为是第一代的 RocketMQ。
  • 2013.07,淘宝内部发布 MetaQ 3.0 版本,增加了主从复制(replication)、延迟消息等特性。
    • 值得注意的是,Kafka 的复制特性,直到 2013.12 发布的 0.8.0 版本才开始支持。MetaQ 实现的复制特性类似与 MySQL 的主从复制,而 Kafka 实现的复制是集群间的分区复制(Intra-cluster Replication),复制的单位是分区(partition),参见 KAFKA-50。分区,在其他系统中也被叫做分片(shard),含义相同。
  • 2013.09,对外开源发布 RocketMQ 3.0。RocketMQ 3.0 和 MetaQ 3.0 等价,阿里内部使用的称为 MetaQ 3.0,外部开源称之为 RocketMQ 3.0[95]
  • 2014.10,阿里云消息队列 ONS(云开放消息服务,Open Notification Service)对外公测,ONS 是基于阿里消息中间件 MetaQ(RocketMQ)打造的云消息产品。
  • 2016.11,阿里巴巴将 RocketMQ 捐赠给 Apache,成为 Apache 孵化器项目。
  • 2017.09,RocketMQ 从孵化器毕业,正式成为 Apache 顶级项目。

LinkedIn(2003)

LinkedIn,2003 年创立,采用纯 Java 技术栈,早期是单体架构,到 2008 年演化为 SOA 架构[96]。到 2010 年拆分的服务数超过 150 个,到 2015 年拆分的服务数超过 750 个[97]

2008 年,LinkedIn 对外介绍的技术架构如下图所示[96:1]

LinkedIn 技术架构(2008)

2012 年,LinkedIn 对外介绍的关注在数据基础设施上的技术架构图[98]

LinkedIn 数据基础设施架构(2012)

当前 LinkedIn 的主要技术栈[96:2][97:1]

  • 应用服务
    • 展示层:Java、Spring MVC、
    • 业务逻辑层:Java、Spring
    • RPC框架
      • Rest.li(自研开源),REST + JSON 框架。2023.04,对外宣布 Rest.li 项目不再活跃,为了提升性能,迁移到 Protobuf + gRPC。
    • 消息队列MQ:ActiveMQ
  • 数据存储[98:1][99][100]
    • 关系数据库:Oracle(主)、MySQL(次)
    • 缓存:Memcached
    • 键值存储Voldemort(自研,2009.01 对外开源)
      • 2009.01 对外开源,设计受 Amazon Dynamo 论文影响。2018 年之后 LinkedIn 不在使用 Voldemort,数据迁移到 LinkedIn 的 Venice 数据库
    • 文档数据库Espresso(自研闭源),分布式文档数据库
      • 2011 年初开始计划和设计,2012.06 在生产环境部署,底层实现基于 MySQL、Lucene、ZooKeeper。
    • 图数据库:LIquid(自研闭源)
    • 搜索引擎:基于 Lucene
    • Blob文件存储Ambry(自研,2016.05 对外开源)
  • 数据分析[98:2][99:1][100:1]
    • 数据采集
      • Databus(自研,2013.02 对外开源)
        • 数据变更抓取 CDC 工具,支持 Oracle 和 MySQL,2012.10 在 SoCC 2012 会议上发表论文,2013.02 对外开源。
      • Apache Kafka(自研,2011.01 对外开源)
        • 2011.07 成为 Apache 孵化器项目,2012.10 从 Apache 孵化器毕业
    • 计算引擎:Apache Hadoop、Apache Samza(自研开源)、Apache Spark、Apache Flink
      • Apache Samza,2013.09 对外开源,2015.01 从 Apache 孵化器毕业
    • 数据仓库:Apache Hive、Presto、Venice

Facebook(2004)

Facebook,2004 年创立,早期采用 LAMP 技术栈,为了应对负载增长开始服务化,将核心业务从 LAMP 中移出到新的服务,新的服务改用使用 C++、Java 等编写。为了解决 PHP 进程与非 PHP 进程的 RPC 通信问题,2006 年内部研发了跨语言的 RPC 库 Thrift,2007.04 对外开源。PHP 代码用于实现前端展示层的 Web 动态页面渲染,以及对服务层的数据聚合。

2010 年,Facebook 工程师 Aditya Agarwal 对外介绍的 Facebook 技术架构如下图所示[101]

Facebook 技术架构(2010)

Facebook 的技术栈图[102]

Facebook 技术架构(2008)

Facebook 的 NewsFeed 服务的架构图[102:1]

Facebook NewsFeed 技术架构(2008)

Facebook 的 Search 服务的架构图[102:2]

Facebook Search 技术架构(2008)

当前 Facebook 的主要技术栈[101:1][102:3][103]

  • 应用服务
    • 展示层:PHP(早期采用 LAMP 技术栈)、HHVM2011.12 对外开源)、Hack(2014.03 对外发布)
    • 业务逻辑层:Hack、C++(主要用于实现性能敏感服务,包括 Ads、News Feed、Search 等)、Rust、Java 等[104][105]
    • RPC框架Apache Thrift(自研开源)
      • 2005 年末开始研发;2007.04 对外开源;2008.05 成为 Apache 孵化器项目;2010.10 从 Apache 孵化器毕业。
    • 消息队列MQ:Wormhole(自研闭源)
      • 2013.06 对外介绍;2015.05 在 NSDI 2015 会议上发表论文。Wormhole 是发布-订阅系统,消息发布者直接读取数据存储系统的写事务日志,投递给对消息感兴趣的订阅者,订阅者可能是 News Feed、Cache、Index Servers 等。
  • 数据存储
    • 关系数据库:MySQL、MySQL 存储引擎 MyRocks(自研,2015.11 对外开源)
      • RocksDB 是 Facebook 在 2012.04 创建的内嵌的键值数据库,基于 Google 开源的 LevelDB 代码。
      • MyRocks 是 Facebook 基于 RocksDB 数据库实现的 MySQL 存储引擎,2014 年开始研究 RocksDB 和 MySQL 的集成,2015.11 对外开源,在 2016.04 在 Percona Live 2016 会议上最早对外介绍。
      • 2017.08,Facebook 将 UDB 数据库(User Database,存储社交活动数据)从 InnoDB 完全迁移到了 MyRocks,迁移后存储空间使用量减少了一半,而 CPU 和 IO 使用率没有明显变化。
      • 2018.06,Facebook 在博客上对外介绍已经将 Messenger 应用的数据从 HBase 迁移到了 MyRocks,迁移后存储空间使用量减少 90%,读取延迟比以前的系统低 50 倍。值得注意的是,Messenger 应用的数据最早存储在 Facebook 自研的 Cassandra 上,2010 年底发布新版的 Messenger 开始,改为存储在 HBase 上。
    • 键值存储ZippyDB(自研闭源),基于 RocksDB 实现的分布式键值数据库,2013 年开始在 Facebook 部署使用
    • 缓存Mcrouter(自研开源),实现分布式扩展的 Memcached
      • Facebook 早在 2005.04 就已经开始使用 Memcached;2013.04NSDI 2013 会议上发表论文,描述对 Memcached 的分布式扩展性改造。
    • 图数据库TAO(自研闭源),底层是 Memcache 和 MySQL
    • 搜索引擎Unicorn(自研闭源),基于标准的搜索引擎的概念,但增加了社交图谱搜索的特性。Facebook 搜索功能(包括 Facebook Graph Search 产品)底层实现基于 Unicorn。
      • 2013.03 Facebook Graph Search 产品对外推出,2014.12 开始原始的图谱搜索公开可见度降低,2019.06 几乎完全弃用。
      • 2015 年初,Instagram 的搜索引擎从 Elasticsearch 迁移到 Unicorn[106]
    • Blob文件存储:Haystack(自研闭源)
      • 2009.04 对外介绍;2010.10 在 OSDI 2010 会议上发表论文。基于 Haystack 论文的开源实现包括:SeaweedFS、bilibili 的 BFS 等。
  • 数据分析[107][108]
    • 日志采集Scribe(自研,2008.10 对外开源)
    • 计算引擎:XStream(Puma、Stylus、Swift)
    • 数据仓库Apache Hive(自研,2008.08 对外开源)、Presto(自研,2013.11 对外开源)、Laser、Scuba

Twitter(2006)

Twitter,2006 年创立,早期采用 Ruby on Rails 技术栈,数据库是 MySQL,2009 年开始服务化,将核心业务从 Ruby on Rails 中移出到新的服务,新的服务用 Scala、Java 编写[109][110]

2013 年,Twitter 工程师总结的 Twitter 从单体架构向分布式架构演进的过程,如下图所示[110:1]

Twitter 单体架构Twitter 服务化架构(2013)

当前 Twitter 的主要技术栈[109:1][110:2]

  • 应用服务
    • 展示层:Ruby on Rails
    • 业务逻辑层:Scala(主要)、Java
    • RPC框架Finagle(自研,2011.08 对外开源)
      • 使用 Finagle 框架的公司包括:Foursquare(2010 PHP 转向 Scala)、Pinterest(Python + Java)、SoundCloud(Ruby + JVM)、Tumblr(PHP + Scala) 等。
    • 消息队列MQ:Kestrel(2008.11 对外开源) -> DistributedLog -> Kafka
    • 链路追踪Zipkin(自研开源)
      • 2012.06,对外开源,是 Google Dapper 链路追踪系统的开源实现。
      • 2015 年中,项目从 Twitter 转交到 OpenZipkin 开源组织。
  • 数据存储[111]
    • 关系数据库:MySQL、Manhattan(自研闭源,基于 MySQL 的分布式数据库)
      • 最初所有数据都存储在 MySQL 上。
      • 2009 年底,计划从 MySQL 迁移到 Cassandra,打算用 Cassandra 存储推文 Tweets 数据,但最终改变了策略,继续使用 MySQL,Cassandra 仅被用于存储分析数据[112]
      • 2010.04,对外开源数据库分片框架 Gizzard,基于 Gizzard 的分布式数据库 T-bird 被用于存储推文 Tweets 数据[113]
      • 2014.04,对外介绍自研的基于 MySQL 的分布式数据库 Manhattan,被用于存储推文 Tweets 等主要数据,Cassandra 被废弃。
      • 2018 年中,开始将 Manhattan 底层使用的 MhBtree 存储引擎改为基于 RocksDB 存储引擎。
    • 缓存和键值存储:Redis、Memcached
    • 图数据库FlockDB(自研开源)
    • 搜索引擎:Earlybird[114](自研闭源)、Elasticsearch[115],用于推文 Tweets、用户、消息等搜索
      • 2010 年,自研基于 Lucene 实现的 Earlybird 搜索引擎,替代旧的基于 MySQL 实现的搜索[114:1]
    • Blob文件存储:Blobstore(自研闭源)
  • 数据分析[116]:Kafka、Cloud BigTable、Cloud BigQuery 等

参考资料


  1. 2007 Jeff Dean: Software Engineering Advice from Building Large-Scale Distributed Systems (Stanford CS295 class lecture, Spring, 2007) https://research.google.com/people/jeff/stanford-295-talk.pdf ↩︎

  2. 2008-11 Google Architecture http://highscalability.com/blog/2008/11/22/google-architecture.html ↩︎

  3. 2008-06 新浪夏清然、徐继哲:自由软件和新浪网. 程序员 2008年第6期54-55 http://lib.cqvip.com/Qikan/Article/Detail?id=27523653 http://www.zeuux.com/blog/content/3620/ ↩︎

  4. 2016-01 微信张文瑞:从无到有:微信后台系统的演进之路 https://www.infoq.cn/article/the-road-of-the-growth-weixin-background ↩︎

  5. 2008-02 Yandex Architecture http://highscalability.com/yandex-architecture ↩︎

  6. 2007-08 Wikimedia architecture http://highscalability.com/wikimedia-architecture ↩︎

  7. 2007-11 Flickr Architecture http://highscalability.com/flickr-architecture ↩︎

  8. 2016-03 What does Etsy's architecture look like today? http://highscalability.com/blog/2016/3/23/what-does-etsys-architecture-look-like-today.html ↩︎

  9. 2011-05 新浪刘晓震:新浪博客应用架构分享 (PHPChina 2011) https://web.archive.org/web/0/http://www.phpchina.com/?action-viewnews-itemid-38418 https://www.modb.pro/doc/121035 ↩︎

  10. 2013-11 百度张东进:百度PHP基础设施构建思路 (QCon上海2013, slides, 30p) https://www.modb.pro/doc/121042 ↩︎

  11. 2013-05 The Tumblr Architecture Yahoo Bought for a Cool Billion Dollars http://highscalability.com/blog/2013/5/20/the-tumblr-architecture-yahoo-bought-for-a-cool-billion-doll.html ↩︎

  12. 2017-06 B站任伟:B站高性能微服务架构 https://zhuanlan.zhihu.com/p/33247332 ↩︎ ↩︎

  13. 2021-05 微博刘道儒:十年三次重大架构升级,微博应对“极端热点”的进阶之路 https://www.infoq.cn/article/qgwbh0wz5bvw9apjos2a ↩︎

  14. 2012-08 腾讯张松国:腾讯微博架构介绍 (ArchSummit深圳2012, slides, 59p) https://www.slideshare.net/dleyanlin/08-13994311 ↩︎

  15. 2016-02 美团夏华夏:从技术细节看美团架构 (ArchSummit北京2014) https://www.infoq.cn/article/see-meituan-architecture-from-technical-details http://bj2014.archsummit.com/node/596/ https://www.modb.pro/doc/8311 ↩︎

  16. 2019-06 滴滴杜欢:大型微服务框架设计实践 (Gopher China 2019) https://www.infoq.cn/article/EfOlY8_rubh4LfoXzF8B https://www.modb.pro/doc/35485 ↩︎ ↩︎

  17. 2018-08 E-Commerce at Scale: Inside Shopify's Tech Stack - Stackshare.io https://shopify.engineering/e-commerce-at-scale-inside-shopifys-tech-stack ↩︎

  18. 2013-03 Phil Calçado @ SoundCloud: From a monolithic Ruby on Rails app to the JVM (slides, 75p) https://www.slideshare.net/pcalcado/from-a-monolithic-ruby-on-rails-app-to-the-jvm ↩︎

  19. 2012-07 Go at SoundCloud https://developers.soundcloud.com/blog/go-at-soundcloud ↩︎ ↩︎

  20. 2014-04 Peter Bourgon @ SoundCloud: Go: Best Practices for Production Environments (GopherCon 2014) http://peter.bourgon.org/go-in-production/ ↩︎ ↩︎

  21. 2009-04 Heroku - Simultaneously Develop and Deploy Automatically Scalable Rails Applications in the Cloud http://highscalability.com/blog/2009/4/24/heroku-simultaneously-develop-and-deploy-automatically-scala.html ↩︎

  22. 2021-07 GitHub’s Journey from Monolith to Microservices https://www.infoq.com/articles/github-monolith-microservices/ ↩︎

  23. 2017-12 Building Services at Airbnb, Part 1 https://medium.com/airbnb-engineering/c4c1d8fa811b ↩︎

  24. 2020-11 Jessica Tai @ Airbnb: How to Tame Your Service APIs: Evolving Airbnb’s Architecture https://www.infoq.com/presentations/airbnb-api-architecture/ ↩︎

  25. 2013-08 Reddit: Lessons Learned from Mistakes Made Scaling to 1 Billion Pageviews a Month http://highscalability.com/blog/2013/8/26/reddit-lessons-learned-from-mistakes-made-scaling-to-1-billi.html ↩︎ ↩︎

  26. 2012-03 7 Years of YouTube Scalability Lessons in 30 Minutes http://highscalability.com/blog/2012/3/26/7-years-of-youtube-scalability-lessons-in-30-minutes.html ↩︎

  27. 2016-04 豆瓣田忠博:豆瓣的服务化体系改造 (QCon北京2016, slides, 37p) http://2016.qconbeijing.com/presentation/2834/ ↩︎

  28. 2010-09 Disqus: Scaling the World's Largest Django App (DjangoCon 2010, slides) https://www.slideshare.net/zeeg/djangocon-2010-scaling-disqus ↩︎

  29. 2021-05 Dropbox: Atlas: Our journey from a Python monolith to a managed platform https://dropbox.tech/infrastructure/atlas--our-journey-from-a-python-monolith-to-a-managed-platform ↩︎

  30. 2014-07 Dropbox: Open Sourcing Our Go Libraries https://dropbox.tech/infrastructure/open-sourcing-our-go-libraries ↩︎ ↩︎

  31. 2017-07 Tammy Butow @ Dropbox: Go Reliability and Durability at Dropbox https://about.sourcegraph.com/blog/go/go-reliability-and-durability-at-dropbox-tammy-butow ↩︎ ↩︎

  32. 2011-02 Adam D'Angelo: Why did Quora choose C++ over C for its high performance services? Does the Quora codebase use a limited subset of C++? https://qr.ae/pKwCE3 ↩︎

  33. 2012-02 A Short on the Pinterest Stack for Handling 3+ Million Users http://highscalability.com/blog/2012/2/16/a-short-on-the-pinterest-stack-for-handling-3-million-users.html ↩︎

  34. 2015-08 Finagle and Java Service Framework at Pinterest (slides) https://www.slideshare.net/yongshengwu/finaglecon2015pinterest ↩︎

  35. 2013-03 Instagram 5位传奇工程师背后的技术揭秘 https://web.archive.org/web/0/http://www.csdn.net/article/2013-03-28/2814698-The-technologie- behind-Instagram ↩︎ ↩︎

  36. 2017-03 Lisa Guo: Scaling Instagram Infrastructure(QCon London 2017, 87p) https://www.infoq.com/presentations/instagram-scale-infrastructure/ ↩︎ ↩︎

  37. 2019-08 Static Analysis at Scale: An Instagram Story https://instagram-engineering.com/8f498ab71a0c ↩︎ ↩︎

  38. 2016-07 The Uber Engineering Tech Stack, Part I: The Foundation https://web.archive.org/web/0/https://eng.uber.com/tech-stack-part-one/ ↩︎ ↩︎

  39. 2018-11 知乎社区核心业务 Golang 化实践 https://zhuanlan.zhihu.com/p/48039838 ↩︎ ↩︎

  40. 2022-10 字节马春辉:字节大规模微服务语言发展之路 https://www.infoq.cn/article/n5hkjwfx1gxklkh8iham ↩︎ ↩︎

  41. 2021-07 字节成国柱:字节跳动微服务架构体系演进 https://mp.weixin.qq.com/s/1dgCQXpeufgMTMq_32YKuQ ↩︎ ↩︎

  42. Why does Google use Java instead of Python for Gmail? https://qr.ae/pKkduC ↩︎

  43. 2011-07 揭秘Google+技术架构 http://www.infoq.com/cn/news/2011/07/Google-Plus ↩︎

  44. 2009-12 人人网架构师张洁:人人网使用的开源软件列表 https://web.archive.org/web/0/http://ugc.renren.com/2009/12/13/a-list-of-open-source-software-in-renren ↩︎

  45. 2018-12 Netflix OSS and Spring Boot — Coming Full Circle https://netflixtechblog.com/4855947713a0 ↩︎

  46. 携程为什么突然技术转型从 .NET 转 Java? https://www.zhihu.com/question/56259195 ↩︎

  47. 京东技术解密,2014,豆瓣:12 少年派的奇幻漂流——从.Net到Java ↩︎

  48. Golang Frequently Asked Questions: Why did you create a new language? https://go.dev/doc/faq#creating_a_new_language ↩︎

  49. 2014-05 Brad Fitzpatrick: Go: 90% Perfect, 100% of the time: Fun vs. Fast https://go.dev/talks/2014/gocon-tokyo.slide#28 ↩︎

  50. 2021-08 百度Geek说:短视频go研发框架实践 https://my.oschina.net/u/4939618/blog/5191598 ↩︎

  51. 2023-07 百度Geek说:从 php5.6 到 golang1.19 - 文库 App 性能跃迁之路 https://my.oschina.net/u/4939618/blog/10086661 ↩︎

  52. 2022-03 2021年,腾讯研发人员增长41%,Go首次超越C++成为最热门语言 https://mp.weixin.qq.com/s/zj-DhASG4S-3z56GTYjisg ↩︎

  53. 2020-05 Which Major Companies Use PostgreSQL? What Do They Use It for? https://learnsql.com/blog/companies-that-use-postgresql-in-business/ ↩︎

  54. 2009-05 Why is MySQL more popular than PostgreSQL? https://news.ycombinator.com/item?id=619871 ↩︎

  55. Why is MySQL more popular than PostgreSQL? https://qr.ae/pKPJcE ↩︎

  56. 2002-10 Michael Radwin: Making the Case for PHP at Yahoo! (PHPCon 2002, slides) https://web.archive.org/web/0/http://www.php-con.com/2002/view/session.php?s=1012 https://speakerdeck.com/yulewei/making-the-case-for-php-at-yahoo ↩︎ ↩︎

  57. 2005-10 Michael Radwin: PHP at Yahoo! (PHP Conference 2005, slides) https://speakerdeck.com/yulewei/php-at-yahoo-zend2005 ↩︎ ↩︎

  58. 2007-06 Federico Feroldi: PHP in Yahoo! (slides) https://www.slideshare.net/fullo/federico-feroldi-php-in-yahoo ↩︎

  59. 2021-02 AWS re:Invent 2020: Amazon.com’s architecture evolution and AWS strategy https://www.youtube.com/watch?v=HtWKZSLLYTE ↩︎ ↩︎

  60. What programming languages are used at Amazon? https://qr.ae/pKFwnw ↩︎

  61. 2011-04 Charlie Cheever: How did Google, Amazon, and the like initially develop and code their websites, databases, etc.? https://qr.ae/pKKyB0 ↩︎

  62. 2016-04 Is Amazon still using Perl Mason to render its content? https://qr.ae/pKFwFm ↩︎

  63. 2019-10 Migration Complete – Amazon’s Consumer Business Just Turned off its Final Oracle Database https://aws.amazon.com/blogs/aws/migration-complete-amazons-consumer-business-just-turned-off-its-final-oracle-database/?nc1=h_ls ↩︎

  64. Amazon RDS for PostgreSQL customers https://aws.amazon.com/rds/postgresql/customers/?nc1=h_ls ↩︎

  65. Amazon ElastiCache for Redis customers https://aws.amazon.com/elasticache/redis/customers/?nc1=h_ls ↩︎

  66. 2006-11 Randy Shoup & Dan Pritchett: The eBay Architecture (SDForum2006, slides, 37p) http://www.addsimplicity.com/downloads/eBaySDForum2006-11-29.pdf ↩︎ ↩︎ ↩︎

  67. 2007-05 eBay Architecture http://highscalability.com/blog/2008/5/27/ebay-architecture.html ↩︎ ↩︎

  68. 2011-10 Tony Ng: eBay Architecture (slides, 46p) https://www.slideshare.net/tcng3716/ebay-architecture ↩︎

  69. 2016-11 Ron Murphy: Microservices at eBay (slides, 20p) https://www.modb.pro/doc/120378 ↩︎ ↩︎ ↩︎

  70. 2020-09 High Efficiency Tool Platform for Framework Migration https://innovation.ebayinc.com/tech/engineering/high-efficiency-tool-platform-for-framework-migration/ ↩︎

  71. 2023-10 BES2:打造eBay下一代高可靠消息中间件 https://mp.weixin.qq.com/s/ThhkO1WM7ck1WO8RqjTCJA ↩︎

  72. 2013-06 Cassandra at eBay - Cassandra Summit 2013 (slides) https://www.slideshare.net/jaykumarpatel/cassandra-at-ebay-cassandra-summit-2013 ↩︎

  73. 2017-03 Sudeep Kumar: 'Elasticsearch as a Service' at eBay https://www.elastic.co/elasticon/conf/2017/sf/elasticsearch-as-a-service-at-ebay ↩︎

  74. 2016-08 How eBay Uses Apache Software to Reach Its Big Data Goals https://www.linux.com/news/how-ebay-uses-apache-software-reach-its-big-data-goals/ ↩︎

  75. 淘宝技术这十年,子柳,2013,豆瓣 ↩︎ ↩︎

  76. 尽在双11:阿里巴巴技术演进与超越,2017,豆瓣:第1章 阿里技术架构演进 ↩︎ ↩︎ ↩︎

  77. 2011-06 淘宝吴泽明范禹:淘宝业务发展及技术架构 (slides, 43p) https://www.modb.pro/doc/116697 ↩︎ ↩︎ ↩︎

  78. 2014-12 阿里云王宇德、张文生:淘宝迁云架构实践 https://web.archive.org/web/1/http://www.csdn.net/article/a/2014-12-09/15821474 ↩︎ ↩︎ ↩︎

  79. 2017-07 阿里谢吉宝唐三:阿里电商架构演变之路 (首届阿里巴巴中间件技术峰会, slides, 33p) https://www.modb.pro/doc/121185 ↩︎ ↩︎ ↩︎ ↩︎

  80. 2010-11 淘宝赵林丹臣:淘宝数据库架构演进历程 (iDataForum2010, slides, 38p) https://www.slideshare.net/ssuser1646de/ss-10163048 ↩︎

  81. 2019-10 阿里刘振飞:十年磨一剑:从2009启动“去IOE”工程到2019年OceanBase拿下TPC-C世界第一 https://mp.weixin.qq.com/s/7B6rp17XVhpAWZr1-6DHqQ https://developer.aliyun.com/article/722414 ↩︎

  82. 2016-02 SSD的30年发展史 https://mp.weixin.qq.com/s/JsHKFilB5fvLY9V9z_xsXw ↩︎

  83. 2010-04 Yoshinori Matsunobu: SSD Deployment Strategies for MySQL (slides, 52p) https://www.slideshare.net/matsunobu/ssd-deployment-strategies-for-mysql ↩︎

  84. 2020-04 阿里王剑英、和利:淘宝万亿级交易订单背后的存储引擎 https://mp.weixin.qq.com/s/MkX1Pr8tERrzK29XG9zMUQ https://help.aliyun.com/zh/rds/apsaradb-rds-for-mysql/storage-engine-that-processes-trillions-of-taobao-order-records ↩︎

  85. 2022-03 阿里云罗庆超:阿里巴巴集团上云之 TFS 迁移 OSS 技术白皮书 https://developer.aliyun.com/article/876301 ↩︎

  86. 2016-12 阿里倪超:阿里巴巴Aliware十年微服务架构演进历程中的挑战与实践 https://www.sohu.com/a/121588928_465959 ↩︎

  87. 2017-10 阿里钟华古谦:企业IT架构转型之道 (杭州云栖大会2017, slides, 18p) https://www.modb.pro/doc/121695 ↩︎

  88. 2021-09 阿里郭浩:Dubbo 和 HSF 在阿里巴巴的实践:携手走向下一代云原生微服务 https://mp.weixin.qq.com/s/_Ug3yEh9gz5mLE_ag1DjwA ↩︎ ↩︎ ↩︎

  89. 2012-11 阿里巴巴分布式服务框架 Dubbo 团队成员梁飞专访 http://www.iteye.com/magazines/103 ↩︎

  90. 2019-01 Dubbo 作者梁飞亲述:那些辉煌、沉寂与重生的故事 https://www.infoq.cn/article/3F3Giujjo-QwSw2wEz7u ↩︎ ↩︎

  91. Dubbo 用户案例:阿里巴巴升级 Dubbo3 全面取代 HSF2 https://cn.dubbo.apache.org/zh-cn/users/alibaba/ https://github.com/apache/dubbo-website/blob/ee727525aa61d68b397cc6ddedb322001f0ca4da/content/zh/users/alibaba.md ↩︎

  92. 2023-01 阿里巴巴升级 Dubbo3 全面取代 HSF2 https://cn.dubbo.apache.org/zh-cn/blog/2023/01/16/阿里巴巴升级-dubbo3-全面取代-hsf2/ ↩︎

  93. 2017-11 阿里林清山隆基:阿里消息中间件架构演进之路:notify和metaq https://zhuanlan.zhihu.com/p/302600352 ↩︎

  94. 2013-07 淘宝张乐伟韩彰:淘宝消息中间件技术演变:MetaQ 1.0、MetaQ 2.0、MetaQ 3.0(sildes, 30p)https://www.modb.pro/doc/109298 ↩︎

  95. 2017-03 阿里冯嘉鼬神:Apache RocketMQ背后的设计思路与最佳实践 https://developer.aliyun.com/article/71889 ↩︎

  96. 2008-05 LinkedIn - A Professional Network built with Java Technologies and Agile Practices (JavaOne2008, slides) https://www.slideshare.net/linkedin/linkedins-communication-architecture ↩︎ ↩︎ ↩︎

  97. 2015-07 Josh Clemm: A Brief History of Scaling LinkedIn https://engineering.linkedin.com/architecture/brief-history-scaling-linkedin https://www.slideshare.net/joshclemm/how-linkedin-scaled-a-brief-history ↩︎ ↩︎

  98. Aditya Auradkar, Chavdar Botev, etc.: Data Infrastructure at LinkedIn. ICDE 2012: 1370-1381,dblp, semanticscholar, slides ↩︎ ↩︎ ↩︎

  99. 2012-06 Sid Anand: LinkedIn Data Infrastructure Slides (Version 2) (slides) https://www.slideshare.net/r39132/linkedin-data-infrastructure-slides-version-2-13394853 ↩︎ ↩︎

  100. 2021-12 Evolving LinkedIn’s analytics tech stack https://engineering.linkedin.com/blog/2021/evolving-linkedin-s-analytics-tech-stack ↩︎ ↩︎

  101. 2010-05 Aditya Agarwal: Scale at Facebook (Qcon London 2010) https://www.infoq.com/presentations/Scale-at-Facebook/ ↩︎ ↩︎

  102. 2008-11 Aditya Agarwal: Facebook architecture (QCon SF 2008, slides, 34p) https://www.slideshare.net/mysqlops/facebook-architecture https://www.infoq.com/presentations/Facebook-Software-Stack/ ↩︎ ↩︎ ↩︎ ↩︎

  103. 2011-04 Michaël Figuière: What is Facebook's architecture? https://qr.ae/pKYg12 ↩︎

  104. 2013-10 Where does Facebook use C++? https://qr.ae/pKCIee ↩︎

  105. 2022-07 Programming languages endorsed for server-side use at Meta https://engineering.fb.com/2022/07/27/developer-tools/programming-languages-endorsed-for-server-side-use-at-meta/ ↩︎

  106. 2015-07 Instagram: Search Architecture https://instagram-engineering.com/eeb34a936d3a ↩︎

  107. Guoqiang Jerry Chen, Janet L. Wiener, etc.: Realtime Data Processing at Facebook. SIGMOD Conference 2016: 1087-1098,dblp, semanticscholar ↩︎

  108. 2021-10 XStream: stream processing platform at facebook (Flink Forward Global 2021, slides) https://www.slideshare.net/aniketmokashi/xstream-stream-processing-platform-at-facebook ↩︎

  109. 2013-01 Johan Oskarsson: The Twitter stack https://blog.oskarsson.nu/post/40196324612/the-twitter-stack ↩︎ ↩︎

  110. 2013-10 Chris Aniszczyk: Evolution of The Twitter Stack (slides) https://www.slideshare.net/caniszczyk/twitter-opensourcestacklinuxcon2013 ↩︎ ↩︎ ↩︎

  111. 2017-01 The Infrastructure Behind Twitter: Scale https://blog.twitter.com/engineering/en_us/topics/infrastructure/2017/the-infrastructure-behind-twitter-scale ↩︎

  112. 2010-07 Cassandra at Twitter Today https://blog.twitter.com/engineering/en_us/a/2010/cassandra-at-twitter-today ↩︎

  113. 2011-12 How Twitter Stores 250 Million Tweets a Day Using MySQL http://highscalability.com/blog/2011/12/19/how-twitter-stores-250-million-tweets-a-day-using-mysql.html ↩︎

  114. 2013-11 Michael Busch: Search at Twitter (Lucene Revolution 2013, slides) https://www.slideshare.net/lucenerevolution/twitter-search-lucenerevolutioneu2013-copy https://www.youtube.com/watch?v=AguWva8P_DI ↩︎ ↩︎

  115. 2022-10 Stability and scalability for search https://blog.twitter.com/engineering/en_us/topics/infrastructure/2022/stability-and-scalability-for-search ↩︎

  116. 2021-10 Processing billions of events in real time at Twitter https://blog.twitter.com/engineering/en_us/topics/infrastructure/2021/processing-billions-of-events-in-real-time-at-twitter- ↩︎

]]>
+ + + <p>技术栈是构建应用的技术集合,由编程语言、框架、库、服务器、数据库、工具等组合而成。组成技术栈的技术是与具体业务无关的基础软件。互联网公司选择的技术栈,倾向于使用开源软件,相对于专有软件,开源软件具有高质量、免费、开放、灵活等优势。互联网的早期开拓者 Yahoo 的技术栈选择是经典案例,受开源运动的影响,在 2000 左右 Yahoo 从最初基于自定义的专属软件迁移了到 LAMP 技术栈。</p> + + + + + + + + + + + + + + +
+ + + 亚马逊网站架构演进 + + https://nullwy.me/2023/11/amazon-architecture-evolution/ + 2023-11-04T04:43:00.000Z + 2023-12-06T13:34:25.634Z + + SOA 与微服务

Amazon,1994 年创立,早期网站是单服务、单数据库的单体架构的系统[1][2][3],全部代码由 C++ 编写,编译成单个二进制文件,整个代码仓库被命名为 Obidos。Obidos 是底层是一个 Web 页面渲染引擎,是一个框架,业务逻辑基于这个框架开发,Obidos 渲染引擎和业务逻辑共同组成整个代码仓库。随着时间的推移,Obidos 变得越来越复杂,编译 Obidos 整个代码库耗时 12 小时,开发调试效率低下[2:1]。另外,全部业务逻辑在单个二进制文件中,导致紧耦合,新功能特性无法快速发布上线。1995 年,Amazon 网站的技术架构,如下图所示[3:1]

Amazon 网站技术架构(1995)

到 2000 年,为了应对流量增长,解决网站的可扩展性问题,开始拆分 Obidos,向可扩展的 SOA 架构演进。拆分出的服务有,用户服务(customer service)、订单服务(order service)、商品服务(item service)等,并且每个服务都拥有各自独立的数据库。2005 年 1 月,Amazon 网站开始从 Obidos 引擎迁移到 Gurupa 引擎。Gurupa 是一个 Web 页面渲染引擎,同时也是一个 SOA 框架,Gurupa 被用于集成背后的数百个服务,使用 Perl 的 Mason 模板将各个服务响应的数据渲染成 Web 页面。到 2006 年完成了到 Gurupa 的全部迁移[4]

Amazon 网站技术架构演进过程,如下图所示[2:2]

Amazon 网站技术架构演进

需要注意的是,图中认为从 2006 年开始 Amazon 网站架构从 SOA 演进为微服务,但是事实上,“微服务”这个术语诞生的时间是 2012 年。2006 年的架构实现与之前的 SOA 架构实现的不同点是,开始更细粒度的服务拆分。

本质上来看,微服务架构是一种特殊的 SOA 架构,在“微服务”术语诞生之前,亚马逊的 SOA 架构实现被认为是“SOA done right”(正确实现的 SOA)[5]。Netflix 的 SOA 架构实现也在“微服务”术语诞生之前,Netflix 认为自己实现架构的是“fine-grained SOA”(细粒度的 SOA)[6]。James Lewis 和 Martin Fowler 等人是“微服务”概念的早期提倡者,他们将亚马逊和 Netflix 的 SOA 架构实现归类为微服务的经典案例[7]。所以,SOA 和微服务的关系可以简单理解为,微服务是“fine-grained SOA”或“SOA done right”。

根据 Martin Fowler 的解释[8],SOA 与微服务的关系,如下图所示:

SOA 与微服务的关系

在 SOA 架构的具体实践上,根据前亚马逊工程师 Steve Yegge 的 2011 年的文章[9][10],在 2002 年左右,亚马逊创始人兼 CEO Jeff Bezos 向全公司发布了一道指令(这个指令被外界称为“API Mandate”),具体内容如下:

  1. 从今天起,所有的团队都要以服务接口的方式提供数据和各种功能。
  2. 团队之间必须通过接口来通信。
  3. 不允许任何其他形式的互操作:不允许直接链接,不允许直接读其他团队的数据,不允许共享内存,不允许任何形式的后门。唯一许可的通信方式就是通过网络调用服务。
  4. 至于具体的技术则不做规定。HTTP、Corba、Pubsub、自定义协议都可以。贝索斯不关心这个。
  5. 所有的服务接口,必须从一开始就要以可以公开为设计导向,没有例外。这就是说,团队必须在设计的时候就计划好,接口要可以对外面的开发人员开放。没有讨价还价的余地。
  6. 不听话的人会被炒鱿鱼。

技术栈演进

Amazon 网站的技术栈演进过程[2:3][4:1][11]

  • 1995 ~ 2000:单体架构,Unix(Sun)、Obidos、Oracle、C++
    • Obidos 是亚马逊内部 Web 动态页面渲染引擎,编程语言是 C++。
  • 2000 ~ 2006:SOA 架构,Linux、Obidos、Oracle、C++
    • 2000 年,将 Sun/Unix 服务器替换为 HP/Linux 服务器[12]
    • 2000 年,开始拆分应用服务,向 SOA 架构演进。
    • 2005 年初,开始将 Obidos 框架替换为 Gurupa 框架,Gurupa 是 Web 页面渲染引擎,同时也是 SOA 框架。Web 动态页面的编程语言从 C++ 替换为 Perl/Mason,同时应用服务开始被更细粒度的拆分。
  • 2006 年开始:微服务架构,Linux、Gurupa、Oracle、Perl & Java & C++
    • 2019.10,彻底去掉 Oracle 数据库,迁移到 Amazon RDS 和 NoSQL[13]

当前 Amazon 网站的主要技术栈:

  • 应用服务[4:2][11:1]
    • 展示层:Perl/Mason[14]
    • 业务逻辑层:Java(主要)、C++ 等
    • RPC框架:Gurupa 框架(自研闭源)
      • 2006 年更早之前使用 Obidos 框架
    • 消息队列MQAmazon SQS
  • 数据存储[13:1]
    • 关系数据库:Amazon RDS for PostgreSQL[15]、Amazon Aurora (PostgreSQL)
      • 2019 年 10 月彻底去掉 Oracle 数据库,迁移到 Amazon RDS 和 NoSQL。
    • 键值存储Amazon DynamoDB
    • 缓存:Amazon ElastiCache for Redis[16]
    • Blob文件存储Amazon S3

AWS 的诞生

Amazon 网站架构演进的过程,伴随着 AWS 云服务的诞生,促使 AWS 云服务诞生的因素主要有[17][18]

  • 技术价值:Amazon 网站在向可扩展架构演进的过程中,其基础设施团队开始善于运营像计算、存储和数据库这样的基础设施,团队已经变得能非常熟练地运营可靠的、可扩展的、具有成本效益的数据中心,这些专业能力推动了亚马逊电商平台的发展。将维护可靠、可扩展的基础设施专业能力通过服务的方式对外交付,能有效节省第三方企业或初创公司的成本,当时亚马逊预计基础设施的成本可能会从 70% 降低至 30% 或更低[19]
  • 原始动机:Amazon 网站的流量有很强的季节性,每年 11 月和 12 月(尤其是在感恩节和圣诞节前后)流量都会飙升。为了应对购物季,不得不扩容,增加服务器资源。在购物季结束后,服务器资源被大量闲置。零售电商的利润很薄,却要面对数据中心基础设施不断扩展所带来的成本压力。所以,很多人(包括部分亚马逊员工)[20][21]认为推出 AWS 产品的一个重要原因是为了出租 SOA 网站在销售淡季时的过剩服务器容量。不过,出租过剩容量的故事是一个神话,因为不可能在每年购物季时把开发商从服务器里踢出去,而且实际上在推出 EC2 云服务后的 2 个月内,AWS 就已经烧掉了过剩的 Amazon 网站容量[19:1]
  • 商业理念Jeff Bezos,将亚马逊定位为一家技术公司,而不仅仅是一家在线零售商,所以在亚马逊的核心业务之外进行很多投资尝试,AWS 产品就是其中之一[17:1]

于是,在 2003 年亚马逊团队内部逐渐开始形成销售基础设施服务的设想。2003 年 9 月[22]Andy Jassy 写了 6 页纸的关于 AWS 的愿景文档(vision document)并提交给管理团队,愿景文档中提议了设想的 AWS 业务,并概述了 AWS 提供的初始的基础设施服务集,首批提供的服务包括存储、计算和数据库等。同年,Jassy 组建了由 57 人组成的 AWS 团队,AWS 团队的 CEO 由 Jassy 担任(Jassy 担任 AWS CEO 一直到 2021 年,2021 年 7 月开始任职亚马逊 CEO)。三年之后,2006 年 3 月 AWS 对外发布 S3 云存储,8 月对外发布 EC2 弹性云计算服务器,S3 和 EC2 是行业内最早的云服务产品。S3 发布的刚开始几个月,并没有引起太大的关注。EC2 发布后,大量开发商开始飞速涌入。在没有其他类似云服务产品最初几年,几乎每一家创业公司都在亚马逊的服务器上构建自己的系统。能吸引大量开发商的原因主要是,按需使用和收费的商业模式,以及亚马逊故意压力利润的价格策略[17:2]

迁移到 AWS

2011 年 11 月,Amazon 网站全部都迁移到了 AWS 云服务器上[23]。迁移到 AWS 上最大的动机是能利用 AWS 云服务器的弹性伸缩能力,从而节省成本。如果没有弹性伸缩能力,在淡季时,总体上服务器资源容量的利用率是 61%,无法有效利用的容量是 39%,到购物季的 11 月,无法有效利用的容量高到 76%。引入弹性伸缩技术后,可以按网站的实际流量负载情况,供应恰当的容量,避免资源浪费。Amazon 网站在淡季和购物季时的静态伸缩与弹性伸缩,如下图所示[23:1][24]

Amazon 网站的典型的周流量分布Amazon 网站的静态伸缩Amazon 网站的弹性伸缩

参考资料


  1. 2006-05 ACM Queue Interview: A Conversation with Amazon CTO Werner Vogels https://queue.acm.org/detail.cfm?id=1142065 ↩︎

  2. 2021-02 Amazon’s architecture evolution and AWS strategy (AWS re:Invent 2020) https://www.youtube.com/watch?v=HtWKZSLLYTE ↩︎ ↩︎ ↩︎ ↩︎

  3. 2022-11 Reliable scalability: How Amazon scales in the cloud (AWS re:Invent 2022) https://www.youtube.com/watch?v=_AhfV5LZmvo ↩︎ ↩︎

  4. 2011-04 Charlie Cheever: How did Google, Amazon, and the like initially develop and code their websites, databases, etc.? https://qr.ae/pKKyB0 ↩︎ ↩︎ ↩︎

  5. 2007-06 SOA done right: the Amazon strategy https://www.zdnet.com/article/soa-done-right-the-amazon-strategy/ ↩︎

  6. 2011-05 How the cloud helps Netflix (interview Adrian Cockcroft) http://radar.oreilly.com/2011/05/netflix-cloud.html ↩︎

  7. 2014-03 James Lewis & Martin Fowler: Microservices https://martinfowler.com/articles/microservices.html ↩︎

  8. 2014-11 Microservices • Martin Fowler • GOTO 2014 https://youtu.be/wgdBVIX9ifA?t=880 ↩︎

  9. 2011-10 Steve's Google Platform rant https://gist.github.com/chitchcock/1281611 ↩︎

  10. 2016-09 亚马逊如何变成 SOA(面向服务的架构)?(摘录自Steve Yegg的《程序员的呐喊》) https://www.ruanyifeng.com/blog/2016/09/how_amazon_take_soa.html ↩︎

  11. What programming languages are used at Amazon? https://qr.ae/pKFwnw ↩︎ ↩︎

  12. 2001-10 How Linux saved Amazon millions https://web.archive.org/web/0/http://news.com.com/2100-1001-275155.html ↩︎

  13. 2019-10 Migration Complete – Amazon’s Consumer Business Just Turned off its Final Oracle Database https://aws.Amazon/blogs/aws/migration-complete-amazons-consumer-business-just-turned-off-its-final-oracle-database/?nc1=h_ls ↩︎ ↩︎

  14. 2016-04 Is Amazon still using Perl Mason to render its content? https://qr.ae/pKFwFm ↩︎

  15. Amazon RDS for PostgreSQL customers https://aws.Amazon/rds/postgresql/customers/?nc1=h_ls ↩︎

  16. Amazon ElastiCache for Redis customers https://aws.Amazon/elasticache/redis/customers/?nc1=h_ls ↩︎

  17. 一网打尽:贝佐斯与亚马逊时代,Brad Stone,2013,豆瓣:第7章 一家技术公司,而非零售商 ↩︎ ↩︎ ↩︎

  18. 2016-07 AWS CEO Andy Jassy: How AWS came to be https://techcrunch.com/2016/07/02/andy-jassys-brief-history-of-the-genesis-of-aws/ ↩︎

  19. 2011-01 Amazon CTO Werner Vogels: How and why did Amazon get into the cloud computing business? https://qr.ae/pKscWd ↩︎ ↩︎

  20. 2016-07 前亚马逊员工在 Reddit 上对文章“How AWS came to be”的评论 https://www.reddit.com/r/programming/comments/4qxthq/comment/d4wrnk7/ ↩︎

  21. 2021-01 前亚马逊员工 Dan Rose:全球最大云厂商AWS是如何诞生的? https://mp.weixin.qq.com/s/C7Mqeh1hyT6k5BQOzpWL9w ↩︎

  22. 2013-11 Andy Jassy's Book Review of "The Everything Store" https://www.Amazon/review/R1Q4CQQV1ALSN0/ ↩︎

  23. 2011-07 2011 AWS Tour Australia, Closing Keynote: How Amazon migrated to AWS, by Jon Jenkins https://www.slideshare.net/AmazonWebServices/2011-aws-tour-australia-closing-keynote-how-amazoncom-migrated-to-aws-by-jon-jenkins ↩︎ ↩︎

  24. 2017-03 AWS: Elasticity and Management https://www.slideshare.net/AmazonWebServices/elasticity-and-management ↩︎

]]>
+ + + <h1 id="SOA-与微服务">SOA 与微服务</h1> +<p>Amazon,1994 年创立,早期网站是单服务、单数据库的单体架构的系统<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup><sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup><sup class="footnote-ref"><a href="#fn3" id="fnref3">[3]</a></sup>,全部代码由 C++ 编写,编译成单个二进制文件,整个代码仓库被命名为 <a href="https://en.wikipedia.org/wiki/Obidos_(software)">Obidos</a>。Obidos 是底层是一个 Web 页面渲染引擎,是一个框架,业务逻辑基于这个框架开发,Obidos 渲染引擎和业务逻辑共同组成整个代码仓库。随着时间的推移,Obidos 变得越来越复杂,编译 Obidos 整个代码库耗时 12 小时,开发调试效率低下<sup class="footnote-ref"><a href="#fn2" id="fnref2:1">[2:1]</a></sup>。另外,全部业务逻辑在单个二进制文件中,导致紧耦合,新功能特性无法快速发布上线。1995 年,Amazon 网站的技术架构,如下图所示<sup class="footnote-ref"><a href="#fn3" id="fnref3:1">[3:1]</a></sup>:</p> + + + + + + + + + + + + + + + + +
+ + + 可靠性工程概述 + + https://nullwy.me/2023/11/reliability-engineering/ + 2023-11-02T04:43:00.000Z + 2023-12-05T10:13:20.751Z + + 为了应对负载的增长,目前大型网站普遍都采用分布式架构。相对于采用单体架构的系统,分布式系统中有大量的服务器及设备,各模块之间存在错综复杂的依赖关系,存在更多的不确定性。整个系统的故障率会随设备的增加而呈指数级增加,单一节点问题可能会被无限放大,日常运行过程中一定会伴随故障发生。所以,可靠性开始成为大型网站关注的最重要的质量属性之一,并因此发展出了站点可靠性工程(Site reliability engineering,SRE)。站点可靠性工程,是从可靠性工程发展而来的,从可靠性工程中借鉴了概念和成果。本文溯本求源,内容主要是总结概括,可靠性工程的历史演进和核心概念,软件可靠性工程的核心概念,以及可靠性设计的方法。

历史演进

可靠性工程起源于第二次世界大战[1]。“二战”期间,美国 60% 的机载电子设备运到远东后不能使用,50% 的电子设备在存储期间失效。经过分析,发现这些电子设备故障的主要原因是电子管的可靠性太差,为此美国在 1943 年成立电子管研究委员会,在 1952 年美国国防部成立一个由军方、工业部门及学术界组成的小组,名为“电子设备可靠性咨询小组”(AGREE,Advisory Group on the Reliability of Electronic Equipment)。1957 年 6 月,AGREE 小组出版报告《军用电子设备可靠性》(Reliability of Military Electronic Equipment),该报告是公认的可靠性工程的奠基性文件,研究报告提出一整套可靠性设计、试验和管理方法,确立了可靠性工程发展方向,标志着可靠性工程学科诞生。此后,它不断向工业和民用产品领域渗透,20 世纪 60 年代推广到核工业, 70 年代在化学工业普及,并陆续扩散到其他工程领域。

随着可靠性工程学科的发展演进,围绕故障展开,逐渐衍生出对产品的维修性(maintainability)、可用性(availability)、保障性(supportability)、测试性(testability)、安全性(safety)等质量特性的工程学研究。“维修性工程”和“安全性工程”是从“可靠性工程”中分离出来的,而“保障性工程”和“测试性工程”又是从“维修性工程”中独立出来的。新的 XX 性陆续分出,因为这些特性紧密相关,已经分出的 XX 性围绕可靠性又重新集成起来,在 20 世纪 80 年代呈现综合化发展趋势。可靠性的含义不断扩展,从狭义可靠性演变为广义可靠性,从狭义可靠性工程演变为广义可靠性工程。

1980 年代初期,为了避免因为扩展可靠性固有的含义引发的可靠性定性含义和可靠性的定量含义之间的理解混乱,Jean-Claude Laprie 选择“可信性”(dependability)作为术语,根据国际电工委员会标准,可信性的定义是,用以描述可用性及其影响因素(可靠性、维修性和维修保障性)的集合性术语,可信性仅用于非定量术语的一般描述。某些情况下,可信性还包含耐久性(durability)、安全性(safety)、安全保密性(security)等其他特性。可信性可以理解为广义可靠性

当今在国际上有两个比较完整的可靠性标准化体系,一个是美国军用标准(MIL-STD),另一个是国际电工委员会(IEC)标准。美国军用标准多年来一直扮演着研究开发可靠性相关标准文件的带头角色,也是最早制定可靠性标准的。最早的可靠性定义是由美国 AGREE 在 1957 年的报告中提出的,1966 年美国的 MIL-STD-721B 又给出了传统的或经典的可靠性定义,即产品在规定的条件下和规定的时间内完成规定功能的能力。最主要的可靠性国际标准组织是国际电工委员会的 TC56 技术委员会,TC56 的发展时间线[2]

  • 1965,国际电工委员会 IEC 成立名为“电子元件和设备可靠性”(Reliability of Electronic Components and Equipment)的技术委员会,即 TC56。
  • 1973,TC56 更名为“可靠性与维修性”(Reliability and Maintainability)技术委员会。
  • 1985,TC56 技术委员会成立了软件可靠性工作组,开始制定软件可靠性和维修性标准。
  • 1989,TC56 更名为“可信性”(Dependability)技术委员会,此名称一直沿用至今。
  • 1990,TC56 在与国际标准化组织(ISO)协商后,工作范围应不再局限于电工技术领域,而是解决所有学科的通用可靠性问题,从而使 IEC/TC56 成为所谓的横向委员会。

我国与 IEC/TC56 对口的专业技术标准化组织是,TC24 全国电工电子产品可靠性与维修性标准化技术委员会(简称“可标委”),成立于 1982 年,挂靠在工业和信息化部电子第五研究所(又名中国电子产品可靠性与环境试验研究所)。

可信性与质量六性

除了上文的“可信性”集合性术语外,有些资料将广义可靠性解释为,“可用性 + 可靠性 + 维修性”,这三个质量特性也被缩写为 RAM。RAM 有时候会再加上安全性(Safety),被缩写为 RAMS。使用 RAMS 缩写的典型例子是国际电工委员会的 IEC 62278:2002 标准(等同的国家标准 GB/T 21562-2008)。

另外,常见的可靠性相关的缩写是 RMS 和 RMTSS。RMS 代表可靠性、维修性、保障性,或称“三性”。RMTSS 代表可靠性、维修性、测试性、保障性、安全性,或称“五性”。质量“三性”或“五性”,也是我国军用武器装备的军用标准要求的通用质量特性。我国武器装备的军用标准学习和借鉴的是美国军用标准,军用装备的质量特性分为专用质量特性和通用质量特性。专用质量特性,反映的是不同系统或者装备自身的特点和个性特征,主要指的是功能和性能,如某型飞机的最大(最小)飞行速度、巡航速度、飞行高度等指标。通用质量特性,则表征不同装备的共性特征。通用质量特性是逐渐演变的,从一开始的“二性”演变为“六性”[3][4],通用质量特性包含的特性如下:

  • 二性:可靠性、维修性(也缩写为 R&M)
  • 三性:可靠性、维修性、保障性(也缩写为 RMS)
  • 五性:可靠性、维修性、测试性、保障性、安全性(也缩写为 RMTSS)
  • 六性:可靠性、维修性、保障性、测试性、安全性、环境适应性

通用质量特性与可信性的含义大体上相同。质量特性、可信性、可靠性的关系,如下图所示:

质量特性、可信性、可靠性的关系

根据国际电工委员会 IEC 60050 (191):1990(等同的国家标准 GB/T 3187-1994 《可靠性、维修性术语》)、IEC 60050-192:2015(等同于 GB/T 2900.99-2016 《电工术语 可信性》)以及国家军用标准 GJB 451A-2005 《可靠性维修性保障性术语》(与美国军用标准 MIL-STD-721C 相似)等标准文档,相关特性的定义和度量指标如下:

  • 可信性(dependability:用以描述可用性及其影响因索(可靠性、维修性和维修保障性)的集合性术语。可信性仅用于非定量术语的一般描述。
  • 可靠性(reliability:在给定的条件,给定的时间区间,能无故障地执行要求的能力。可靠性一般用可靠度(reliability)、平均故障间隔时间(MTBF)、使用寿命(useful life)等参数来度量。
  • 可用性(availability:在所要求的外部资源得到提供的情况下,产品在给定的条件下,在给定的时刻或时间区间内处于能完成要求的功能的状态的能力。此能力是产品的可靠性、维修性和维修保障性的综合反映。可用性的度量指标称为可用度(availability),表示为平均可用时间同平均可用时间与平均不可用时间的和之比。
  • 维修性(maintainability:在给定的条件下,使用所述的程序和资源实施维修时,产品在给定的使用条件下保持或恢复能完成要求的功能的状态的能力。维修性反映产品修理的难易程度,主要使用平均修复时间(MTTR)来度量。
  • 保障性(supportability:在规定的运行剖面和给定的后勤与维修资源下,保防能维待要求的可用性的能力。维修保障(maintenance support),是维修产品的资源的供给,资源包括人力资源、保障设备、材料和备件、维修设施、文档和信息以及维修信息系统。保障性一般用平均保障延误时间、资源满足率、资源利用率等参数来度量。
  • 测试性(testability):是指产品能及时并准确地确定其状态(可工作、不可工作或性能下降),并隔离其内部故障的能力。测试性反映产品是否易于测试、出现故障时是否易于检测和隔离,一般用检测时间、技术准备时间、故障检测率、故障隔离率等参数来度量。
  • 安全性(safety):是指产品所具有的不导致人员伤亡、系统毁坏、重大财产损失或不危及人员健康和环境的能力。安全性可理解为产品在任何情况下对人员、系统、财产和环境都不构成安全威胁。它可定义为产品在规定的条件下和规定的时间内,以可接受的风险执行规定功能的能力。安全性一般用事故概率、损失率、安全可靠度等参数来度量。
  • 环境适应性(environmental worthiness):是指产品在其寿命期内预计可能遇到的各种环境作用下能实现其所有预定功能、性能和(或)不被破坏的能力。它反映了产品对各种环境的适应能力,即在其可能遇到的各种环境下均能正常工作的能力,是可靠性的一种特殊情况。环境适应性鉴定试验通过的判定准则是,在所有试验条件下“零故障”。

通用质量特性的“六性”之间是紧密联系的[4:1][5]

  • 维修性是对可靠性的补充,如果产品不发生故障就不需要修复性维修。
  • 可用性是产品的可靠性、维修性和维修保障性的综合反映。
  • 保障性为产品正常使用与维修提供外部资源的支持,提供使用保障和维修保障,可靠性和维修性依赖于保障性。
  • 测试性是维修性的基础,维修依赖于测试,产品要修理一定要先发现故障和隔离故障,所以测试性设计得好,维修时间就可大大缩短。
  • 安全性本是可靠性的一部分,是避免人员伤亡、健康损害、财产或环境损害风险的可靠性。可靠性是安全性的基础,很多安全性问题都是因为产品不可靠造成的,所以提高产品可靠性也能提高安全性,当然并非所有安全性问题都是不可靠引起的。
  • 环境适应性是可靠性的一种特殊情况,是可靠性研究的前提,研究可靠性首先要确定产品是否有足够的环境适应性。

通用质量特性的“六性”工作围绕故障(failure)而展开,也被人称为“故障六性”[6][4:2]。可靠性的目标是减少故障;维修性的目标是修复故障;测试性的目标是检测故障;保障性保证出现故障时可以快速供应维修资源;安全性旨在出现故障以后降低风险;环境适应性鉴定试验通过的判定准则是,在所有试验条件下“零故障”[5:1]

故障六性

可靠性是产品质量特性之一,是一种面向时间的质量特性(time oriented quality characteristic)[7]。Lloyd Condra 在书中对可靠性和质量的关系的解释是,“可靠性是质量随着时间的变化(reliability is quality over time)”,“为了衡量产品的质量水平,我们对现在的产品进行评判,而为了度量产品的可靠性水平,则要对产品未来会是什么样子进行评判”。这里的讨论的质量其实指的是符合性质量,质量管理一开始是从符合性质量开始的,质量管理的主要工作是质量检验(Quality Inspection),检测产品是否符合规格,质量检验的结果即合格品率。质量管理的关注焦点是产品的合格品率,而可靠性关注焦点是产品在用户使用过程中合格水平随着时间的保持能力,如下图所示 [5:2]

质量与可靠性关系示意图

故障与失效的区别

可靠性工程中有两个基本而重要的术语“fault”和“failure”。在我国的可靠性标准文档中,把“fault”翻译为“故障”,把“failure”翻译为“失效”或“故障”,也就是说,“失效”对应的英文只有“failure”;而“故障”对应的英文是“fault”或“failure”[8][9]

我国第一个定义可靠性相关的常用术语的国家标准是 GB 3187-1982 《可靠性基本名词术语及定义》,该标准对英文术语“failure”的中文翻译是“失效”或“故障”,并把“mean time between failures”翻译是“平均无故障时间”:[8:1]

2.2.1 失效(故障) failure:产品丧失规定的功能。对可修复产品通常也称故障。
2.5.5 平均寿命(平均无故障时间) mean life (mean time between failures):寿命(无故障时间)的平均值。

替代 GB 3187-1982 的新国家标准是 GB/T 3187-1994 《可靠性、维修性术语》(等同于 IEC 60050-191:1991),该标准把“failure”仅翻译为“失效”,不再又称“故障”。完整的术语定义如下:

4.1.1 失效 failure
产品终止完成规定功能的能力这样的事件。
4.2.1 故障 fault
产品不能执行规定功能的状态。预防性维修或共他计划性活动或缺乏外部资源的情况除外。故障通常是产品本身失效后的状态,但也可能在失效前就存在。

基于上述的定义,对于性能随时间逐渐退化的产品,故障(fault)与失效(failure)的区别,如下图所示[10]

故障(fault)与失效(failure)的区别

国外历来都是将“fault”和“failure”的定义加以区分的,我国新的标准文档也区分翻译为“故障”和“失效”,但是实际上在我国的电工行业中的惯用情况是把“fault”和“failure”都翻译为“故障”,很多书籍资料也不严格区分。比如,中国质量协会的《可靠性工程师手册》(第 2 版 2017[5:3]),不严格区分“故障”与“失效”术语,统一都使用“故障”,书中的解释如下:

在我国的可靠性工程应用中,一般不对故障与失效进行严格的区分,如失效树分析也称为故障树分析,故障模式、影响分析也称为失效模式、影响分析。因此本书也不做严格区分,多数情况下故障一词也可用失效代替。

一般而言,故障是产品本身失效后的状态,此时产品处于故障状态,这时故障和失效是不需要严格加以区分。对无故障容忍能力的产品而言,故障即失效。然而,对有故障容忍能力的产品,产品可以出故障,但不会失效,这时我们就必须区分失效和故障的概念[9:1]。故障容忍(容错,fault tolerance),是在某些故障出现时继续运行的能力,只有当所有冗余的硬件同时有故障时,产品才失效。

可靠性的度量

可靠性的度量指标是可靠度reliability),根据国际电工委员会的标准文档,可靠度的定义是:在给定的条件下在时间区间 (t1, t2) 内按要求执行的概率。当 t1=0 和 t2=t,则 R(0,t) 可简化为 R(t),并称为产品的可靠度函数(reliability function)。

若在 t=0 时产品的总数为N0N_0,在 0 ~ t 的时间内累计的故障数为Nf(t)N_f(t),正常的产品数为Ns(t)N_s(t),则有:

N0=Nf(t)+Ns(t)N_0 = N_f(t) + N_s(t)

产品在 t 时刻的可靠度的估计值为:

R(t)^=Ns(t)N0\hat{R(t)}=\frac{N_s(t)}{N_0}

显然,当 t=0 时,R(0) = 1,当 t=∞ 时,R(∞) = 0。

可靠度的反面是不可靠度(unreliability),含义是:在规定的条件下,在规定的时间内,不能完成规定功能的概率。不可靠度函数通常记为F(t)F(t),不可靠度的估计值的计算公式为:

F(t)^=Nf(t)N0=N0Ns(t)N0=1R(t)^\hat{F(t)} = \frac{N_f(t)}{N_0} = \frac{N_0 - N_s(t)}{N_0} = 1 - \hat{R(t)}

示例:假设在 t=0,投入工作的 10000 只灯泡,以天作为度量时间的单位,在 t= 365 天时,发现有 300 只灯泡坏了,这时的可靠度和不可靠度的计算如下:

R(365)^=10003001000=0.97\hat{R(365)} = \frac{1000 - 300}{1000} = 0.97F(365)^=3001000=0.03\hat{F(365)} = \frac{300}{1000} = 0.03

对不可靠度函数求导,其导数称为故障概率密度函数,通常记为f(t)f(t)

f(t)=limΔt0F(t+Δt)F(t)Δtf(t) = \lim_{\Delta t \to 0} \frac{F(t + \Delta t) - F(t)} {\Delta t}

某时刻尚未发生故障的产品,在该时刻后单位时间内发生故障的概率,称为产品的故障率failure rate),记为记为λ(t)λ(t)。故障率的计算公式如下:

λ(t)^=Ns(t)Ns(t+Δt)Ns(t)Δt=间隔时间内的故障数间隔起点的存活数×时间间隔\hat{λ(t)} = \frac{N_s(t) - N_s(t + \Delta t)} {N_s(t) \Delta t} = \frac{间隔时间内的故障数}{间隔起点的存活数 × 时间间隔}

λ(t)=limΔt0Ns(t)Ns(t+Δt)Ns(t)Δt=limΔt0F(t+Δt)F(t)R(t)Δt=f(t)R(t)λ(t) = \lim_{\Delta t \to 0} \frac{N_s(t) - N_s(t + \Delta t)} {N_s(t) \Delta t} = \lim_{\Delta t \to 0} \frac{F(t + \Delta t) - F(t)}{R(t)\Delta t} = \frac{f(t)}{R(t)}

在长期的可靠性实践中,人们发现许多产品的故障率随时间的变化曲线形似浴盆,所以习惯性的将故障率曲线称为“浴盆曲线”(bathtub curve),如下图所示[5:4]。大多数电子产品的故障率曲线的形状就是浴盆曲线。

产品典型的故障率曲线

故障率随时间的变化大致可以分为以下三个阶段:早期故障期(early failure period)、偶然故障期(random failure period)、耗损故障期(wear-out failure period)。三个阶段有时也被称为:早夭期(infant mortality period)、使用寿命期(useful life period)和耗损期(wear-out period)。故障率曲线与人类的死亡率曲线相似,曲线的三个阶段分别对应人类生命周期的婴幼儿时期、壮年期以及老年期。在偶然故障期,产品的故障率可降到一个较低的水平,且基本处于平稳状态,可以近似认为故障率为常数。

如果产品的故障率为常数,那么其故障的概率分布可以用指数分布(exponential distribution)描述,指数分布是唯一具有恒定故障率的连续概率分布。恒定故障率的特性也被称为“无记忆性”(memorylessness),该特性说明故障率在任何时刻都与系统已工作过的时间长短没有关系。服从指数分布的概率密度函数为:

f(t)=λeλtf(t) = {\lambda} e^{-\lambda t}

服从指数分布的可靠度函数、不可靠度函数和故障率函数依次为:

R(t)=eλtR(t) = e^{-\lambda t}F(t)=1eλtF(t) = 1 - e^{-\lambda t}λ(t)=λ\lambda(t) = \lambda

公式中的λ\lambda为常数。

上面提到的这些指标是概率相关的度量指标。另外,还有一些是时间相关的度量指标:

  • 平均故障间隔时间(MTBF,mean time between failures):相邻两次故障间的持续时间的平均值。失效间隔时间(time between failures)包括可用时间和不可用时间。MTBF 只能用于可修复产品。
  • 平均故障间隔工作时间(MTBF /MOTBF,mean operating time between failures):相邻两次故障间的累计工作时间的平均值。MOTBF 只能用于可修复产品,该值也被成为可修复产品的平均寿命(mean life)。
  • 平均故障前工作时间MTTF,mean operating time to failure):故障前工作时间的平均值。等同于,平均失效前时间(MTTF,mean time to failure)。MTTF 可以用于不可修复产品和可修复产品。MTTF 值也被成为不可修复产品的平均寿命(mean life)。
  • 平均恢复时间MTTR,mean time to restoration):恢复时间的平均值。最新的国际电工委员会 IEV 标准文档,废弃了平均恢复时间(mean time to recovery)和平均修理时间(mean time to repair)。平均恢复时间是维修性的主要度量指标。
  • 可用性availability):或者翻译为“可用度”,可以表示为平均可用时间除以平均可用时间与平均不可用时间之和。可用性是反映可靠性和维修的综合性指标。

根据国际电工委员会标准文档 IEC 60050-192:2015(等同的国家标准文档是 GB/T 2900.99-2016《电工术语 可信性》),MTBF 和 MOTBF 缩写代表的都是平均故障间隔工作时间(mean operating time between failures),统计的值是故障间隔工作时间operating time between failures),即相邻两次故障间的累计工作时间;而故障间隔时间time between failures),包括可用时间和不可用时间。所以,平均故障间隔时间平均故障间隔工作时间的含义是不同的,前者同时统计包括工作时间(operating time)和非工作时间(non-operating time),而后者只统计工作时间(operating time)。但是在很多其他文档中,比如维基百科的词条“平均故障间隔时间”(Mean time between failures)词条,“平均失效间隔时间”的缩写也是 MTBF。也就说, MTBF 即是“平均故障间隔时间”的缩写,也是“平均故障间隔工作时间”的缩写,但两者含义却不同,需要读者自行辨别。本文使用 MTBF,统一都表示“平均故障间隔时间”。

MTBF 只能用于可修复产品,MTTF 用于不可修复产品和可修复产品。对于不可修复产品,MTTF 等同于 MTBF,对于可修复产品,MTTF 等同于 MOTBF。MTBF 是 MTTR 和 MTTF 的总和,即MTBF=MTTR+MTTFMTBF = MTTR + MTTF

产品的平均寿命(mean life)的理论值为故障概率密度函数的期望值,记为 θ。该期望值也是可修复产品的 MOTBF 的理论值,是不可修复产品的 MTTF 的理论值。平均寿命或 MTTF 的计算公式如下:

MTTF=θ=E(T)=0tf(t)dxMTTF = θ = E(T) = \int_{0}^\infty t f(t)\,\mathrm{d}x

如果概率密度函数服从指数分布,那么平均寿命或 MTTF 值为:

MTTF=θ=1/λMTTF = θ = 1/\lambda

对于服从指数分布的产品,当产品工作时间到达平均寿命时,可靠度的值 36.8%:

R(θ)=e1=36.8%R(θ) = e^{-1} = 36.8\%

假设某可修复产品的正常工作时间为{TFF1,TFF2...,TFFn}\left\{ {TFF}_1, {TFF}_2 ..., {TFF}_n \right\},故障时间为{TTR1,TTR2...,TTRn}\left\{ {TTR}_1, {TTR}_2 ..., {TTR}_n \right\},如下图所示:

MTBF、MTTF 和 MTTR 示意图

MTBF、MTTF、MTTR 和可用性(availability)的估计值的计算公式如下:

MTBF=i=1nTBFin=total uptime + total downtimetotal number of failuresMTBF = \frac{\sum_{i=1}^n {TBF}_i}{n} = \frac{\text{total uptime + total downtime}}{\text{total number of failures}}

MTTF=i=1nTTFin=total uptimetotal number of failuresMTTF = \frac{\sum_{i=1}^n {TTF}_i}{n} = \frac{\text{total uptime}}{\text{total number of failures}}

MTTR=i=1nTTRin=total downtimetotal number of failuresMTTR = \frac{\sum_{i=1}^n {TTR}_i}{n} = \frac{\text{total downtime}}{\text{total number of failures}}

可用性=MTTFMTTF+MTTR=MTTFMTBF=total uptimetotal uptime+total downtime可用性 = \frac {MTTF} {MTTF + MTTR} = \frac {MTTF} {MTBF} = \frac{\text{total uptime}}{\text{total uptime} + \text{total downtime}}

对于电子设备,MTBF 近似常量,比如,典型的企业级固态硬盘 SSD 的 MTBF 值可能是 200 万小时[11],也就是 228 年,年故障率 AFR(Annualized Failure Rate) 为 0.44%(1/228)。

可以利用数学和统计方法对可靠性进行预计和度量,并分析可靠性数据。但是可靠性的量化涉及大量不确定性,由于可靠性经常关系到制造和使用产品的人,人的行为和表现不像植物对肥料的反应、气象模型对海洋温度的反应那样服从于数学分析和预测,而且产品可能在大范围变化的环境中工作,因此还会有其他不确定性因素被引入。数学和统计方法虽然在适当的场合是非常有价值的,但是由于涉及大量不确定性,在实际的可靠性工程中的作用有限,在实际的工程实践中优先需要确定的是故障的原因和解决方案[12]

软件可靠性工程

软件可靠性工程是从硬件可靠性工程发展而来的[13]。在软件工程学建立初期,一些软件工程专家利用和改造硬件可靠性工程学的成果,使之移植到软件领域,从而开创了软件可靠性学科。

类似的,起源于 Google 的“站点可靠性工程”(SRE, Site reliability engineering)也源自可靠性工程,区别是站点可靠性工程关注的是大型网站和网络服务这样的软件系统 [14][15]

术语与概念

国家标准 GB/T 11457-2006 《信息技术 软件工程术语》,对软件可靠性的定义如下:

2.1662 系统可靠性 system reliability
包括全部硬件和软件子系统在内的某个系统,在规定的环境及时间里正确执行所要求的任务或使命的概率。
2.1528 软件可靠性 software reliability
a) 在规定条件下,在规定的时间内,软件不引起系统失效的概率。该概率是系统输人和系统使用的函数,也是软件中存在的缺陷的函数。系统输人将确定是否会遇到已存在的缺陷(如果有缺陷存在的话)。
b) 在规定的时间周期内所述条件下程序执行所需要的功能的能力。

GB/T 11457-2006 吸收了 IEEE Std 610.12-1990 全部术语,包括术语“软件可靠性”,国标的术语定义只是对 IEEE 术语定义的中文翻译。IEEE 最早在标准文档中定义“软件可靠性”是在 IEEE Std 729-1983,这个标准之后被 IEEE Std 610.12-1990 替代。

IEEE 对“软件可靠性”术语给出两个定义,定义 a) 是定量的定义,也就是“可靠度”,定义 b) 是定性的定义。对比后容易发现,硬件可靠性和软件可靠性的定义是相同的。这种相容性,使这种可靠性定义能够用于既包括软件又包括硬件的系统。

故障相关的术语,国家标准 GB/T 11457-2006 《信息技术 软件工程术语》的定义是:

2.163 隐错 bug
见:出错 error(2.561) 和故障 fault(2.609)。
2.421 缺陷 defect
见:故障 fault(2.609)。
2.561 出错, 误差, 差错 error
a) 计算的、观察的或测量的值或条件与实际的、规定的或理论上正确的值或条件的差别。例如,在计算的结果和正确的结果之间差30m;
b) 不正确的步骤、过程或数据定义。例如,在计算机程序中的不正确的指定;
c) 不正确的结果。例如,当正确的结果是10,而计算的结果是12;
d) 产生不正确结果的人为动作。例如,在编程或操作的一部分上的不正确动作。
注:当上述所有四种定义是公共使用时,一种区分赋给定义 a) 为字差错(error),定义 b) 为字过错(fault),定义 c) 为字失效(failure)和定义 d) 为字错误(mistake)。
2.601 失效 failure
系统或部件不能按规定的性能要求执行它所要求的功能。注:故障容忍在人们的动作(弄错-mistake)、它的显示(硬件或软件故障 fault)、故障的结果(失效 failure)和不正确(差错-error)结果的总数之间进行区分
2.609 故障, 缺陷 fault
a) 硬件设备或部件中的缺陷。例如,短路或断线。
b) 在计算机程序中不正确的步骤、过程或数据定义。注:此定义最初由容错(fault tolerance)系统使用。在通常用法中,术语“差错(error)”和“隐错(bug)”表示同样含义。

基于 IEEE 的定义,容易发现术语“fault、“bug”和“defect”是同义词,术语“error”同时具有“mistake”、“fault”和“failure”的含义。这些术语之间的因果关系是,开发者在软件开发过程中产生人为失误(mistake),导致在软件中存在缺陷(fault, bug, defect),在软件运行时如果用户遭遇缺陷(fault, bug, defect),会引发失效(failure),如下图所示:

软件故障的因果关系

失效(failure)是指系统或部件在特定约束下不能完成所要求的功能,用户在测试或实际使用中会观察到失效(failure)。失效(failure)是系统运行行为对用户要求的偏离,是一种面向用户的概念。故障(fault)是在系统运行时引起或可能潜在地引起失效(failure)的缺陷(defect),是一种面向开发者的概念。

可靠性的度量

早期的软件可靠性度量工作试图将硬件可靠性理论中的数学公式外推来进行软件可靠性的预测。大多数与硬件相关的可靠性模型依据的是由于“磨损”而导致的故障,而不是由于设计缺陷而导致的故障。在硬件中,由于物理磨损(如温度、腐蚀、振动的影响)导致的故障远比与设计缺陷有关的故障多。不幸的是,软件恰好相反。实际上,所有软件故障都可以追溯到设计或实现问题,磨损根本没有影响[16]

软件系统的故障主要是人为差错造成,涉及大量不确定性,利用数学和统计方法对可靠性进行预计和度量,在实际的工程实践中的作用有限。少数常用的与可靠性相关的度量指标是:MTBF、MTTR 和可用性。

MTBF 指标衡量的是系统无故障运行的能力,也就是可靠性。MTTR 指标衡量的是系统快速从故障中恢复的能力,这种能力在硬件产品下被称为“维修性”(maintainability),但在软件系统下通常为称“韧性”(resilience)。术语“maintainability”,在硬件上下文中通常被翻译为“维修性”,而在软件上下文中通常被翻译为“维护性”或“可维护性”,软件可维护性指的是软件可被修改的能力,修改可能包括修复缺陷、增加或完善功能等。

MTBF 反映的是硬件产品的寿命,是硬件产品质量的最重要的指标之一。与硬件不同,软件的 MTBF 不可控,而故障恢复的工作流程清晰,可干预程度高,研发团队可以对各环节展开精细化管理,轻松、高效地达成 MTTR 优化目标,所以软件系统的 MTTR 相对 MTBF 更加重要[17][18]

可用性是衡量可靠性和韧性的综合性指标。想要提高系统的可用性,需要做的是延长无故障时间(MTTF)和缩短故障恢复时间(MTTR)。

可靠性设计

Laprie 等人把提高系统可靠性的方法总结为四种

  • 故障避免(fault avoidonce,简称“避错”):在系统的设计和实现过程中使用一些开发方法来减少故障发生,并在系统投入使用之前发现系统中的故障。
  • 故障排除(fault removal,简称“排错”):故障排除可以细分为两个子类别:开发期间的排除和使用期间的排除。在系统使用之前通过验证和确认(V&V)来发现和去除系统中的故障;如果系统已经投入使用,通过维护周期将其消除。
  • 故障容忍(fault tolerance,简称“容错”):容错是使系统在其某些组件中出现一个或多个故障时能够继续提供服务的能力,尽管该服务可能处于降级级别。容错技术主要是采用冗余redundancy)方法来消除故障的影响,冗余的含意是指当系统无故障时取消冗余资源不会影响系统正常运行。
  • 故障预报(fault forecasting):通过收集故障数据,建立可靠性建模,预测可能的故障。

针对软件可靠性设计,软件故障避免技术,包括采用优秀的软件设计方法、使用强类型的程序设计语言、全面的编译器检查等;软件故障排除技术,主要是代码评审和软件测试;故障预报,能提高硬件可靠性,但是很少应用于软件可靠性。

系统的资源包括硬件资源、软件资源、信息资源、时间资源,所以冗余区分 4 种方式:

  • 硬件冗余(hardware redundancy):通过配置额外的硬件组件实现冗余
  • 软件冗余(software redundancy):通过配置额外的软件版本实现冗余,例如 N 版本编程(NVP
  • 信息冗余(information redundancy):通过对信息中外加一部分信息码或将信息存放在多个内存单元或将信息进行备份等实现冗余,例如循环冗余校验码、数据库备份等。
  • 时间冗余(time redundancy):多次执行相同的操作(重试)实现冗余,例如多次执行程序或传输数据的多个副本。

硬件冗余和软件冗余被合称为结构冗余(structural redundancy)。相对与时间冗余,硬件冗余、软件冗余、信息冗余被合称为空间冗余(space redundancy)。

在工程领域,利用冗余提高可靠性的例子很多,比如汽车的备胎、大货车的多个轮子、飞机的四台发动机或双台发动机、火箭的多台引擎和多台计算机等。《像火箭科学家一样思考》书中的“为什么冗余不是多余的”小节[19]中有这样一段阐述:

航天器上的计算机也使用冗余装置。在地球上,电脑往往免不了崩溃或死机,而在有压力的太空环境中,计算机发生故障的概率有增无减,因为计算机在太空中要经历无数振动、冲击、变化的电流和波动的温度。正因为如此,航天飞机的计算机是4倍冗余的,即飞机上有4台计算机在运行着同样的软件。这4台计算机会通过一个多数投票系统就下一步动作进行单独投票。如果其中一台计算机发生故障,开始乱输出数据,其他3台计算机就会投票将其排除在外(没错,伙计们,火箭科学比你想象的更民主)。
冗余装置要正常工作,就必须独立运行。一架航天飞机配备4台计算机,这听起来非常棒,但由于它们运行着相同的软件,所以只要一个软件出现错误,4台计算机就会同时瘫痪。因此,航天飞机还配备了第5个备用飞行系统。该系统安装有一款不同的软件,而这款软件由不同于其他4款软件的分包商提供。如果某个一般性的软件错误使4台相同的主计算机瘫痪,则备用系统将启动,并会将航天飞机送回地球。

在航天飞机上配备 4 台计算机属于硬件冗余,第 5 个备用飞行系统属于软件冗余。

IDC 数据中心等级划分(data centre tiers)主要是根据线路、电源、冷却等核心组件的冗余程度而划分的,不同的等级代表不同的可靠性和可用性。按 Uptime Institute 和 TIA-942 标准的建议,数据中心由低到高划分为 T1、T2、T3、T4 共 4 个等级,T1 级为基本型、T2 级为冗余型、T3 级为可并行维护冗余型、T4 级为容错型。4 个等级的冗余程度分别是,T1 级无冗余,T2 级部分 N+1 冗余,T3 级全部 N+1 冗余,T4 级 2N 或 2N+1 冗余。按我国国家标准《GB 50174-2017 数据中心设计规范》,数据中心由高到低划分为 A、B、C 三级,A 级为容错型,B 级为冗余型,C 级为基本型。不同的数据中心等级的对比,如下表所示(表格参考自 [20]):

数据中心等级划分

大多数商业数据中心都介于 T3 级和 T4 级之间,平衡了建设成本和可靠性。金融等行业的数据中心,如银行的数据中心,通常会同时遵循最高等级的国家标准 A 级和 Uptime Institute 的 Tier 4 级标准来建设。

在生物学中,冗余是生物体的一种重要特征。生物体中的冗余结构和功能可以提高生物体的适应性和生存能力。例如,人体的很多器官是冗余的,比如耳朵、眼睛、肾、肺。冗余的器官如果出现“故障”,虽然不会让人完全失去该器官的机能,但会导致机能降级。其中一个眼睛如果完全失去视力,不会让人失明,不过视觉上无法识别远近。其中一个耳朵如果完全没有听力,不会让人失聪,但无法透过耳朵识别声音的位置。

尽管冗余是一种很好的提高可靠性的措施,但额外的冗余增加到某种程度之后,就会无谓地增加设备的复杂性和成本,遵循边际效益递减规律。典型的例子是客机,随着发动机本身可靠性的提高,出于安全性和成本之间的权衡,之前的四发动机的客机越来越少见,逐渐被更省油、更低维护成本的双发动机的客机取代。

参考资料


  1. 秦咏红,吕乃基:工程系统可靠性的演进,东北大学学报,2011年第4期295-299,cqvip ↩︎

  2. 可靠性概论,工信部电子第五研究所潘勇,2015,豆瓣:第11章 可靠性标准 ↩︎

  3. 2022-09 【标准解读】用标准语言解读装备“六性” https://mp.weixin.qq.com/s/FqfLL_ovGIZ-GO998HB4uw ↩︎

  4. 2021-07 张健:装备通用质量特性关系概述 https://mp.weixin.qq.com/s/nXmrTrz7c5EnEh4C_h4JEg ↩︎ ↩︎ ↩︎

  5. 可靠性工程师手册,中国质量协会,第2版 2017,豆瓣 ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  6. 2018-01 北航康锐:可靠性的历史与今世 | 可靠性系统工程三部曲(上) https://mp.weixin.qq.com/s/275pk9Z-V4T3lntI-ZzYCA ↩︎

  7. 可靠性工程(Reliability Engineering),Kapur & Pecht,2014,豆瓣:第1章 21世纪的可靠性工程 ↩︎

  8. 2002-03 褚善元:failure和fault的定名问题 http://www.term.org.cn/CN/abstract/abstract10076.shtml ↩︎ ↩︎

  9. 2002-03 朱美娴:关于failure和fault定义的研讨 http://www.term.org.cn/CN/abstract/abstract10081.shtml ↩︎ ↩︎

  10. System Reliability Theory, Rausand, etc., 3rd 2020,豆瓣:3 Failures and Faults, Figure 3.3 Illustration of the difference between failure and fault for a degrading item. ↩︎

  11. 2021-09 揭秘:SSD 的“可靠性”到底可不可靠 https://memblaze.com/innovate/technical-articles/169.html ↩︎

  12. 实用可靠性工程(Practical Reliability Engineering),O'Connor, etc.,第5版2012,豆瓣 ↩︎

  13. 陈光宇,黄锡滋:软件可靠性学科发展现状及展望,电子科技大学学报社科版,2002年第3期99-102,cqvip ↩︎

  14. SRE:Google运维解密,Beyer, etc. 2016,豆瓣:序言 ↩︎

  15. SRE原理与实践:构建高可靠性互联网应用,张观石,2022,豆瓣:第1章 互联网软件可靠性概论 ↩︎

  16. 软件工程:实践者的研究方法,Pressman,第8版2014,豆瓣:第21章 软件质量保证,21.7 软件可靠性 ↩︎

  17. 2010-07 John Allspaw: Thoughts on systems safety, software operations, and sociotechnical systems https://www.kitchensoap.com/2010/11/07/mttr-mtbf-for-most-types-of-f/ ↩︎

  18. 2023-07 LigaAI:研发质量指标大 PK:MTTR vs MTBF,谁是靠谱王? https://segmentfault.com/a/1190000043971564 ↩︎

  19. 像火箭科学家一样思考,Ozan Varol,2020,豆瓣:第1章 与不确定性共舞,为什么冗余不是多余的 ↩︎

  20. 2020-12 艾瑞咨询:2020年中国数据中心行业研究报告 https://report.iresearch.cn/report/202012/3699.shtml ↩︎

]]>
+ + + <p>为了应对负载的增长,目前大型网站普遍都采用分布式架构。相对于采用单体架构的系统,分布式系统中有大量的服务器及设备,各模块之间存在错综复杂的依赖关系,存在更多的不确定性。整个系统的故障率会随设备的增加而呈指数级增加,单一节点问题可能会被无限放大,日常运行过程中一定会伴随故障发生。所以,可靠性开始成为大型网站关注的最重要的质量属性之一,并因此发展出了站点可靠性工程(<a href="https://en.wikipedia.org/wiki/Site_reliability_engineering">Site reliability engineering</a>,SRE)。站点可靠性工程,是从可靠性工程发展而来的,从可靠性工程中借鉴了概念和成果。本文溯本求源,内容主要是总结概括,可靠性工程的历史演进和核心概念,软件可靠性工程的核心概念,以及可靠性设计的方法。</p> + + + + + + + + + + + + +
+ + + I/O 多路复用与网络服务器并发策略 + + https://nullwy.me/2023/07/io-multiplexing-network-server/ + 2023-07-25T16:44:00.000Z + 2023-12-05T06:14:18.570Z + + 目前主流的网络服务器,网络 I/O 相关的底层最核心的技术都是 I/O 多路复用(I/O Multiplexing),比如 Apache HTTP Server、Nginx、Redis 等。本文尝试解释各种 I/O 模型,包括解释什么是 I/O 多路复用,同时也总结 I/O 多路复用底层的系统调用 select、poll、kqueue 和 epoll 的演进和区别,并编写了使用这些函数的示例代码。另外,本文还总结了各种基于 I/O 多路复用实现的网络服务器的并发策略的三种模式,包括对 Apache HTTP Server、Nginx 和 Redis 等网络服务器的并发策略的具体案例的解析。

I/O 模型与多路复用

类 Unix 系统下的 I/O 操作,默认是阻塞 I/O(Blocking I/O,缩写为 BIO)。比如,当一个进程发出了读操作请求,但没有可访问的数据时,该进程通常会阻塞在内核中,直到出现可以访问的数据为止。然而,进程有时要处理对多个描述符的 I/O 操作,需要在多个文件描述符上阻塞,典型的场景是终端 I/O 和网络 I/O。

例如,有一个远程登录程序,它要从键盘读入数据然后把这些数据通过套接字发送到一个远程的计算机上。这个程序还需要从和远程终端相连接的套接字上读取数据,并将数据显示于屏幕上。如果进程在读键盘数据时阻塞,它就不能读那些从远程终端发送到屏幕上的数据。这样一来,在来自远程终端的更多数据到达之前,用户就不知道该通过键盘输入些什么,于是,死锁便产生了。相反的,如果进程在读从远程终端送来的数据时阻塞,它将不能读来自键盘终端的数据。

历史上,Unix 系统通过使用多个进程让应用能同时处理多个文件描述符,这些进程间可以通过管道或者是其他的进程间通信方法进行通信。然而,如果处理上下文切换的代价比处理输入的代价更大,那么这种方法就会导致巨大的系统开销,因为它要求在进程间进行频繁的上下文切换。并且,在一个进程内实现这种应用会显得比较直观。由于上述原因,BSD 提供了三种机制,允许对描述符进行多路 I/O 访问,非阻塞式 I/O、 I/O 多路复用和信号驱动 I/O[1]

  • 非阻塞 I/O(Nonblocking I/O,缩写为 NIO):进程对描述符尝试 I/O 操作,如果描述符未就绪(ready),系统不把本进程投入睡眠,而是返回一个错误(EAGAINEWOULDBLOCK)。进程收到错误后,要么放弃,要么不停地轮询(polling),直至发现有描述符可以进行 I/O 操作为止。这种轮询的方法的问题在于,进程必须连续不断地运行,检查描述符是否就绪,很浪费 CPU 时间。
  • I/O 多路复用(I/O Multiplexing):让系统提供一种方法在多个感兴趣的描述符中查找哪个描述符可以进行 I/O 操作,如果没有这样的描述符,系统会让进程处于睡眠状态,直到出现这样的描述符为止。这种方法的缺点是对于每个操作,进程要完成两个系统调用,一个用来查找就绪描述符,另一个是 I/O 操作本身。非阻塞 I/O 是在用户空间轮询查找就绪描述符,而 I/O 多路复用是执行特殊的系统调用在内核空间查找就绪描述符。
  • 信号驱动 I/O(Signal-Driven I/O):当可以进行 I/O 操作时,使所有描述符发信号。进程只用等待这些信号就可以知道是否可以进行 I/O 操作。这种方法的缺点在于捕获这些信号的开销是巨大的,所以此方法对于那些涉及大量 I/O 操作的应用并不实用。

类 Unix 系统下,默认的 I/O 操作都是阻塞 I/O。有两种方法可以将描述符设置非阻塞 I/O:(1) 如果是调用 open() 获得描述符,则可以在调用时设置 O_NONBLOCK 标志;(2) 对于已经打开的一个描述符,则可调用 fcntl(),由该函数为描述符设置 O_NONBLOCK 标志。另外,对于网络套接字的描述符,如果想在获得描述符时直接指定为非阻塞 I/O,可以在调用 socket() 或 accept() 时传入 SOCK_NONBLOCK 标志,当然也可以在获得描述符后,再调用 fcntl()修改。

I/O 多路复用,最早是在 4.2BSD(1983.08)中由 select() 系统调用提供的。虽然该系统调用主要用于终端 I/O 和网络 I/O,但它对其他描述符同样是起作用的。poll() 是另外一个实现 I/O 多路复用的系统调用,和 select() 功能几乎相同。SVR3(1987)在增加 STREAMS 机制时增加了 poll() 系统调用。但在 SVR4 (1988)之前,poll() 只对 STREAMS 设备起作用。SVR4 开始支持对任意描述符起作用的 poll()select()poll() 系统调用,都是在 POSIX.1-2001 开始标准化定义,然而从可移植性角度考虑,支持 select() 的系统比支持 poll() 的系统要多,所以在应用的实现上,相比于 poll() 基于 select() 实现更多。另外 POSIX 还定义了 pselect(),它是能够处理信号阻塞并提供了更高时间分辨率的 select() 的增强版本。

在 Linux 系统下,poll() 系统调用从 2.1.23 版本(1997.01)开始提供,而 poll() 库函数由 libc 5.4.28(1997.05)开始提供。早期 Linux 内核未提供 poll() 系统调用,glibc 使用 select() 来模拟实现 poll()。另外,Linux 还提供特有的 I/O 多路复用解决方案,即 epoll,详细介绍参见下文。

为了能持续不断的监听 I/O 操作就绪事件,应用实现上需要循环调用 select()poll()。为了方便使用,封装各个不同的 I/O 多路复用函数的第三方库,通常会把这样的循环调用被抽象为事件循环(event loop),然后把 I/O 就绪事件的处理抽象成回调函数(callback)。最早的提供事件循环(event loop)抽象的典型的第三方库是 libevent 库(最早在 2002.04 发布)。

信号驱动 I/O,在描述符就绪时内核会发送 SIGIO 信号。但是信号驱动 I/O 对于 TCP 套接字近乎无用,问题在于 SIGIO 信号产生得过于频繁,并且它的出现并没有告诉我们发生了什么事件,无法区分触发信号的各种情况。在 UDP 上使用信号驱动式 I/O 没有上述问题。关于信号驱动 I/O 的详细阐述,可以参阅《UNIX网络编程 卷1》的第 25 章[2]

描述符就绪条件

select()poll() 系统调用是在多个文件描述符中查找就绪(ready)的描述符。就绪条件具体指是什么呢?select()man 文档,有如下描述(poll() 的就绪条件类似,不展开讨论):

A file descriptor is considered ready if it is possible to perform a corresponding I/O operation (e.g., read(2), or a sufficiently small write(2)) without blocking.
...
A file descriptor is ready for reading if a read operation will not block; in particular, a file descriptor is also ready on end-of-file.
A file descriptor is ready for writing if a write operation will not block. However, even if a file descriptor indicates as writable, a large write may still block.

针对网络套接字描述符的就绪条件,《UNIX网络编程 卷1》如下总结:

套接字描述的就绪条件小结

表中的“有数据可读”含义是,该套接字接收缓冲区中的数据字节数大于等于套接字接收缓冲区低水位标记的当前大小。对这样的套接字执行读操作不会阻塞并将返回一个大于 0 的值(也就是返回准备好读入的数据)。接收低水位标记,可以通过调用 setsockopt() 的 SO_RCVLOWAT 选项来设置,默认值为 1。

表中的“有可用于写的空间”含义是,该套接字发送缓冲区中的可用空间字节数大于等于套接字发送缓冲区低水位标记的当前大小,并且或者该套接字已连接,或者该套接字不需要连接(如UDP套接字)。发送低水位标记,可以通过调用 setsockopt() 的 SO_SNDLOWAT 选项来设置,默认值为 1024。

表中的“关闭连接的读一半”和“关闭连接的写一半”含义是,套接字的 TCP 连接接收了关闭 FIN,此时会收到读就绪事件和写就绪事件。对这样的套接字做读操作将不阻塞并返回 0(也就是返回 EOF);对这样的套接字做写操作将产生 SIGPIPE 信号(Broken pipe: write to pipe with no readers)。

I/O 模型的比较

上文阐述的就是 Unix 系统的 4 种 I/O 模型,阻塞 I/O、非阻塞 I/O、I/O 多路复用和信号驱动式 I/O。另外,还有一种 I/O 模型是,异步 I/O(Asynchronous I/O,缩写为 AIO)。异步 I/O,由 POSIX 规范定义,工作机制是,告知内核启动某个操作,并让内核在整个操作(包括将数据从内核复制到我们自己的缓冲区)完成后通知进程。这种模型与信号驱动模型的主要区别在于:信号驱动 I/O 是由内核通知我们何时可以启动一个 I/O 操作,而异步 I/O 模型是由内核通知我们 I/O 操作何时完成。POSIX 定义的异步 I/O 的函数为,aio_write()aio_read() 等。

关于 POSIX 异步 IO,Linux 的 aio 的 man 文档,有如下说明:

The current Linux POSIX AIO implementation is provided in user space by glibc. This has a number of limitations, most notably that maintaining multiple threads to perform I/O operations is expensive and scales poorly. Work has been in progress for some time on a kernel state-machine-based implementation of asynchronous I/O (see io_submit(2), io_setup(2), io_cancel(2), io_destroy(2), io_getevents(2)), but this implementation hasn't yet matured to the point where the POSIX AIO implementation can be completely reimplemented using the kernel system calls.

本质上,Linux 下的 POSIX AIO 是在用户空间下用线程模拟实现的 AIO,并非真正的 AIO,性能很差,所以很少被使用。

Linux 内核实现的 AIO 是 io_submitio_setupio_getevents 等系统调用,也被成为“Linux Native AIO”,或者缩写为 KAIO(kernel AIO),从 Linux 2.5 开始支持(2001.11),这些系统调用对应的库函数由 libaio 库提供。但是 Linux Native AIO 几乎不可用,只适合以 O_DIRECT 方式做直接 IO(无缓存的 I/O)。如果真的实现了异步 AIO,io_submit 系统调用不应该阻塞,但是对缓存 I/O、网络访问、管道等,io_submit 会发生阻塞,整个操作将在 io_submit 系统调用期间执行,并且通过调用 io_getevents,I/O 操作完成结果可以立即访问,这样也就破坏了异步 I/O 的目的[3]

最新的内核实现的 AIO 是 io_uring,已经被 Linux 5.1(2019.05)采纳。很多开源项目,比如 libeventlibuvNginxRedis 等,都有打算支持或甚至已经支持 io_uring。io_uring 的杂类资料整理,可以参考“Awesome io_uring”[4]。本文主要关注 I/O 多路复用,io_uring 不再展开讨论。

《UNIX网络编程 卷1》对这 5 种 I/O 模型做了对比[2:1]

5 种 I/O 模型的比较

可以看出,前 4 种模型的主要区别在于第一阶段(等待描述符就绪),因为它们的第二阶段是一样的:在数据从内核复制到调用者的缓冲区期间,进程阻塞于 recvfrom 调用。相反,异步 I/O 模型在这两个阶段都要处理,从而不同于其他 4 种模型。

各个 I/O 模型,用户空间的应用与内核空间的交互过程如下图所示(信号驱动 I/O 实际场景较少使用,所以忽略)[5]

阻塞式 I/O非阻塞式 I/O
非阻塞式 I/O + I/O 多路复用异步 I/O

通常对“I/O 多路复用”术语的理解,其实就是特指,由 select() 、poll() 或类似的系统调用实现的在多个文件描述符中查找就绪状态描述符的技术。不过,根据 McKusick 书籍的描述[1:1]I/O 多路复用也可以泛指为,单个进程同时处理多个文件描述符的技术,与之相对立的技术是早期的由多个进程同时处理多个描述符的解决方案。广义理解的话,I/O 多路复用包括非阻塞 I/O、狭义的 I/O 多路复用、信号驱动式 I/O、异步 IO 等技术

单独的“多路复用(multiplexing)”术语,维基百科的解释是,一个通信和计算机网络领域的专业术语,多路复用通常表示在一个信道上传输多路信号或数据流的过程和技术。

阻塞、非阻塞与同步、异步的区别

在概念上,阻塞 I/O 和非阻塞 I/O,是根据系统是否会阻塞进程的执行而区分的:

  • 阻塞 I/O,在执行 I/O 操作后,如果 I/O 操作的描述符未就绪,系统会让进程进入睡眠状态,直到描述符就绪为止。
  • 非阻塞 I/O,在执行 I/O 操作后,不会阻塞当前进程,可以继续执行其他的任务。

另外,POSIX 定义了同步 I/O(Synchronous I/O)和异步 I/O(Asynchronous I/O)两个术语[2:2]

  • 同步 I/O 操作,导致请求进程阻塞,直到 I/O 操作完成
  • 异步 I/O 操作,不导致请求进程阻塞。

A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes.
An asynchronous I/O operation does not cause the requesting process to be blocked.

按照这个定义,阻塞 I/O、非阻塞 I/O、I/O 多路复用和信号驱动 I/O 都是同步 I/O,因为其中真正的 I/O 操作将阻塞进程(第二阶段,将数据从内核复制到用户空间的缓冲区阶段)。只有异步 I/O 模型与 POSIX 定义的异步 I/O 相匹配。

不过,对于 I/O 多路复用是属于同步 I/O 还是异步 I/O 存在争议,不同视角下存在不同的理解。I/O 多路复用,单看等待 I/O 就绪阶段,其实是异步的。所以很多时候,I/O 多路复用,虽然没有实现真正的 POSIX 定义的异步 I/O,但也被归类为异步 I/O。比如,Jones 的文章[5:1]将 I/O 多路复用归类为阻塞的异步 I/O,将 POSIX AIO 归类为非阻塞的异步 I/O。类似的,封装各个不同的 I/O 多路复用函数的 libevent 库的官方文档[6]自称是“Asynchronous I/O”。Node.js 底层是基于 I/O 多路复用封装的 libuv 库,libuv 库也自称是“Asynchronous I/O”。另外,如果跳出 I/O 视角,从整体应用的执行流程角度看,基于 I/O 多路复用实现的应用,相对于在多个描述符列表上主轮询流程,在单个描述符上 I/O 事件的应用处理流程相对独立,可以认为是异步的。Node.js 文档对“异步”的解释如下[7]

Asynchronous means that things can happen independently of the main program flow.

严格意义上,典型的 I/O 多路复用的应用是单进程单线程执行的,本质上都是串行执行的,是假异步。

服务器并发策略与 C10K 问题

世界上第一个 HTTP 服务器,CERN httpd,早期实现采用的 I/O 模型是阻塞 I/O,然后为了能同时处理多个客户端连接,会为每个客户端连接创建一个新的处理请求的子进程(process-per-connection),这种并发模式被称为 fork 模式,这也是传统的 Unix 服务器采用的并发模式。之后的版本,改为基于 select() 的 I/O 多路复用 + fork 模式(参见源码 HTDaemon.c)。

NCSA HTTPd,是早期的第一个流行的 HTTP 服务器,在版本 1.3 以及之前版本,也是采用阻塞 I/O + fork 模式实现,会为每个客户端连接创建一个新的子进程(参见源码 httpd.c)。之后 NCSA HTTPd 的 1.4 版本,I/O 模型改造为基于 select() 的 I/O 多路复用,进程模型改为“pre-forking”模式,但这种模式本质上还是每个客户端连接对应单个子进程(process-per-connection),“pre-forking”的优点是在创建新客户端连接时有预先创建的子进程直接处理请求(类似进程池),避免在创建新连接的同时执行创建子进程这样的重型操作,具体可以参见 1996.03 的官方文档的对“pre-forking”模型的性能测试[8](相关的实现源码参见 httpd.c)。

Apache HTTP Server,最早在 1995.04 对外公开发布首个版本 0.6.2,这个版本的代码基于 NCSA httpd 1.3[9]。 之后在 5 月和 6 月,Apache 也开始实现“pre-forking”特性,在版本 0.8.0 开始正式支持[9:1][10]。一直到 Apache HTTP Server 2.2,prefork 模式依然是 Unix 系统下的默认模式[11]在 Apache 的 prefork 模式下,每个客户端连接由单独的子进程处理,这样的子进程被 Apache 称为 worker 进程,worker 进程数就是同时处理的客户端连接数。因为线程相对进程更加轻量,理论上每个客户端连接对应单个线程(thread-per-connection)更有优势。所以,在 2002.04,Apache 发布 2.0 的首个 GA 版本时,新增了 worker 模式,一种多进程和多线程混合的模式。在 Apache 的 worker 模式下,每个客户端连接由单独的子线程处理,这样的子线程也就是 worker 线程,worker 线程数就是同时处理的客户端连接数。

相对单线程,多进程或多线程的问题是,占用更多内存(每个线程都需要维护自己的线程栈),以及频繁的上下文切换。所以,有些 HTTP 服务器倾向于基于 select() 实现单进程单线程的网络服务器。这种模式实现的服务器一般会把循环调用 select() 的过程抽象为事件循环(event loop),把 I/O 操作就绪事件的处理抽象成回调函数(callback),所以也被称为事件驱动服务器(event-driven server)。多核 CPU 时,为了能充分使用 CPU 多核资源,事件驱动服务器的进程数(或线程数)通常为 CPU 核数。事件驱动模式,在软件架构中被也称为 Reactor 模式。基于事件并发和基于线程的并发的比较,可以阅读 John Ousterhout 的 1995 年的经典 slides:“Why Threads Are A Bad Idea (for most purposes)”[12]

早期的典型的基于 select() 实现的单线程 HTTP 服务器的例子,是由 ACME 实验室开发并开源的 thttpd(1995.11 对外发布 1.0 版)。thttpd 服务器作者 Jef Poskanzer 在文章“Web Server Comparisons”(1998.07)[13]中对比了各个 Web 服务器。根据文章的对比,容易发现基于 select() 实现的单线程服务器,在响应性能和最大并发连接数上都占优,thttpd 支持的最大的每秒请求数 QPS 是 720,thttpd 支持的最大并发连接数是 1000+。

虽然在实验条件下表现良好,但是在真实场景下,基于 select() 实现的 HTTP 单线程服务器,性能并没有优于传统的基于 fork 模式的服务器[14]。Banga 等人经过分析后得出的主要原因是,当服务器同时处理的客户端连接数超过几千后,系统调用 select()poll() 的性能很差,不具备可伸缩性。

最早的 HTTP 1.0 协议,在服务响应完成后连接会立即关闭,连接无法保持。HTTP 底层是 TCP 协议,建立 TCP 连接需要经过三次握手的过程。如果能复用 TCP 连接,同一个 HTTP 连接上的后续的 HTTP 请求就不用重新建立 TCP 连接,也就是能在同一个 HTTP 连接上支持多次 HTTP 请求和响应,这样 HTTP 性能也就得到了提高。于是,HTTP 1.1 协议(RFC 2068,1997.01)开始持久连接(persistent connection),默认让 HTTP 连接“keep-alive”。关于 HTTP 持久连接的详细介绍,可以参考 RFC 2068 的“8.1 Persistent Connections”。

HTTP 协议支持持久连接后,也带来了另外一个问题,就是出现大量的冷链接(cold connection)。浏览器如果未主动关闭连接,停留在网页上,并且如果连接未超时,此时的连接虽然不活跃但会保持一段时间,这样的连接就是冷链接。同时,随着互联网的快速发展,访问网站的用户量不断上升,Web 服务器需要维持的链接数也不断上升,如何让服务支持更多客户端连接问题也愈发尖锐。当时 Web 服务器支持的最大并发连接数大致是 1K,于是 Dan Kegel 在 1999 年提出了 C10k 问题,如何能让服务器支持 10K 的客户端连接,字母“C”代表的是“client connection”。在文章“The C10K problem”[15]中,Dan Kegel 对 C10K 问题的描述如下:

It's time for web servers to handle ten thousand clients simultaneously, don't you think? After all, the web is a big place now.

另外,值得一提的是,HTTP 1.0 和 HTTP 1.1 协议存在队头阻塞问题(HOL 阻塞,head of line blocking),为了避免队头阻塞,从而使网页能更快响应,大多数浏览器会为每个域名同时开启多个 HTTP 连接,通常是 6 个并发连接[16],结果导致 Web 服务器需要维持的链接数增加数倍。在发布 HTTP 1.1 协议的十几年后的 2012 年,HTTP 2.0 的首个草稿发布,而制定 HTTP/2 协议的最大的目标之一就是解决队头阻塞问题。

select 和 poll 性能问题

当 Web 服务器需要同时处理大量客户端连接时,服务器的性能表现差,原因就出在系统调用 select()poll() 的性能上,具体的问题有如下三点[17]

  • 每次调用 select()poll(),内核都必须检查所有被指定的文件描述符,看它们是否处于就绪状态。随着待检查的文件描述符数量的增加,调用耗时也随之线性增加。若待检查的文件描述符数为 n,select()poll() 的时间复杂度为 O(n)。
  • 每次调用 select()poll(),程序都必须传递一个表示所有需要被检查的文件描述符的数据结构到内核,内核检查过描述符后,修改这个数据结构并返回给程序。(此外,对于 select() 来说,我们还必须在每次调用前初始化这个数据结构。)随着待检查的文件描述符数量的增加,传递给内核的数据结构大小也会随之增加。当检查大量文件描述符时,从用户空间到内核空间来回拷贝这个数据结构将占用大量的 CPU 时间。
  • select()poll() 调用完成后,程序必须检查返回的数据结构中的每个元素,以此查明哪个文件描述符处于就绪状态。

解决系统调用 select()poll() 的性能问题,让服务器能同时处理大量连接,比较典型的解决方案是,FreeBSD 4.1(2000.07 发布)开始支持的 kqueue 系统调用 ,以及 Linux 2.5.44(2002.10 发布)开始支持的 epoll 系统调用。

kqueue 和 epoll 系统调用

kqueue 相关的 API 主要涉及两个系统调用 kqueue()kevent()

  • kqueue():用于在内核空间创建 kqueue 数据结构
  • kevent()
    • 当传入其中的 changelist 等参数时,用于将感兴趣的 kevent 事件对象注册到 kqueuekevent 对象上记录感兴趣文件描述符和事件类型
    • 当传入其中的 eventlist 等参数时,用于查询就绪的 kevent 事件对象列表

kqueue 的实现原理[18]:调用 kqueue() 创建由内核空间维护 kqueue 实例,kqueue 实例内包含链表,链表上保存全部监听的 kevent 事件对象,kevent 对象上感兴趣的记录文件描述符和事件类型。通过 kevent() 系统调用,可以在链表上注册、删除某 kevent 对象。当设备 I/O 事件触发时,设备与 kqueue 实例关联的钩子函数(hook)会被执行,钩子函数会判断事件是否与监听的事件相符合,如果符合就把事件添加到 kqueue 实例内下链表 active list 的末尾。查询就绪事件列表时,调用 kevent(),内核只需要检查链表 active list 是否有元素,若有就把就绪事件列表拷贝到用户空间。

epoll 相关的 API 主要涉及三个系统调用 epoll_create()epoll_ctl()epoll_wait()

  • epoll_create():用于在内核空间创建 epoll 实例
  • epoll_ctl():用于添加感兴趣的 epoll_event 事件对象到 epoll 实例,epoll_event 对象上记录感兴趣文件描述符和事件类型
  • epoll_wait():用于查询就绪的 epoll_event 事件对象列表

epoll 的实现原理:调用 epoll_create() 创建由内核空间维护的 epoll 实例,epoll 实例内包含红黑树,红黑树上保存全部监听的 epoll_event 事件对象,epoll_event 对象上记录感兴趣的文件描述符和事件类型。通过 epoll_ctl() 系统调用,可以在红黑树上注册、删除某 epoll_event 对象。所有添加到红黑树中的事件都会与设备驱动程序建立回调关系,当 I/O 就绪事件触发时,会把事件添加到 epoll 实例内的链表 rdllist。查询就绪事件列表时,调用 epoll_wait(),内核只需要检查链表 rdllist 是否有元素,若有就把就绪事件列表拷贝到用户空间。

水平触发和边缘触发

epoll 系统调用的事件通知模式,区分水平触发(level-triggered,LT)和边缘触发(edge-triggered,ET),默认通知模式是水平触发 LT,EPOLLET 标志可以将通知模式改为边缘触发。poll()select() 所提供的通知模式是水平触发,不支持边缘触发。水平触发和边缘触发的通知模式的含义如下[17:1]

  • 水平触发通知模式:如果文件描述符上可以非阻塞地执行 I/O 系统调用,此时认为它已经就绪。水平触发模式下,应用程序可以不立即处理该事件,当应用程序下一次调用 epoll_wait() 时,epoll_wait() 还会再次向应用程序通告此事件,直到该事件被处理。这种模式下 epoll 相当于一个效率较高的 poll。
  • 边缘触发通知模式:如果文件描述符自上次状态检查以来有了新的 I/O 事件,此时需要触发通知。也就是说,当 epoll_wait() 检测到某 I/O 事件发生并将此事件通知应用程序后,后续的 epoll_wait() 调用将不再向应用程序通知这一事件,只通知新的 I/O 事件。边缘触发模式在很大程度上降低了同一个 epoll 事件被重复触发的次数,因此效率要比水平触发模式高。但是相对水平触发,边缘触发模式下开发难度更大。

“水平触发”和“边缘触发”术语源于电子工程领域。水平触发是只要有状态发生就触发。边缘触发是只有在状态改变的时候才会发生。条件触发关心的是事件状态,边缘触发关心的是事件本身。

采用边缘触发通知的程序通常要按照如下规则来设计:

  • 在接收到一个 I/O 事件通知后,程序在某个时刻应该在相应的文件描述符上尽可能多地执行 I/O(比如尽可能多地读取字节)。如果程序没这么做,那么就可能失去执行 I/O 的机会。
  • 如果尽可能多地执行 I/O,而文件描述符被设置为阻塞模式,那么最终当没有更多的 I/O 可执行时,I/O 系统调用就会阻塞。所以,每个被检查的文件描述符通常都应该设置为非阻塞模式。

另外,在边缘触发 ET 模式下,如果多个线程同时监听相同的描述符,只会有一个线程被唤醒用来处理 I/O 事件。epoll 的 man 文档对这个特性有如下描述,这个特性也避免了“惊群问题”(thundering herd problem)。

If multiple threads (or processes, if child processes have inherited the epoll file descriptor across fork(2)) are blocked in epoll_wait(2) waiting on the same epoll file descriptor and a file descriptor in the interest list that is marked for edge-triggered (EPOLLET) notification becomes ready, just one of the threads (or processes) is awoken from epoll_wait(2). This provides a useful optimization for avoiding "thundering herd" wake-ups in some scenarios.

因此,边缘触发通知模式其中一个适用的场景是,多核 CPU 上的多线程服务器,每个 CPU 核上运行一个线程,这些线程同时监听相同的描述符[19]

kqueue 文档没有使用水平触发和边缘触发术语。但接口效果上,默认是水平触发。开启EV_CLEAR标志可以达到类似边缘触发的效果。EV_CLEAR 标志的 man 文档描述:

After the event is retrieved by the user, its state is reset.

因为边缘触发通知模式效率更高,Nginx 服务器采用的就是边缘触发,参见源码 ngx_epoll_module.cngx_kqueue_module.c

select、poll、kqueue 和 epoll 的比较

selectpollkqueueepoll 系统调用的多个维度的对比总结,如下表:

系统调用selectpollkqueueepoll
类 Unix 系统的支持情况POSIX 标准。最早 4.2BSD 提供(1983)POSIX 标准。最早 SVR3 提供(1987)BSD 专有。最早 FreeBSD 4.1 提供 (2000.08)Linux 专有。最早 Linux 2.5.44 提供(2002.10)
查询就绪描述符的时间复杂度O(n)O(n)O(1)O(1)
感兴趣描述符列表传递每次 select() 都全量拷贝到内核空间每次 poll() 都全量拷贝到内核空间由内核空间维护由内核空间维护
就绪描述符列表的返回只返回就绪描述符数量,需要检查感兴趣描述符列表来判断哪些是就绪描述符只返回就绪描述符数量,需要检查感兴趣描述符列表来判断哪些是就绪描述符返回就绪事件数量,并同时返回就绪事件列表返回就绪事件数量,并同时返回就绪事件列表
最大描述符数被常数 FD_SETSIZE 限制(值为 1024)无限制无限制无限制
触发通知模式水平水平水平和边缘水平和边缘

附注:查询就绪描述符的时间复杂度,selectpoll 都是 O(n),n 为感兴趣描述符的总数,因为内核实现上需要轮询全部感兴趣的描述符列表。kqueueepoll 都是 O(1),实际的查询耗时与就绪描述符总数线性有关,但真实场景下就绪描述符数量相对描述符总数很小,可以认为是常数,所以复杂度是 O(1)。

总体上,selectpoll 之间大同小异,而 kqueueepoll 之间也是大同小异。

libevent 库,对系统调用 selectpollkqueueepoll 做了性能基准测试,如下图所示(图片来源)。基准测试声明了大量连接(文件描述符),大多数连接是冷的,只有少数是活跃的。测试衡量的是,在不同的总连接数下,为 100 个活动连接提供服务所需的时间。可以看到,系统调用 selectpoll,随着文件描述符的增加,耗时也随之线性增加,2500 个文件描述符时耗时大约 20ms,5000 个文件描述符时耗时大约 40ms,10000 个文件描述符时耗时大约 80ms。而系统调用 kqueueepoll,耗时始终在 3ms ~ 5ms 之间。

性能基准测试:select vs poll vs kqueue vs epoll

echo 服务的简单示例代码

上文总结了 selectpollkqueueepoll 的接口特性和实现原理,但对具体应该如何使用这些函数没有切身感受。笔者使用 I/O 多路复用函数 select、poll、epoll 和 kqueue 以及 libevent 库,各自编写了 echo 服务的简单示例代码。所谓 echo 服务,即服务端接收到客户端的字符串输入,然后响应相同的字符串(为了方便区分响应字符串加了 > 前缀)。比如,如果客户端输入字符串 hello,服务端将响应字符串 > hello;如果客户端输入字符串 world,服务端将响应字符串 > world。完整的示例代码参见 io-multiplexing-demo

Nginx 服务器的并发策略解析

上文介绍了 NCSA HTTPd、Apache HTTP Server 和 thttpd 等 Web 服务器的并发策略。主要的并发策略有三种模式:单连接单进程模式、单连接单线程模式和单线程的事件驱动模式。

Nginx 最早是 2002 年开始开发的,2004.08 采用 BSD 协议对外开源首个版本 0.1.0,开发 Nginx 的目的是为了解决 C10k 问题[20]。2002 年,当时 FreeBSD 已经提供 kqueue 系统调用,而 Linux 的 epoll 即将正式发布,新的 kqueueepoll 系统调用让 Nginx 解决 C10k 问题成为可能。根据 w3techs 的统计,在 2013.07 Nginx 超越 Apache 成为 top 1000 网站使用最多的 Web 服务器[21]

Nginx 采用的是事件驱动架构,在单线程的进程上执行事件循环,以异步非阻塞的方式处理 I/O 操作事件,事件循环底层基于高效的 epollkqueue 实现的 I/O 多路复用[22]

Nginx 服务器,区分 Master 进程和 Worker 进程。Master 进程,用于加载配置文件、启动 Worker 进程和平滑升级等。Worker 进程,是单线程的进程,用于执行事件循环,并以非阻塞方式处理 I/O 操作,因此单个 Worker 进程就能并发处理大量连接。一个完整的请求完全由 Worker 进程来处理,而且只在一个 Worker 进程中处理。为了能充分利用多核 CPU 资源,通常生产环境配置的 Worker 进程数量等于 CPU 核心数。Nginx 的架构图如下[22:1]

Nginx 架构图

Redis 服务器的并发策略解析

Redis 是内存数据库,处理网络请求也是采用单线程的事件驱动模式,底层基于高效的 epollkqueue 实现的 I/O 多路复用。事件循环处理的事件主要有,建立客户端新连接事件、客户端连接的缓冲区可读事件、客户端连接的缓冲区可写事件。Redis 的命令处理过程如下:

  • 在收到建立客户端新连接事件后,会在新建立的客户端套接字上监听可读事件,用于等待客户端发起命令请求。客户端连接可能会一直保持,处理之后的多个客户端命令请求。
  • 如果监听到客户端连接的缓冲区可读事件,也就是收到客户端的命令请求,服务器会读取命令、解析命令,然后执行命令,最后把命令响应结果输出到内存缓冲区。值得注意的是,命令响应结果输出到内存缓冲区,但并未输出客户端连接的缓冲区。
  • 在等到开启新的事件循环时,Redis 会在等待接收新的 I/O 事件之前,统一将全部内存缓冲区的命令响应结果输出到各个客户端。当命令响应结果数据量非常大时,无法一次性将所有数据都发送给某客户端,这时就会监听该客户端缓冲区可写事件。
  • 如果监听到客户端连接的缓冲区可写事件,Redis 就会发送剩余部分的数据给客户端。

上述的命令处理过程,在源码层面上涉及的核心代码都在 networking.c 中:处理客户端新连接建立的事件的回调函数是 acceptTcpHandler,处理客户端命令请求事件的回调函数 readQueryFromClient,命令响应结果输出到各个客户端对应的函数是 handleClientsWithPendingWrites,处理客户端的可写事件的回调函数是 sendReplyToClient。更详细的实现原理解析,本文不再展开,可以自行深入阅读相关源代码或书籍资料。

Redis 与 Nginx 在并发策略上有不同的选择,Nginx 有多个 Worker 进程,每个 Worker 进程都运行自己的事件循环,而 Redis 整体上只有一个事件循环,采用的是单线程架构。这样的架构设计带来的问题就是 Redis 无法多核 CPU 并发。针对无法多核 CPU 并发问题,Redis 官方 FAQ 的推荐的解决方案是[23]:在多核 CPU 的单台机器上启动多个 Redis 实例。Redis 作者 antirez,解释了选择单线程而不选择多线程的原因,主要是:在 Redis 的数据结构上实现并发控制太复杂,多线程编程降低开发速度并且导致 bug 修复困难[24][25]。采用单线程的原因,概况成一句话就是[25:1]

There is less to gain, and a lot of complexity to add.

不过,随着 Redis 版本的演进,部分逻辑已经改成了多线程实现,Redis 新增的多线程特性有三处,Redis 2.4 新增的异步磁盘 IO、Redis 4.0 新增的“Lazy Freeing”和 Redis 6.0 新增的“Threaded I/O”。但整体设计上,还是可以认为 Redis 主要使用单线程设计,依然是单线程的事件循环,并以单线程的方式执行命令(绝大多数命令,“Lazy Freeing”相关的命令除外)[26][27]

参考资料


  1. FreeBSD操作系统设计与实现,McKusick,2004:6.4.5 描述符上的多路I/O操作 ↩︎ ↩︎

  2. Unix网络编程 卷1:套接字联网API,Stevens,第3版2003 ↩︎ ↩︎ ↩︎

  3. 2014-04 AIO User Guide: A description of how to use AIO https://web.archive.org/web/0/http://code.google.com/p/kernel/wiki/AIOUserGuide ↩︎

  4. Awesome io_uring https://github.com/espoal/awesome-iouring ↩︎

  5. 2006-08 M. Jones: Boost application performance using asynchronous I/O https://developer.ibm.com/articles/l-async/ ↩︎ ↩︎

  6. Learning Libevent: A tiny introduction to asynchronous IO https://libevent.org/libevent-book/01_intro.html ↩︎

  7. Node.js: JavaScript Asynchronous Programming and Callbacks https://nodejs.dev/en/learn/javascript-asynchronous-programming-and-callbacks/ ↩︎

  8. 1995-04 NCSA httpd: Performance of Several HTTP Demons on an HP 735 Workstation https://web.archive.org/web/0/http://www.ncsa.uiuc.edu/InformationServers/Performance/V1.4/report.html ↩︎

  9. About the Apache HTTP Server Project https://httpd.apache.org/ABOUT_APACHE.html ↩︎ ↩︎

  10. Changes with Apache (12 Jun 1995: This release included modified versions of a lot of code from the Apache 0.6.4 public release, plus an early pre-forking patch codeveloped by Robert Thau and Rob Hartill.) https://github.com/apache/httpd/blob/1.3.x/src/CHANGES#L9427 ↩︎

  11. Apache HTTP Server Version 2.2: Multi-Processing Modules (MPMs) https://httpd.apache.org/docs/2.2/en/mpm.html#defaults ↩︎

  12. 1995 John Ousterhout: Why Threads Are A Bad Idea (for most purposes) (slides) http://www.cc.gatech.edu/classes/AY2010/cs4210_fall/papers/ousterhout-threads.pdf ↩︎

  13. 1998-07 Jef Poskanzer: Web Server Comparisons(thttpd 服务器作者) http://www.acme.com/software/thttpd/benchmarks.html ↩︎

  14. 1998 Gaurav Banga, Jeffrey C. Mogul: Scalable Kernel Performance for Internet Servers Under Realistic Loads. USENIX Annual Technical Conference 1998 dblp usenix.org ↩︎

  15. 1999-05 Dan Kegel: The C10K problem(最后更新时间 2011.07) http://www.kegel.com/c10k.html ↩︎

  16. 2014-02 详解浏览器最大并发连接数 https://web.archive.org/web/0/http://www.iefans.net/liulanqi-zuida-bingfa-lianjieshu ↩︎

  17. Linux Unix系统编程手册,Kerrisk 下册:第63章 其他备选的I/O模型 ↩︎ ↩︎

  18. 2001 Jonathan Lemon: Kqueue - A Generic and Scalable Event Notification Facility. USENIX Annual Technical Conference 2001 dblp usenix.org ↩︎

  19. What is the purpose of epoll's edge triggered option? https://stackoverflow.com/a/73540436/689699 ↩︎

  20. 2012-01 Interview with Igor Sysoev, author of Apache's competitor NGINX https://web.archive.org/web/0/http://www.freesoftwaremagazine.com/articles/interview_igor_sysoev_author_apaches_competitor_nginx ↩︎

  21. 2013-07 Nginx just became the most used web server among the top 1000 websites https://w3techs.com/blog/entry/nginx_just_became_the_most_used_web_server_among_the_top_1000_websites ↩︎

  22. 2012-03 AOSA Volume 2 - nginx (Andrew Alexeev) https://aosabook.org/en/v2/nginx.html ↩︎ ↩︎

  23. Redis FAQ: How can Redis use multiple CPUs or cores? https://redis.io/docs/getting-started/faq/#how-can-redis-use-multiple-cpus-or-cores ↩︎

  24. 2010-09 antirez: An update on the Memcached/Redis benchmark http://oldblog.antirez.com/post/update-on-memcached-redis-benchmark.html ↩︎

  25. 2019-02 antirez: An update about Redis developments in 2019 http://antirez.com/news/126 ↩︎ ↩︎

  26. Redis Doc: Diagnosing latency issues: Single threaded nature of Redis https://redis.io/docs/management/optimization/latency/#single-threaded-nature-of-redis ↩︎

  27. 2019-08 林添毅:正式支持多线程!Redis 6.0与老版性能对比评测 https://mp.weixin.qq.com/s/6WQNq5dNk-GuEhZXtVCo-A ↩︎

]]>
+ + + <p>目前主流的网络服务器,网络 I/O 相关的底层最核心的技术都是 I/O 多路复用(I/O Multiplexing),比如 Apache HTTP Server、Nginx、Redis 等。本文尝试解释各种 I/O 模型,包括解释什么是 I/O 多路复用,同时也总结 I/O 多路复用底层的系统调用 select、poll、kqueue 和 epoll 的演进和区别,并编写了使用这些函数的示例代码。另外,本文还总结了各种基于 I/O 多路复用实现的网络服务器的并发策略的三种模式,包括对 Apache HTTP Server、Nginx 和 Redis 等网络服务器的并发策略的具体案例的解析。</p> + + + + + + + + + + + + + + + + +
+ + + InnoDB 的并发控制:锁与 MVCC + + https://nullwy.me/2023/07/innodb-locking/ + 2023-07-10T13:20:00.000Z + 2023-12-05T06:14:12.594Z + + 目前主流数据库事务的并发控制实现,如 MySQL InnoDB、PostgreSQL、Oracle,都使用两阶段封锁 2PLMVCC 技术,但具体实现细节上存在差异。InnoDB 是在以封锁技术为主体的情况下,用 MVCC 技术辅助实现读-写、写-读操作的并发。PostgreSQL 的并发控制技术是以 MVCC 技术为主,封锁技术为辅。本文主要关注 InnoDB 事务的并发控制实现。

背景知识

并发控制,是数据库系统的 ACID 特性中的隔离性(Isolation)的保障。所谓隔离性,就是事务的执行不应受到其他并发执行事务的干扰,事务的执行看上去应与其他事务是隔离的。被隔离的执行,等价于事务的某种串行执行,或者说,它等价于一个没有并发的执行。保证串行性可能只允许极小的并发度,采用较弱隔离性,能带来更高的并发度,是并发事务的正确性和性能之间的妥协。

早期各大数据库厂商实现并发控制时多采用基于封锁的并发控制技术,所以在基于封锁的技术背景下,才在 ANSI SQL-92 标准中提出了四种隔离级别:未提交读(Read Uncommitted)、己提交读(Read Committed)、可重复读(Repeatable Read)、可串行化(Serializable)(附注:为了书写简便本文将各个隔离级别依次缩写为 RU、RC、RR、SER)。ANSI SQL-92 标准的四种隔离级别,是根据三种读异常现象(phenomena)定义的,隔离级别和异常现象的关系如下:

隔离级别P1 脏读P2 不可重复读P4 幻读
Read Uncommitted可能可能可能
Read Committed避免可能可能
Repeatable Read避免避免可能
Serializable避免避免避免

ANSI SQL-92 标准文档对三种读异常现象的定义原文如下 [ref]:

The isolation level specifies the kind of phenomena that can occur during the execution of concurrent SQL-transactions. The following phenomena are possible:
1) P1 ("Dirty read"): SQL-transaction T1 modifies a row. SQL-transaction T2 then reads that row before T1 performs a COMMIT. If T1 then performs a ROLLBACK, T2 will have read a row that was never committed and that may thus be considered to have never existed.
2) P2 ("Non-repeatable read"): SQL-transaction T1 reads a row. SQL-transaction T2 then modifies or deletes that row and performs a COMMIT. If T1 then attempts to reread the row, it may receive the modified value or discover that the row has been deleted.
3) P3 ("Phantom"): SQL-transaction T1 reads the set of rows N that satisfy some . SQL-transaction T2 then executes SQL-statements that generate one or more rows that satisfy the used by SQL-transaction T1. If SQL-transaction T1 then repeats the initial read with the same , it obtains a different collection of rows.

除了脏读、不可重复读和幻读这 3 种读数据异常外,还有写数据异常,即脏写和丢失更新。各个异常的含义如下:

  • P0 脏写(Dirty Write):事务 T1 写某数据项,并且未提交或回滚,事务 T2 也写该数据项,然后事务 T1 或事务 T2 回滚,回滚导致另外一个事务的修改被连带回滚。脏写异常会导致事务无法回滚,原子性无法得到保障,所以全部隔离级别下都应该避免。脏写也可以叫回滚丢失。
  • P1 脏读(Dirty Read):读到了其他事务还未提交的数据。
  • P2 不可重复读(Non-Repeatable):事务 T1 读取某数据项,事务 T2 修改 update 或删除 delete 该数据项,事务 T1 再次读取该数据项,结果不同。
  • P3 幻读(Phantom):事务 T1 读取满足某条件的数据项集合,事务 T2 生成新的满足该条件的数据项,事务 T2 再次读取满足该条件的数据项集合,结果不同。
  • P4 丢失更新(Lost Update):事务 T1 读取某数据项,事务 T2 更新该数据项并提交,事务 T1 忽略事务 T2 的更新,直接基于最初的读取数据项做更新并提交,导致事务 T2 的更新丢失。丢失更新也可以叫覆盖丢失。

各个异常的读写操作序列的简化符号表示如下 [Berenson 1995]:

1
2
3
4
5
P0: w1[x]...w2[x]...(c1 or a1)                 事务 T2 脏写
A1: w1[x]...r2[x]...(a1 and c2 in any order) 事务 T2 脏读,r2[x] 为脏读
A2: r1[x]...w2[x]...c2...r1[x]...c1 事务 T1 不可重复读,两次 r1[x] 结果不同
A3: r1[P]...w2[y in P]...c2...r1[P]...c1 事务 T1 幻读,两次 r1[P] 结果不同
P4: r1[x]...w2[x]...w1[x]...c1 事务 T2 更新丢失,c1 导致 w2[x] 丢失

其中 w1[x] 表示事务 T1 写入记录 x,r1[x] 表示事务 T1 读取记录 x,c1 表示事务 T1 提交,a1 表示事务 T1 回滚,r1[P] 表示事务 T1 按照谓词 P 的条件读取若干条记录,w1[y in P] 表示事务 T1 写入记录 y 满足谓词 P 的条件。

Berenson 的论文评判了 ANSI SQL-92 标准的异常定义。ANSI SQL-92 标准的异常的定义存在歧义,可以严格解释,也可以宽松解释,A1、A2 和 A3 的符号表示为严格解释,按严格解释,某些特殊的异常无法囊括,所以推荐宽松解释。按照标准的定义,容易引起误解的是,在排除 P1 脏读、P2 不可重复、P3 幻读这三种读异常后就会得到可串行化隔离级别,但是事实并非如此。标准没有定义 P0 脏写和 P4 更新丢失异常。另外,基于 MVCC 技术实现的快照隔离(Snapshot Isolation),能避免标准定义的 P1 脏读、P2 不可重复、P3 幻读,并且避免 P0 脏写和 P4 更新丢失,但还存在写偏序(Write Skew)异常。

不可重复读和幻读的区别:

  • 不可重复读对于事务 T2 的写操作是更新或删除操作,而幻读对于事务 T2 的写操作是插入(插入的新数据满足条件)或更新(使不满足条件的数据在更新后满足条件)操作。
  • 对于幻读现象中事务 T2 的操作,如果操作是对现有数据的更新或删除操作,则表明这样的操作等同于不可重复读,即是在多个行数据上进行更新或删除,即在多个行数据上批量化重演了不可重复读现象
  • 不可重复读和幻象最大的区别就是前者只需要“锁住”(考虑)已经读过的数据,而幻读需要对“还不存在的数据“做出预防。不可重复读现象中事务 T2 着眼于对现有数据进行操作;而幻读现象中事务 T2 着眼于对新增(或不在锁定范围内已经存在的数据上做更新后而得的数据满足了谓词条件)数据

异常由并发冲突引起,对应关系如下:

  • 写写冲突:P0 脏写、P4 丢失更新
  • 写读冲突:P1 脏读
  • 读写冲突:P2 不可重复读、P3 幻读

早期各大数据库厂商实现并发控制时多采用基于封锁的并发控制技术,所以在基于封锁的技术背景下,才在ANSI SQL 标准中提出了四种隔离级别。基于锁的并发控制技术的加锁方式与隔离级别的关系表 [Berenson 1995]:

隔离级别写锁数据项的读锁谓词的读锁
Read Uncommitted长写锁无锁要求无锁要求
Read Commited长写锁短读锁短谓词锁
Repeatable Read长写锁长读锁短谓词锁
Serializable长写锁长读锁长谓词锁

说明:

  • 短锁(short duration lock),当前正在执行的语句持有锁,语句执行完毕锁被释放。长锁(long duration lock),当锁被持有后,直到事务提交之后才被释放。
  • RU 隔离级别,阻止 P0,长写锁
  • RC 隔离级别,阻止 P0、P1,长写锁 + 短读锁 + 短谓词锁
  • RR 隔离级别,阻止 P0、P1、P4、P2,长写锁 + 长写锁 + 短谓词锁
  • SER 隔离级别,阻止 P0、P1、P4、P2、P3,长写锁 + 长写锁 + 长谓词锁

基于锁的并发控制下,隔离级别和异常现象的关系:

隔离级别P0 脏写P1 脏读P4 丢失更新P2 不可重复读P4 幻读
Read Uncommitted避免可能可能可能可能
Read Committed避免避免可能可能可能
Repeatable Read避免避免避免避免可能
Serializable避免避免避免避免避免

各个隔离级别在基于锁的并发控制技术下的具体的实现说明(参考自腾讯李海翔的《数据库事务处理的艺术》第 2 章):

基于锁的并发控制

基于锁的并发控制,读-读操作可以并发执行,但读-写、写-读、写-写操作无法并发执行,阻塞等待。MVCC 结合封锁技术,使得读-写、写-读操作互不阻塞,即只有写-写操作不能并发,并发度被提高到 75%,这就是 MVCC 被广为使用的原因。

InnoDB 的并发控制以封锁技术为主,MVCC 技术为辅助。让我们先看下 InnoDB 的封锁技术。

共享锁与排他锁

InnoDB 存储引擎实现两种标准的行级锁模式,共享锁(读锁)和排他锁(写锁)[doc]:

  • 共享锁(shared lock,S):允许事务读一行数据。
  • 排他锁(exclusive Lock,X):允许事务删除或更新一行数据。

如果事务 T1 持有行 r 上的共享锁(S),则来自某个不同事务 T2 的对行 r 上的锁的请求将按如下方式处理:

  • T2 对 S 锁的请求可以立即被授予。因此,T1 和 T2 持有 r 上的锁。
  • T2 对 X 锁的请求不能立即被授予。

如果事务 T1 持有行 r 上的排他锁(X),则某个不同事务 T2 对 r 上任一类型的锁的请求无法立即被授予。相反,事务 T2 必须等待事务 T1 释放其对行 r 的锁定。

共享锁和排他锁的兼容性:

待申请 \ 已持有共享锁 S排他锁 X
共享锁 S兼容冲突
排他锁 X冲突冲突

区分共享锁(读锁)和排它锁(写锁)后,读锁与读锁的并发可被允许进行,并发能力得以提高。

对于 updatedeleteinsert 语句,InnoDB 会自动给涉及数据集加排他锁(X);对于普通 select 语句,InnoDB 不会加任何锁(SERIALIZABLE隔离级别下除外);事务可以通过以下语句显式给查询 select 显式加共享锁或排他锁:

  • 共享锁(S):select ... for share
  • 排他锁(X):select ... for update

现在让我们来试验下共享锁和排他锁。创建 tbl 表,并添加表数据:

1
2
3
4
5
6
7
create table tbl 
(a int, b int, c int, d int, primary key(a), unique key(b), key(c));
insert into tbl values
(10, 10, 10, 10), (20, 20, 20, 20), (30, 30, 30, 30),
(40, 40, 40, 40), (50, 50, 50, 50), (60, 60, 60, 60),
(70, 70, 70, 70), (80, 80, 80, 80), (90, 90, 90, 90),
(100, 100, 100, 100);

InnoDB 的排它锁示例,如下:

事务1事务2
mysql> begin;mysql> begin;
-- 在 a = 10 的索引记录上添加排他锁
mysql> select * from tbl where a = 10 for update;
-- 阻塞,获取 a = 10 的排他锁超时
mysql> update tbl set b = 42 where a = 10;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
-- 阻塞,获取 a = 10 的排他锁超时
mysql> update tbl set b = 42 where a >= 10;
-- 阻塞,获取 a = 10 的排他锁超时
mysql> delete from tbl where a = 10;
-- 阻塞,获取 a = 10 的排他锁超时
mysql> select * from tbl where a = 10 for update;
-- 更新成功,可以获得其他记录的排他锁
mysql> update tbl set b = 42 where a = 20;
mysql> commit;
-- 更新成功,在事务 1 释放锁后,其他事务可以获取排他锁
mysql> update tbl set b = 42 where a = 10;

InnoDB的共享锁示例,如下:

事务1事务2
mysql> begin;mysql> begin;
-- 在 a = 10 的索引记录上添加共享锁
mysql> select * from tbl where a = 10 for share;
-- 获取 a = 10 的共享锁成功
mysql> select * from tbl where a = 10 for share;
-- 阻塞,获取 a = 10 的排他锁超时
mysql> update tbl set b = 42 where a = 10;
mysql> commit;
-- 更新成功,在事务 1 释放锁后,其他事务可以获取排他锁
mysql> update tbl set b = 42 where a = 10;

多粒度与意向锁

InnoDB 存储引擎支持多粒度锁定(multiple granularity locking),这种锁定允许事务在行级上的锁和表级上的锁同时存在。为了支持在不同粒度上进行加锁操作,InnoDB 存储引擎支持一种额外的锁方式,称之为意向锁(Intention Lock)。意向锁是将锁定的对象分为多个层次,意向锁意味着事务希望在更细粒度上进行加锁。

若将上锁的对象看成一棵树,那么对最下层的对象上锁,也就是对最细粒度的对象进行上锁,那么首先需要对粗粒度的对象上锁。如果需要对页上的记录 r 进行上 X 锁,那么分别需要对数据库 A、表、页上意向锁 IX,最后对记录 r 上 X 锁。若其中任何一个部分导致等待,那么该操作需要等待粗粒度锁的完成。

在一个对象加锁之前,该对象的全部祖先节点均加上了意向锁。希望给某个记录加锁的事务必须遍历从根到记录的路径。在遍历树的过程中,该事务给各节点加上意向锁。

粒度层次图

举例来说,假设在表 1 的记录 r 上持有 X 锁,表 1 上必定持有 IX 锁。如果其他事务想在表 1 上加 S 表锁或 X 表锁,但与已有 IX 锁不兼容,所以该事务需要等待。再举例,假设表 1 持有 S 锁,如果其他事务想在表 1 的记录 r 上加 X 锁,需要先获得表 1 的 IX 锁,但与已有 S 锁不兼容,所以该事务需要等待。有了意向锁之后,就能快速判断行锁和表锁之间是否兼容。

InnoDB 存储引擎支持意向锁设计比较简练,其意向锁即为表级别的锁,两种意向锁 [doc]:

  • 意向共享锁(IS):事务打算给数据行加行共享锁(S),事务在给一个数据行加共享锁(S)前必须先取得该表的 IS 锁。
  • 意向排他锁(IX):事务打算给数据行加行排他锁(X),事务在给一个数据行加排他锁(X)前必须先取得该表的 IX 锁。

IS、IX、S、X 锁的兼容性:

待申请 \ 已持有ISIXSX
IS兼容兼容兼容冲突
IX兼容兼容冲突冲突
S兼容冲突兼容冲突
X冲突冲突冲突冲突

兼容关系:各种意向锁(IS、IX)之间全部兼容,意向共享锁 IS 和共享锁 S 兼容,共享锁 S 和共享锁 S 兼容,其他冲突。

SQL 语句可以分为数据定义语言(DDL)、数据控制语言(DCL)、数据查询语言(DQL)、数据操纵语言(DML)四种类型的语句,前两种语句,涉及的对象在数据之上,所以加锁的范围,通常是表级,对应表级锁。后两种语句操作的对象是数据,加锁的范围,通常是数据级,这就对应行级锁。

三种行锁:记录锁、间隙锁和 next-key 锁

InnoDB 行锁分为 3 种类型 [doc]:

  • 记录锁(record lock):对索引记录项加锁。
  • 间隙锁(gap lock):间隙锁,对索引记录项之间的“间隙”、笫一条记录前的“间隙”或最后一条记录后的“间隙“加锁。锁定一个范围,但不包含索引记录本身。
  • next-key 锁(next-key Lock):前两种锁的组合,记录锁 + 间隙锁,锁定一个范围,并且锁定索引记录本身。(中文世界有时将 next-key lock 翻译为“临键锁”)

如果索引上包含 10, 20, 30, 40, 50 这些记录,那么可能的 next-key 锁的锁区间(interval),如下:

1
2
3
4
5
6
(-无穷, 10]     即,间隙锁 (-无穷, 10) + 记录锁 10。区间为,左开右闭区间
(10, 20] 即,间隙锁 (10, 20) + 记录锁 20
(20, 30] 即,间隙锁 (20, 30) + 记录锁 30
(30, 40] 即,间隙锁 (30, 40) + 记录锁 40
(40, 50] 即,间隙锁 (40, 50) + 记录锁 50
(50, +无穷] 即,间隙锁 (50, +无穷)

最后一个锁区间 (50, +无穷],对应的是上界伪记录(supremum pseudo-record),不是真实存在的记录。这个锁区间用于防止在最大值 50 之后插入记录。

记录锁总是会去锁住索引记录,如果 InnoDB 存储引擎表在建立的时候没有设置任何一个索引,那么这时 InnoDB 存储引擎会使用隐式的主键来进行锁定。

MySQL 默认的事务隔离级别是可重复读(REPEATABLE-READ),如果把事务隔离级别改成已提交读(READ-COMMITTED),间隙锁会被禁用。禁用间隙锁后,幻读异常会出现,因为其他事务可以在间隙中插入新行。InnoDB 的间隙锁,就是为了解决幻读异常而引入的。关于幻读异常,参见官方文档 doc

RR 隔离级别下,InnoDB 的锁通常使用 next-key 锁。但是,在唯一索引(和主键索引)上的等值查询next-key 锁退化为记录锁,间隙锁并不需要,即仅锁住索引本身,而不是范围。如果在唯一索引(和主键索引)上做范围查询,间隙锁依然需要。官方文档描述如下 [doc]:

Gap locking is not needed for statements that lock rows using a unique index to search for a unique row. (This does not include the case that the search condition includes only some columns of a multiple-column unique index; in that case, gap locking does occur.)

间隙锁是“纯抑制性的”,间隙锁唯一的作用就是为了防止其他事务的插入到间隙中。间隙锁和间隙锁之间是互不冲突的,所以间隙共享 S 锁和间隙排他 X 锁没有任何区别。

另外,还有一种锁叫插入意向锁(insert intention lock),基于间隙锁,专门用于 insert 操作。在执行 insert 操作时,需要先申请获取插入意向锁,也就是说,需要先检查当前插入位置上的下一条记录上是否持有间隙锁,如果被间隙锁锁住,则锁冲突,插入被阻塞。多个事务做 insert 操作,被相同的间隙锁阻塞,如果插入的值各不相同,这些事务的 insert 操作之间不阻塞。

所以,间隙锁与插入意向锁的兼容关系是,已持有的间隙锁与待申请的插入意向锁冲突,而插入意向锁之间兼容,在一个间隙锁锁上可以有多个意向锁等待。

IS、IX、X、S 锁和记录锁、间隙锁、next-key 锁的关系:

  • IS、IX、S、X 是锁模式(lock mode)(源码层面上对应 lock_mode 枚举)。
  • 记录锁、间隙锁、next-key 锁、插入意向锁是行锁类型(record lock type)。
  • 每一种行锁类型,都包含 IS、IX、S、X 锁模式,如共享的记录锁、排他的记录锁、共享的间隙录锁、排他的间隙锁等。

锁监控:data_locks 和 data_lock_waits 表

MySQL 8.0 之前,information_schema 库提供 innodb_trxinnodb_locksinnodb_lock_waits 三张表,用来监控事务和诊断潜在的锁问题,具体介绍可以参见官方 5.7 文档 doc

  • innodb_trx:当前事务表
  • innodb_locks:锁等待中的锁信息表
  • innodb_lock_waits:锁等待中的事务表

在 MySQL 8.0 之前,要想获得当前已持有的锁信息,需要开启参数 innodb_status_output_locks 并且执行命令 show engine innodb status,具体介绍可以参见官方文档“15.17 InnoDB Monitors”,doc

MySQL 8.0 开始,innodb_locks 表和 innodb_lock_waits 表,被 performance_schema 库的 data_locks 表和 data_lock_waits 表替代。其中值得注意的不同点是,新的 data_locks 表,同时包含了已持有的锁和请求中的锁的信息,这样查看当前已持有的锁信息更加方便。相关 SQL 示例:

1
2
3
4
5
6
7
8
9
10
11
-- 查询全部锁信息
select * from performance_schema.data_locks \G
-- 查询全部记录锁的锁信息
select * from performance_schema.data_locks where LOCK_TYPE = 'RECORD' \G
-- 查询等待中的锁信息
select * from performance_schema.data_locks where LOCK_STATUS = 'WAITING' \G
-- 查询锁等待中的事务
select * from performance_schema.data_lock_waits \G
-- 使用 sys 库的 innodb_lock_waits 视图
-- 查询锁等待中的事务
select * from sys.innodb_lock_waits \G

命令 show engine innodb status 的输出和 data_locks 表的对应关系,可以参考文章 link

行锁加锁案例分析

RR 隔离级别

本文的全部案例采用的 MySQL 版本为 8.0.30。MySQL 的默认事务隔离级别是 REPEATABLE-READ(可重复读),事务隔离级别可以通过系统变量 transaction_isolation 控制。

1
2
3
4
5
6
7
8
-- 事务隔离级别,默认为可重复读(Repeatable Read)
mysql> select @@global.transaction_isolation, @@transaction_isolation;
+--------------------------------+-------------------------+
| @@global.transaction_isolation | @@transaction_isolation |
+--------------------------------+-------------------------+
| REPEATABLE-READ | REPEATABLE-READ |
+--------------------------------+-------------------------+
1 row in set (0.00 sec)

tbl 表的数据如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mysql> select * from tbl;
+-----+------+------+------+
| a | b | c | d |
+-----+------+------+------+
| 10 | 10 | 10 | 10 |
| 20 | 20 | 20 | 20 |
| 30 | 30 | 30 | 30 |
| 40 | 40 | 40 | 40 |
| 50 | 50 | 50 | 50 |
| 60 | 60 | 60 | 60 |
| 70 | 70 | 70 | 70 |
| 80 | 80 | 80 | 80 |
| 90 | 90 | 90 | 90 |
| 100 | 100 | 100 | 100 |
+-----+------+------+------+
10 rows in set (0.00 sec)

(a1) 主键索引上的等值查询

SQL 语句:

1
select * from tbl where a = 10 for update;

data_locks 表中的行锁数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
mysql> select * from performance_schema.data_locks where LOCK_TYPE = 'RECORD' \G
*************************** 1. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 4816436360:185:4:3:140408965390368
ENGINE_TRANSACTION_ID: 56664
THREAD_ID: 367
EVENT_ID: 22
OBJECT_SCHEMA: testdb
OBJECT_NAME: tbl
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: PRIMARY
OBJECT_INSTANCE_BEGIN: 140408965390368
LOCK_TYPE: RECORD
LOCK_MODE: X,REC_NOT_GAP
LOCK_STATUS: GRANTED
LOCK_DATA: 10

加锁情况:

  • 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)

其他 SQL 语句的加锁情况(通过查 data_locks 表确认):

1
2
3
4
5
6
7
8
-- 在 a = 10 的索引记录上添加共享记录锁(S,REC_NOT_GAP)
select * from tbl where a = 10 for share;

-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
update tbl set b = 42 where a = 10;

-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
delete from tbl where a = 10;

加锁与锁冲突 SQL 演示:

事务1事务2
mysql> begin;mysql> begin;
-- 在 a = 10 的索引记录上添加排他记录锁
mysql> select * from tbl where a = 10 for update;
-- 阻塞,因为 a = 10 上存在排他记录锁
mysql> select * from tbl where a = 10 for update;
-- 阻塞,因为 a = 10 上存在排他记录锁
mysql> insert into tbl (a) values (10);
-- 插入成功
mysql> insert into tbl (a) values (9);
-- 插入成功
mysql> insert into tbl (a) values (11);
mysql> rollback;mysql> rollback;

(a2) 唯一索引上的等值查询

SQL 语句的加锁情况(通过查 data_locks 表确认):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
-- 在 b = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
select * from tbl where b = 10 for update;

-- 在 b = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 覆盖索引,但系统会认为接下来要更新数据,因此会顺便给主键索引上满足条件的行加上行锁
select a from tbl where b = 10 for update;

-- 在 b = 10 的索引记录上添加共享记录锁(S,REC_NOT_GAP)
-- 在 a = 10 的索引记录上添加共享记录锁(S,REC_NOT_GAP)
select * from tbl where b = 10 for share;

-- 在 b = 10 的索引记录上添加共享记录锁(S,REC_NOT_GAP)
-- 覆盖索引,所以只在字段 b 上加锁
select a from tbl where b = 10 for share;

-- 在 b = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
update tbl set b = 42 where b = 10;

-- 在 b = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
delete from tbl where b = 10;

上面的全部 SQL,除了走覆盖索引的 select for share 外,其他的加锁范围都相同。

(a3) 非唯一索引上的等值查询

SQL 语句的加锁情况(通过查 data_locks 表确认):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
-- 在 c = 10 的索引记录上添加排他 next-key 锁,区间为 (-无穷, 10](X)
-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 c = 20 的索引记录上添加排他间隙锁,区间为 (10, 20)(X,GAP)
select * from tbl where c = 10 for update;

-- 在 c = 10 的索引记录上添加共享 next-key 锁,区间为 (-无穷, 10](S)
-- 在 a = 10 的索引记录上添加共享记录锁(S,REC_NOT_GAP)
-- 在 c = 20 的索引记录上添加共享间隙锁,区间为 (10, 20)(S,GAP)
select * from tbl where c = 10 for share;

-- 在 c = 10 的索引记录上添加共享 next-key 锁,区间为 (-无穷, 10](S)
-- 在 c = 20 的索引记录上添加共享间隙锁,区间为 (10, 20)(S,GAP)
-- 覆盖索引,所以只在字段 c 上加锁
select a from tbl where c = 10 for share;

-- 在 c = 10 的索引记录上添加排他 next-key 锁,区间为 (-无穷, 10](X)
-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 c = 20 的索引记录上添加排他间隙锁,区间为 (10, 20)(X,GAP)
update tbl set c = 42 where c = 10;

-- 在 c = 10 的索引记录上添加排他 next-key 锁,区间为 (-无穷, 10](X)
-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 c = 20 的索引记录上添加排他间隙锁,区间为 (10, 20)(X,GAP)
delete from tbl where c = 10;

上面的全部 SQL,除了走覆盖索引的 select for share 外,其他的加锁范围都相同。

加锁与锁冲突 SQL 演示:

事务1事务2
mysql> begin;mysql> begin;
-- 在 c = 10 的索引记录上添加排他 next-key 锁,区间为 (-无穷, 10]
-- 在 a = 10 的索引记录上添加排他记录锁
-- 在 c = 20 的索引记录上添加排他间隙锁,区间为 (10, 20)
mysql> select * from tbl where c = 10 for update;
-- 阻塞,因为 c = 10 上存在排他 next-key 锁
mysql> select * from tbl where c = 10 for update;
-- 阻塞,因为 a = 10 上存在排他记录锁
mysql> select * from tbl where a = 10 for update;
-- 阻塞,因为 c = 10 上存在排他 next-key 锁,区间为 (-无穷, 10]
mysql> insert into tbl (a, c) values (1, 9);
-- 阻塞,因为 c = 10 上存在排他 next-key 锁,区间为 (-无穷, 10]
mysql> insert into tbl (a, c) values (1, 10);
-- 阻塞,因为 c = (10, 20) 区间存在间隙锁
mysql> insert into tbl (a, c) values (1, 11);
-- 插入成功
mysql> insert into tbl (a, c) values (1, 21);
mysql> rollback;mysql> rollback;

(a4) 无索引的等值查询

SQL 语句的加锁情况(通过查 data_locks 表确认):

1
2
-- 在 a 主键的全部索引记录上添加排他 next-key 锁
select * from tbl where d = 10 for update;

因为字段 d 上没有索引,这个 SQL 语句,只能在聚簇索引上全表扫描。加锁情况,在 a 主键的全部索引记录上添加排他 next-key 锁。表 tbl 共 10 条记录,全部的持有的 next-key 锁的锁区间,如下:

1
2
3
4
5
6
7
8
9
10
11
(-无穷, 10]
(10, 20]
(20, 30]
(30, 40]
(40, 50]
(50, 60]
(60, 70]
(70, 80]
(80, 90]
(90, 100]
(100, +无穷]

(a5) 值不存在的等值查询

SQL 语句的加锁情况(通过查 data_locks 表确认):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
---- 主键索引上的值不存在的等值查询
-- 在 a = 100 的索引记录上添加排他间隙锁,区间为 (90, 100)(X,GAP)
select * from tbl where a = 95 for update;
-- 在 a 的索引记录上添加排他 next-key 锁,区间为 (100, +无穷](X)
select * from tbl where a = 105 for update;

---- 唯一索引上的值不存在的等值查询
-- 在 b = 100 的索引记录上添加间隙锁,区间为 (90, 100)(X,GAP)
select * from tbl where b = 95 for update;
-- 在 b 的索引记录上添加排他 next-key 锁,区间为 (100, +无穷](X)
select * from tbl where b = 105 for update;

---- 非唯一索引上的值不存在的等值查询
-- 在 c = 100 的索引记录上添加间隙锁,区间为 (90, 100)
select * from tbl where c = 95 for update;
-- 在 c 的索引记录上添加排他 next-key 锁,区间为 (100, +无穷](X)
select * from tbl where c = 105 for update;

(b1) 主键索引上的范围查询

SQL 语句的加锁情况(通过查 data_locks 表确认):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)
-- 在 a 的索引记录上添加排他 next-key 锁,区间为 (100, +无穷](X)
select * from tbl where a >= 90 for update;

-- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a 的索引记录上添加排他 next-key 锁,区间为 (100, +无穷](X)
select * from tbl where a >= 100 for update;

-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 100 的索引记录上添加排他间隙锁,区间为 (90, 100)(X,GAP)
-- 附注:与主键上的等值查询 `a = 90` 的加锁范围的区别是额外加了区间为 (90, 100) 间隙锁
select * from tbl where a >= 90 and a < 91 for update;

-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 100 的索引记录上添加排他间隙锁,区间为 (90, 100)(X,GAP)
-- 附注:与相同查询条件的 `select for update`,加锁范围相同
update tbl set d = 42 where a >= 90 and a < 91;

-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 100 的索引记录上添加排他间隙锁,区间为 (90, 100)(X,GAP)
-- 附注:与相同查询条件的 `select for update` 的 SQL,加锁范围相同
delete from tbl where a >= 90 and a < 91;

(b2) 唯一索引上的范围查询

SQL 语句的加锁情况(通过查 data_locks 表确认):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
-- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)
-- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 b 的索引记录上添加排他 next-key 锁,区间为 (100, +无穷](X)
select * from tbl where b >= 90 for update;

-- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)(不必要的记录锁)
select * from tbl where b >= 90 and b < 91 for update;

-- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)(不必要的记录锁)
-- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)(不必要的记录锁)
update tbl set d = 42 where b >= 90 and b < 91;

-- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)(不必要的记录锁)
-- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)(不必要的记录锁)
delete from tbl where b >= 90 and b < 91;

加锁与锁冲突 SQL 演示:

事务1事务2
mysql> begin;mysql> begin;
-- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90]
-- 在 a = 90 的索引记录上添加排他记录锁
-- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100]
mysql> select * from tbl where b >= 90 and b < 91 for update;
-- 阻塞,因为 b = 90 上存在排他 next-key 锁
mysql> select * from tbl where b = 90 for update;
-- 阻塞,因为 b = 100 上存在排他 next-key 锁(不必要的记录锁)
mysql> select * from tbl where b = 100 for update;
-- 阻塞,因为 a = 90 上存在排他记录锁
mysql> select * from tbl where a = 90 for update;
mysql> rollback;mysql> rollback;

(b3) 非唯一索引上的范围查询

SQL 语句的加锁情况(通过查 data_locks 表确认):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
-- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)
-- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 b 的索引记录上添加排他 next-key 锁,区间为 (100, +无穷](X)
select * from tbl where c >= 90 for update;

-- 在 c = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 c = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)(不必要的记录锁)
select * from tbl where c >= 90 and c < 91 for update;

-- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)(不必要的记录锁)
-- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)(不必要的记录锁)
update tbl set d = 42 where c >= 90 and c < 91;

-- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)(不必要的记录锁)
-- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)(不必要的记录锁)
delete from tbl where c >= 90 and c < 91;

对比,唯一索引上的范围查询的加锁情况,容易得出结论,唯一索引和普通索引上的范围查询的加锁规则相同

RC 隔离级别

把事务隔离级别修改为已提交读(Read Committed):

1
2
-- 事务隔离级别,修改为已提交读(Read Committed)
mysql> set @@transaction_isolation = 'READ-COMMITTED';

(a1) 主键索引上的等值查询

SQL 语句的加锁情况(通过查 data_locks 表确认):

1
2
3
4
5
6
7
8
9
10
11
-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
select * from tbl where a = 10 for update;

-- 在 a = 10 的索引记录上添加共享记录锁(S,REC_NOT_GAP)
select * from tbl where a = 10 for share;

-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
update tbl set b = 42 where a = 10;

-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
delete from tbl where a = 10;

结论:因为主键索引上的等值查询不涉及间隙锁,所以 RR 和 RC 隔离级别下的加锁规则相同。

(a2) 唯一索引上的等值查询

同样的,因为唯一索引上的等值查询不涉及间隙锁,所以 RR 和 RC 隔离级别下的加锁规则相同。

(a3) 非唯一索引上的等值查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
-- 在 c = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
select * from tbl where c = 10 for update;

-- 在 c = 10 的索引记录上添加排他记录锁(S,REC_NOT_GAP)
-- 在 a = 10 的索引记录上添加排他记录锁(S,REC_NOT_GAP)
select * from tbl where c = 10 for share;

-- 在 c = 10 的索引记录上添加排他记录锁(S,REC_NOT_GAP)
-- 覆盖索引,所以只在字段 b 上加锁
select a from tbl where c = 10 for share;

-- 在 c = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
update tbl set c = 42 where c = 10;

-- 在 c = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
delete from tbl where c = 10;

(a4) 无索引的等值查询

1
2
-- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
select * from tbl where d = 10 for update;

(a5) 值不存在的等值查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
---- 主键索引上的值不存在的等值查询
-- 无锁
select * from tbl where a = 95 for update;
-- 无锁
select * from tbl where a = 105 for update;

---- 唯一索引上的值不存在的等值查询
-- 无锁
select * from tbl where b = 95 for update;
-- 无锁
select * from tbl where b = 105 for update;

---- 非唯一索引上的值不存在的等值查询
-- 无锁
select * from tbl where c = 95 for update;
-- 无锁
select * from tbl where c = 105 for update;

(b1) 主键索引上的范围查询

1
2
3
4
5
6
7
8
9
10
11
12
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
select * from tbl where a >= 90 for update;

-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
select * from tbl where a >= 90 and a < 91 for update;

-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
update tbl set d = 42 where a >= 90 and a < 91;

-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
delete from tbl where a >= 90 and a < 91;

(b2) 唯一索引上的范围查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-- 在 b = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 b = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
select * from tbl where b >= 90 for update;

-- 在 b = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
select * from tbl where b >= 90 and b < 91 for update;

-- 在 b = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
update tbl set d = 42 where b >= 90 and b < 91;

-- 在 b = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
delete from tbl where b >= 90 and b < 91;

(b3) 非唯一索引上的范围查询

加锁情况,和 RC 隔离级别的唯一索引上的范围查询完全相同。

行锁加锁规则总结

RC 隔离级别时的加锁规则:

  • 间隙锁被禁用,只有记录锁,没有间隙锁和 next-key 锁。
  • 对全部满足查询条件的索引记录加记录锁。如果查询条件满足覆盖索引,就只对辅助索引加记录锁。如果需要回表,对辅助索引记录和聚簇索引记录引同时加锁。
  • 如果不存在满足查询条件的索引记录,就不加锁。

RR 隔离级别时的加锁规则:

  • 加锁的基本单位是 next-key 锁。
  • 对全部满足查询条件的索引记录加 next-key 锁。如果查询条件满足覆盖索引,就只对辅助索引加记录锁。如果需要回表,对辅助索引记录和聚簇索引记录引同时加锁。
  • 范围查询时,或值不存在的等值查询时,在从右扫描到的最后的不满足查询条件的记录上加间隙锁。如果索引的最大记录值,满足查询条件,则在上界伪记录(supremum pseudo-record)上加 next-key 锁(相当于间隙锁)。
  • 等值查询时,在主键索引和唯一索引上加锁,next-key 锁退化为记录锁。

范围查询时的不必要加锁 bug

注意,RR 隔离级别时,在主键索引上的范围查询时,确实是按上文的规则加间隙锁。但实际验证发现,在辅助索引(包括唯一索引和普通索引)上的范围查询时,在最后的不满足查询条件的记录上实际加的是 next-key 锁。这样加锁的问题是,会在不满足查询条件的记录上记录锁,这个记录锁其实是不必要的,是一个 bug。

其实,这个不必要的记录锁 bug,在 MySQL 8.0.18 之前,主键索引的场景下也存在,MySQL 8.0.18 修复了,但只修复了主键索引的场景,辅助索引的场景未修复。修复对应 bug 为“Bug #29508068 UNNECESSARY NEXT-KEY LOCK TAKEN”,修复提交记录见 github

在 MySQL 8.0.19 版本上,有人再次提了 bug,“Bug #98639 Redundant row-level locking for secondary index”。不过 MySQL 官方认为“Not a Bug”。然后,提 bug 的人,也只好妥协认为这个是“performance issue”。

对比下面这 3 个 SQL 的加锁情况,可以发现后 2 个 SQL 存在不必要的加锁问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-- 主键索引上的范围查询
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 a = 100 的索引记录上添加排他间隙锁,区间为 (90, 100)(X,GAP)
select * from tbl where a >= 90 and a < 91 for update;

-- 唯一索引上的范围查询
-- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)(不必要的记录锁)
select * from tbl where b >= 90 and b < 91 for update;

-- 非唯一索引上的范围查询
-- 在 c = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
-- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
-- 在 c = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)(不必要的记录锁)
select * from tbl where c >= 90 and c < 91 for update;

隔离级别的实现

上文提到,PostgreSQL 的并发控制技术是以 MVCC 技术为主,封锁技术为辅。先看下 PostgreSQL 对隔离级别的实现 [doc]:

  • PostgreSQL 支持 SQL 标准的 4 种隔离级别,默认的隔离级别是 RC。但 PostgreSQL 内部只实现 3 种隔离级别 RC、RR 和 SER。若选择 RU 隔离,实际上是 RC。
  • PostgreSQL 的 RR 隔离级别,底层是基于 MVCC 技术实现的快照隔离(SI,Snapshot Isolation)。快照隔离下,能避免 SQL-92 定义的三种异常,脏读、不可重复读和幻读异常,但是可能会出现写偏序(Write Skew)异常。
  • PostgreSQL 的 SER 隔离,底层是可串行化的快照隔离(SSI,Serializable Snapshot Isolation)。

InnoDB 的并发控制以封锁技术为主,MVCC 技术辅助,各个隔离级别的具体实现是:

  • RC 隔离级别:快照读 + 写长锁
    • 快照读,能避免脏读
  • RR 隔离级别:快照读 + 写长锁 + 间隙锁(没有实现真正的快照隔离 SI)
    • 快照读,能一定程度避免不可重复读和幻读异常,但因为 InnoDB 的刷新快照的特殊实现,不能完全避免
    • 间隙锁,能避免幻读异常,只有锁定读时才会申请获取间隙锁
  • 可串行化隔离级别:读长锁 + 写长锁 + 间隙锁
    • 完全基于锁实现串行化,并发度很低,性能不好

InnoDB 实现的 MVCC 技术,能让事务以快照读的方式执行查询。快照读snapshot read),或者叫一致性非锁定读(consistent nonlocking read),或者一致性读(consistent read),即使用多版本技术实现的读取数据在某个时间点的快照的查询。在 RR 和 RC 隔离级别下,一致性读是普通的 select 语句的默认模式。快照读避免加锁,从而提高并发度。在 RR 和 RC 隔离级别下快照读的区别:

  • RR 隔离级别时,事务中的所有一致性读都会读取该事务中第一次此类读取建立的快照。
  • RC 隔离级别时,事务中的每个一致性读都会设置并读取其自己的最新快照,快照是最新已提交的数据。

如果事务在查询数据后,要对该数据做修改操作,快照读无法提供足够的保护,因为其他事务可以对这些数据做修改操作。为了提供额外的保护,InnoDB 提供锁定读locking read),即同时执行锁定操作的 select 语句,锁持有直到事务结束。锁定读分两种:

  • select ... for share 是加共享锁的查询数据
  • select ... for update 是加排他锁的查询数据

RR 隔离级别下的不可重复读和幻读异常

上文提到,“快照读,能一定程度避免不可重复读和幻读异常,但因为 InnoDB 的刷新快照的特殊实现,不能完全避免”。现在来看下 RR 隔离级别下的不可重复读异常的示例:

事务1事务2
mysql> begin;mysql> begin;
-- 返回值为 10,快照读
mysql> select b from tbl where a = 10;
-- 把 b 值修改为 0
mysql> update tbl set b = 0 where a = 10;
mysql> commit;
-- 返回值为 10,没有出现不可重复读异常
mysql> select b from tbl where a = 10;
-- update 会读取 a = 10 的已提交的最新值
-- 同时 a = 10 记录的快照会被刷新
mysql> update tbl set b = b + 1 where a = 10;
-- 返回值为 1,出现不可重复读异常
mysql> select b from tbl where a = 10;

这个问题在 MySQL 的 Bug 系统中可以找到,参见:Bug #57973、Bug #63870 等。官方认为,这不是 Bug,InnoDB 就是按这种方式设计。Bug #57973 下 MySQL 工程师 Kevin Lewis 对这个问题的解答 [ref]:

[16 Aug 2013 19:23] Kevin Lewis
Rejecting this bug because InnoDB is working as designed for the following reason;
...
But when InnoDB Repeatable Read transactions modify the database, it is possible to get phantom reads added into the static view of the database, just as the ANSI description allows. Moreover, InnoDB relaxes the ANSI description for Repeatable Read isolation in that it will also allow non-repeatable reads during an UPDATE or DELETE. Specifically, it will write to newly committed records within its read view. And because of gap locking, it will actually wait on other transactions that have pending records that may become committed within its read view. So not only is an UPDATE or DELETE affected by pending or newly committed records that satisfy the predicate, but also 'SELECT … LOCK IN SHARE MODE' and 'SELECT … FOR UPDATE'.
This WRITE COMMITTED implementation of REPEATABLE READ is not typical of any other database that I am aware of. But it has some real advantages over a standard 'Snapshot' isolation. When an update conflict would occur in other database engines that implement a snapshot isolation for Repeatable Read, an error message would typically say that you need to restart your transaction in order to see the current data. So the normal activity would be to restart the entire transaction and do the same changes over again. But InnoDB allows you to just keep going with the current transaction by waiting on other records which might join your view of the data and including them on the fly when the UPDATE or DELETE is done. This WRITE COMMITTED implementation combined with implicit record and gap locking actually adds a serializable component to Repeatable Read isolation.

就是说,InnoDB 实现的 RR 隔离级别,放松了 SQL 标准对 RR 隔离级别的要求。事务 T1 在快照读后,如果其他事务 T2 修改了快照对应的记录并提交,之后事务 T1 执行涉及快照的 DML 语句(update、delete、insert)或锁定读,会触发快照刷新,事务 T2 最新提交的修改会刷新进快照。最终导致事务 T1 再次执行相同条件的快照读,读取结果不同,出现不可重复读或幻读异常。简单概括就是,在快照失效后,又刷新快照,导致两次读到的快照不同。另外,如果实现上选择不刷新快照,并且事务 T1 正常执行,会出现 P4 丢失更新异常。

不可重复读异常的避免(一定程度上避免,但没有完全避免):

  • 如果事务重复的两次读都是快照读(普通 select 语句),并且中间没有执行涉及快照的 DML 或锁定读,这样两次读到的是相同的快照读,所以不会出现不可重复读异常。
  • 如果事务重复的两次读都是当前读(select for update/share),因为第一次加锁,其他事务无法更新该记录,所以也不会出现不可重复读异常。
  • 如果事务重复的两次读都是快照读,但是中间执行涉及快照的 DML 或锁定读,触发了快照刷新,如果快照被更新,就会出现不可重复读异常。

幻读异常的避免(一定程度上避免,但没有完全避免):

  • 如果事务重复的两次读都是快照读(普通 select 语句),并且中间没有执行涉及快照的 DML 或锁定读,这样两次读到的是相同的快照读,所以不会出现幻读异常。
  • 如果事务重复的两次读都是当前读(select for update/share),因为第一次当前读加间隙锁,其他事务无法插入,被阻塞,所以也不会出现幻读异常。
  • 如果事务重复的两次读都是快照读,但是中间执行涉及快照的 DML 或锁定读,触发了快照刷新,如果快照被更新,就会出现幻读异常。

上述的快照失效的场景,PostgreSQL 的处理方式是,事务会被回滚并报错提示,应用程序收到这个报错,可以尝试重试,重试的事务读到的快照是最新的,这样即避免丢失更新异常,也避免了幻读和不可重复读异常(参见官方文档 doc)。

参考资料

MySQL 8.0 Reference Manual

其他参考资料:

]]>
+ + + <p>目前主流数据库事务的并发控制实现,如 MySQL InnoDB、PostgreSQL、Oracle,都使用两阶段封锁 <a href="https://en.wikipedia.org/wiki/Two-phase_locking">2PL</a> 与 <a href="https://en.wikipedia.org/wiki/Multiversion_concurrency_control">MVCC</a> 技术,但具体实现细节上存在差异。InnoDB 是在以封锁技术为主体的情况下,用 MVCC 技术辅助实现读-写、写-读操作的并发。PostgreSQL 的并发控制技术是以 MVCC 技术为主,封锁技术为辅。本文主要关注 InnoDB 事务的并发控制实现。</p> + + + + + + + + + + + + + + + + +
+ + + 微服务 API 网关 Kong 实践 + + https://nullwy.me/2020/05/kong-gateway/ + 2020-05-30T07:22:41.000Z + 2023-12-05T06:15:32.036Z + + Kong 简介

Kong 是云原生、高效、可扩展、分布式的微服务抽象层,被称为 API 网关,或者 API 中间件。Kong 在 2015 年 4 月由 Mashape 公司开源,基于 OpenResty 和 Apache Cassandra/PostgreSQL 构建,提供易于使用的 RESTful API 来操作和配置 API 系统[1][2]

Mashape 是 API 集市,是为应用开发者与 API 提供者服务的 API 交易市场,Mashape 让发者能够方便地查找与购买 API,而 API 提供商则能轻松地销售与管理 API[3]。随着 Mashape 市场上的 API 越来越多,原先基于 Node.js 实现的 API 代理不再适用,不能处理大流量尖峰,无法快速扩容。于是,寻找处理大流量的方案,同时需要保证可靠性和安全性,成为 Mashape 亟待解决的问题。2013 年,在 CloudFlare(当时 OpenResty 背后的公司)的工程师的建议下,Mashape 开始在 OpenResty 基础上开发 Kong 项目[4]。Mashape 公司的名字,MashAPE,有人猿猩猩的含义,公司 logo 也是相应动物。类似的,Kong,对应的是,King Kong,就是电影里的金刚[4:1]。在 Mashape 开启 Kong 项目两年后,2015 年 4 月,Mashape 公司开源了 Kong[2:1]

2017 年 5月,Mashape 和 RapidAPI 合并,组成全球最大的 API 集市[5][6]。5 个月后,Mashape, Inc. 改名为 Kong Inc.,新的公司以 Kong 项目为聚焦,把全部工程师投入到 Kong 开发中,并且于此同时他们发布了 Kong 企业版[7]

Kong,作为微服务的请求的网关,能通过插件提供负载均衡、日志记录、鉴权、限流、转换以及其他等功能。相对与旧的、没有使用网关的方式,Kong 把这些通用功能中心化,让微服务更加专注于业务本身。

The Old way vs. The Kong Way

Kong 的整体架构,如下图所示[1:1]

  • 管理 API:通过 RESTful API 管理 Kong;能自动化集成;管理 API 能通过插件扩展
  • 插件:使用 Lua 脚本创建 Plugins;实现强力的定制化;与第三方服务集成
  • 集群和数据存储:数据存储可选择 PostgreSQL 或 Cassandra;能从单节点扩展为集群;使用内存缓存提高性能
  • OpenResty:拦截请求/响应生命周期;基于 NGINX 扩展;Lua 脚本化
  • NGINX:验证过的高性能基础组件;HTTP 和反向代理服务器;处理底层操作
Kong Architecture

Kong 安装

目前最新的 Kong 版本是 2.0.x,2.0 发布时间是 2020 年 1 月,而 1.0 发布时间是 2018 年 12 月[8][9]。笔者公司使用的 Kong 版本是 0.14.1,暂时未升级自最新版,所以下文阐述的 Kong 版本主要以 0.14.1 为准,并同时会提及其他版本的特性。

安装 Kong 很简单,参见官方文档即可。在 Ubuntu 18.04 下安装 Kong 0.14.1,可以执行下面的命令:

1
2
3
4
5
6
7
# kong 安装
$ sudo apt update
$ sudo apt install openssl libpcre3 procps perl
$ wget -O kong-community-edition-0.14.1.trusty.all.deb https://bintray.com/kong/kong-community-edition-deb/download_file?file_path=dists/kong-community-edition-0.14.1.trusty.all.deb
$ sudo dpkg -i kong-community-edition-0.14.1.trusty.all.deb
$ kong version
0.14.1

Kong 依赖数据库,Postgres 或者 Cassandra,默认依赖 Postgres(kong 1.1 开始支持无数据库声明式配置[10])。我们预先安装 Postgres:

1
2
3
4
5
# 安装 postgresql
$ sudo apt install postgresql
$ sudo service postgresql start
$ psql --version
psql (PostgreSQL) 10.12 (Ubuntu 10.12-0ubuntu0.18.04.1)

在 Postgres 下添加 Kong 需要的的数据库实例和用户。下面的示例,创建数据库 kong,用户名 kong,密码为 kong

1
2
3
4
$ sudo -u postgres psql
postgres=# CREATE USER kong; CREATE DATABASE kong OWNER kong;
postgres=# ALTER USER kong WITH PASSWORD 'kong';
postgres=# \q

执行完成后,即可使用用户名为 kong 的用户连接 Postgres,psql -h localhost -U kong -d kong

Kong 安装完成后,默认会创建配置文件 /etc/kong/kong.conf.default,这份配置文件在 GitHub 上也能找到,被注释掉的配置项,就是默认设置。

在启动 Kong 网关服务器前,我们参考 kong.conf.default,创建自己的 kong.conf 配置文件。我们把配置文件放在 /home/yulewei/kong 目录下,同时也把这目录当作为 Kong 的 prefix 目录。修改这配置 kong.conf,文件末尾添加:

1
2
3
4
prefix = /home/yulewei/kong/
pg_user=kong
pg_password=kong
pg_database = kong

使用 kong 命令,启动 Kong 网关服务器:

1
2
3
4
# 初始化或迁移数据库数据
$ kong migrations up -c /home/yulewei/kong/kong.conf
# 启动 kong
$ kong start -c /home/yulewei/kong/kong.conf

Kong 默认绑定 4 个端口:

  • :8000 用来接收来自客户端的 HTTP 流量的请求,并转发到上游服务
  • :8443 用来接收来自客户端的 HTTPS 流量的请求,并转发到上游服务
  • :8001 用来接收访问 Admin API 的 HTTP 流量的请求
  • :8444 用来接收访问 Admin API 的 HTTPS 流量的请求

所以,可以执行下面的命令,来确认 Kong 是否正常运行:

1
2
3
# 确认 Kong 是否正常运行
$ curl -i http://localhost:8000/
$ curl -i http://localhost:8001/

Kong 底层依赖 OpenResty,启动 Kong 后,可以看到 nginx 进程:

1
2
3
4
5
# 查看 nginx 进程
$ ps -ef | grep nginx
yulewei 19090 1 0 16:05 ? 00:00:00 nginx: master process /usr/local/openresty/nginx/sbin/nginx -p /home/yulewei/kong -c nginx.conf
yulewei 19091 19090 0 16:05 ? 00:00:00 nginx: worker process
yulewei 19092 19090 0 16:05 ? 00:00:00 nginx: worker process

安装 Kong 0.14.1,自动安装的 OpenResty 版本是 1.13.6.2,OpenResty 捆绑的安装了 LuaJIT。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ /usr/local/openresty/nginx/sbin/nginx -v
nginx version: openresty/1.13.6.2

$ /usr/local/openresty/bin/resty -V
resty 0.21
nginx version: openresty/1.13.6.2
built by gcc 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.4)
built with OpenSSL 1.0.2n 7 Dec 2017
TLS SNI support enabled
configure arguments: ... 省略 ...

$ /usr/local/openresty/luajit/bin/luajit -v
LuaJIT 2.1.0-beta3 -- Copyright (C) 2005-2017 Mike Pall. http://luajit.org/

另外,同时也安装了 LuaRocks,LuaRocks 关联的是 OpenResty 捆绑的 LuaJIT。事实上,Kong 就是一个 LuaRocks 的 rock 包,在Kong 项目的 GitHub 上可以看到 rockspec 文件。Kong 的安装,底层实现上,是通过 luarocks 命令完成的,类似这样的命令,luarocks install kong 0.14.1-0[11][12]。可以使用 luarocks show 命令查看这个 Kong 的 rcok 包:

1
2
3
4
5
6
7
8
9
10
11
$ luarocks show kong
kong 0.14.1-0 - Kong is a scalable and customizable API Management Layer built on top of Nginx.

License: MIT
Homepage: http://getkong.org
Installed in: /usr/local

Modules:
kong (/usr/local/share/lua/5.1/kong/init.lua)
kong.api (/usr/local/share/lua/5.1/kong/api/init.lua)
... 省略 ...

有个小细节值得注意,通过 luarocks 看到,Kong 采用的协议是 MIT。但事实上,Kong 0.5.0 开始协议从 MIT 改成了 Apache 2.0。此处是一个小 bug,Kong 的 rockspec 文件没有及时更新,这个问题后来修复了,参见 #4125

GUI 管理工具

管理 Kong 可以直接使用 Admin API,当然也有基于 Admin API 实现 GUI 管理工具。

Kong 官方的企业版提供了 GUI 管理工具,Kong Manager(Kong EE 0.34 之前称为 Admin GUI),Kong 社区版没有提供 GUI 管理工具。

第三方的开源 GUI 工具,比较活跃的就是 Konga,值得推荐,如下图。

konga

另外,还有其他的 GUI 工具,比如 Kong Dashboard,也可以了解下。

Kong 使用

Kong 核心概念:

  • Service:对应位于 Kong 后方的自身的 Upstream API 或微服务。
  • Route:Kong 的入口点,定义了如何把请求发送到特定 Service 的规则。一个 Service 可以有多个Route
  • Plugin:插件提供了模块化系统,用来修改或控制 Kong。插件提供了大量功能,比如访问控制、缓存、限流、日志记录等。
  • Consumer:消费者,表示使用 API 的用户,能用来对用户进行访问控制、跟踪等。

Kong 网关的请求响应工作流,如下图所示:

Kong Overview

反向代理

Kong 的核心功能就是对现有的上游服务的 API 作反向代理。反向代理,官方的完整的文档参见[13]。现在我们来试验下 Kong 的反向代理功能,执行下面的命令:

1
2
3
4
5
6
7
8
9
# 添加 service
$ curl -XPOST -H 'Content-Type: application/json' \
-d '{"name":"example.service","url":"http://httpbin.org"}' \
http://localhost:8001/services/

# 在 service 上添加 route
$ curl -XPOST -H 'Content-Type: application/json' \
-d '{"paths":["/base64"],"strip_path":false}' \
http://localhost:8001/services/example.service/routes

上面的第一条命令,通过调用 Kong 提供的 Admin API,让 Kong 创建了名为 example.serviceserviceservice 指向的上游服务是 http://httpbin.org。第二条命令,在 example.service 上添加 route 规则,规则是让请求路径前缀为 /base64 的请求转发到这个 service。来验证下,刚刚的 Kong 的配置:

1
2
3
4
5
# 验证 Kong 配置结果
$ curl http://httpbin.org/base64/aGVsbG8ga29uZw==
hello kong
$ curl http://localhost:8000/base64/aGVsbG8ga29uZw==
hello kong

上文的 Kong 配置,等价的 nginx.conf 配置文件的写法是:

1
2
3
4
5
6
server {
listen 8000;
location /base64 {
proxy_pass http://httpbin.org/base64;
}
}

除了前缀外,route 规则的 paths 字段也支持 PCRE 正则表达式,来看下示例:

1
2
3
curl -XPOST -H 'Content-Type: application/json' \
-d '{"paths":["/status/\\d+"],"strip_path":false}' \
http://localhost:8001/services/example.service/routes

上面的命令,添加 route 规则,设置的 paths 字段值为 /status/\d+,让只有请求路径的中包含数字才能匹配。

1
2
3
4
5
6
7
8
9
# 验证 Kong 配置结果
$ curl -sI http://httpbin.org/status/418 | head -n1
HTTP/1.1 418 I'M A TEAPOT
$ curl -sI http://localhost:8000/status/418 | head -n1
HTTP/1.1 418 I'M A TEAPOT
$ curl -sI http://localhost:8000/status/200 | head -n1
HTTP/1.1 200 OK
$ curl http://localhost:8000/status/abc
{"message":"no route and no API found with those values"}

负载均衡

上文的反向代理指向的是单台的上游服务器,如果要指向多台上游服务器,实现负载均衡,要如何配置呢?负载均衡,Nginx 可以通过 upstream 指令实现,而类似的,Kong 通过创建 upstream 对象实现。

假设在服务器 192.168.2.100:80192.168.2.101:80 上运行着本地版的 httpbin.org 的 REST API 服务(通过 docker run -p 80:80 kennethreitz/httpbin)。执行下面的命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 添加 upstream
curl -XPOST -H 'Content-Type: application/json' \
-d '{"name":"example.upstream"}' \
http://localhost:8001/upstreams/

# 在 upstream 上添加 target
curl -XPOST -H 'Content-Type: application/json' \
-d '{"target":"192.168.2.100:80"}' \
http://localhost:8001/upstreams/example.upstream/targets

# 在 upstream 上添加 target
curl -XPOST -H 'Content-Type: application/json' \
-d '{"target":"192.168.2.101:80"}' \
http://localhost:8001/upstreams/example.upstream/targets

# 添加 service
curl -XPOST -H 'Content-Type: application/json' \
-d '{"name":"example.service","host":"example.upstream"}' \
http://localhost:8001/services/

# 在 service 上添加 route
curl -XPOST -H 'Content-Type: application/json' \
-d '{"paths":["/base64"],"strip_path":false}' \
http://localhost:8001/services/example.service/routes

上面的命令,先创建了 upstream 对象,虚拟主机名(virtual hostname)为 example.upstream 。然后在这个 upstream 上添加 target192.168.2.100:80192.168.2.101:80。再然后把 service 对象的 host 字段值设置为 example.upstream。这样全部发送到这个 service 的请求都会被转发到 example.upstream 这个 upstreamupstream 再执行负载均衡算法,把请求转发到最终的上游服务器。和 Nginx 一样,默认的负载均衡算法为加权轮询算法(weighted-round-robin)。

1
2
3
# 验证 Kong 配置结果
$ curl http://localhost:8000/base64/aGVsbG8ga29uZw==
hello kong

上文的 Kong 配置,等价的 nginx.conf 配置文件的写法是:

1
2
3
4
5
6
7
8
9
10
upstream example.upstream {
server 192.168.2.100:80;
server 192.168.2.101:80;
}
server {
listen 8000;
location /base64 {
proxy_pass http://example.upstream/base64;
}
}

关于 Kong 负载均衡的更多介绍,可以阅读官方文档[14],本文不再展开。

开启插件

Kong 提供了很多插件,官方整理维护的全部插件列表,可以在官网上看到。全部插件分 8 大类:身份认证类插件(Authentication)、安全控制类插件(Security)、流量控制类插件(Traffic Control)、无服务器计算类插件(Serverless)、分析与监控类插件(Analytics & Monitoring)、协议转换类插件(Transformations)、日志记录类插件(Logging)、部署类插件(Deployment)。Kong 0.14.1 社区版默认绑定的预定义插件,全部 31 个,调用下面的 Admin API 可以查看:

1
2
3
# Kong 社区版全部默认绑定的插件,共 31 个
$ curl http://localhost:8001/plugins/enabled
{"enabled_plugins":["response-transformer","oauth2","acl","correlation-id","pre-function","jwt","cors","ip-restriction","basic-auth","key-auth","rate-limiting","request-transformer","http-log","file-log","hmac-auth","ldap-auth","datadog","tcp-log","zipkin","post-function","request-size-limiting","bot-detection","syslog","loggly","azure-functions","udp-log","response-ratelimiting","aws-lambda","statsd","prometheus","request-termination"]}

现在我们来试下 Kong 的 basic-auth 插件,用来实现 HTTP Basic 认证(RFC 7617)。执行下面的命令,在上文的 example.serviceservice 上开启 basic-auth 插件:

1
2
3
# 在 service 上开启 basic-auth 插件
$ curl -XPOST --data "name=basic-auth" \
http://localhost:8001/services/example.service/plugins

这样全部到 example.service 的请求都需要进行 Basic 认证。再次请求之前的 /base64 接口,返回状态码 401 Unauthorized

1
2
3
4
5
6
# 接口 HTTP 状态码返回 401
$ curl -i http://localhost:8000/base64/aGVsbG8ga29uZw==
HTTP/1.1 401 Unauthorized
... 省略 ...

{"message":"Unauthorized"}

添加身份认证的凭证,添加 username/password:

1
2
3
4
5
6
# 添加 consumer
$ curl -XPOST --data "username=Jason" \
http://localhost:8001/consumers/
# 在 consumer 上添加 basic-auth 插件的凭证 username/password
$ curl -XPOST --data "username=test&password=123456" \
http://localhost:8001/consumers/Jason/basic-auth

现在请求头上带上凭证,重新请求 /base64 接口,响应正常:

1
2
$ curl -u 'test:123456' http://localhost:8000/base64/aGVsbG8ga29uZw==
hello kong

Kong 插件,除了绑定到 service 上外,也可以绑定在 routeconsumer 上。如果开启插件时,servicerouteconsumer 全部都不关联,就是全局范围开启插件,插件会在全部请求上运行。全局范围上开启 basic-auth 插件,命令如下:

1
2
3
# 全局范围上开启 basic-auth 插件
$ curl -XPOST --data "name=basic-auth" \
http://localhost:8001/plugins

关于 Kong 插件的更多介绍,可以阅读官方文档,本文不再展开。

Kong 插件开发

Kong 基于 OpenResty,OpenResty 通过 ngx_http_lua_module 模块实现了在 Nginx 中内嵌 Lua 脚本的能力。Kong 插件,使用 Lua 脚本实现,全部默认加载的预定义插件对应的 Lua 源码(包括上文提到的 basic-auth 插件),可以在 Kong 项目仓库的 kong/plugins 目录下看到。

除了能使用 Kong 预定义插件,我们可以根据 Kong 插件开发文档[15],开发自定义插件。

如何开发插件,文本不展开。Kong 官方提供了自定义插件的模板代码,源码参见项目 kong-plugin[16]。另外,有兴趣也可以参考笔者提供的 Kong 自定义插件示例,源码参见 kong-plugin-demo[17]

值得注意的是,Kong 使用 Lua 的 rxi/classic 模块来模拟 Lua 中的类,自定义 Kong 的插件时,实现 handler 需要继承 BasePlugin class,目前最新的文档还是采用这种写法。不过,Kong 1.2 开始,Kong 内部的预定义实现的插件,废弃了继承 BasePlugin class 的写法,参见 Pull Request #4590,“plugins handlers do not have to inherit from BasePlugin anymore #4590”。去掉对 BasePlugin class 的继承后,在开启单个插件(key-auth)的场景下,压测 Kong 性能提升 6%,开启多个插件的场景,性能提升更高。

参考资料


  1. What is Kong? https://konghq.com/about-kong/ ↩︎ ↩︎

  2. 2015-04 Mashape 开源 API 网关——Kong https://www.infoq.cn/article/2015/04/kong/ ↩︎ ↩︎

  3. 2012-07 打造大集市:API交易网站Mashape正式推出 https://www.csdn.net/article/2012-07-31/2807936 ↩︎

  4. 2015-10 How Mashape Manages Over 15,000 APIs & Microservices https://stackshare.io/kong/how-mashape-manages-over-15000-apis-and-microservices ↩︎ ↩︎

  5. 2017-05 Mashape 和 RapidAPI 合并,组成全球最大的应用编程接口(API)集市! https://www.sohu.com/a/144114294_465914 ↩︎

  6. 2017-05 The API Marketplace Joins RapidAPI https://konghq.com/blog/the-api-marketplace-joins-rapidapi/ ↩︎

  7. 2017-10 Welcome Kong Inc. A New Name, a New Product, a New Era. https://konghq.com/blog/introducing-kong-inc/ ↩︎

  8. 2018-12 Kong 1.0 GA https://konghq.com/blog/kong-1-0-ga/ ↩︎

  9. 2020-01 Kong Gateway 2.0 GA https://konghq.com/blog/kong-gateway-2-0-0-released/ ↩︎

  10. Documentation for Kong: DB-less and Declarative Configuration https://docs.konghq.com/1.1.x/db-less-and-declarative-config/ ↩︎

  11. Kong Installation: Compile Source https://docs.konghq.com/install/source/ ↩︎

  12. Build tools to package and release Kong https://github.com/Kong/kong-build-tools ↩︎

  13. Documentation for Kong: Proxy Reference https://docs.konghq.com/0.14.x/proxy/ ↩︎

  14. Documentation for Kong: Load Balancing Reference https://docs.konghq.com/0.14.x/loadbalancing/ ↩︎

  15. Documentation for Kong: Plugin Development https://docs.konghq.com/0.14.x/plugin-development/ ↩︎

  16. Kong 官方自定义插件的模板代码 https://github.com/Kong/kong-plugin ↩︎

  17. Kong 自定义插件示例 https://github.com/yulewei/kong-plugin-demo ↩︎

]]>
+ + + <h1 id="Kong-简介">Kong 简介</h1> +<p>Kong 是云原生、高效、可扩展、分布式的微服务抽象层,被称为 API 网关,或者 API 中间件。Kong 在 2015 年 4 月由 Mashape 公司开源,基于 OpenResty 和 Apache Cassandra/PostgreSQL 构建,提供易于使用的 RESTful API 来操作和配置 API 系统<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup><sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup>。</p> + + + + + + + + + + + + + + + + + + + + +
+ + + MySQL 5.7 的 JSON 类型 + + https://nullwy.me/2019/06/mysql-5.7-json/ + 2019-06-24T19:18:31.000Z + 2023-12-05T06:15:50.678Z + + 2015 年 8 月,MySQL 5.7.8 开始提供对 JSON 的原生支持[1][2]。MySQL 对 JSON 的支持可以说是千呼万唤始出来。2009 年开始 NoSQL 逐渐流行起来,相继出现了键值对数据库、文档数据库、列族数据库、图数据库等各类 NoSQL,解决经典关系型数据库无法解决的痛点。其中,对灵活存储半结构化数据的需求,使得类似 MongoDB 这类文档数据库涌现出来。各大主流关系型数据库也在响应趋势,开始支持半结构化数据。早在 2012 年,PostgreSQL 9.2 就已经添加了 JSON 数据类型[3]。Oracle 也在 2014 年 7 月发布 12c Release 1 后开始支持 JSON[4][5]。Facebook 在 MySQL 5.7 没发布之前,对 5.6 版本的 MySQL 添加了存储 JSON 功能,这个特性被 Facebook 命名为 DocStore (Document Database for MySQL at Facebook)[6][7]。另外,SQL 标准组织行动也很快,在 2014 年 3 月已经完成了 SQL/JSON 标准草案(SQL/JSON Proposals)[8][9][10]。完整的草案在 2016 年 12 月正式被采纳为标准,即 SQL:2016。

浏览 SQL/JSON 标准草案可以发现,全部作者共有 9 人,这些作者来自两个公司,Oracle 和 IBM,而排前面的作者如 Jim Melton, Fred Zemke, Beda Hammerschmidt 都 Oracle 的专家(有兴趣可以看下他们的 LinkedIn)。正因为 SQL:2016 主要就是 Oracle 参与制定的,目前,Oracle 数据库对 SQL:2016 的支持也是最全的[11]

MySQL 对 JSON 的支持,设计文档主要是 WL#7909: Server side JSON functions[12],另外还有 WL#8132: JSON datatype and binary storage format[13]、WL#8249: JSON comparator[14]、WL#8607: Inline JSON path expressions in SQL[15] 等。在 MySQL 开始 WL#7909 之时,SQL/JSON 标准草案已经公开,WL#7909 中也提及了这份标准,但是如果拿 MySQL 提供 JSON 的功能与 SQL:2016 比较,可以发现 MySQL 虽然融入了部分的设计,但并没有完全参考标准,定义的 JSON 函数多数有区别。

回到正题,下面来看下 MySQL 5.7 的 JSON 的用法。

JSON 函数列表

MySQL 官方列出 JSON 相关的函数,完整列表如下[16]

分类函数描述
json 创建函数json_array()创建 json 数组
json_object()创建 json 对象
json_quote()用双引号包裹 json 文档
json 查询函数json_contains()判断是否包含某个 json 值
json_contains_path()判断某个路径下是否包 json 值
json_extract()提取 json 值
column->pathjson_extract() 的简洁写法,5.7.9 开始支持
column->>pathjson_unquote(json_extract()) 的简洁写法,5.7.13 开始支持
json_keys()把 json 对象的顶层的全部键提取为 json 数组
json_search()按给定字符串关键字搜索 json,返回匹配的路径
json 修改函数json_append()5.7.9 废弃,改名为 json_array_append()
json_array_append()在 josn 文档末尾添加数组元素
json_array_insert()在 josn 数组中插入元素
json_insert()插入值(只插入新值,不替换旧值)
json_merge()5.7.22 废弃,与 json_merge_preserve() 同义
json_merge_patch()合并 json 文档,重复键的值将被替换掉
json_merge_preserve()合并 json 文档,保留重复键
json_remove()删除 json 文档中的数据
json_replace()替换值(只替换旧值,不插入新值)
json_set()设置值(替换旧值,或插入新值)
json_unquote()移除 json 值的双引号包裹
json 属性函数json_depth()返回 json 文档的最大深度
json_length()返回 json 文档的长度
json_type()返回 json 值的类型
json_valid()判断是否为合法 json 文档
json 工具函数json_pretty()美化输出 json 文档,5.7.22 新增
json_storage_size()返回 json 文档占用的存储空间,5.7.22 新增

官方文档对全部函数都作了充分解释并提供一定的示例代码。另外,官方博客也有极佳的相关介绍文章[17][18]。下文挑选了部分函数,演示它们的使用方法。

创建与插入 JSON

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
-- 创建 tbl 表,字段 data 为 json 类型
mysql> create table tbl (data JSON);
Query OK, 0 rows affected (0.17 sec)

-- 插入 json 对象
mysql> insert into tbl values ('{"id": 1, "name": "Will"}');
Query OK, 1 row affected (0.04 sec)

-- 插入 json 数组
mysql> insert into tbl values ('[1, 42, 1024]');
Query OK, 1 row affected (0.01 sec)

-- 使用 json_object() 创建 json 对象
mysql> insert into tbl values (json_object('id', 2, 'name', 'Joe'));
Query OK, 1 row affected (0.02 sec)

-- 使用 json_array() 创建 json 数组
mysql> insert into tbl values (json_array(1, "abc", null, true, curtime()));
Query OK, 1 row affected (0.02 sec)

-- 查询 tbl 表数据
mysql> select * from tbl;
+-------------------------------------------+
| data |
+-------------------------------------------+
| {"id": 1, "name": "Will"} |
| [1, 42, 1024] |
| {"id": 2, "name": "Andy"} |
| [1, "abc", null, true, "20:27:41.000000"] |
+-------------------------------------------+
4 rows in set (0.00 sec)

上面的 SQL 示例简单验演示了创建 JSON 列以及写入并查询 JSON 数据,比较简单,就不做解释了。

查询 JSON

json_extract() 与 -> 操作符

如果要查询 JSON 文档中内容,提取 JSON 中的值,可以使用 json_extract() 函数。函数定义如下:

1
json_extract(json_doc, path[, path] ...)

先来看下 SQL 示例:

1
2
3
4
5
6
7
8
-- 使用 json_extract() 函数查询 json 对象
mysql> select json_extract('{"id": 1, "name": "Will"}', '$.name');
+-------------------------------------------------------+
| json_extract('{"id": 1, "name": "Will"}', '$.name') |
|-------------------------------------------------------|
| "Will" |
+-------------------------------------------------------+
1 row in set (0.01 sec)

示例中的 $.name,使用的是 JSON 路径语法,用来提取 JSON 文档的内容。JSON 路径语法,源自 Stefan Goessner 的 JsonPath[19],不过 MySQL 作了简化。路径语法使用 $ 开头来表示整个 JSON 文档。如果要提取部分 JSON 文档,可以在路径后面添加选择符:

  • 在路径 path 后上追加对象的键名称,可以获取这个键下成员。如果加键名称后,路径表达式非法,需要对键名称用双引号包裹(比如,键名称中包含空格的情况)
  • 在路径 path 后加上追加 [N],用于选择数组的第 N 个元素。数组索引从 0 开始。如果 path 下并不是数组,path[0] 获取结果就是 path 本身。
  • 路径可以包含 *** 通配符:
    • .[*] 用于获取 JSON 对象的全部成员。
    • [*] 用于获取 JSON 数组的全部元素。
    • prefix**suffix 表示全部以 prefix 开始,以 suffix 结尾的路径。
  • 如果路径在 JSON 文档中不存在数据,将返回 NULL

假设 $ 引用的是如下 JSON 数组:

1
[3, {"a": [5, 6], "b": 10}, [99, 100]]

$[0] 获取到的值为 3,$[1] 获取到 {"a": [5, 6], "b": 10}$[2] 获取到 [99, 100]$[3] 获取到 NULL(因为不存在第 4 个元素)。

因为 $[1]$[2] 获取的并非纯量(nonscalar),它们可以进一步使用路径访问到内嵌的值,比如:$[1].a 获取到 [5, 6]$[1].a[1] 获取到 6$[1].b 获取到 10$[2][0] 获取到 99

上文提到,如果追加键值名后,路径表达式非法,需要对键名称用双引号包裹。假设 $ 引用的是如下 JSON 对象:

1
{"name 1": "Will", "name 2": "Andy"}

两个键都包含空格,需要加上双引号,才能使用路径表达式访问。$."name 1" 将获取到 Will,而 $."name 2" 将获取到 Andy

现在来看下通配符的示例,假设 JSON 对象如下:

1
{"a": {"b": 1}, "c": {"b": 2}, "d": [3, 4, 5]}

使用 $.* 将获取到 [{"b": 1}, {"b": 2}, [3, 4, 5]]
使用 $.d[*] 将获取到 [3, 4, 5]
使用 $**.b(对应 $.a.b$.c.b)将获取到 [1, 2]

MySQL 5.7.9 开始,官方支持 json_extract(column, path) 的简洁写法,内联 JSON 路径表达式 column->path(WL#8607)。示例如下:

1
2
3
4
5
6
7
8
-- 使用内联 json 路径表达式,查询 json 对象
mysql> select * from tbl where data -> '$.id' = 2;
+---------------------------+
| data |
+---------------------------+
| {"id": 2, "name": "Andy"} |
+---------------------------+
1 row in set (0.00 sec)

本质上,这种写法是语法糖,column->path 等价于 json_extract(column, path),内联 JSON 路径表达式会在语法解析阶段被转换为 json_extract() 调用。另外,column->path,存在以下限制[20]

限制

即,1. 数据源必须是表字段,2. 路径表达式必须为字符串,3. SQL 语句中最多只支持一个。

现在来试验下这个限制,如果使用内联 JSON 路径表达式查询 MySQL 变量,将会报语法错误:

1
2
3
4
5
mysql> set @j = '["a", "b"]';

-- 语法错误
mysql> select @j -> '$[0]';
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-> '$[0]'' at line 1

json_unquote() 与 ->> 操作符

假设数据如下:

1
2
3
4
5
6
7
8
mysql> select * from tbl;
+-----------------------------------------------+
| data |
+-----------------------------------------------+
| {"id": 1, "name": "Will"} |
| {"id": 2, "name": "printf(\"hello world\");"} |
+-----------------------------------------------+
2 rows in set (0.00 sec)

来看下使用 -> 提取获得 JSON 值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
mysql> select data -> '$.id', data -> '$.name', substr(data -> '$.name', 1, 1) from tbl;
+----------------+----------------------------+--------------------------------+
| data -> '$.id' | data -> '$.name' | substr(data -> '$.name', 1, 1) |
+----------------+----------------------------+--------------------------------+
| 1 | "Will" | " |
| 2 | "printf(\"hello world\");" | " |
+----------------+----------------------------+--------------------------------+
2 rows in set (0.00 sec)

mysql> create table tmp (id int, name varchar(50));
mysql> insert tmp select data -> '$.id', data -> '$.name' from tbl;
mysql> select *, substr(name, 1, 1) from tmp;
+------+----------------------------+--------------------+
| id | name | substr(name, 1, 1) |
+------+----------------------------+--------------------+
| 1 | "Will" | " |
| 2 | "printf(\"hello world\");" | " |
+------+----------------------------+--------------------+
2 rows in set (0.01 sec)

可以看到,对于 string 类型的 JSON 值,使用 json_extract()-> 获取的都是被双引号包裹的字符串。MySQL 提供 json_unquote() 函数,用于去掉双引号包裹。另外,MySQL 支持 column->>path 语法,通过 ->> 操作符获取纯量(scalar)。column->>path 写法等价于 json_unquote( json_extract(column, path) ) 或者 json_unquote(column -> path)。来看下 SQL 示例:

1
2
3
4
5
6
7
8
9
mysql> select data ->> '$.id' as id, data -> '$.name' as name,
-> data ->> '$.name' as name, json_unquote(data -> '$.name') as name from tbl;
+------+----------------------------+------------------------+------------------------+
| id | name | name | name |
+------+----------------------------+------------------------+------------------------+
| 1 | "Will" | Will | Will |
| 2 | "printf(\"hello world\");" | printf("hello world"); | printf("hello world"); |
+------+----------------------------+------------------------+------------------------+
2 rows in set (0.00 sec)

MySQL 这种区分 ->->> 的写法,怀疑是源自 Postgres。因为 Postgres 也分别提供了 ->->> 操作符,-> 也是保留双引号(get JSON object field by key),而 ->> 才能获取实际的字符串值(get JSON object field as text)[21][22]

在笔者看来,这种需要通过 json_unquote() 才能获取实际字符串值的写法完全没有必要,因为很难想到有需要保留双引号的使用场景,而就获取实际的字符串值才是多数情况。实际上,SQLite 的开发者也持有相同的想法。2015 年 10 月,SQLite 3.9 发布,开始支持 JSON 类型[23][24]。简单对比下,可以发现 SQLite 提供的 JSON 函数和 MySQL 极其相似,很多函数同名并且同语义。SQLite 也提供了 json_extract() 函数,与 MySQL 不同,SQLite 返回的是移除双引号后的字符串(the dequoted text for a JSON string value)。看下示例:

1
2
3
4
sqlite> select json_extract('{"id": 1, "name": "Will"}', '$.name');
Will
sqlite> select json_extract('{"code": "printf(\"hello world\");"}', '$.code');
printf("hello world");

对于提取 JSON 文档中的纯量(scalar),SQL 标准定义了的 json_value() 函数,MySQL 没有支持,但 Oracle、MariaDB、MSSQL 都有支持。MariaDB 在兼容 MySQL 的同时也支持 SQL 标准,json_extract() 和 json_value() 在 MariaDB 下都可用。来看下 SQL 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
MariaDB [testdb]> select * from tbl;
+-----------------------------------------------+
| data |
+-----------------------------------------------+
| {"id": 1, "name": "Will"} |
| {"id": 2, "name": "printf(\"hello world\");"} |
+-----------------------------------------------+
2 rows in set (0.00 sec)

-- 使用 json_extract() 提取 JSON 值,string 类型的值保留双引号
MariaDB [testdb]> select json_extract(data, '$.id'), json_extract(data, '$.name') from tbl;
+----------------------------+------------------------------+
| json_extract(data, '$.id') | json_extract(data, '$.name') |
+----------------------------+------------------------------+
| 1 | "Will" |
| 2 | "printf(\"hello world\");" |
+----------------------------+------------------------------+
2 rows in set (0.00 sec)

-- 使用 json_value() 提取 JSON 值,string 类型的值自动移除双引号
MariaDB [testdb]> select json_value(data, '$.id'), json_value(data, '$.name') from tbl;
+--------------------------+----------------------------+
| json_value(data, '$.id') | json_value(data, '$.name') |
+--------------------------+----------------------------+
| 1 | Will |
| 2 | printf("hello world"); |
+--------------------------+----------------------------+
2 rows in set (0.00 sec)

其他查询函数

除了上文的 json_extract() 函数,查询 JSON 文档相关的还有其他函数,如 json_contains()、json_contains_path()、json_keys()、json_search()。示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
mysql> set @j = '{"a": 1, "b": 2, "c": {"d": 4}}';
Query OK, 0 rows affected (0.00 sec)

-- 使用 json_contains() 函数判断是否存在某 JSON 值
mysql> select json_contains(@j, '{"a": 1}');
+-------------------------------+
| json_contains(@j, '{"a": 1}') |
+-------------------------------+
| 1 |
+-------------------------------+
1 row in set (0.00 sec)

-- 使用 json_contains_path() 函数判断是否存在某 JSON 路径
mysql> select json_contains_path(@j, 'one', '$.a', '$.e');
+-----------------------------------------------+
| json_contains_path(@j, 'one', '$.a', '$.e') |
|-----------------------------------------------|
| 1 |
+-----------------------------------------------+
1 row in set (0.00 sec)

-- 使用 json_contains_path() 函数判断是否存在某 JSON 路径
mysql> select json_contains_path(@j, 'all', '$.a', '$.e');
+-----------------------------------------------+
| json_contains_path(@j, 'all', '$.a', '$.e') |
|-----------------------------------------------|
| 0 |
+-----------------------------------------------+
1 row in set (0.00 sec)

函数的完整定义和用法可以参考官方文档,本文不再一一举例说明。

修改 JSON

对于 MySQL 的 JSON 类型的数据,若要修改数据,可以使用类似如下的 SQL:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mysql> select * from tbl where data->'$.id' = 2;
+---------------------------+
| data |
+---------------------------+
| {"id": 2, "name": "Will"} |
+---------------------------+
1 row in set (0.00 sec)

-- 对 data 整个字段修改
mysql> update tbl set data = '{"id": 2, "name": "Andy"}' where data->'$.id' = 2;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 0

mysql> select * from tbl where data->'$.id'= 2;
+---------------------------+
| data |
+---------------------------+
| {"id": 2, "name": "Andy"} |
+---------------------------+
1 row in set (0.00 sec)

如果要修改 JSON 内部数据,是否可以通过 JSON 路径表达式直接赋值呢?答案是,不行,MySQL 不支持。

1
2
3
-- 语法错误,不支持通过 JSON 路径表达式赋值,修改 JSON 数据
mysql> update tbl set data->'$.name' = 'Andy' where data->'$.id' = 2;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '->'$.name' = 'Andy' where data->'$.id' = 2' at line 1

MySQL 提供了数个函数来修改 JSON 数据。我们先来看看 json_replace()、json_set() 和 json_insert() 这三个函数:

  • json_replace():替换值。替换旧值,但不插入新值
  • json_set():设置值。替换旧值,或插入新值
  • json_insert():插入值。只插入新值,不替换旧值

json_insert() 只能插入数据, json_replace() 只能更新数据,json_set() 能更新或插入数据。

替换值,json_replace() 示例:

1
2
3
4
5
6
7
8
-- 使用 json_replace() 函数
-- 把 {"id": 2, "name": "Will"} 修改为 {"id": 2, "name": "Andy"}
-- 路径 $.name 指向的值存在,旧值被替换为新值
mysql> update tbl
-> set data = json_replace(data, '$.name', 'Andy')
-> where data->'$.id' = 2;
Query OK, 1 row affected (0.03 sec)
Rows matched: 1 Changed: 1 Warnings: 0

设置值,json_set() 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-- 使用 json_set() 函数
-- 把 {"id": 2, "name": "Will"} 修改为 {"id": 2, "city": "北京", "name": "Bill"}
-- 路径 $.name 指向的值存在,旧值被替换为新值;路径 $.city 指向的值不存在,将插入新值
mysql> update tbl
-> set data = json_set(data, '$.name', 'Bill', '$.city', '北京')
-> where data->'$.id'= 2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> select * from tbl where data->'$.id'= 2;
+---------------------------------------------+
| data |
+---------------------------------------------+
| {"id": 2, "city": "北京", "name": "Bill"} |
+---------------------------------------------+
1 row in set (0.00 sec)

插入值,json_insert() 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-- 使用 json_set() 函数
-- 把 {"id": 2, "name": "Will"} 修改为 {"id": 2, "address": "故宫"}
-- 路径 $.name 指向的值存在,将不替换这个旧值;路径 $.address 指向的值不存在,将插入新值
mysql> update tbl
-> set data = json_insert(data, '$.name', 'Bill', '$.address', '故宫')
-> where data->'$.id'= 2;
Query OK, 1 row affected (0.04 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> select * from tbl where data->'$.id'= 2;
+---------------------------------------------------------------------+
| data |
+---------------------------------------------------------------------+
| {"id": 2, "name": "Will", "address": "故宫"} |
+---------------------------------------------------------------------+
1 row in set (0.00 sec)

现在,我们来看下修改 JSON 数组的两个函数,json_array_insert() 和 json_array_append(),函数定义如下:

1
2
json_array_insert(json_doc, path, val[, path, val] ...)
json_array_append(json_doc, path, val[, path, val] ...)

json_array_insert(),参数 path 必须指向 JSON 数组某个位置的元素,若该位置存在值,将会把 val 插入该位置,然后其他元素向右移动;若该位置超出数组大小范围,将会把 val 插入到数组末尾。SQL 示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
mysql> set @j = '["a", {"b": [1, 2]}, [3, 4]]';

-- 在数组的索引 1 的位置上插入值 5,原本索引 1 位置上的 {"b": [1, 2]} 被挤到后边
mysql> select json_array_insert(@j, '$[1]', 5);
+------------------------------------+
| json_array_insert(@j, '$[1]', 5) |
|------------------------------------|
| ["a", 5, {"b": [1, 2]}, [3, 4]] |
+------------------------------------+
1 row in set (0.00 sec)

-- 插入位置超出数组大小范围,将会把值插入到数组末尾
mysql> select json_array_insert(@j, '$[100]', 5);
+--------------------------------------+
| json_array_insert(@j, '$[100]', 5) |
|--------------------------------------|
| ["a", {"b": [1, 2]}, [3, 4], 5] |
+--------------------------------------+
1 row in set (0.00 sec)

-- path 指向不是 JSON 数组的元素,SQL 执行报错
mysql> select json_array_insert(@j, '$[1].b', 5);
(3165, 'A path expression is not a path to a cell in an array.')

json_array_append(),如果参数 path 指向的 JSON 是数组,将在数组末尾添加元素;如果参数 path 指向的 JSON 是值或对象,该值或对象将被包裹为数组,然后在这个数组末尾添加元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
mysql> set @j = '["a", {"b": [1, 2]}, [3, 4]]';

-- path 指向的 JSON 是数组,将在数组末尾添加元素
mysql> select json_array_append(@j, '$', 5);
+---------------------------------+
| json_array_append(@j, '$', 5) |
+---------------------------------+
| ["a", {"b": [1, 2]}, [3, 4], 5] |
+---------------------------------+
1 row in set (0.00 sec)

-- path 指向的 JSON 是值或对象,该值或对象将被包裹为数组,然后在这个数组末尾添加元素
mysql> select json_array_append(@j, '$[1]', 5);
+-----------------------------------+
| json_array_append(@j, '$[1]', 5) |
+-----------------------------------+
| ["a", [{"b": [1, 2]}, 5], [3, 4]] |
+-----------------------------------+
1 row in set (0.00 sec)

除了上文提到的函数,还有 json_merge_patch()、json_merge_preserve()、json_remove() 这个些函数,可以参考官方文档的介绍,本文不再一一举例说明。

索引 JSON:生成列

现在来看下根据 JSON 列查询表数据的执行计划,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mysql> explain select * from tbl where data -> "$.id" = 1 \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: tbl
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 2
filtered: 100.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)

可以看到,因为没有加索引,访问类型是全表扫描 type: ALL。来试下在 JSON 类型的 data 列上添加索引,会提示如下错误:

1
2
mysql> alter table tbl add index (data);
ERROR 3152 (42000): JSON column 'data' cannot be used in key specification.

对于索引 JSON 类型列问题,MySQL 文档有如下阐述[2:1]

JSON columns, like columns of other binary types, are not indexed directly; instead, you can create an index on a generated column that extracts a scalar value from the JSON column. See Indexing a Generated Column to Provide a JSON Column Index, for a detailed example.

就是说,不能直接在 JSON 列上创建索引;替代方式是,先创建提取 JSON 纯量的生成列(generated column),然后在这个生成列上创建索引。回过头来,ERROR 3152,这个报错提示信息其实让人有点困惑,对没仔细阅读文档的人来说,可能会误以为 MySQL 不支持索引 JSON 列(Bug #81364[25])。于是,在 MySQL 8.0 错误提示信息优化为:

ERROR 3152 (42000): JSON column '%s' supports indexing only via generated columns on a specified JSON path.

生成列以及在生成列上创建索引,是 MySQL 5.7 开始支持的新特性。但其实,在 SQL:2003 标准中,生成列就早已经被定义为可选特性,“Optional Features of SQL/Foundation:2003, T175 Generated columns”。这个特性在其他 DBMS 中很早就有支持。2007 年 9 月发布的 Oracle Database 11g 开始支持生成列,不过它们称之为称之为虚拟列(virtual column)。2008 年 8 月发布的 SQL Server 2008 开始支持计算列(computed column),实现的就是 SQL 标准中的生成列。在相近的时间点,MySQL 创建了WL#411: Computed virtual columns as MS SQL server has[26]。之后,MySQL 的社区贡献者 Andrey Zhakov 实现了 WL#411 描述的特性,并发布了实现的代码补丁[27][28][29]。可惜的是 MySQL 官方很长一段时间都没把这个补丁合并进来,直到 2015 年的 MySQL 5.7(7年后)才官方实现 WL#411[30],同时 WL#411 的标题也被更新为符合 SQL 标准术语的 “Generated columns”。与之相对比的是,2010 年 4 月发布的 MariaDB 5.2 就开始支持虚拟列[31],实现上同样也是基于 Andrey Zhakov 贡献的代码。关于生成列或虚拟列,Wikipedia 的 Virtual column 词条[32]总结了各大 DBMS 的支持情况,可以参阅。总结下,标准 SQL 定义生成列的语法和 SQL Server 2008、Oracle 11g、MariaDB、MySQL 的区别[30:1][33]

1
2
3
4
5
6
7
8
9
Standard             MSSQL 2008      Oracle 11g           MariaDB 10.1           MySQL 5.7               
-------- ----------- ---------- ------------ ---------
column_name column_name column_name column_name column_name
[data type] [data type] data_type data type
GENERATED ALWAYS AS AS GENERATED ALWAYS AS [GENERATED ALWAYS] AS [GENERATED ALWAYS] AS
(expression) (expression) (expression) (expression) (expression)
[PERSISTENT] [VIRTUAL] [VIRTUAL | PERSISTENT] [VIRTUAL | STORED]
[constraints] [constraints] [constraints] [constraints] [constraints]
[COMMENT 'string'] [COMMENT 'string']

回到正题,我们现在来试试 MySQL 的生成列:

1
2
3
4
5
6
7
8
9
10
11
12
13
-- 添加生成列
mysql> alter table tbl add id int as (data -> "$.id");
Query OK, 0 rows affected (0.15 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> select * from tbl;
+-----------------------------------------------+------+
| data | id |
+-----------------------------------------------+------+
| {"id": 1, "name": "Will"} | 1 |
| {"id": 2, "name": "printf(\"hello world\");"} | 2 |
+-----------------------------------------------+------+
2 rows in set (0.00 sec)

上面的示例,创建生成列 id,生成列对应的表达式是 data -> "$.id"。现在再试试在生成列 id 上,创建索引:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
-- 在生成列上创建索引 idx_id
mysql> create index idx_id on tbl (id);
Query OK, 0 rows affected (0.05 sec)
Records: 0 Duplicates: 0 Warnings: 0

-- 执行计划
mysql> explain select * from tbl where id = 1 \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: tbl
partitions: NULL
type: ref
possible_keys: idx_id
key: idx_id
key_len: 5
ref: const
rows: 1
filtered: 100.00
Extra: NULL
1 row in set, 1 warning (0.00 sec)

-- 执行计划
mysql> explain select * from tbl where data -> "$.id" = 1 \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: tbl
partitions: NULL
type: ref
possible_keys: idx_id
key: idx_id
key_len: 5
ref: const
rows: 1
filtered: 100.00
Extra: NULL
1 row in set, 1 warning (0.00 sec)

从上面的执行计划可以看到,查询条件用 id 或者 data -> "$.id" 都能使用索引 idx_id

JSON 二进制格式

内部实现上,保存到数据库的 JSON 数据并非以 JSON 文本存储,而是二进制格式,具体可以参见,WL#8132: JSON datatype and binary storage format,当然也可以直接阅读源码 json_binary.h[34]、json_binary.cc[35]或 doxygen[36]

MySQL 的 JSON 二进制格式,其中有一点比较值得注意,WL#8132 提到:

The keys are sorted, so that lookup can use binary search to locate the key quickly.

就是,为了能利用二分搜索快速定位键,存入数据库的JSON 对象的键是被排序过的。来看下下面的 SQL:

1
2
3
4
5
6
7
8
9
10
11
mysql> truncate tbl;
mysql> insert into tbl values ('{"b": "c", "a": {"y": 1, "x": 2}}');
Query OK, 1 row affected (0.02 sec)

mysql> select * from tbl;
+-----------------------------------+
| data |
+-----------------------------------+
| {"a": {"x": 2, "y": 1}, "b": "c"} |
+-----------------------------------+
1 row in set (0.00 sec)

上面的 SQL 可以看到,insert 写入时键并没有按次序排列,而用 select 将 JSON 数据反序列化读出,发现实际保存的键是有序的。排序规则是,先按字符串长度排序,若长度相同按字母排序。同样的,键关联的值,按键排序后的次序排列。对键排序,显然只能针对 JSON 对象,若要存储 JSON 数组,值按索引位置排序。

MySQL 5.7.22 新增 json_storage_size() 函数,用于返回 json 文档二进制表示占用的存储空间。先来看下 SQL 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
mysql> select json_storage_size('"abc"');
+----------------------------+
| json_storage_size('"abc"') |
+----------------------------+
| 5 |
+----------------------------+
1 row in set (0.00 sec)

mysql> select json_storage_size('[42, "xy", "abc"]');
+----------------------------------------+
| json_storage_size('[42, "xy", "abc"]') |
+----------------------------------------+
| 21 |
+----------------------------------------+
1 row in set (0.00 sec)

mysql> select json_storage_size('{"b": 42, "a": "xy"}');
+-------------------------------------------+
| json_storage_size('{"b": 42, "a": "xy"}') |
+-------------------------------------------+
| 24 |
+-------------------------------------------+
1 row in set (0.00 sec)

WL#8132 给出了 JSON 二进制格式的 BNF 语法描述。参考这个语法描述,可以推算出上文示例中的 "abc"[42, "xy", "abc"]{"b": 42, "a": "xy"} 对应的二进制表示。先来看下 "abc" 纯量,语法推导过程如下:

1
2
3
4
5
6
7
doc
=> type value // 使用产生式 doc ::= type value
=> 0x0c value // 使用产生式 type ::= 0x0c (utf8mb4 string 类型)
=> 0x0c string // 使用产生式 value ::= string
=> 0x0c data-length utf8mb4-data // 使用产生式 string ::= data-length utf8mb4-data
=> 0x0c 0x03 utf8mb4-data // 使用产生式 data-length ::= uint8*
=> 0x0c 0x03 0x61 0x62 0x63

对应的二进制值,共 5 个字节,依次为 0x0c 0x03 0x61 0x62 0x63,其中 0x61 0x62 0x63,就是 16 进制表示的字符串 abc。占用 5个字节,与 json_storage_size() 函数返回的结果一致。相应的语法树如下:

mysql-jsonb-syntax-tree-w350

从二进制的角度看,纯量 "abc" 的 JSON 二进制表示如下:

mysql-jsonb-scalar-w350

[42, "xy", "abc"] 的推导过程,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
doc 
=> type value // 使用产生式 doc ::= type value
=> 0x02 array // 使用产生式 type ::= 0x02 (small JSON array 类型)
=> 0x02 element-count size value-entry* value* // 使用产生式 array ::= element-count size value-entry* value*
=> 0x02 0x03 0x00 size value-entry* value* // 使用产生式 element-count ::= uint16 (使用 little-endian)
=> 0x02 0x03 0x00 0x14 0x00 value-entry* value* // 使用产生式 size ::= uint16 (使用 little-endian)
=> 0x02 0x03 0x00 0x14 0x00 type offset-or-inlined-value value-entry* value* // 使用产生式 value-entry ::= type offset-or-inlined-value
=> 0x02 0x03 0x00 0x14 0x00 0x06 offset-or-inlined-value value-entry* value* // 使用产生式 type ::= 0x06 (uint16 类型)
=> 0x02 0x03 0x00 0x14 0x00 0x06 0x2a 0x00 value-entry* value* // 使用产生式 offset-or-inlined-value ::= uint16
... 省略
=> 0x02 0x03 0x00 0x14 0x00 0x06 0x2a 0x00 0x0c 0x0d 0x00 0x0c 0x10 0x00 value*
=> 0x02 0x03 0x00 0x14 0x00 0x06 0x2a 0x00 0x0c 0x0d 0x00 0x0c 0x10 0x00 string value // 使用产生式 value ::= string
=> 0x02 0x03 0x00 0x14 0x00 0x06 0x2a 0x00 0x0c 0x0d 0x00 0x0c 0x10 0x00 data-length utf8mb4-data value // 使用产生式 string ::= data-length utf8mb4-data
=> 0x02 0x03 0x00 0x14 0x00 0x06 0x2a 0x00 0x0c 0x0d 0x00 0x0c 0x10 0x00 0x02 utf8mb4-data value // 使用产生式 data-length ::= uint8*
=> 0x02 0x03 0x00 0x14 0x00 0x06 0x2a 0x00 0x0c 0x0d 0x00 0x0c 0x10 0x00 0x02 0x78 0x78 value
... 省略
=> 0x02 0x03 0x00 0x14 0x00 0x06 0x2a 0x00 0x0c 0x0d 0x00 0x0c 0x10 0x00 0x02 0x78 0x79 0x03 0x61 0x62 0x63

[42, "xy", "abc"] 对应的二进制表示,共 21 个字节,依次为 0x02 0x03 0x00 0x14 0x00 0x06 0x2a 0x00 0x0c 0x0d 0x00 0x0c 0x10 0x00 0x02 0x78 0x79 0x03 0x61 0x62 0x63。如下图:

mysql-jsonb-array

相对来说,产生式 array ::= element-count size value-entry* value*,是整个JSON 数组二进制表示语法的核心。element-count,表示元素个数。上图中,第 4、5 个字节是 size 字段,十进制值为 20(0x14),是完整二进制表示去掉开头 type 字段后的大小(文档没有明确这个字段的含义,不过通过源码推断出来)。另外,value-entrytypeoffset-or-inlined-value 字段组成。type 很好理解,不做解释。offset-or-inlined-value 字段,官方文档给出了含义,含义如下:

1
2
3
4
5
6
// This field holds either the offset to where the value is stored,
// or the value itself if it is small enough to be inlined (that is,
// if it is a JSON literal or a small enough [u]int).
offset-or-inlined-value ::=
uint16 | // if used in small JSON object/array
uint32 // if used in large JSON object/array

就是说,如果实际要保存的值足够小,将直接内联在这个字段中,否则将保存偏移量(offset),也就是指向实际值的指针。在示例中,保存 xy 对应的 offset 值为 13(0x0d),指向的相对地址是 14。因为这里的 offset 并不是以相对地址 0 为基准地址,是以相对地址 1 为基准地址(图中箭头 B 指向的位置),所以偏移量是 13 而不是 14(这个字段的明确含义也是从源码推断而来)。类似的,保存 abc 对应的 offset 值为 16(0x10),指向的相对地址是 17。

阅读文档容易发现,element-countsizeoffset 字段占用的字节大小是固定的,小 JSON(64KB 以内)是 2 字节,大 JSON 是 4 字节。所以,若要查找 JSON 数组的第 pos 个元素的 value-entry 的偏移量,可以使用下面的式子快速定位:

1
entry_offset = offset_size * 2 + (1 + offset_size) * pos

JSON 数组二进制表示的其他字段比较容易理解,文档都有解释,就不展开阐述了。

现在来看下,JSON 对象 {"b": 42, "a": "xy"} 的二进制表示,如下图:

mysql-jsonb-object

对于 JSON 对象二进制表示的语法,核心的产生式是 object ::= element-count size key-entry* value-entry* key* value*element-countsizevalue-entry 字段,在 JSON 数组中也有,不再赘述。而 key-entry 字段,类似于 value-entrykey-entry 中的 key-offset 保存的是偏移量,是指向键的指针。另外,正如上文提到的 MySQL 会对 JSON 键排序,所以上图示例的第 20 和 21 个字节值分别是 0x610x62,即 ab,而非 ba。同样的,键关联的值,按键排序后的次序排列,依次是 "xy"42

参考资料


  1. MySQL 5.7 Reference Manual, What Is New in MySQL 5.7 https://dev.mysql.com/doc/refman/5.7/en/mysql-nutshell.html ↩︎

  2. MySQL 5.7 Reference Manual, 12 Data Types, 12.6 The JSON Data Type http://dev.mysql.com/doc/refman/5.7/en/json.html ↩︎ ↩︎

  3. 2012-09 PostgreSQL 9.2 released https://www.postgresql.org/about/news/postgresql-92-released-1415/ ↩︎

  4. JSON Support in Oracle Database 12c Release 1 (12.1.0.2) https://oracle-base.com/articles/12c/json-support-in-oracle-database-12cr1 ↩︎

  5. Oracle Database 12c Release 1 (12.1.0.2) New Features, 1.9 JSON Support https://docs.oracle.com/database/121/NEWFT/chapter12102.htm#NEWFT505 ↩︎

  6. Facebook DocStore: Document column type [Deprecated] https://github.com/facebook/mysql-5.6/wiki/Document-column-type-[Deprecated] ↩︎

  7. 2015-04 DocStore: Document Database for MySQL at Facebook (slides) https://web.archive.org/web/20161022061349/https://www.percona.com/live/mysql-conference-2015/sites/default/files/slides/Facebook DocStore Percona 2015.pdf ↩︎

  8. 2014-03 SQL/JSON Proposals, Part 1 https://www.wiscorp.com/pub/DM32.2-2014-00024R1_JSON-SQL-Proposal-1.pdf ↩︎

  9. 2014-03 SQL/JSON Proposals, Part 2 https://www.wiscorp.com/pub/DM32.2-2014-00025r1-sql-json-part-2.pdf ↩︎

  10. 2014-03 SQL Support for JSON (slides) https://web.archive.org/web/20150919002536/http://jtc1bigdatasg.nist.gov/_workshop/08_SQL_Support_for_JSON_abstract.pdf ↩︎

  11. 2017-06 What’s New in SQL:2016 https://modern-sql.com/blog/2017-06/whats-new-in-sql-2016 ↩︎

  12. WL#7909: Server side JSON functions https://dev.mysql.com/worklog/task/?id=7909 ↩︎

  13. WL#8132: JSON datatype and binary storage format https://dev.mysql.com/worklog/task/?id=8132 ↩︎

  14. WL#8249: JSON comparator https://dev.mysql.com/worklog/task/?id=8249 ↩︎

  15. WL#8607: Inline JSON path expressions in SQL https://dev.mysql.com/worklog/task/?id=8607 ↩︎

  16. MySQL 5.7 Reference Manual, 13 Functions and Operators, 13.16 JSON Functions https://dev.mysql.com/doc/refman/5.7/en/json-functions.html ↩︎

  17. 2015-04 JSON Labs Release: JSON Functions, Part 1 — Manipulation JSON Data http://mysqlserverteam.com/json-labs-release-json-functions-part-1-manipulation-json-data/ ↩︎

  18. 2015-04 JSON Labs Release: JSON Functions, Part 2 — Querying JSON Data http://mysqlserverteam.com/mysql-5-7-lab-release-json-functions-part-2-querying-json-data/ ↩︎

  19. JSONPath - XPath for JSON https://goessner.net/articles/JsonPath/ ↩︎

  20. 2015-10 Inline JSON Path Expressions in MySQL 5.7 http://mysqlserverteam.com/inline-json-path-expressions-in-mysql-5-7/ ↩︎

  21. PostgreSQL 11.10 Documentation, 9.15. JSON Functions and Operators https://www.postgresql.org/docs/11/functions-json.html ↩︎

  22. What is the difference between ->> and -> in Postgres SQL? https://stackoverflow.com/a/47270495 ↩︎

  23. 2015-10 SQLite Release 3.9.0 https://sqlite.org/releaselog/3_9_0.html ↩︎

  24. SQLite: The JSON1 Extension https://www.sqlite.org/json1.html ↩︎

  25. Bug #81364: Indexing JSON column should suggest generated columns https://bugs.mysql.com/bug.php?id=81364 ↩︎

  26. WL#411: Computed virtual columns as MS SQL server has https://web.archive.org/web/20080917094638/http://forge.mysql.com/worklog/task.php?id=411 ↩︎

  27. Bug #46491: Patch: Virtual columns (WL#411) https://bugs.mysql.com/bug.php?id=46491 ↩︎

  28. 2008-09 MySQL virtual columns https://datacharmer.blogspot.com/2008/09/mysql-virtual-columns.html ↩︎

  29. MySQL virtual columns preview https://web.archive.org/web/20120629093123/http://forge.mysql.com/wiki/MySQL_virtual_columns_preview ↩︎

  30. WL#411: Generated columns https://dev.mysql.com/worklog/task/?id=411 ↩︎ ↩︎

  31. MariaDB: Generated (Virtual and Persistent/Stored) Columns https://mariadb.com/kb/en/generated-columns/ ↩︎

  32. Virtual column https://en.wikipedia.org/wiki/Virtual_column ↩︎

  33. 2016-02 Generated columns in MariaDB and MySQL https://planet.mysql.com/entry/?id=5994068 ↩︎

  34. MySQL 5.7 Source Code: sql/json_binary.h https://github.com/mysql/mysql-server/blob/5.7/sql/json_binary.h ↩︎

  35. MySQL 5.7 Source Code: sql/json_binary.cc https://github.com/mysql/mysql-server/blob/5.7/sql/json_binary.cc ↩︎

  36. MySQL 8.0 Source Code Documentation: json_binary.h File Reference (doxygen) https://dev.mysql.com/doc/dev/mysql-server/8.0.16/json__binary_8h.html#details ↩︎

]]>
+ + + <p>2015 年 8 月,MySQL 5.7.8 开始提供对 JSON 的原生支持<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup><sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup>。MySQL 对 JSON 的支持可以说是千呼万唤始出来。2009 年开始 NoSQL 逐渐流行起来,相继出现了键值对数据库、文档数据库、列族数据库、图数据库等各类 NoSQL,解决经典关系型数据库无法解决的痛点。其中,对灵活存储半结构化数据的需求,使得类似 MongoDB 这类文档数据库涌现出来。各大主流关系型数据库也在响应趋势,开始支持半结构化数据。早在 2012 年,PostgreSQL 9.2 就已经添加了 JSON 数据类型<sup class="footnote-ref"><a href="#fn3" id="fnref3">[3]</a></sup>。Oracle 也在 2014 年 7 月发布 12c Release 1 后开始支持 JSON<sup class="footnote-ref"><a href="#fn4" id="fnref4">[4]</a></sup><sup class="footnote-ref"><a href="#fn5" id="fnref5">[5]</a></sup>。Facebook 在 MySQL 5.7 没发布之前,对 5.6 版本的 MySQL 添加了存储 JSON 功能,这个特性被 Facebook 命名为 DocStore (Document Database for MySQL at Facebook)<sup class="footnote-ref"><a href="#fn6" id="fnref6">[6]</a></sup><sup class="footnote-ref"><a href="#fn7" id="fnref7">[7]</a></sup>。另外,SQL 标准组织行动也很快,在 2014 年 3 月已经完成了 SQL/JSON 标准草案(SQL/JSON Proposals)<sup class="footnote-ref"><a href="#fn8" id="fnref8">[8]</a></sup><sup class="footnote-ref"><a href="#fn9" id="fnref9">[9]</a></sup><sup class="footnote-ref"><a href="#fn10" id="fnref10">[10]</a></sup>。完整的草案在 2016 年 12 月正式被采纳为标准,即 SQL:2016。</p> + + + + + + + + + + +
+ + + Elastic Stack 日志分析平台搭建笔记 + + https://nullwy.me/2019/01/elastic-stack/ + 2019-01-14T06:58:20.000Z + 2023-12-05T06:14:06.883Z + + Elastic Stack(旧称 ELK Stack)是最受欢迎的开源日志平台 [ ref ]。Elastic Stack 由 Elasticsearch、Logstash、Kibana 和 Beats 四个组件组成:

  • Beats,是轻量型采集器的平台,从边缘机器向 Logstash 和 Elasticsearch 发送数据。
  • Logstash,集中、转换和存储数据,是动态数据收集管道,拥有可扩展的插件生态系统,能够与 Elasticsearch 产生强大的协同作用。
  • Elasticsearch,搜索、分析和存储您的数据,是基于 JSON 的分布式搜索和分析引擎,专为实现水平扩展、高可靠性和管理便捷性而设计。
  • Kibana,实现数据可视化,导览 Elastic Stack。能够以图表的形式呈现数据,并且具有可扩展的用户界面,供您全方位配置和管理 Elastic Stack。

Elastic Stack 是逐步发展而来的,一开始只有 Elasticsearch,专注做搜索引擎,2013 年 1 月 Kibana 及其作者 Rashid Khan 加入 Elasticsearch 公司,同年 8 月 Logstash 及作者 Jordan Sissel 也加入,原本的非官方的 ELK Stack,正式成为官方用语。2015 年 3 月,旧金山举行的第 1 届 Elastic{ON} 大会上,Elasticsearch 公司改名为 Elastic。两个月后,Packetbeat 项目也加入 Elastic,Packetbeat 和 Filebeat(之前叫做 Logstash-forwarder,由 Logstash 作者 Jordan Sissel 开发)项目被整合改造为 Beats。加上 Beats 以后,官方不知道如何将 “B” 和 E-L-K 组合在一起(用过 ELKB 或 BELK),ELK Stack 于是改名为 Elastic Stack,并在 2016 年 10 月正式发布 Elastic Stack 5.0 [ ref1, ref2, ref3 ]。

使用 Logstash

Logstash(home, github)最初是来自 Dreamhost 运维工程师 Jordan Sissel 的开源项目,是管理事件和日志的工具,能够用于采集数据,转换数据,然后将数据发送到您最喜欢的“存储库”中(比如 Elasticsearch)。Logstash 使用 JRuby 开发,2011 年 5 月发布 1.0 版本。2013 年 8 月 Jordan Sissel 带着 Logstash 加入 Elasticsearch 公司,Logstash 成为 Elastic Stack 一员。

在 Ubuntu 下安装启动 Logstash 可以使用下面命令:

1
2
3
4
5
6
$ sudo apt-get install logstash                # 安装 logstash
$ sudo systemctl start logstash.service # 系统服务方式启动 logstash
$ /usr/share/logstash/bin/logstash --version # 查看 logstash 版本
logstash 6.5.4
$ sudo vim /etc/logstash/logstash.yml # 查看默认 logstash.yml
$ sudo vim /etc/logstash/logstash-sample.conf # 查看示例 logstash-sample.conf

安装完成后,二进制文件在 /usr/share/logstash/bin 目录下,配置文件位于 /etc/logstash 目录,日志输出位于 /var/log/logstash 目录,其他详细的目录位置的分布情况,可以阅读官方文档

最简单的示例

Logstash 管道(pipeline)由 inputfilteroutput 三个元素组成,其中 inputoutput 必须设置,而 filter 可选。input 插件从数据源中消费数据,filter 插件按指定方式修改数据,output 插件将数据写入特定目标中 [ doc ]。

Logstash 管道

现在来试试 Logstash 下 Hello Wolrd 级别的示例,运行下面命令:

1
$ sudo /usr/share/logstash/bin/logstash -e 'input { stdin { } } output { stdout {} }'

-e 选项能够使 Logstash 直接在命令行中设置管道配置。示例中 input 插件为 stdin (标准输入),output 插件是 stdout (标准输出)。若在控制台输入 hello world,相应的控制台将输出:

1
2
3
4
5
6
{
"@version" => "1",
"host" => "ubuntu109",
"@timestamp" => 2019-01-12T05:52:56.291Z,
"message" => "hello world"
}

值得注意的是,输出内容编码格式默认为 rubydebug,使用 Ruby 的 "awesome_print" 库打印。另外,响应输出 @timestamp 字段的值为 2019-01-12T05:52:56.291Z,这是 ISO 8601 时间格式,时区是 0(zero),和北京时间相差 8 个小时。

输出内容编码格式,可以通过 codec 指令指定。除了默认的 rubydebug 外,官方还支持其他 20 多种编码格式,参见 doc。若把编码格式改为 json,即 stdout { codec => json },输出结果将变成:

1
{"message":"hello world","@version":"1","@timestamp":"2019-01-12T05:52:56.291Z","host":"ubuntu109"}

管道配置也可以保存到文件中,以 *.conf 作为文件后缀,比如保存为 test-stdin-stdout.conf

1
2
3
4
5
6
input {
stdin { }
}
output {
stdout { }
}

启动 logstash 时,-f 选项用于指定管道配置文件的路径:

1
$ sudo /usr/share/logstash/bin/logstash -f ~/test-stdin-stdout.conf

默认情况下,在启动 logstash 后,若再修改管道配置文件,新的修改需要重启 logstash 才能加载生效。在开发调试时,不太方便。解决这个问题,可以使用 -r 命令行选项。开启这个选项后,只要确定配置文件已经发生变更,便会自动重新加载配置文件。

file 输入插件

上文日志是控制台输入的,但真实情况日志在日志文件中,要想使用 Logstash 读取日志文件,官方提供了 file 输入插件。管道配置文件示例 test-file-stdout.conf,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
input {
file {
path => ["/home/yulewei/test.log"]
sincedb_path => "/dev/null"
start_position => "beginning"
}
}
filter {
}
output {
stdout {
codec => rubydebug
}
}

启动 Logstash:

1
$ sudo /usr/share/logstash/bin/logstash -r -f ~/test-file-stdout.conf

配置文件中的 path 指令用于指定日志文件的路径。start_position 指令设置 Logstash 启动时读取日志文件的位置,可以设置为 beginning 或者 end,默认是 end,即文件末尾。

为了跟踪每个输入文件中已处理了哪些数据,Logstash 文件输入插件会使用名为 sincedb 的文件来记录现有位置。由于我们的配置用于开发,所以我们希望能够重复读取文件,并进而希望禁用 sincedb 文件。在 Linux 系统上,将 sincedb_path 指令设置为 “/dev/null” 即可禁用。若没有禁用,默认保存的 sincedb 文件将在 /usr/share/logstash/data/plugins/inputs/file/ 目录下。

grok 过滤插件

上文的例子,做的核心事情就是把日志行转换到 message 字段,并附加某些元数据,如 @timestamp。如果要想解析自己的日志,把非结构化日志转换结构换日志,有两个过滤器特别常用:dissect 会根据分界符来解析日志,而 grok 则会根据正则表达式匹配来运行。

如果数据结构定义非常完善,dissect 过滤插件的运行效果非常好,而且运行速度非常快捷高效。同时,其也更加容易上手,对于不熟悉正则表达式的用户而言,更是如此。通常而言,grok 的功能更加强大,而且可以处理各种各样的数据。然而,正则表达式匹配会耗费更多资源,而且速度也会慢一些,如果未能正确进行优化的话,尤为如此。

现在先来看下 grok 过滤插件。grok 模式的基本语法是 %{SYNTAX:SEMANTIC}SYNTAX 是用于匹配数据的模式(或正则表达式)名称,SEMANTIC 是标识符或字段名称。Logstash 提供了超过 120 种默认的 grok 模式,全部预定义的模式可以在 github 上找到。典型的预定义模式(非完整列表)[ github ]:

  • WORD - 匹配单个词汇的模式
  • NUMBER - 匹配整数或浮点数(正值或负值均可)的模式
  • POSINT - 匹配正整数的模式
  • EMAILADDRESS - 邮箱地址
  • IP - 匹配 IPv4 或 IPv6 IP 地址的模式
  • URI - URI 地址
  • TIMESTAMP_ISO8601 - ISO8601 格式的时间
  • NOTSPACE - 匹配非空格的任何内容的格式
  • SPACE - 匹配任何数量的连续空格的模式
  • DATA - 匹配任何数据类型的限定数量的模式
  • GREEDYDATA - 匹配剩余所有数据的格式

比如,3.44 可以使用 NUMBER 模式进行匹配,192.168.2.104 可以使用 IP 模式。%{NUMBER:num} %{IP:client} 模式,将会用 NUMBER 模式把 3.44 识别为 num 字段,用 IP 模式把 192.168.2.104 识别为 client 字段。默认情况识别获得的字段值是字符串类型,grok 插件支持把类型转换为 intfloat。要想把 3.44 转换为浮点数,可以使用 %{NUMBER:num:float}

假设有如下日志内容:

1
Will, yulewei@gmail.com, 42, 1024, 3.14

grok 匹配表达式可以写成这样:

1
%{WORD:name}, %{EMAILADDRESS:email}, %{NUMBER:num1}, %{NUMBER:num2:int}, %{NUMBER:pi:float}

即,在这一行日志中依次提取出,nameemailnum1num2pi 字段。完整的 filter 过滤器配置的写法:

1
2
3
4
5
filter {
grok {
match => { "message" => "%{WORD:name}, %{EMAILADDRESS:email}, %{NUMBER:num1}, %{NUMBER:num2:int}, %{NUMBER:pi:float}" }
}
}

启动 logstash:

1
$ sudo /usr/share/logstash/bin/logstash -r -f ~/test-file-grok-stdout.conf

控制台将输出:

1
2
3
4
5
6
7
8
9
10
11
12
{
"@version" => "1",
"message" => "Will, yulewei@gmail.com, 42, 1024, 3.14",
"num1" => "42",
"pi" => 3.14,
"@timestamp" => 2019-01-12T08:12:49.581Z,
"path" => "/home/yulewei/test-grok.log",
"host" => "ubuntu109",
"email" => "yulewei@gmail.com",
"name" => "Will",
"num2" => 1024
}

Logstash 提供了超过 120 种默认的 grok 模式,基本上满足大多数使用场景。若没有符合要求的预定义的模式,可以使用 Oniguruma 语法指定正则表达式:

1
(?<field_name>the pattern here)

上文中的 %{WORD:name}%{EMAILADDRESS:email},等价的正则表达式的写法如下 [ ref1, ref2 ]:

1
2
(?<name>\w+)
(?<email>[a-zA-Z][a-zA-Z0-9_.+-=:]+@[0-9A-Za-z][0-9A-Za-z-]{0,62}\.[0-9A-Za-z][0-9A-Za-z-]{0,62})

调试 grok 匹配表达式容易出错,官方提供可视化的 Grok Debugger 工具,提高调试效率。

Grok Debugger

解析 http 服务器日志

现在来看下,真实的日志解析案例,使用 grok 过滤插件解析 http 服务器日志。通用日志格式(Common Log Format),是 http 服务器的标准的日志格式。对通用日志格式扩展,加上额外的 referer 和 user-agent 字段,称为组合日志格式(Combined Log Format)。两种日志格式包含的字段如下:

1
2
3
4
# 通用日志格式
%remote-host %ident %authuser %timestamp "%request" %status %bytes
# 组合日志格式
%remote-host %ident %authuser %timestamp "%request" %status %bytes "%referer" "%user-agent"

ApacheNginx 服务器默认的日志格式,采用的就是通用日志格式或者组合日志格式。解析这两种日志格式,Logstash 提供预定义模式 COMMONAPACHELOGCOMBINEDAPACHELOG

典型的 nginx 日志例子:

1
192.168.2.104 - - [13/Jan/2019:02:01:15 +0800] "GET /images/avatar.png HTTP/1.1" 200 266975 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:64.0) Gecko/20100101 Firefox/64.0"

管道配置文件示例 test-file-grokhttp-stdout.conf,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
input {
file {
path => ["/var/log/nginx/access.log"]
sincedb_path => "/dev/null"
start_position => "beginning"
}
}
filter {
grok {
match => { "message" => "%{COMBINEDAPACHELOG}" }
remove_field => ["message"]
}
}
output {
stdout { }
}

示例中使用了 grok 的预定义模式 COMBINEDAPACHELOG。另外,remove_field 指令用于把输出事件中某字段删除,示例中是 message 字段。

启动 logstash:

1
$ sudo /usr/share/logstash/bin/logstash -r -f ~/test-file-grokhttp-stdout.conf

解析获得的结构化数据,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"auth" => "-",
"host" => "ubuntu109",
"verb" => "GET",
"clientip" => "192.168.2.104",
"@version" => "1",
"httpversion" => "1.1",
"@timestamp" => 2019-01-13T13:35:52.983Z,
"bytes" => "266975",
"timestamp" => "13/Jan/2019:02:01:15 +0800",
"request" => "/images/avatar.png",
"response" => "200",
"referrer" => "\"-\"",
"path" => "/var/log/nginx/access.log",
"agent" => "\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:64.0) Gecko/20100101 Firefox/64.0\"",
"ident" => "-"
}

dissect 过滤插件

和 grok 过滤插件使用正则表达式提取字段不同,dissect 过滤插件使用分界符切割来提取字段。由于没有使用正则表达式,运行速度相对 grok 快很多。使用 dissect 过滤插件时,需要指明提取字段的顺序,还要指明这些字段之间的分界符。过滤插件会对数据进行单次传输,并匹配模式中的分界符。同时,过滤插件还会将分界符之间的数据分配至指定字段。过滤插件不会对所提取数据的格式进行验证。

现在看下示例,test-dissect.log 文件内容如下:

1
Will, yulewei@gmail.com, 42, 1024, 3.14

dissect 匹配规则可以写成这样:

1
%{name}, %{email}, %{num1}, %{num2}, %{num3}

完整的配置文件,test-file-dissect-stdout.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
input {
file {
path => ["/home/yulewei/test-dissect.log"]
sincedb_path => "/dev/null"
start_position => "beginning"
}
}
filter {
dissect {
mapping => {
"message" => "%{name}, %{email}, %{num1}, %{num2}, %{num3}"
}
convert_datatype => {
"num2" => "int"
"num3" => "float"
}
}
}
output {
stdout { }
}

和 grok 插件一样,默认提取的字段是字符串类型。配置文件中的 convert_datatype 指令用于将类型转为 intfloat

启动 logstash:

1
$ sudo /usr/share/logstash/bin/logstash -r -f ~/test-file-dissect-stdout.conf

输出结果:

1
2
3
4
5
6
7
8
9
10
11
12
{
"host" => "ubuntu109",
"num1" => "42",
"message" => "Will, yulewei@gmail.com, 42, 1024, 3.14",
"@version" => "1",
"name" => "Will",
"num2" => 1024,
"@timestamp" => 2019-01-13T13:32:10.900Z,
"path" => "/home/yulewei/test-dissect.log",
"email" => "yulewei@gmail.com",
"num3" => 3.14
}

输出到 Elasticsearch

上文举的例子全部都是,输出控制台,使用 stdout 输出插件,没有实用价值。Elastic Stack 的核心其实是 Elasticsearch,使用Elasticsearch 搜索和分析日志。想要将数据发送到 Elasticsearch,可以使用 elasticsearch 输出插件。

安装 Elasticsearch

如果没有安装 Elasticsearch,参考官方文档按步骤安装。唯一要注意的是,在执行 apt install 命令前,必须先添加 elastic 的软件源地址,否则无法正常启动。核心命令如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ sudo apt-get install elasticsearch           # 安装 elasticsearch
$ sudo systemctl start elasticsearch.service # 系统服务方式启动 elasticsearch
$ curl http://localhost:9200/ # 用 rest 接口查看 elasticsearch
{
"name" : "1t9JXt5",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "yQgVsvupSqGCGQbwqnanIg",
"version" : {
"number" : "6.5.4",
"build_flavor" : "default",
"build_type" : "deb",
"build_hash" : "d2ef93d",
"build_date" : "2018-12-17T21:17:40.758843Z",
"build_snapshot" : false,
"lucene_version" : "7.5.0",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}

默认情况下 elasticsearch 服务器绑定的 ip 地址是回环地址 127.0.0.1,若想绑定特定 ip 地址,可以修改 /etc/elasticsearch/elasticsearch.yml 配置文件中的 network.host 选项:

1
network.host: 192.168.2.109

修改完成并重启后,elasticsearch 服务器访问地址从 http://localhost:9200/ 变成 http://192.168.2.109:9200/

输出到 Elasticsearch

现在来看下 elasticsearch 输出插件。示例,test-file-elasticsearch.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
input {
file {
path => ["/home/yulewei/test.log"]
sincedb_path => "/dev/null"
start_position => "beginning"
}
}
output {
elasticsearch {
hosts => ["http://192.168.2.109:9200"]
index => "logstash-%{+YYYY.MM.dd}"
}
}

示例的 elasticsearch 输出插件使用了 hostsindex 指令。hosts 指令,用于指定 elasticsearch 服务器的地址。而 index 指令,用于指定 elasticsearch 索引的名称模式,该指令默认值为 logstash-%{+YYYY.MM.dd}。在字符串内部的 %{...},是 Logstash 字符串插值语法,官方称之为 sprintf format [ doc ]。+YYYY.MM.dd,用于指定 @timestamp 的格式化的格式。logstash-%{+YYYY.MM.dd},格式化后最终生成的值可能将是 logstash-2019.01.13

启动 logstash:

1
$ sudo /usr/share/logstash/bin/logstash -r -f ~/test-file-elasticsearch.conf

查看在 elasticsearch 上新创建的 logstash-* 索引以及从 logstash 同步过来的日志数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$ curl http://192.168.2.109:9200/_cat/indices
yellow open logstash-2019.01.13 tFjc5xL_QYeNw4oqe4odeg 5 1 3 0 15.5kb 15.5kb
$ curl 'http://192.168.2.109:9200/logstash-*/_search?pretty' -H 'Content-Type: application/json' -d'{"size": 1}'
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 3,
"max_score" : 1.0,
"hits" : [
{
"_index" : "logstash-2019.01.13",
"_type" : "doc",
"_id" : "RUHNRWgBLIBntI4FV8Rf",
"_score" : 1.0,
"_source" : {
"path" : "/home/yulewei/test.log",
"@timestamp" : "2019-01-13T06:01:51.303Z",
"@version" : "1",
"host" : "ubuntu109",
"message" : "hello world"
}
}
]
}
}

可以看到,新的索引名为 logstash-2019.01.13。同步过来的日志记录全部有 5 条,第 1 条日志的 message 内容是 hello world

使用 Kibana

Kibana,能够对 Elasticsearch 中的数据进行可视化,是 Elastic Stack 的窗口。在 Ubuntu 下安装 Kibana 可以使用下面命令:

1
2
$ sudo apt-get install kibana          # 安装 kibana,当前最新版为 6.5.4
$ sudo systemctl start kibana.service # 系统服务方式启动 kibana

默认配置下,kibana 服务访问地址是 http://localhost:5601/,连接的 elasticsearch 地址是 http://localhost:9200,这两个配置分别由 server.hostelasticsearch.url 控制 [ doc ]。上文尝试过把 elasticsearch 服务 ip 地址绑定到 192.168.2.109。现在来试下绑定 ip 地址到 kibana,编辑配置文件 /etc/kibana/kibana.yml,修改为:

1
2
server.host: "192.168.2.109"
elasticsearch.url: "http://192.168.2.109:9200"

使用 sudo systemctl restart kibana.service 重启后,kibana 服务访问地址变成 http://192.168.2.109:5601/

elasticsearch 服务器上存在索引 logstash-2019.01.13,要想把这个索引导入到 kibana,参考官方教程即可。点击 Management 菜单,然后创建索引模式(index pattern)。索引模式可以直接为 logstash-2019.01.13,这样匹配单个索引。若要匹配多个时间的 logstash 索引,可以使用通配符 *,比如 logstash-*。如果要匹配全部 2019 年 01 月的索引,可以写成 logstash-2019.01*。完成索引模式定义后,便可以在 Discover 菜单下查看索引,如图:

Kibana

使用 Filebeat

Filebeat,轻量型日志采集器 [ home ]。其前身是由 Logstash 作者 Jordan Sissel 开发的 Logstash Forwarder。Logstash Forwarder 项目因为和收购过来的 Packetbeat 项目功能相近,并且都是 Go 语言开发,就一起被整合改造为 Beats [ ref ]。

我们知道,Logstash 使用 JRuby 开发,运行依赖 JVM,会消耗较多的系统资源。为了减少系统资源(CPU、内存和网络)的使用,Logstash Forwarder 改用 Go 语言开发。另外,在功能上也做了精简,只做单一的数据传输,不像 Logstash 有数据过滤能力。Logstash 类似于功能多样的“瑞士军刀”,能提供从多个数据源加载数据的功能,使用各种强大的插件来处理日志,并提供将多个来源的输出数据进行存储的功能。简而言之,Logstash 提供数据 ETL(数据的提取、变换和加载)的功能;而 Beats 是轻量级的数据传输工具,能将数据传输到 Logstash 或 Elasticsearch 中,其间没有对数据进行任何转换 [ Gupta2017 ]。Filebeat 和 Logstash 的关系如下图所示 [ logz.io ]:

Filebeat 和 Logstash 的关系

安装 filebeat 很简单,参考官方文档即可,核心命令如下:

1
2
3
4
$ sudo apt-get install filebeat           # 安装 filebeat
$ filebeat version # 查看 filebeat 版本
filebeat version 6.5.4 (amd64), libbeat 6.5.4 [bd8922f1c7e93d12b07e0b3f7d349e17107f7826 built 2018-12-17 20:22:29 +0000 UTC]
$ sudo systemctl start filebeat.service # 系统服务方式启动 filebeat

输出到 Elasticsearch

修改 filebeat 配置文件 /etc/filebeat/filebeat.yml,示例如下:

1
2
3
4
5
6
7
filebeat.inputs:
- type: log
paths:
- /home/yulewei/test.log

output.elasticsearch:
hosts: ["192.168.2.109:9200"]

filebeat.inputs 选项用于配置日志的输入方式。子选项 type 支持 logstdinredisudptcp 等,示例中使用了 log,表明从日志文件输入。

output 选项用于配置日志的输出方式,配置支持 elasticsearch、logstash、kafka、redis、file、console 等,一次只能选择配置其中某一个。示例配置了 output.elasticsearch.hosts,指定日志输出目标 elasticsearch 的主机地址。output.elasticsearch.index 可以用来指定索引 index 名称模式,默认是 filebeat-%{[beat.version]}-%{+yyyy.MM.dd}(比如 filebeat-6.5.4-2019.01.12)[ doc ]。

完成 filebeat.yml 修改后,重启 filebeat,将可以看到,在 elasticsearch 上新创建的 filebeat-* 索引:

1
2
$ curl http://192.168.2.109:9200/_cat/indices
yellow open filebeat-6.5.4-2019.01.12 B4JbQDnZQuK5XvsQ77uedA 3 1 11043 0 1.7mb 1.7mb

输出到 Logstash

上文的示例直接把 Filebeat 采集的日志传输到 Elasticsearch,日志数据并没有被解析或者转换。若想解析和转换日志,需要在Filebeat 和 Elasticsearch 中间引入 Logstash。现在看下把日志输出到 Logstash 的示例配置文件,filebeat.yml 示例:

1
2
3
4
5
6
7
filebeat.inputs:
- type: log
paths:
- /home/yulewei/test.log

output.logstash:
hosts: ["localhost:5044"]

filebeat.inputs 和上文的示例一样。不同的是,把 output.elasticsearch.hosts 改成了 output.logstash.hosts,指定日志输出目标 Logstash 的主机地址。5044 这个端口是 Logstash 用于监听 Filebeat 的端口。

现在来看下 Logstash 的管道配置文件,示例 test-beats-stdout.conf

1
2
3
4
5
6
7
8
9
10
input {
beats {
port => 5044
}
}
output {
stdout {
codec => rubydebug
}
}

示例中,使用了 beats 输入插件,配置的端口就 filebeat.yml 中指定的 5044。输出插件为 stdout,即把 Logstash 采集到日志输出到控制台。

重启 filebeat 和 logstash:

1
2
3
4
$ cat test.log                              # 查看日志文件内容
hello world
$ sudo systemctl restart filebeat.service # 重启 filebeat
$ sudo /usr/share/logstash/bin/logstash -r -f ~/test-beats-stdout.conf

控制台输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
"tags" => [
[0] "beats_input_codec_plain_applied"
],
"source" => "/home/yulewei/test.log",
"input" => {
"type" => "log"
},
"message" => "hello world",
"@timestamp" => 2019-01-12T13:32:05.131Z,
"@version" => "1",
"prospector" => {
"type" => "log"
},
"beat" => {
"hostname" => "ubuntu109",
"version" => "6.5.4",
"name" => "ubuntu109"
},
"offset" => 0,
"host" => {
"os" => {
"version" => "16.04.4 LTS (Xenial Xerus)",
"platform" => "ubuntu",
"codename" => "xenial",
"family" => "debian"
},
"architecture" => "x86_64",
"id" => "29b1bf39547d4ca9ae26c3b7656ff9e3",
"containerized" => false,
"name" => "ubuntu109"
}
}

集成 Filebeat, Logstash, Elasticsearch, Kibana

真实场景下,日志文件可能分布在多台服务器上,同一台服务器上也可能分布着不同来源类型的日志。现在我们来尝试下,使用 Filebeat 把两个日志文件各自采集到两个不同的 Elasticsearch 索引中,并用 Kibana 可视化。有两个日志文件 test-beats1.logtest-beats2.log,内容如下:

1
2
3
4
5
$ cat test-beats1.log
hello world1
hello world1
$ cat test-beats2.log
hello world2

filebeat.yml 配置示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
filebeat.inputs:
- type: log
paths:
- /home/yulewei/test-beats1.log
fields:
log_type: test1
- type: log
paths:
- /home/yulewei/test-beats2.log
fields:
log_type: test2

output.logstash:
hosts: ["localhost:5044"]

示例配置文件使用了 filebeat.inputs.fields 选项,fields 选项用于在日志事件输出中添加字段。添加的字段名可以任意指定,示例中名为 log_type。因为现在在 filebeat 配置中同时导入两个日志文件,输出到同一个 logstash 中。使用这个额外字段是为了区分日志是来自 test-beats1.log 还是 test-beats2.log。示例中,第 1 个日志事件输出的 log_type 字段值配置为 test1, 第 2 个日志配置为 test2

管道配置文件示例,test-beats-elasticsearch.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
input {
beats {
port => 5044
}
}
output {
elasticsearch {
hosts => ["http://192.168.2.109:9200"]
index => "filebeat-%{[fields][log_type]}-%{+YYYY.MM.dd}"
}
stdout {
codec => rubydebug
}
}

输出插件同时使用了 elasticsearchstdout。配置文件中的 elasticsearch 输出插件的 index 指令被设置为 filebeat-%{[fields][log_type]}-%{+YYYY.MM.dd}[fields][log_type] 引用的是在 filebeat.ymlfilebeat.inputs.fields 选项添加的 log_type 字段(关于在配置文件引用字段的语法,可以参考官方文档)。根据 log_type 字段不同,把日志将输出到不同的索引中。因为 filebeat.yml 配置文件中设置的 log_type 字段是 test1 或者 test2,所以最终生成的索引名是 filebeat-test1-* 或者 filebeat-test1-*filebeat-test1-* 索引中全部日志数据来自 test-beats1.log 日志文件,filebeat-test2-* 索引数据来自 test-beats2.log

启动 filebeat 和 logstash:

1
2
$ sudo systemctl restart filebeat.service
$ sudo /usr/share/logstash/bin/logstash -r -f ~/test-beats-elasticsearch.conf

控制台输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
...
{
"@version" => "1",
"host" => {
"name" => "ubuntu109"
},
"message" => "hello world2",
"prospector" => {
"type" => "log"
},
"fields" => {
"log_type" => "test2"
},
"offset" => 0,
"tags" => [
[0] "beats_input_codec_plain_applied"
],
"beat" => {
"name" => "ubuntu109",
"version" => "6.5.4",
"hostname" => "ubuntu109"
},
"@timestamp" => 2019-01-13T09:32:11.845Z,
"source" => "/home/yulewei/test-beats2.log",
"input" => {
"type" => "log"
}
}
...

查看在 elasticsearch 上新创建的 filebeat-test1-*filebeat-test1-* 索引:

1
2
3
$ curl http://192.168.2.109:9200/_cat/indices/filebeat-*
yellow open filebeat-test1-2019.01.13 NLVfFJl5TQ-7I1r9KoVLaQ 5 1 5 0 31.8kb 31.8kb
yellow open filebeat-test2-2019.01.13 NnsBp3P9Q3-mLc8chE-Tiw 5 1 3 0 24.1kb 24.1kb

在 kibana 上查看收集的日志:

Kibana

整体架构上,如下图所示 [ doc ]:

Deploying Logstash

附注:本文中提到的配置文件,可以在 github 上访问得到,elastic-stack-conf

参考资料

]]>
+ + + <p>Elastic Stack(旧称 ELK Stack)是最受欢迎的开源日志平台 [ <a href="https://www.elastic.co/cn/solutions/logging">ref</a> ]。Elastic Stack 由 Elasticsearch、Logstash、Kibana 和 Beats 四个组件组成:</p> +<ul> +<li><a href="https://www.elastic.co/cn/products/beats">Beats</a>,是轻量型采集器的平台,从边缘机器向 Logstash 和 Elasticsearch 发送数据。</li> +<li><a href="https://www.elastic.co/cn/products/logstash">Logstash</a>,集中、转换和存储数据,是动态数据收集管道,拥有可扩展的插件生态系统,能够与 Elasticsearch 产生强大的协同作用。</li> +<li><a href="https://www.elastic.co/cn/products/elasticsearch">Elasticsearch</a>,搜索、分析和存储您的数据,是基于 JSON 的分布式搜索和分析引擎,专为实现水平扩展、高可靠性和管理便捷性而设计。</li> +<li><a href="https://www.elastic.co/cn/products/kibana">Kibana</a>,实现数据可视化,导览 Elastic Stack。能够以图表的形式呈现数据,并且具有可扩展的用户界面,供您全方位配置和管理 Elastic Stack。</li> +</ul> + + + + + + + + + + + + + + +
+ + + Java Agent 学习笔记 + + https://nullwy.me/2018/10/java-agent/ + 2018-10-04T15:26:20.000Z + 2023-12-05T06:14:35.160Z + + Java 从 1.5 开始提供了 java.lang.instrumentdoc)包,该包为检测(instrument) Java 程序提供 API,比如用于监控、收集性能信息、诊断问题。通过 java.lang.instrument 实现工具被称为 Java Agent。Java Agent 可以修改类文件的字节码,通常是,在字节码方法插入额外的字节码来完成检测。关于如何使用 java.lang.instrument 包,可以参考 javadoc 的包描述(en, zh)。

开发 Java Agent 的涉及的要点如下图所示 [ ref ]
Java Agent

Java Agent 支持两种方式加载,启动时加载,即在 JVM 程序启动时在命令行指定一个选项来启动代理;启动后加载,这种方式使用从 JDK 1.6 开始提供的 Attach API 来动态加载代理。

启动时加载 agent

最简单的例子

现在创建命名为 proj-demo 的 gradle 项目,目录布局如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ tree proj-demo
proj-demo
├── build.gradle
└── src
├── main
│   └── java
│   └── com
│   └── demo
│   └── App.java
└── test
└── java

7 directories, 2 files

com.demo.App 类的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class App {

public static void main(String[] args) throws InterruptedException {
while (true) {
System.out.println(getGreeting());
Thread.sleep(1000L);
}
}

public static String getGreeting() {
return "hello world";
}
}

运行 com.demo.App,每隔 1 秒输出 hello world

1
2
3
4
$ gradle build
$ java -cp "target/classes/java/main" com.demo.App
hello world
hello world

现在创建名称为 proj-premain 的 gradle 项目,com.demo.MyPremain 类实现 premain 方法:

1
2
3
4
5
6
7
package com.demo;

public class MyPremain {
public static void premain(String agentArgs, Instrumentation inst) {
System.out.println(agentArgs);
}
}

META-INF/MANIFEST.MF 文件指定 Premain-Class 属性:

1
2
3
4
5
6
7
8
jar {
manifest {
attributes 'Premain-Class': 'com.demo.MyPremain'
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}

打包生成 proj-premain.jar,这个 jar 包就是 javaagent 代理。现在来试试运行 com.demo.App 时,启动这个 javaagent 代理。根据 javadoc 的描述,可以将以下选项添加到命令行来启动代理:

1
-javaagent:jarpath[=options] 

指定 -javaagent:"proj-premain.jar=hello agent",传入的 agentArgshello agent,再次运行 com.demo.App

1
2
3
4
$ java -javaagent:"proj-premain.jar=hello agent" -cp "target/classes/java/main" com.demo.App
hello agent
hello world
hello world

可以看到,在运行 main 之前,运行了 premain 方法,即先输出 hello agent,每隔 1 秒输出 hello world

修改字节码

在实现 premain 时,除了能获取 agentArgs 参数,还能获取 Instrumentation 实例。Instrumentation 类提供 addTransformer 方法,用于注册提供的转换器 ClassFileTransformer

1
2
// 注册提供的转换器
void addTransformer(ClassFileTransformer transformer)

ClassFileTransformer 是抽象接口,唯一需要实现的是 transform 方法。在转换器使用 addTransformer 注册之后,每次定义新类时(调用 ClassLoader.defineClass)都将调用该转换器的 transform 方法。该方法签名如下:

1
2
3
4
5
6
7
// 此方法的实现可以转换提供的类文件,并返回一个新的替换类文件
byte[] transform(ClassLoader loader,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer)
throws IllegalClassFormatException

操作字节码可以使用 ASM、Apache BCEL、Javassist、cglib、Byte Buddy 等库。下面示例代码,使用 BCEL 库实现名为 GreetingTransformer 转换器。该转换器实现的逻辑就是,将 com.demo.App.getGreeting() 方法输出的 hello world,替换为输出 premain 方法的传入的参数 agentArgs

1
2
3
4
5
public class MyPremain {
public static void premain(String agentArgs, Instrumentation inst) {
inst.addTransformer(new GreetingTransformer(agentArgs));
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import org.apache.bcel.*;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;

public class GreetingTransformer implements ClassFileTransformer {
private String agentArgs;

public GreetingTransformer(String agentArgs) {
this.agentArgs = agentArgs;
}

@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, byte[] classfileBuffer) {
if (!className.equals("com/demo/App")) {
return classfileBuffer;
}
try {
JavaClass clazz = Repository.lookupClass(className);
ClassGen cg = new ClassGen(clazz);
ConstantPoolGen cp = cg.getConstantPool();
for (Method method : clazz.getMethods()) {
if (method.getName().equals("getGreeting")) {
MethodGen mg = new MethodGen(method, cg.getClassName(), cp);
InstructionList il = new InstructionList();
il.append(new PUSH(cp, this.agentArgs));
il.append(InstructionFactory.createReturn(Type.STRING));
mg.setInstructionList(il);
mg.setMaxStack();
mg.setMaxLocals();
cg.replaceMethod(method, mg.getMethod());
}
}
return cg.getJavaClass().getBytes();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}

启动后加载 agent

最早 JDK 1.5发布 java.lang.instrument 包时,agent 是必须在 JVM 启动时,通过命令行选项附着(attach)上去。但在 JVM 正常运行时,加载 agent 没有意义,只有出现问题,需要诊断才需要附着 agent。JDK 1.6 实现了 attach-on-demand(按需附着)[ JDK-4882798 ],可以使用 Attach API 动态加载 agent [ oracle blog, javadoc ]。这个 Attach API 在 tools.jar 中。JVM 启动时默认不加载这个 jar 包,需要在 classpath 中额外指定。使用 Attach API 动态加载 agent 的示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;

public class AgentLoader {

public static void main(String[] args) throws Exception {
if (args.length < 2) {
System.err.println("Usage: java -cp .:$JAVA_HOME/lib/tools.jar"
+ " com.demo.AgentLoader <pid/name> <agent> [options]");
System.exit(0);
}

String jvmPid = args[0];
String agentJar = args[1];
String options = args.length > 2 ? args[2] : null;
for (VirtualMachineDescriptor jvm : VirtualMachine.list()) {
if (jvm.displayName().contains(args[0])) {
jvmPid = jvm.id();
break;
}
}

VirtualMachine jvm = VirtualMachine.attach(jvmPid);
jvm.loadAgent(agentJar, options);
jvm.detach();
}
}

启动时加载 agent,-javaagent 传入的 jar 包需要在 MANIFEST.MF 中包含 Premain-Class 属性,此属性的值是 代理类 的名称,并且这个 代理类 要实现 premain 静态方法。启动后加载 agent 也是类似,通过 Agent-Class 属性指定 代理类代理类 要实现 agentemain 静态方法。agent 被加载后,JVM 将尝试调用 agentmain 方法。

上文提到每次定义新类(调用 ClassLoader.defineClass)时,都将调用该转换器的 transform 方法。对于已经定义加载的类,需要使用重定义类(调用 Instrumentation.redefineClass)或重转换类(调用 Instrumentation.retransformClass)。

1
2
3
4
5
6
7
8
// 注册提供的转换器。如果 canRetransform 为 true,那么重转换类时也将调用该转换器
void addTransformer(ClassFileTransformer transformer, boolean canRetransform)
// 使用提供的类文件重定义提供的类集。新的类文件字节,通过 ClassDefinition 传入
void redefineClasses(ClassDefinition... definitions)
throws ClassNotFoundException, UnmodifiableClassException
// 重转换提供的类集。对于每个添加时 canRetransform 设为 true 的转换器,在这些转换器中调用 transform 方法
void retransformClasses(Class<?>... classes)
throws UnmodifiableClassException

重定义类(redefineClass)从 JDK 1.5 开始支持,而重转换类(retransformClass)是 JDK 1.6 引入。相对来说,重转换类能力更强,当存在多个转换器时,重转换将由 transform 调用链组成,而重定义类无法组成调用链。重定义类能实现的逻辑,重转换类同样能完成,所以保留重定义类方法(Instrumentation.redefineClass)可能只是为了向后兼容 [ stackoverflow ]。

实现 agentmain 的示例代码如下,其中 GreetingTransformer 转换器的类定义和上文一样。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyAgentMain {

public static void agentmain(String agentArgs, Instrumentation inst) {
inst.addTransformer(new GreetingTransformer(agentArgs), true);
try {
Class clazz = Class.forName("com.demo.App");
if (inst.isModifiableClass(clazz)) {
inst.retransformClasses(clazz);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

MANIFEST.MF 文件配置:

1
2
3
4
5
6
7
8
9
10
jar {
manifest {
attributes 'Agent-Class': 'com.demo.MyAgentMain'
attributes 'Can-Redefine-Classes' : true
attributes 'Can-Retransform-Classes' : true
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}

需要注意的是,和定义新类不同,重定义类和重转换类,可能会更改方法体、常量池和属性,但不得添加、移除、重命名字段或方法;不得更改方法签名、继承关系 [ javadoc ]。这个限制将来可能会通过 “JEP 159: Enhanced Class Redefinition” 移除 [ ref ]。

使用 Byte Buddy

Byte Buddy(home, github, javadoc),运行时的代码生成和操作库,2015 年获得 Oracle 官方 Duke's Choice award,提供高级别的创建和修改 Java 类文件的 API,使用这个库时,不需要了解字节码。另外,对 Java Agent 的开发 Byte Buddy 也有很好的支持,可以参考 Byte Buddy 作者 Rafael Winterhalter 写的介绍文章 [ ref1, ref2 ]。

上文使用 BCEL 实现的 GreetingTransformer,现在改用 Byte Buddy,会变得非常简单。实现 premain 示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void premain(String agentArgs, Instrumentation inst) {
new AgentBuilder.Default()
.type(ElementMatchers.named("com.demo.App"))
.transform(new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
TypeDescription typeDescription,
ClassLoader classLoader,
JavaModule module) {
return builder.method(ElementMatchers.named("getGreeting"))
.intercept(FixedValue.value(agentArgs));
}
}).installOn(inst);
}

实现 agentmain

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void agentmain(String agentArgs, Instrumentation inst) {
new AgentBuilder.Default()
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.disableClassFormatChanges()
.type(ElementMatchers.named("com.demo.App"))
.transform(new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
TypeDescription typeDescription,
ClassLoader classLoader,
JavaModule module) {
return builder.method(ElementMatchers.named("getGreeting"))
.intercept(FixedValue.value(agentArgs));
}
}).installOn(inst);
}

另外,Byte Buddy 对 Attach API 作了封装,屏蔽了对 tools.jar 的加载,可以直接使用 ByteBuddyAgent 类:

1
ByteBuddyAgent.attach(new File(agentJar), jvmPid, options);

上文中的 AgentLoader,可以使用这个 API 简化,实现的完整示例参见 AgentLoader2

实现性能计时器

Byte Buddy 的 github 的 README 文档提供了一个性能计时拦截器的代码示例,能对某个方法的运行耗时做统计。现在我们来看下是如何实现的。假设 com.demo.App2 类如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class App2 {

public static void main(String[] args) {
while (true) {
System.out.println(getGreeting());
}
}

public static String getGreeting() {
try {
Thread.sleep((long) (1000 * Math.random()));
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello world";
}
}

使用 Byte Buddy 实现计时拦截器的 agent,如下:

1
2
3
4
5
6
7
8
9
10
11
public class TimerAgent {

public static void premain(String agentArgs, Instrumentation inst) {
new AgentBuilder.Default()
.type(ElementMatchers.any())
.transform((builder, type, classLoader, module) ->
builder.method(ElementMatchers.nameMatches(agentArgs))
.intercept(MethodDelegation.to(TimingInterceptor.class)))
.installOn(inst);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
public class TimingInterceptor {

@RuntimeType
public static Object intercept(@Origin Method method, @SuperCall Callable<?> callable) throws Exception {
long start = System.currentTimeMillis();
try {
return callable.call();
} finally {
System.out.println(method + " took " + (System.currentTimeMillis() - start) + "ms");
}
}
}

getGreeting 方法进行性能剖析,运行结果如下:

1
2
3
4
5
$ java -javaagent:"proj-byte-buddy.jar=get.*" -cp "target/classes/java/main" com.demo.App2
public static java.lang.String com.demo.App2.getGreeting() took 694ms
hello world
public static java.lang.String com.demo.App2.getGreeting() took 507ms
hello world

示例代码中的 premain 参数 agentArgs 用于指定需要剖析性能的方法名,支持正则表达式。当实际参数传入 get.* 时,匹配到 getGreeting 方法。上面的示例,使用的是 Byte Buddy 的方法委托 Method Delegation API [ javadoc ]。Delegation API 实现原理就是,将被拦截的方法委托到另一个办法上,如下左图所示(图片来自 Rafael Winterhalter 的 slides)。这种写法会修改被代理类的类定义格式,只能用在启动时加载 agent,即 premain 方式代理。

若要通过 Byte Buddy 实现启动后动态加载 agent,官方提供了 Advice API [ javadoc ]。Advice API 实现原理上是,在被拦截方法内部的开始和结尾添加代码,如下右图所示。这样只更改了方法体,不更改方法签名,也没添加额外的方法,符合重定义类(redefineClass)和重转换类(retransformClass)的限制。

delegation vs. advice

现在来看下使用 Advice API 实现性能定时器的代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class TimingAdvice {

@Advice.OnMethodEnter
public static long enter() {
return System.currentTimeMillis();
}

@Advice.OnMethodExit
public static void exit(@Advice.Origin Method method, @Advice.Enter long start) {
long duration = System.currentTimeMillis() - start;
System.out.println(method + " took " + duration + "ms");
}
}
1
2
3
4
5
6
7
8
9
10
11
public static void agentmain(String agentArgs, Instrumentation inst) {
new AgentBuilder.Default()
.disableClassFormatChanges()
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
// .with(AgentBuilder.Listener.StreamWriting.toSystemOut())
.type(ElementMatchers.any())
.transform((builder, type, classLoader, module) ->
builder.visit(Advice.to(TimingAdvice.class)
.on(ElementMatchers.nameMatches(agentArgs))))
.installOn(inst);
}

若对 com.demo.App 类,动态加载这个 Advice API 实现的 agent,getGreeting() 方法将会被重定义为(真正的实现可能稍有不同,但原理一致):

1
2
3
4
5
6
7
public static String getGreeting() {
long $start = System.nanoTime();
String $result = "hello world";
long $duration = System.nanoTime() – $start;
System.out.println("App.getGreeting()" + " took " + $duration + "ms");
return $result;
}

实际应用案例

Java Agent 的实际应用案例很多,举些笔者实际工作中使用到的开源软件的应用案例。

微服务是目前流行的互联网架构,实施微服务架构其中用于观察分布式服务的 APM (应用性能管理)系统是必不可缺的一环。典型的 APM 系统,如 PinpointSkyWalking,为了减少的 Java 服务应用代码的入侵,底层实现上都采用 Java Agent 技术,在 Java 服务应用启动时加载 agent,进行字节码增强技术,实现分布式追踪、服务性能监控等特性。具体可参见 Pinpoint 文档和 SkyWalking 文档

Alibaba Java 诊断利器 Arthas,实现上使用了动态 Attach API,相关源代码参见 github。Arthas 4.0 开始支持 premain 方式启动时加载 agent,参见 issue #550


**附注:**本文中提到的代码,可以在 github 上访问得到,javaagent-demo

参考资料

]]>
+ + + <p>Java 从 1.5 开始提供了 <code>java.lang.instrument</code>(<a href="https://docs.oracle.com/javase/8/docs/technotes/guides/instrumentation/">doc</a>)包,该包为检测(<a href="https://en.wikipedia.org/wiki/Instrumentation_%28computer_programming%29">instrument</a>) Java 程序提供 API,比如用于监控、收集性能信息、诊断问题。通过 <code>java.lang.instrument</code> 实现工具被称为 Java Agent。Java Agent 可以修改类文件的字节码,通常是,在字节码方法插入额外的字节码来完成检测。关于如何使用 <code>java.lang.instrument</code> 包,可以参考 javadoc 的包描述(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/instrument/package-summary.html">en</a>, <a href="http://www.cjsdn.net/doc/jdk60/java/lang/instrument/package-summary.html">zh</a>)。</p> + + + + + + + + + + + + + + +
+ + + MySQL binlog:格式、增量恢复、闪回、Java 解析 + + https://nullwy.me/2018/06/mysql-binlog/ + 2018-06-18T07:09:51.000Z + 2023-12-05T06:15:57.833Z + + MySQL 的 binlog 日志文件,记录了数据库表的全部修改操作。本文简单整理 MySQL binlog 相关知识,以及如何使用 binlog 恢复或闪回数据库数据。

STATEMENT 格式的 binlog

要想开启 binlog,需要在启动 MySQL 时传入 --log-bin 参数。或者也可以在 MySQL 配置文件 /etc/my.cnf,设置 log_bin 开启 binlog。MySQL 5.7 开始,开启 binlog 后,--server-id 参数也必须指定,否则 MySQL 服务器会启动失败。

binlog_format 支持 STATEMENT, ROW, MIXED 三种格式,MySQL 5.5 和 5.6 默认为 STATEMENT,MySQL 5.7.7 开始默认为 ROW。若 SQL 使用 UUID(), RAND(), VERSION() 等函数,或者使用存储过程、自定义函数,基于 STATEMENT 的主从复时,是不安全的(很多人可能会认为 NOW(), CURRENT_TIMESTAMP 这些函数也是不安全的,事实上是安全的)[ doc1, doc2 ]。基于 ROW 的主从复制,是最安全的复制方式。

现在先来看下 STATEMENT 格式的 binlog,/etc/my.cnf 文件修改的内容如下:

1
2
3
4
server_id = 1
log_bin = mysql-bin
binlog_format = STATEMENT
binlog_row_image=FULL

重启 MySQL 后,在数据目录 datadir 下,比如 /var/lib/mysql/,将会生成相应的 binlog 文件,mysql-bin.indexmysql-bin.000001.index 后缀的文件保存全部 binlog 文件名。mysql-bin.000001 文件记录 binlog 内容。每次 MySQL 启动或者 flush 日志,都将按序号创建一个新的日志文件。另外,当日志文件大小超过 max_binlog_size 时,也会创建一个新的日志文件。

现在来试一试 binlog 功能。假设在 testdb 库在有 hello 表,并对其中某行做修改操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> select * from hello;
+----+-------+
| id | name |
+----+-------+
| 1 | Andy |
| 2 | Bill |
| 3 | Candy |
+----+-------+
4 rows in set (0.00 sec)

mysql> update hello set name = 'Will' where id = 3;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0

binlog 为二进制文件,需要使用 mysqlbinlogdoc, man)命令查看:

1
2
$ sudo mysqlbinlog /var/lib/mysql/mysql-bin.000001  # 直接在 mysql 服务器上读取 binlog 文件
$ mysqlbinlog -R -h192.168.2.107 -uroot -p123456 mysql-bin.000001 # 或者,远程读取 binlog 文件

执行 update 后相应新增的 binlog 文件内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# at 154
#180617 22:47:49 server id 1 end_log_pos 219 CRC32 0x4bd9d69b Anonymous_GTIDlast_committed=0sequence_number=1rbr_only=no
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 219
#180617 22:47:49 server id 1 end_log_pos 302 CRC32 0x476fafc9 Querythread_id=2exec_time=0error_code=0
SET TIMESTAMP=1529246869/*!*/;
SET @@session.pseudo_thread_id=2/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1075838976/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;
# at 302
#180617 22:47:49 server id 1 end_log_pos 423 CRC32 0x7f2c2c7a Querythread_id=2exec_time=0error_code=0
use `testdb`/*!*/;
SET TIMESTAMP=1529246869/*!*/;
update hello set name = 'Will' where id = 3
/*!*/;
# at 423
#180617 22:47:49 server id 1 end_log_pos 454 CRC32 0x68da744a Xid = 12
COMMIT/*!*/;

ROW 格式的 binlog

修改 /etc/my.cnfbinlog_formatROW,再重启 MySQL。格式修改后,会生成一个新的 binlog 文件 mysql-bin.000002

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
mysql> show create table hello;
+-------+-------------------------------------------------------------------------+
| Table | Create Table
+-------+-------------------------------------------------------------------------+
| hello | CREATE TABLE `hello` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 |
+-------+-------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select * from hello where id;
+----+------+
| id | name |
+----+------+
| 1 | Andy |
| 2 | Lily |
| 3 | Will |
+----+------+
1 row in set (0.00 sec)

mysql> update hello set name = 'David' where id = 3;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0

查看 ROW 格式的 binlog,需要使用 sudo mysqlbinlog -v --base64-output=DECODE-ROWS /var/lib/mysql/mysql-bin.000002 命令。执行 update 后相应新增的 binlog 内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# at 154
#180617 22:54:13 server id 1 end_log_pos 219 CRC32 0x2ce70d4d Anonymous_GTIDlast_committed=0sequence_number=1rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 219
#180617 22:54:13 server id 1 end_log_pos 293 CRC32 0x8183fddf Querythread_id=2exec_time=0error_code=0
SET TIMESTAMP=1529247253/*!*/;
SET @@session.pseudo_thread_id=2/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1075838976/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;
# at 293
#180617 22:54:13 server id 1 end_log_pos 346 CRC32 0x0fc7e1a4 Table_map: `testdb`.`hello` mapped to number 110
# at 346
#180617 22:54:13 server id 1 end_log_pos 411 CRC32 0xb58e729d Update_rows: table id 110 flags: STMT_END_F
### UPDATE `testdb`.`hello`
### WHERE
### @1=3
### @2='Will'
### SET
### @1=3
### @2='David'
# at 411
#180617 22:54:13 server id 1 end_log_pos 442 CRC32 0xef964db8 Xid = 13
COMMIT/*!*/;

若执行如下 SQL:

1
2
mysql> insert hello (name) values ('Frank');
Query OK, 1 row affected (0.02 sec)

相应生成的 binlog 内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# at 442
#180617 22:55:47 server id 1 end_log_pos 507 CRC32 0x79de08a7 Anonymous_GTIDlast_committed=1sequence_number=2rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 507
#180617 22:55:47 server id 1 end_log_pos 581 CRC32 0x56f9eb6a Querythread_id=2exec_time=0error_code=0
SET TIMESTAMP=1529247347/*!*/;
BEGIN
/*!*/;
# at 581
#180617 22:55:47 server id 1 end_log_pos 634 CRC32 0xedb73620 Table_map: `testdb`.`hello` mapped to number 110
# at 634
#180617 22:55:47 server id 1 end_log_pos 684 CRC32 0x525a6a70 Write_rows: table id 110 flags: STMT_END_F
### INSERT INTO `testdb`.`hello`
### SET
### @1=4
### @2='Frank'
# at 684
#180617 22:55:47 server id 1 end_log_pos 715 CRC32 0x09a0d4de Xid = 14
COMMIT/*!*/;

若执行如下 SQL:

1
2
mysql> delete from hello where id = 2;
Query OK, 1 row affected (0.02 sec)

相应生成的 binlog 内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# at 715
#180617 22:56:44 server id 1 end_log_pos 780 CRC32 0x9f52450e Anonymous_GTIDlast_committed=2sequence_number=3rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 780
#180617 22:56:44 server id 1 end_log_pos 854 CRC32 0x0959bc8d Querythread_id=2exec_time=0error_code=0
SET TIMESTAMP=1529247404/*!*/;
BEGIN
/*!*/;
# at 854
#180617 22:56:44 server id 1 end_log_pos 907 CRC32 0x2945260f Table_map: `testdb`.`hello` mapped to number 110
# at 907
#180617 22:56:44 server id 1 end_log_pos 956 CRC32 0xc70df255 Delete_rows: table id 110 flags: STMT_END_F
### DELETE FROM `testdb`.`hello`
### WHERE
### @1=2
### @2='Bill'
# at 956
#180617 22:56:44 server id 1 end_log_pos 987 CRC32 0x0c98f18e Xid = 15
COMMIT/*!*/;

使用 binlog 增量恢复

MySQL 逻辑备份通常会结合全量备份增量备份,使用 mysqldump 定期全量备份数据库,然后利用 binlog 保存增量数据。恢复数据时,就是用 mysqldump 备份的数据恢复到备份的时间点。数据库在备份时间点到当前时间的增量修改,则通过 mysqlbinlog 将 binlog 中的增量数据恢复到数据库。现在假设已经使用 mysqldump 将数据库还原到:

1
2
3
4
5
6
7
8
9
mysql> select * from hello;
+----+------+
| id | name |
+----+------+
| 1 | Andy |
| 2 | Lily |
| 3 | Will |
+----+------+
3 rows in set (0.00 sec)

之后执行的 SQL:

1
2
3
update hello set name = 'David' where id = 3;
insert hello (name) values ('Frank');
delete from hello where id = 2;

不管是使用 STATEMENT 还是 ROWmysqlbinlog 命令都可以将 binlog 增量恢复到数据库 [ doc ]。

观察 binlog 可以看到,从最开始的 update hello set name = 'David' where id = 3; 到最终的 delete from hello where id = 2;,时间上从 "2018-06-17 22:54:13" 到 "2018-06-17 22:56:44",所以基于时间点恢复,命令如下:

1
$ sudo mysqlbinlog --start-datetime="2018-06-17 22:54:13" --stop-datetime="2018-06-17 22:56:44" mysql-bin.000002 | mysql -uroot -p123456

binlog 的事件位置号是从 "154" 到 "956",但需要注意的是 用 --start-position--stop-position 指定位置点范围,逻辑上对应的是 start <= position < stop,所以基于时间点恢复,命令如下:

1
$ sudo mysqlbinlog --start-position=154 --stop-position=957 mysql-bin.000002 | mysql -uroot -p123456

两种方式任意执行,都能将数据恢复到:

1
2
3
4
5
6
7
8
9
mysql> select * from hello;
+----+-------+
| id | name |
+----+-------+
| 1 | Andy |
| 3 | David |
| 4 | Frank |
+----+-------+
3 rows in set (0.00 sec)

使用 binlog2sql 闪回

binlog2sql,作者为曹单锋,大众点评 DBA。binlog2sql,从 MySQL binlog 解析出你要的 SQL。根据不同选项,你可以得到原始 SQL、回滚 SQL、去除主键的 INSERT SQL 等。binlog2sql,底层实现依赖 python-mysql-replication,由该库完成 MySQL 复制协议和 binlog 格式的解析。

1
2
3
4
$ python binlog2sql/binlog2sql.py -h192.168.2.107 -uroot -p123456 --start-position=154 --stop-position=957 --start-file='mysql-bin.000002'
UPDATE `testdb`.`hello` SET `id`=3, `name`='David' WHERE `id`=3 AND `name`='Will' LIMIT 1; #start 4 end 411 time 2018-06-17 22:54:13
INSERT INTO `testdb`.`hello`(`id`, `name`) VALUES (4, 'Frank'); #start 442 end 684 time 2018-06-17 22:55:47
DELETE FROM `testdb`.`hello` WHERE `id`=2 AND `name`='Bill' LIMIT 1; #start 715 end 956 time 2018-06-17 22:56:44

生成回滚 sql:

1
2
3
4
$ python binlog2sql/binlog2sql.py --flashback -h192.168.2.107 -uroot -p123456 --start-position=154 --stop-position=956 --start-file='mysql-bin.000002'
INSERT INTO `testdb`.`hello`(`id`, `name`) VALUES (2, 'Bill'); #start 715 end 956 time 2018-06-17 22:56:44
DELETE FROM `testdb`.`hello` WHERE `id`=4 AND `name`='Frank' LIMIT 1; #start 442 end 684 time 2018-06-17 22:55:47
UPDATE `testdb`.`hello` SET `id`=3, `name`='Will' WHERE `id`=3 AND `name`='David' LIMIT 1; #start 154 end 411 time 2018-06-17 22:54:13

闪回的现实原理很简单,先通过 MySQL 复制协议com-binlog-dump 命令 dump 出 binlog,然后按照 binlog 的格式规范解析 binlog,将 binlog 转换成 SQL,再将这些 SQL 转换反向逻辑的 SQL,最后再倒序执行。具体可以看,binlog2sql 作者的文章 [ ref ]。

Java 解析 binlog

上文中的 binlog2sql 其实底层依赖 python-mysql-replication 库,这是 Python 库。如果想使用 Java 解析 binlog 可以使用 mysql-binlog-connector-javagithub)库。目前开源的 CDC 工具,如 Zendesk maxwell、Redhat debezium、LinkedIn Databus 等都底层依赖 mysql-binlog-connector-java 或者其前身 open-replicator。使用 mysql-binlog-connector-java 的示例代码如下:

1
2
3
4
5
6
7
8
BinaryLogClient client = new BinaryLogClient("192.168.2.107", 3306, "root", "123456");
client.setBinlogFilename("mysql-bin.000001");
client.setBinlogPosition(4);
client.setBlocking(false);
client.registerEventListener(event -> {
System.out.println(event);
});
client.connect();

输出(省略部分内容):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
Event{header=EventHeaderV4{timestamp=1529247253000, eventType=TABLE_MAP, serverId=1, headerLength=19, dataLength=34, nextPosition=346, flags=0}, data=TableMapEventData{tableId=110, database='testdb', table='hello', columnTypes=8, 15, columnMetadata=0, 40, columnNullability={1}}}
Event{header=EventHeaderV4{timestamp=1529247253000, eventType=EXT_UPDATE_ROWS, serverId=1, headerLength=19, dataLength=46, nextPosition=411, flags=0}, data=UpdateRowsEventData{tableId=110, includedColumnsBeforeUpdate={0, 1}, includedColumns={0, 1}, rows=[
{before=[3, Will], after=[3, David]}
]}}
...
Event{header=EventHeaderV4{timestamp=1529247347000, eventType=TABLE_MAP, serverId=1, headerLength=19, dataLength=34, nextPosition=634, flags=0}, data=TableMapEventData{tableId=110, database='testdb', table='hello', columnTypes=8, 15, columnMetadata=0, 40, columnNullability={1}}}
Event{header=EventHeaderV4{timestamp=1529247347000, eventType=EXT_WRITE_ROWS, serverId=1, headerLength=19, dataLength=31, nextPosition=684, flags=0}, data=WriteRowsEventData{tableId=110, includedColumns={0, 1}, rows=[
[4, Frank]
]}}
...
Event{header=EventHeaderV4{timestamp=1529247404000, eventType=TABLE_MAP, serverId=1, headerLength=19, dataLength=34, nextPosition=907, flags=0}, data=TableMapEventData{tableId=110, database='testdb', table='hello', columnTypes=8, 15, columnMetadata=0, 40, columnNullability={1}}}
Event{header=EventHeaderV4{timestamp=1529247404000, eventType=EXT_DELETE_ROWS, serverId=1, headerLength=19, dataLength=30, nextPosition=956, flags=0}, data=DeleteRowsEventData{tableId=110, includedColumns={0, 1}, rows=[
[2, Bill]
]}}

参考资料

  1. MySQL Replication: 5.1.1 Advantages and Disadvantages of Statement-Based and Row-Based Replication https://dev.mysql.com/doc/mysql-replication-excerpt/5.7/en/replication-sbr-rbr.html
  2. Unsafe Statements for Statement-based Replication https://mariadb.com/kb/en/library/unsafe-statements-for-statement-based-replication/
  3. MySQL 5.7 Reference Manual: 4.6.7 mysqlbinlog https://dev.mysql.com/doc/refman/5.7/en/mysqlbinlog.html
  4. MySQL Internals Manual: 14.9 Replication Protocol https://dev.mysql.com/doc/internals/en/replication-protocol.html
  5. MySQL Internals Manual: 20 The Binary Log https://dev.mysql.com/doc/internals/en/binary-log.html
  6. MySQL闪回原理与实战 https://github.com/danfengcao/binlog2sql/blob/master/example/mysql-flashback-priciple-and-practice.md
  7. https://dev.mysql.com/doc/dev/mysql-server/8.0.11/classbinary__log_1_1Table__map__event.html#details
  8. https://dev.mysql.com/doc/dev/mysql-server/8.0.11/classbinary__log_1_1Rows__event.html#details
]]>
+ + + <p>MySQL 的 <a href="https://dev.mysql.com/doc/refman/5.7/en/binary-log.html">binlog</a> 日志文件,记录了数据库表的全部修改操作。本文简单整理 MySQL binlog 相关知识,以及如何使用 binlog 恢复或闪回数据库数据。</p> +<h1 id="STATEMENT-格式的-binlog">STATEMENT 格式的 binlog</h1> +<p>要想开启 binlog,需要在启动 MySQL 时传入 --<a href="https://dev.mysql.com/doc/refman/5.7/en/replication-options-binary-log.html#option_mysqld_log-bin">log-bin</a> 参数。或者也可以在 MySQL 配置文件 <code>/etc/my.cnf</code>,设置 <code>log_bin</code> 开启 binlog。MySQL 5.7 开始,开启 binlog 后,<code>--server-id</code> 参数也必须指定,否则 MySQL 服务器会启动失败。</p> + + + + + + + + + + + + +
+ + + 栈帧与调用惯例 + + https://nullwy.me/2018/01/stack-frame-calling-convention/ + 2018-01-29T09:09:51.000Z + 2023-12-05T06:16:34.112Z + + 栈与栈帧

要想知道函数是怎么被调用的,需要了解栈帧和调用惯例相关知识。俞甲子2009 的“第10章 内存: 栈与堆”对相关概念有很好的介绍。本文是对相关知识的学习笔记。

栈与栈帧布局

附注,栈帧之间的划分边界,其实有两种不一样说法。在有些资料中 [ wikipedia; 俞甲子2009 ],callee 参数被划分在 callee 栈帧,但在 Intel 官方一些权威文档中 [ Intel ASDM, Vol.1, Ch.6; Intel X86-psABI ],callee 参数被划分在 caller 栈帧。

调用惯例

调用惯例,规定以下内容:(1) 函数参数的传递顺序和方式;(2) 栈的清理方式;(3) 名称修饰(name mangling)。常见的 x86 调用惯例列表有:cdecl(C 语言默认)、stdcall(Win32 API 标准)、fastcall、pascal。这些调用惯例如下下表所示(更加全面的列表参见 wikipedia):

调用惯例栈帧清理参数传递名称修饰
cdel调用者 caller从右至左入栈 RTL下划线+函数名,如 _sum
stdcall被调用者 callee从右至左入栈 RTL下划线+函数名+@+参数字节数,如 _sum@8
fastcall被调用者 callee头两参数存入寄存器 ECX 和 EDX,其余参数从右至左入栈 RTL@+函数名+@+参数字节数,如 @sum@8
pascal被调用者 callee从左至右入栈 LTR较为复杂,参见 pascal 文档

下面举例说明,cdecl 和 stdcall 两种调用惯例。

cdecl 调用惯例

cdecl,调用者负责清理堆栈(caller clean-up),参数从右至左(Right-to-Left,RTL)压入栈。举例说明 [ ref1 ref2 ]:

1
2
3
4
5
6
// cdecl 调用惯例
int __cdecl sum(int a, int b) {
return a + b;
}
// 调用
int c = sum(2, 3);

编译器生成的等价汇编代码:

1
2
3
4
5
; 调用者清理堆栈(caller clean-up),参数 RTL 入栈
push 3
push 2
call _sum ; 将返回地址压入栈, 同时 sum 的地址装入 eip
add esp, 8 ; 清理堆栈, 两个参数占用 8 字节
1
2
3
4
5
6
7
8
9
10
11
; sum 函数等价汇编代码
; // function prolog
push ebp
mov ebp, esp
; // return a + b;
mov eax, [ebp + 12]
add eax, [ebp + 8] ; 返回值规定保存在 eax
; // function epilog
mov esp, ebp ; 设置栈顶 esp
pop ebp ; 恢复 old ebp
ret ; 将栈中保存的返回地址装入 eip

stdcall 调用惯例

stdcall,被调用者负责清理堆栈(callee clean-up),参数从右至左(Right-to-Left,RTL)压入栈。举例说明:

1
2
3
4
5
6
// stdcall 调用惯例
int __stdcall sum(int a, int b) {
return a + b;
}
// 调用
int c = sum(2, 3);

编译器生成的等价汇编代码:

1
2
3
4
; 被调用者清理堆栈(callee clean-up),参数 RTL 入栈
push 3
push 2
call _sum@8 ; 将返回地址压入栈, 同时 sum 的地址装入 eip
1
2
3
4
5
6
7
8
9
10
11
; sum 函数等价汇编代码
; // function prolog
push ebp
mov ebp, esp
; // return a + b;
mov eax, [ebp + 12]
add eax, [ebp + 8] ; 返回值规定保存在 eax
; // function epilog
mov esp, ebp ; 设置栈顶 esp
pop ebp ; 恢复 old ebp
ret 8 ; 清理堆栈,并将栈中保存的返回地址装入 eip

gcc 汇编代码

hello1.c 文件内容如下:

1
2
3
4
5
6
7
8
9
int __cdecl sum(int a, int b) {
return a + b;
}

int main() {
sum(1, 2);
sum(3, 4);
return 0;
}

生成汇编代码:

1
2
3
4
$ gcc -m32 -S -masm=intel hello1.c -o hello1.s
$ gcc -m32 hello1.s -o hello
$ ./hello || echo $?
0

生成的 hello1.s,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
  .section  __TEXT,__text,regular,pure_instructions
.macosx_version_min 10, 12
.intel_syntax noprefix
.globl _sum
.p2align 4, 0x90
_sum: ## @sum
## BB#0:
push ebp
mov ebp, esp
sub esp, 8 ; 预先分配 8 字节栈空间,保存 2 个布局变量
mov eax, dword ptr [ebp + 12] ; 堆栈中读取参数 2
mov ecx, dword ptr [ebp + 8] ; 堆栈中读取参数 1
mov dword ptr [ebp - 4], ecx ; 布局变量 1
mov dword ptr [ebp - 8], eax ; 布局变量 2
mov eax, dword ptr [ebp - 4]
add eax, dword ptr [ebp - 8]
add esp, 8 ; 清理 8 字节栈空间
pop ebp
ret

.globl _main
.p2align 4, 0x90
_main: ## @main
## BB#0:
push ebp
mov ebp, esp
sub esp, 40 ; 预先分配 40 字节栈空间
mov eax, 1
mov ecx, 2
mov dword ptr [ebp - 4], 0
mov dword ptr [esp], 1
mov dword ptr [esp + 4], 2
mov dword ptr [ebp - 8], eax ## 4-byte Spill
mov dword ptr [ebp - 12], ecx ## 4-byte Spill
call _sum
mov ecx, 3
mov edx, 4
mov dword ptr [esp], 3
mov dword ptr [esp + 4], 4
mov dword ptr [ebp - 16], eax ## 4-byte Spill
mov dword ptr [ebp - 20], ecx ## 4-byte Spill
mov dword ptr [ebp - 24], edx ## 4-byte Spill
call _sum
xor ecx, ecx
mov dword ptr [ebp - 28], eax ## 4-byte Spill
mov eax, ecx
add esp, 40 ; 清理 40 字节栈空间
pop ebp
ret

.subsections_via_symbols

GCC 生成的汇编代码并没有使用 push 而是通过 sub esp, 40 直接预先分配栈空间,然后使用 mov 指令将参数写进栈中,清理栈使用 add esp, 40。逻辑上,还是符合 cdecl 调用惯例,调用者负责清理堆栈(caller clean-up),参数从右至左(Right-to-Left,RTL)压入栈。这样做的好处是,如果同时多次调用 sum,清理栈空间的指令,只需要最后的时候调用一次就可以了。统一使用 sub espadd esp 去操作 esp 值,避免 push 指令操作 esp。

现在再来看看,stdcall 调用惯例下,GCC 生成的汇编代码。把 sum 函数改为 __stdcall,运行下面的命令:

1
2
$ gcc -m32 -S -masm=intel hello2.c -o hello2.s
$ diff -C1 hello1.s hello2.s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
*** hello1.s    Thu Feb 05 22:43:59 2018
--- hello2.s Thu Feb 05 22:45:24 2018
***************
*** 18,20 ****
pop ebp
! ret

--- 18,20 ----
pop ebp
! ret 8

***************
*** 35,36 ****
--- 35,37 ----
call _sum
+ sub esp, 8
mov ecx, 3
***************
*** 43,44 ****
--- 44,46 ----
call _sum
+ sub esp, 8
xor ecx, ecx

反汇编代码

反汇编 objdumpgdb/lldb,或者商业工具使用,IDA Pro 或者 Hopper Disassembler [ wiki ]

objdump 反汇编

1
2
$ gobjdump -d -Mintel hello1                # 使用 GNU objdump
$ objdump -d -x86-asm-syntax=intel hello1 # 使用 llvm-objdump
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
hello1:file format Mach-O 32-bit i386

Disassembly of section __TEXT,__text:
__text:
1f30:55 pushebp
1f31:89 e5 movebp, esp
1f33:83 ec 08 subesp, 8
1f36:8b 45 0c moveax, dword ptr [ebp + 12]
1f39:8b 4d 08 movecx, dword ptr [ebp + 8]
1f3c:89 4d fc movdword ptr [ebp - 4], ecx
1f3f:89 45 f8 movdword ptr [ebp - 8], eax
1f42:8b 45 fc moveax, dword ptr [ebp - 4]
1f45:03 45 f8 addeax, dword ptr [ebp - 8]
1f48:83 c4 08 addesp, 8
1f4b:5d popebp
1f4c:c3 ret
1f4d:0f 1f 00 nopdword ptr [eax]
1f50:55 pushebp
1f51:89 e5 movebp, esp
1f53:83 ec 28 subesp, 40
1f56:b8 01 00 00 00 moveax, 1
1f5b:b9 02 00 00 00 movecx, 2
1f60:c7 45 fc 00 00 00 00 movdword ptr [ebp - 4], 0
1f67:c7 04 24 01 00 00 00 movdword ptr [esp], 1
1f6e:c7 44 24 04 02 00 00 00 movdword ptr [esp + 4], 2
1f76:89 45 f8 movdword ptr [ebp - 8], eax
1f79:89 4d f4 movdword ptr [ebp - 12], ecx
1f7c:e8 af ff ff ff call-81 <_sum>
1f81:b9 03 00 00 00 movecx, 3
1f86:ba 04 00 00 00 movedx, 4
1f8b:c7 04 24 03 00 00 00 movdword ptr [esp], 3
1f92:c7 44 24 04 04 00 00 00 movdword ptr [esp + 4], 4
1f9a:89 45 f0 movdword ptr [ebp - 16], eax
1f9d:89 4d ec movdword ptr [ebp - 20], ecx
1fa0:89 55 e8 movdword ptr [ebp - 24], edx
1fa3:e8 88 ff ff ff call-120 <_sum>
1fa8:31 c9 xorecx, ecx
1faa:89 45 e4 movdword ptr [ebp - 28], eax
1fad:89 c8 moveax, ecx
1faf:83 c4 28 addesp, 40
1fb2:5d popebp
1fb3:c3 ret

_sum:
1f30:55 pushebp
1f31:89 e5 movebp, esp
1f33:83 ec 08 subesp, 8
1f36:8b 45 0c moveax, dword ptr [ebp + 12]
1f39:8b 4d 08 movecx, dword ptr [ebp + 8]
1f3c:89 4d fc movdword ptr [ebp - 4], ecx
1f3f:89 45 f8 movdword ptr [ebp - 8], eax
1f42:8b 45 fc moveax, dword ptr [ebp - 4]
1f45:03 45 f8 addeax, dword ptr [ebp - 8]
1f48:83 c4 08 addesp, 8
1f4b:5d popebp
1f4c:c3 ret
1f4d:0f 1f 00 nopdword ptr [eax]

_main:
1f50:55 pushebp
1f51:89 e5 movebp, esp
1f53:83 ec 28 subesp, 40
1f56:b8 01 00 00 00 moveax, 1
1f5b:b9 02 00 00 00 movecx, 2
1f60:c7 45 fc 00 00 00 00 movdword ptr [ebp - 4], 0
1f67:c7 04 24 01 00 00 00 movdword ptr [esp], 1
1f6e:c7 44 24 04 02 00 00 00 movdword ptr [esp + 4], 2
1f76:89 45 f8 movdword ptr [ebp - 8], eax
1f79:89 4d f4 movdword ptr [ebp - 12], ecx
1f7c:e8 af ff ff ff call-81 <_sum>
1f81:b9 03 00 00 00 movecx, 3
1f86:ba 04 00 00 00 movedx, 4
1f8b:c7 04 24 03 00 00 00 movdword ptr [esp], 3
1f92:c7 44 24 04 04 00 00 00 movdword ptr [esp + 4], 4
1f9a:89 45 f0 movdword ptr [ebp - 16], eax
1f9d:89 4d ec movdword ptr [ebp - 20], ecx
1fa0:89 55 e8 movdword ptr [ebp - 24], edx
1fa3:e8 88 ff ff ff call-120 <_sum>
1fa8:31 c9 xorecx, ecx
1faa:89 45 e4 movdword ptr [ebp - 28], eax
1fad:89 c8 moveax, ecx
1faf:83 c4 28 addesp, 40
1fb2:5d popebp
1fb3:c3 ret

lldb 反汇编

使用 lldb 反汇编:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
$ lldb hello1
(lldb) target create "hello1"
Current executable set to 'hello1' (i386).
(lldb) settings set target.x86-disassembly-flavor intel
(lldb) disassemble --name main
hello1`main:
hello1[0x1f50] <+0>: push ebp
hello1[0x1f51] <+1>: mov ebp, esp
hello1[0x1f53] <+3>: sub esp, 0x28
hello1[0x1f56] <+6>: mov eax, 0x1
hello1[0x1f5b] <+11>: mov ecx, 0x2
hello1[0x1f60] <+16>: mov dword ptr [ebp - 0x4], 0x0
hello1[0x1f67] <+23>: mov dword ptr [esp], 0x1
hello1[0x1f6e] <+30>: mov dword ptr [esp + 0x4], 0x2
hello1[0x1f76] <+38>: mov dword ptr [ebp - 0x8], eax
hello1[0x1f79] <+41>: mov dword ptr [ebp - 0xc], ecx
hello1[0x1f7c] <+44>: call 0x1f30 ; sum
hello1[0x1f81] <+49>: mov ecx, 0x3
hello1[0x1f86] <+54>: mov edx, 0x4
hello1[0x1f8b] <+59>: mov dword ptr [esp], 0x3
hello1[0x1f92] <+66>: mov dword ptr [esp + 0x4], 0x4
hello1[0x1f9a] <+74>: mov dword ptr [ebp - 0x10], eax
hello1[0x1f9d] <+77>: mov dword ptr [ebp - 0x14], ecx
hello1[0x1fa0] <+80>: mov dword ptr [ebp - 0x18], edx
hello1[0x1fa3] <+83>: call 0x1f30 ; sum
hello1[0x1fa8] <+88>: xor ecx, ecx
hello1[0x1faa] <+90>: mov dword ptr [ebp - 0x1c], eax
hello1[0x1fad] <+93>: mov eax, ecx
hello1[0x1faf] <+95>: add esp, 0x28
hello1[0x1fb2] <+98>: pop ebp
hello1[0x1fb3] <+99>: ret

(lldb) disassemble --name sum
hello1`sum:
hello1[0x1f30] <+0>: push ebp
hello1[0x1f31] <+1>: mov ebp, esp
hello1[0x1f33] <+3>: sub esp, 0x8
hello1[0x1f36] <+6>: mov eax, dword ptr [ebp + 0xc]
hello1[0x1f39] <+9>: mov ecx, dword ptr [ebp + 0x8]
hello1[0x1f3c] <+12>: mov dword ptr [ebp - 0x4], ecx
hello1[0x1f3f] <+15>: mov dword ptr [ebp - 0x8], eax
hello1[0x1f42] <+18>: mov eax, dword ptr [ebp - 0x4]
hello1[0x1f45] <+21>: add eax, dword ptr [ebp - 0x8]
hello1[0x1f48] <+24>: add esp, 0x8
hello1[0x1f4b] <+27>: pop ebp
hello1[0x1f4c] <+28>: ret
hello1[0x1f4d] <+29>: nop dword ptr [eax]

参考资料

  1. 链接、装载与库,俞甲子,2009:第10章 内存: 栈与堆,豆瓣
  2. IDA Pro权威指南,Eagle,第2版2011:6.2.1 调用约定,豆瓣
  3. 2001-09 Calling Conventions Demystified https://www.codeproject.com/Articles/1388/Calling-Conventions-Demystified
  4. Calling Conventions https://en.wikibooks.org/wiki/X86_Disassembly/Calling_Conventions
  5. https://en.wikipedia.org/wiki/X86_calling_conventions
]]>
+ + + <h1 id="栈与栈帧">栈与栈帧</h1> +<p>要想知道函数是怎么被调用的,需要了解栈帧和调用惯例相关知识。<a href="https://book.douban.com/subject/3652388/">俞甲子2009</a> 的“<strong>第10章 内存: 栈与堆</strong>”对相关概念有很好的介绍。本文是对相关知识的学习笔记。</p> + + + + + + + + + + + + + + + + +
+ + + Java 外部函数接口:JNI, JNA, JNR + + https://nullwy.me/2018/01/java-ffi/ + 2018-01-24T08:09:51.000Z + 2023-12-05T06:14:52.544Z + + 遇到的问题

前段时间开发的时候,遇到一个问题,就是如何用 Java 实现 chdir?网上搜索一番,发现了 JNR-POSIX 项目 [ stackoverflow ]。俗话说,好记性不如烂笔头。现在将涉及到的相关知识点总结成笔记。

其实针对 Java 实现 chdir 问题,官方 20 多年前就存在对应的 bug,即 JDK-4045688 'Add chdir or equivalent notion of changing working directory'。这个 bug 在 1997.04 创建,目前的状态是 Won't Fix(不予解决),理由大致是,若实现与操作系统一样的进程级别的 chdir,将影响 JVM 上的全部线程,这样引入了可变(mutable)的全局状态,这与 Java 的安全性优先原则冲突,现在添加全局可变的进程状态,已经太迟了,对不变性(immutability)的支持才是 Java 要实现的特性。

chdir 是平台相关的操作系统接口,POSIX 下对应的 APIint chdir(const char *path);,而 Windows 下对应的 APIBOOL WINAPI SetCurrentDirectory(_In_ LPCTSTR lpPathName);,另外 Windows 下也可以使用 MSVCRT 中 APIint _chdir(const char *dirname);(MSVCRT 下内部实现其实就是调用 SetCurrentDirectory [ reactos ] )。

Java 设计理念是跨平台,"write once, run anywhere"。很平台相关的 API,虽然各个平台都有自己的类似的实现,但存在会差异。除了多数常见功能,Java 并没有对全部操作系统接口提供完整支持,比如很多 POSIX API。除了 chdir,另外一个典型的例子是,在 Java 9 以前 JDK 获取进程 id 一直没有简洁的方法 [ stackoverflow ],最新发布的 Java 9 中的 JEP 102(Process API Updates)才增强了进程 API。获取进程 id 可以使用以下方式 [ javadoc ]:

1
long pid = ProcessHandle.current().pid();

相比其他语言,Pyhon 和 Ruby,对操作系统相关的接口都有更多的原生支持。Pyhon 和 Ruby 实现的相关 API 基本上都带有 POSIX 风格。比如上文提到,chdirgetpid,在 Pyhon 和 Ruby 下对应的 API 为:Pyhon 的 os 模块 os.chdir(path)os.getpid();Ruby 的 Dir 类的 Dir.chdir( [ string] ) 类方法和 Process 类的 Process.pid 类属性。Python 解释器的 chdir 对应源码为 posixmodule.c#L2611,Ruby 解释器的 chdir 对应源码为 dir.c#L848win32.c#L6741

JNI 实现 getpid

Java 下要想实现本地方法调用,需要通过 JNI。关于 JNI 的介绍,可以参阅“Java核心技术,卷II:高级特性,第9版2013”的“第12章 本地方法”,或者读当年 Sun 公司 JNI 设计者 Sheng Liang(梁胜)写的“Java Native Interface: Programmer's Guide and Specification”。本文只给出实现 getpid 的一个简单示例。

首先使用 Maven 创建一个简单的脚手架:

1
2
3
4
5
mvn archetype:generate     \
-DgroupId=com.test \
-DartifactId=jni-jnr \
-DpackageName=com.test \
-DinteractiveMode=false

com.test 包下添加 GetPidJni 类:

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.test;

public class GetPidJni {
public static native long getpid();

static {
System.loadLibrary("getpidjni");
}

public static void main(String[] args) {
System.out.println(getpid());
}
}

javac 编译代码 GetPidJNI.java,然后用 javah 生成 JNI 头文件:

1
2
3
$ mkdir -p target/classes
$ javac src/main/java/com/test/GetPidJni.java -d "target/classes"
$ javah -cp "target/classes" com.test.GetPidJni

生成的 JNI 头文件 com_test_GetPidJni.h,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_test_GetPidJni */

#ifndef _Included_com_test_GetPidJni
#define _Included_com_test_GetPidJni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_test_GetPidJni
* Method: getpid
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_com_test_GetPidJni_getpid
(JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

现在有了头文件声明,但还没有实现,手动敲入 com_test_GetPidJni.c

1
2
3
4
5
6
#include "com_test_GetPidJni.h"

JNIEXPORT jlong JNICALL
Java_com_test_GetPidJni_getpid (JNIEnv * env, jclass c) {
return getpid();
}

编译 com_test_GetPidJni.c,生成 libgetpidjni.dylib

1
$ gcc -I $JAVA_HOME/include -I $JAVA_HOME/include/darwin -dynamiclib -o libgetpidjni.dylib com_test_GetPidJni.c

生成的 libgetpidjni.dylib,就是 GetPidJni.java 代码中的 System.loadLibrary("getpidjni");,需要加载的 lib。

现在运行 GetPidJni 类,就能正确获取 pid:

1
$ java -Djava.library.path=`pwd` -cp "target/classes" com.test.GetPidJni

JNI 的问题是,胶水代码(黏合 Java 和 C 库的代码)需要程序员手动书写,对不熟悉 C/C++ 的同学是很大的挑战。

JNA 实现 getpid

JNA(Java Native Access, wiki, github, javadoc, mvn),提供了相对 JNI 更加简洁的调用本地方法的方式。除了 Java 代码外,不再需要额外的胶水代码。这个项目最早可以追溯到 Sun 公司 JNI 设计者 Sheng Liang 在 1999 年 JavaOne 上的分享。2006 年 11月,Todd Fast (也来自 Sun 公司) 首次将 JNA 发布到 dev.java.net 上。Todd Fast 在发布时提到,自己在这个项目上已经断断续续开发并完善了 6-7 年时间,项目刚刚在 JDK 5 上重构和重设计过,还可能有很多缺陷或缺点,希望其他人能浏览代码并参与进来。Timothy Wall 在 2007 年 2 月重启了这项目,引入了很多重要功能,添加了 Linux 和 OSX 支持(原本只在 Win32 上测试过),加强了 lib 的可用性(而非仅仅基本功能可用)[ ref ]。

看下示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import com.sun.jna.Library;
import com.sun.jna.Native;

public class GetPidJNA {

public interface LibC extends Library {
long getpid();
}

public static void main(String[] args) {
LibC libc = Native.loadLibrary("c", LibC.class);
System.out.println(libc.getpid());
}
}

JNR 实现 getpid

最初,JRuby 的核心开发者 Charles Nutter 在实现 Ruby 的 POSIX 集成时就使用了 JNA [ ref ]。但过了一段时候后,开始开发 JNR(Java Native Runtime, github, mvn) 替代 JNA。Charles Nutter 在介绍 JNR 的 slides 中阐述了原因:

1
2
3
4
5
Why Not JNA?
- Preprocessor constants?
- Standard API sets out of the box
- C callbacks?
- Performance?!?

即,(1) 预处理器的常量支持(通过 jnr-constants 解决);(2) 开箱即用的标准 API(作者实现了 jnr-posix, jnr-x86asm, jnr-enxio, jnr-unixsocket);(3) C 回调 callback 支持;(4) 性能(提升 8-10 倍)。

JNR 各个模块的层次结构

使用 JNR-FFI(github, mvn)实现 getpid,示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
import jnr.ffi.LibraryLoader;

public class GetPidJnr {

public interface LibC {
long getpid();
}

public static void main(String[] args) {
LibC libc = LibraryLoader.create(LibC.class).load("c");
System.out.println(libc.getpid());
}
}

使用 JNR-POSIX(github, mvn)实现 chdirgetpid,示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import jnr.posix.POSIX;
import jnr.posix.POSIXFactory;

public class GetPidJnrPosix {

private static POSIX posix = POSIXFactory.getPOSIX();

public static void main(String[] args) {
System.out.println(posix.getcwd());
posix.chdir("..");
System.out.println(posix.getcwd());
System.out.println(posix.getpid());
}
}

JMH 性能比较

性能测试代码为 BenchmarkFFI.javagithub),测试结果如下:

1
2
3
4
5
6
7
8
# JMH version: 1.19
# VM version: JDK 1.8.0_144, VM 25.144-b01

Benchmark Mode Cnt Score Error Units
BenchmarkFFI.testGetPidJna thrpt 10 8225.209 ± 206.829 ops/ms
BenchmarkFFI.testGetPidJnaDirect thrpt 10 10257.505 ± 736.135 ops/ms
BenchmarkFFI.testGetPidJni thrpt 10 77852.899 ± 3167.101 ops/ms
BenchmarkFFI.testGetPidJnr thrpt 10 58261.657 ± 5187.550 ops/ms

即:JNI > JNR > JNA (Direct Mapping) > JNA (Interface Mapping)。相对 JNI 的实现性能,其他三种方式,从大到小的性能百分比依次为:74.8% (JNR), 13.2% (JnaDirect), 10.6% (JNA)。在博主电脑上测试,JNR 相比 JNA 将近快了 6-7 倍(JNR 作者 Charles Nutter 针对 getpid 的测试结果是 JNR 比 JNA 快 8-10 倍 [ twitter slides ])。

实现原理

JNA 源码简析

先来看下 JNA,JNA 官方文档 FunctionalDescription.md,对其实现原理有很好的阐述。这里将从源码角度分析实现的核心逻辑。

回顾下代码,我们现实定义了接口 LibC,然后通过 Native.loadLibrary("c", LibC.class) 获取了接口实现。这一步是怎么做到的呢?翻下源码 Native.java#L547 就知道,其实是通过**动态代理(dynamic proxy)**实现的。使用动态代理需要实现 InvocationHandler 接口,这个接口的实现在 JNA 源码中是类 com.sun.jna.Library.Handler。示例中的 LibC 接口定义的全部方法,将全部分派到 Handler 的 invoke 方法下。

1
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;

然后根据返回参数的不同,分派到 Native 类的,invokeXxx 本地方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* Call the native function.
*
* @param function Present to prevent the GC to collect the Function object
* prematurely
* @param fp function pointer
* @param callFlags calling convention to be used
* @param args Arguments to pass to the native function
*
* @return The value returned by the target native function
*/
static native int invokeInt(Function function, long fp, int callFlags, Object[] args);

static native long invokeLong(Function function, long fp, int callFlags, Object[] args);

static native Object invokeObject(Function function, long fp, int callFlags, Object[] args);
...

比如,long getpid() 会被分派到 invokeLong,而 int chmod(String filename, int mode) 会被分派到 invokeInt。invokeXxx 本地方法参数:

  • 参数 Function function,记录了 lib 信息、函数名称、函数指针地址、调用惯例等元信息;
  • 参数 long fp,即函数指针地址,函数指针地址通过 Native#findSymbol()获得(底层是 Linux API dlsym 或 Windows API GetProcAddress )。
  • 参数 int callFlags,即调用约定,对应 cdecl 或 stdcall。
  • 参数 int callFlags,即函数入参,若无参数,args 大小为 0,若有多个参数,原本的入参被从左到右依次保存到 args 数组中。

再来看下 invokeXxx 本地方法的实现 dispatch.c#L2122invokeIntinvokeLong 实现源码类似):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
* Class: com_sun_jna_Native
* Method: invokeInt
* Signature: (Lcom/sun/jna/Function;JI[Ljava/lang/Object;)I
*/
JNIEXPORT jint JNICALL
Java_com_sun_jna_Native_invokeInt(JNIEnv *env, jclass UNUSED(cls),
jobject UNUSED(function), jlong fp, jint callconv,
jobjectArray arr)
{
ffi_arg result;
dispatch(env, L2A(fp), callconv, arr, &ffi_type_sint32, &result);
return (jint)result;
}

即,全部 invokeXxx 本地方法统一被分派到 dispatch 函数 dispatch.c#L439

1
2
3
static void
dispatch(JNIEnv *env, void* func, jint flags, jobjectArray args,
ffi_type *return_type, void *presult)

这个 dispatch 函数是全部逻辑的核心,实现最终的本地函数调用。

我们知道,发起函数调用,需要构造一个栈帧stack frame)。构造栈帧,涉及到参数压栈次序(参数从左到右压入还是从右到左压入)和清理栈帧(调用者清理还是被调用者清理)等实现细节问题。不同的编译器在不同的 CPU 架构下有不同的选择。构造栈帧的具体实现细节的选择,被称为调用惯例calling convention)。按照调用惯例构造整个栈帧,这个过程由编译器在编译阶段完成的。比如要想发起 sum(2, 3) 这个函数调用,编译器可能会生成如下等价汇编代码:

1
2
3
4
5
; 调用者清理堆栈(caller clean-up),参数从右到左压入栈
push 3
push 2
call _sum ; 将返回地址压入栈, 同时 sum 的地址装入 eip
add esp, 8 ; 清理堆栈, 两个参数占用 8 字节

dispatch 函数是,需要调用的函数指针地址、输入参数和返回参数,全部是运行时确定。要想完成这个函数调用逻辑,就要运行时构造栈帧,生成参数压栈和清理堆栈的工作。JNA 3.0 之前,实现运行时构造栈帧的逻辑的对应代码 dispatch_i386.cdispatch_ppc.cdispatch_sparc.s,分别实现 Intel x86、PowerPC 和 Sparc 三种 CPU 架构。

运行时函数调用,这个问题其实是一个一般性的通用问题。早在 1996 年 10 月,Cygnus Solutions 的工程师 Anthony Green 等人就开发了 libffi(home, wiki, github, doc),解决的正是这个问题。目前,libffi 几乎支持全部常见的 CPU 架构。于是,从 JNA 3.0 开始,摒弃了原先手动构造栈帧的做法,把 libffi 集成进了 JNA。

直接映射(Direct Mapping)
https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#RegisterNatives
http://www.chiark.greenend.org.uk/doc/libffi-dev/html/The-Closure-API.html

JNR 源码简析

JNR 底层同样也是依赖 libffi,参见 jffi。但 JNR 相比 JNA 性能更好,做了很有优化。比较重要的点是,JNA 使用动态代理生成实现类,而 JNR 使用 ASM 字节码操作库生成直接实现类,去除了每次调用本地方法时额外的动态代理的逻辑。使用 ASM 生成实现类,对应的代码为 AsmLibraryLoader.java。其他细节,限于文档不全,本人精力有限,不再展开。

Java 9 的 getpid 实现

Java 9 以前 JDK 获取进程 id 没有简洁的方法,最新发布的 Java 9 中的 JEP 102(Process API Updates)增强了进程 API。进程 id 可以使用以下方式 [ javadoc ]

1
long pid = ProcessHandle.current().pid();

翻阅实现源码,可以看到对应的实现就是 JNI 调用:

jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl [ src ]

1
2
3
4
5
6
/**
* Return the pid of the current process.
*
* @return the pid of the current process
*/
private static native long getCurrentPid0();

*nix 平台下实现为:

jdk/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c [ src ]

1
2
3
4
5
6
7
8
9
10
/*
* Class: java_lang_ProcessHandleImpl
* Method: getCurrentPid0
* Signature: ()J
*/
JNIEXPORT jlong JNICALL
Java_java_lang_ProcessHandleImpl_getCurrentPid0(JNIEnv *env, jclass clazz) {
pid_t pid = getpid();
return (jlong) pid;
}

Windows 平台下实现为:

jdk/src/java.base/windows/native/libjava/ProcessHandleImpl_win.c [ src ]

1
2
3
4
5
6
7
8
9
10
11
12
/*
* Returns the pid of the caller.
*
* Class: java_lang_ProcessHandleImpl
* Method: getCurrentPid0
* Signature: ()J
*/
JNIEXPORT jlong JNICALL
Java_java_lang_ProcessHandleImpl_getCurrentPid0(JNIEnv *env, jclass clazz) {
DWORD pid = GetCurrentProcessId();
return (jlong)pid;
}

参考资料

  1. Changing the current working directory in Java? https://stackoverflow.com/q/840190
  2. How can a Java program get its own process ID? http://stackoverflow.com/q/35842
  3. Java核心技术,卷II:高级特性,第9版2013:第12章 本地方法,豆瓣
  4. Java Native Interface: Programmer's Guide and Specification, Sheng Liang (wikilinkedinmsa), 1999,豆瓣:作者梁胜,中国科技大学少年班83级,并拥有耶鲁大学计算机博士学位(1990-1996),目前 Rancher Labs 创始人兼 CEO [ ref ]
  5. 2013-07 Charles Nutter: Java Native Runtime http://www.oracle.com/technetwork/java/jvmls2013nutter-2013526.pdf
  6. JEP 191: Foreign Function Interface http://openjdk.java.net/jeps/191 作者是Charles Nutter
  7. 2014-03 Java 外部函数接口 http://www.infoq.com/cn/news/2014/03/java-foreign-function-interface
  8. 2005-08 Brian Goetz:用动态代理进行修饰 https://www.ibm.com/developerworks/cn/java/j-jtp08305.html
]]>
+ + + <h1 id="遇到的问题">遇到的问题</h1> +<p>前段时间开发的时候,遇到一个问题,就是如何用 Java 实现 <code>chdir</code>?网上搜索一番,发现了 <code>JNR-POSIX</code> 项目 [ <a href="https://stackoverflow.com/q/840190">stackoverflow</a> ]。俗话说,好记性不如烂笔头。现在将涉及到的相关知识点总结成笔记。</p> + + + + + + + + + + + + + + + + + + + + +
+ + + ZooKeeper 学习笔记 + + https://nullwy.me/2017/11/zookeeper-note/ + 2017-11-23T07:52:51.000Z + 2023-12-05T06:16:40.082Z + + ZooKeeper 介绍

ZooKeeper(wikihomegithub) 是用于分布式应用的开源的分布式协调服务。通过暴露简单的原语,分布式应用能在之上构建更高层的服务,如同步、配置管理和组成员管理等。在设计上易于编程开发,并且数据模型使用了熟知的文件系统目录树结构 [ doc ]。

共识与 Paxos

在介绍 ZooKeeper 之前,有必要了解下 Paxos 和 Chubby。2006 年 Google 在 OSDI 发表关于 BigtableChubby 的两篇会议论文,之后再在 2007 年 PODC 会议上发表了论文“Paxos Made Live”,介绍 Chubby 底层实现的共识(consensus)协议 Multi-Paxos,该协议对 Lamport 的原始 Paxos 算法做了改进,提高了运行效率 [ ref ]。Chubby 作为锁服务被 Google 应用在 GFS 和 Bigtable 中。受 Chubby 的影响,来自 Yahoo 研究院的 Benjamin Reed 和 Flavio Junqueira 等人开发了被业界称为开源版的 Chubby 的 ZooKeeper(内部实现事实上稍有不同 [ ref ]),底层的共识协议为 ZAB。Lamport 的 Paxos 算法出了名的难懂,如何让算法更加可理解(understandable),便成了 Stanford 博士生 Diego Ongaro 的研究课题。Diego Ongaro 在 2014 年发表了介绍 Raft 算法的论文,“In search of an understandable consensus algorithm”。Raft 是可理解版的 Paxos,很快就成为解决共识问题的流行协议之一。这些类 Paxos 协议和 Paxos 系统之间的关系,如下 [ Ailijiang2016 ]:

Paxos 协议和 Paxos 系统

Google 的 Chubby 没有开源,在云计算和大数据技术的风口下,Yahoo 开源的 ZooKeeper 便在工业界流行起来。ZooKeeper 重要的时间线如下:

  • 2007 年 11 月 ZooKeeper 1.0 在 SourceForge 上发布 [ ref ]
  • 2008 年 6 月开始从 SourceForge 迁移到 Apache [ ref ],在 10 月 Zookeeper 3.0 发布,并成为 Hadoop 的子项目 [ ref1 ref2 ]

关于 ZooKeeper 名字的来源,Flavio Junqueira 和 Benjamin Reed 在介绍 ZooKeeper 的书中有如下阐述:

ZooKeeper 由雅虎研究院开发。我们小组在进行 ZooKeeper 的开发一段时间之后,开始推荐给其他小组,因此我们需要为我们的项目起一个名字。与此同时,小组也一同致力于 Hadoop 项目,参与了很多动物命名的项目,其中有广为人知的 Apache Pig 项目(http://pig.apache.org)。我们在讨论各种各样的名字时,一位团队成员提到我们不能再使用动物的名字了,因为我们的主管觉得这样下去会觉得我们生活在动物园中。大家对此产生了共鸣,分布式系统就像一个动物园,混乱且难以管理,而 ZooKeeper 就是将这一切变得可控。

体系结构

ZooKeeper 服务由若干台服务器构成,其中的一台通过 ZAB 原子广播协议选举作为主控服务器(leader),其他的作为从属服务器(follower)。客户端可以通过 TCP 协议连接任意一台服务器。如果客户端是读操作请求,则任意一个服务器都可以直接响应请求;如果是更新数据操作(写数据或者更新数据)。则只能由主控服务器来协调更新操作;如果客户端连接的是从属服务器,则从属服务器会将更新据请求转发到主控服务器,由其完成更新操作。主控服务器将所有更新操作序列化,利用 ZAB 协议将数据更新请求通知所有从属服务器,ZAB 保证更新操作。

zookeeper-service

读和写操作,如下图所示 [ Haloi2015 ]:
ZooKeeper 读和写操作

ZooKeeper 的任意一台服务器都可以响应客户端的读操作,这样可以提高吞吐量。Chubby 在这点上与 ZooKeeper 不同,所有读/写操作都由主控服务器完成,从属服务器只是为了提高整个协调系统的可用性,即主控服务器发生故障后能够在从属服务器中快速选举出新的主控服务器。在带来高吞吐量优势的同时,ZooKeeper 这样做也带来潜在的问题:客户端可能会读到过期数据,因为即使主控服务器已经更新了某个内存数据,但是 ZAB 协议还未能将其广播到从属服务器。为了解决这一问题,在 ZooKeeper 的接口 API 函数中提供了 sync 操作,应用可以根据需要在读数据前调用该操作,其含义是:接收到 sync 命令的从属服务器从主控服务器同步状态信息,保证两者完全一致。这样如果在读操作前调用 sync 操作,则可以保证客户端一定可以读取到最新状态的数据。

数据模型

ZooKeeper 所提供的命名空间跟标准文件系统很相似。路径中一系列元素是用斜杠(/)分隔的。每个节点在 ZooKeper 命名空间中是用路径来识别的。在 ZooKeeper 术语下,节点被称为 znode。默认每个 znode 最大只能存储 1M 数据(可以通过配置参数修改),这与 Chubby 一样是出于避免应用将协调系统当作存储系统来用。znode 只能使用绝对路径,相对路径不能被 ZooKeeper 识别。znode 命名可以是任意 Unicode 字符。唯一的例外是,名称"/zookeeper"。命名为"/zookeeper"的 znode,由 ZooKeeper 系统自动生成,用配额(quota)管理。

ZooKeeper 数据模型

ZooKeeper 使用

安装与配置

ZooKeeper 安装与启动:

1
2
3
4
5
6
7
8
9
10
11
12
$ brew info zookeeper
zookeeper: stable 3.4.10 (bottled), HEAD
Centralized server for distributed coordination of services
https://zookeeper.apache.org/
... 省略
$ brew install zookeeper
$ zkServer start # 启动
$ zkServer stop # 终止
$ zkServer help
ZooKeeper JMX enabled by default
Using config: /usr/local/etc/zookeeper/zoo.cfg
Usage: ./zkServer.sh {start|start-foreground|stop|restart|status|upgrade|print-cmd}

若不修改配置文件,默认是单机模式启动。若要使用集群模式,需要修改 /usr/local/etc/zookeeper/zoo.cfg(默认路径)。示例 zoo.cfg [ doc ]:

1
2
3
4
5
6
7
8
tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181
initLimit=5
syncLimit=2
server.1=192.168.211.11:2888:3888
server.2=192.168.211.12:2888:3888
server.3=192.168.211.13:2888:3888

clientPort:客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。
server.X=YYY:A:B

  • X:表示的服务器编号;
  • YYY:表示服务器的ip地址;
  • A:表示服务器节点间的通信端口,用于 follower 和 leader 节点的通信;
  • B:表示选举端口,表示选举新 leader 时服务器间相互通信的端口,当 leader 挂掉时,其余服务器会相互通信,选择出新的 leader。

若想在单台主机上试验集群模式,可以将 YYY 都修改为 localhost,并且让两个端口 A:B 也相互不同(比如:2888:3888, 2889:3889, 2890:3890),即可实现伪集群模式。示例 zoo.cfg 如下 [ doc ]:

1
2
3
server.1=localhost:2888:3888
server.2=localhost:2889:3889
server.3=localhost:2890:3890

zkCli 支持的全部命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ zkCli help
ZooKeeper -server host:port cmd args
stat path [watch]
set path data [version]
ls path [watch]
delquota [-n|-b] path
ls2 path [watch]
setAcl path acl
setquota -n|-b val path
history
redo cmdno
printwatches on|off
delete path [version]
sync path
listquota path
rmr path
get path [watch]
create [-s] [-e] path data acl
addauth scheme auth
quit
getAcl path
close
connect host:port

节点类型及其操作

Zookeeper 支持两种类型节点:持久节点(persistent znode)和临时节点(ephemeral znode)。持久节点不论客户端会话情况,一直存在,只有当客户端显式调用删除操作才会消失。而临时节点则不同,会在客户端会话结束或者发生故障的时候被 ZooKeeper 系统自动清除。另外,这两种类型的节点都可以添加是否是顺序(sequential)的特性,这样就有了:持久顺序节点和临时顺序节点。

(1) 持久节点(persistent znode)

使用 create 创建节点(默认持久节点),以及使用 get 查看该节点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ zkCli -server 127.0.0.1  # 启动客户端
[zk: localhost:2181(CONNECTED) 1] create /zoo 'hello zookeeper'
Created /zoo
[zk: localhost:2181(CONNECTED) 2] get /zoo
hello zookeeper
cZxid = 0x8d
ctime = Thu Nov 08 20:42:55 CST 2017
mZxid = 0x8d
mtime = Thu Nov 08 20:42:55 CST 2017
pZxid = 0x8d
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 15
numChildren = 0

create 创建子节点,以及使用 ls 查看全部子节点:

1
2
3
4
5
6
7
8
[zk: localhost:2181(CONNECTED) 3] create /zoo/duck ''
Created /zoo/duck
[zk: localhost:2181(CONNECTED) 4] create /zoo/goat ''
Created /zoo/goat
[zk: localhost:2181(CONNECTED) 5] create /zoo/cow ''
Created /zoo/cow
[zk: localhost:2181(CONNECTED) 6] ls /zoo
[cow, goat, duck]

delete 删除节点,以及使用 rmr 递归删除:

1
2
3
4
5
6
7
8
[zk: localhost:2181(CONNECTED) 7] delete /zoo/duck
[zk: localhost:2181(CONNECTED) 8] ls /zoo
[cow, goat]
[zk: localhost:2181(CONNECTED) 9] delete /zoo
Node not empty: /zoo
[zk: localhost:2181(CONNECTED) 10] rmr /zoo
[zk: localhost:2181(CONNECTED) 11] ls /zoo
Node does not exist: /zoo

(2) 临时节点(ephemeral znode)

和持久节点不同,临时节点不能创建子节点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ zkCli  # 启动第1个客户端
[zk: localhost:2181(CONNECTED) 0] create -e /node 'hello'
Created /node
[zk: localhost:2181(CONNECTED) 40] get /node
hello
cZxid = 0x97
ctime = Thu Nov 08 21:01:25 CST 2017
mZxid = 0x97
mtime = Thu Nov 08 21:01:25 CST 2017
pZxid = 0x97
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x161092a0ff30000
dataLength = 5
numChildren = 0
[zk: localhost:2181(CONNECTED) 1] create /node/child ''
Ephemerals cannot have children: /node/child

临时节点在客户端会话结束或者发生故障的时候被 ZooKeeper 系统自动清除。现在试验下的针对临时节点自动清除的监视:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ zkCli  # 启动第2个客户端
[zk: localhost:2181(CONNECTED) 0] create -e /node 'hello'
Node already exists: /node
[zk: localhost:2181(CONNECTED) 1] stat /node true
cZxid = 0x97
ctime = Thu Nov 08 21:01:25 CST 2017
mZxid = 0x97
mtime = Thu Nov 08 21:01:25 CST 2017
pZxid = 0x97
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x161092a0ff30000
dataLength = 5
numChildren = 0

若客户端1,退出 quit 或崩溃,客户端2将收到监视事件:

1
2
3
4
[zk: localhost:2181(CONNECTED) 2]
WATCHER::

WatchedEvent state:SyncConnected type:NodeDeleted path:/node

(3) 顺序节点(sequential znode)

顺序节点在其创建时 ZooKeeper 会自动在 znode 名称上附加上顺序编号。顺序编号,由父 znode 维护,并且单调递增。顺序编号,由 4 字节的有符号整数组成,并被格式化为 0 填充的 10 位数字。

1
2
3
4
5
6
7
8
9
10
[zk: localhost:2181(CONNECTED) 1] create /test ''
Created /test
[zk: localhost:2181(CONNECTED) 2] create -s /test/seq ''
Created /test/seq0000000000
[zk: localhost:2181(CONNECTED) 3] create -s /test/seq ''
Created /test/seq0000000001
[zk: localhost:2181(CONNECTED) 4] create -s /test/seq ''
Created /test/seq0000000002
[zk: localhost:2181(CONNECTED) 5] ls /test
[seq0000000000, seq0000000001, seq0000000002]

客户端 API

ZooKeeper 提供的主要 znode 操作 API 如下表所示:

API 操作描述CLI 命令
create创建 znodecreate
delete删除 znodedelete/rmr/delquota
exists检查 znode 是否存在stat
getChildren读取 znode 全部的子节点ls/ls2
getData读取 znode 数据get/listquota
setData设置 znode 数据set/setquota
getACL读取 znode 的 ACLgetACL
setACL设置 znode 的 ACLsetACL
sync同步sync

Java 的 ZooKeeper 类实现了上述提供的 API。

Zookeeper 底层是 Java 实现,zkCli 命令行工具底层也是 Java 实现,对应的 Java 实现类为 org.apache.zookeeper.ZooKeeperMain [ src1 src2 ]。ZooKeeper 3.5.x 下,CLI 命令与底层实现 API 对应关系:

命名 CLIJava API (ZooKeeper 类)
addauth scheme authpublic void addAuthInfo(String scheme, byte[] auth)
closepublic void close()
create [-s] [-e] path data aclpublic String create(final String path, byte data[], List acl, CreateMode createMode)
delete path [version]public void delete(String path, int version)
delquota [-n|-b] pathpublic void delete(String path, int version)
get path [watch]public byte[] getData(String path, boolean watch, Stat stat)
getAcl pathpublic List getACL(final String path, Stat stat)
listquota pathpublic byte[] getData(String path, boolean watch, Stat stat)
ls path [watch]public List getChildren(String path, Watcher watcher, Stat stat)
ls2 path [watch]-
quitpublic void close()
rmr pathpublic void delete(final String path, int version)
set path data [version]public Stat setData(String path, byte[] data, int version)
setAcl path aclpublic Stat setACL(final String path, List acl, int aclVersion)
setquota -n|-b val pathpublic Stat setData(String path, byte[] data, int version)
stat path [watch]public Stat exists(String path, boolean watch)
sync pathpublic void sync(String path, AsyncCallback.VoidCallback cb, Object ctx)

监视点(watch)

ZooKeeper 提供了处理变化的重要机制一一监视点(watch)。通过监视点,客户端可以对指定的 znode 节点注册一个通知请求,在发生变化时就会收到一个单次的通知。当应用程序注册了一个监视点来接收通知,匹配该监视点条件的第一个事件会触发监视点的通知,并且最多只触发一次。例如,当 znode 节点也被删除,客户端需要知道该变化,客户端在 /z 节点执行 exists 操作并设置监视点标志位,等待通知,客户端会以回调函数的形式收到通知。

ZooKeeper 的 API 中的读操作:getData、getChildren 和 exists,均可以选择在读取的 znode 节点上设置监视点。使用监视点机制,我们需要实现 Watcher 接口类,该接口唯一方法为 process:

1
void process(WatchedEvent event)

WatchedEvent 数据结构包括以下信息:

  • ZooKeeper会话状态(KeeperState):Disconnected、SyncConnected、AuthFailed、ConnectedReadOnly 、SaslAuthenticated、Expired。
  • 事件类型(EventType):NodeCreated 、NodeDeleted 、NodeDataChanged、NodeChildrenChanged 和 None 。
  • 若事件类型不是 None,还包括 znode 路径。

若收到 WatchedEvent, 在 zkCli 中会输出类似如下结果:

1
WatchedEvent state:SyncConnected type:NodeDeleted path:/node

监视点有两种类型:数据监视点和子节点监视点。创建、删除或设置一个 znode 节点的数据都会触发数据监视点,exists 和 getData 这两个操作可以设置数据监视点。只有 getChildren 操作可以设置子节点监视点,这种监视点只有在 znode 子节点创建或删除时才被触发。对于每种事件类型,我们通过以下调用设置监视点:

NodeCreated
   通过 exists 调用设置一个监视点。
NodeDeleted
   通过 exists 或 getData 调用设置监视点。
NodeDataChanged
   通过 exists 或getData 调用设置监视点。
NodeChildrenChanged
   通过 getChildren 调用设置监视点。

Java 示例代码

在 Java 下使用 ZooKeeper 需要先添加如下 maven 依赖:

1
2
3
4
5
6
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.11</version>
<type>pom</type>
</dependency>

ZookeeperDemo 示例,展示了建立连接会话,以及对 znode 的创建、读取、修改、删除和设置监视点等操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import java.io.IOException;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;

public class ZookeeperDemo {

public static void main(String[] args) throws KeeperException, InterruptedException, IOException {
// 创建服务器连接
ZooKeeper zk = new ZooKeeper("127.0.0.1:2181", 100, new Watcher() {
// 监控所有被触发的事件
public void process(WatchedEvent event) {
System.out.printf("WatchedEvent state:%s type:%s path:%s\n", event.getState(), event.getType(), event.getPath());
}
});

// 创建节点
zk.create("/zoo", "hello ZooKeeper".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
// 读取节点数据
Stat stat = new Stat();
System.out.println(new String(zk.getData("/zoo", false, stat)));
printStat(stat);

// 创建子节点
zk.create("/zoo/duck", "hello duck".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zk.create("/zoo/goat", "hello goat".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zk.create("/zoo/cow", "hello cow".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

// 读取子节点列表,并设置监视点
System.out.println(zk.getChildren("/zoo", true));

// 读取子节点数据,并设置监视点
System.out.println(new String(zk.getData("/zoo/duck", true, null)));

// 修改子节点数据
zk.setData("/zoo/duck", "hi duck".getBytes(), -1);
// 读取修改后的子节点数据
System.out.println(new String(zk.getData("/zoo/duck", true, null)));

// 删除子节点
zk.delete("/zoo/duck", -1);
zk.delete("/zoo/goat", -1);
zk.delete("/zoo/cow", -1);
// 删除父节点
zk.delete("/zoo", -1);

// 关闭连接
zk.close();
}

private static void printStat(Stat stat) {
System.out.println("cZxid = 0x" + Long.toHexString(stat.getCzxid()));
System.out.println("ctime = " + DateFormatUtils.format(stat.getCtime(), "yyyy-MM-dd HH:mm:ss"));
System.out.println("mZxid = 0x" + Long.toHexString(stat.getMzxid()));
System.out.println("mtime = " + DateFormatUtils.format(stat.getMtime(), "yyyy-MM-dd HH:mm:ss"));
System.out.println("pZxid = 0x" + Long.toHexString(stat.getPzxid()));
System.out.println("cversion = " + stat.getCversion());
System.out.println("dataVersion = " + stat.getVersion());
System.out.println("aclVersion = " + stat.getAversion());
System.out.println("ephemeralOwner = 0x" + Long.toHexString(stat.getEphemeralOwner()));
System.out.println("dataLength = " + stat.getDataLength());
System.out.println("numChildren = " + stat.getNumChildren());
}
}

输出结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
WatchedEvent state:SyncConnected type:None path:null
hello ZooKeeper
cZxid = 0x1e1
ctime = 2017-11-20 12:18:36
mZxid = 0x1e1
mtime = 2017-11-20 12:18:36
pZxid = 0x1e1
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 15
numChildren = 0
[cow, goat, duck]
hello duck
WatchedEvent state:SyncConnected type:NodeDataChanged path:/zoo/duck
hi duck
WatchedEvent state:SyncConnected type:NodeDeleted path:/zoo/duck
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/zoo

ZooInspector

ZooInspector 是 ZooKeeper 3.3.0 开始官方提供的可视化查看和编辑 ZooKeeper 实例的工具 [ ZOOKEEPER-678 ]。源码位于目录 src/contrib/zooinspector 下,GitHub 地址为:link。可以根据 README.txt 的说明运行使用。或者可以直接用 ZOOKEEPER-678 下提供的可执行 jar 包。

ZooInspector

参考资料

  1. 官方文档:ZooKeeper http://zookeeper.apache.org/doc/current/index.html
  2. 2010-11 许令波:分布式服务框架 Zookeeper https://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/
  3. ZooKeeper:分布式过程协同技术详解,Benjamin Reed & Flavio Junqueira,2013,豆瓣
  4. Apache ZooKeeper Essentials, Haloi 2015,豆瓣
  5. 从Paxos到Zookeeper,阿里倪超 2015,豆瓣
  6. 大数据日知录:架构与算法,张俊林 2014,第5章 分布式协调系统,豆瓣
  7. 2010,Patrick Hunt, Mahadev Konar, Flavio Paiva Junqueira, Benjamin Reed: ZooKeeper: Wait-free Coordination for Internet-scale Systems. USENIX ATC 2010,dblpmsausenix
]]>
+ + + <h1 id="ZooKeeper-介绍">ZooKeeper 介绍</h1> +<p>ZooKeeper(<a href="https://en.wikipedia.org/wiki/Apache_ZooKeeper">wiki</a>,<a href="http://zookeeper.apache.org/">home</a>,<a href="https://github.com/apache/zookeeper">github</a>) 是用于分布式应用的开源的分布式协调服务。通过暴露简单的原语,分布式应用能在之上构建更高层的服务,如同步、配置管理和组成员管理等。在设计上易于编程开发,并且数据模型使用了熟知的文件系统目录树结构 [ <a href="http://zookeeper.apache.org/doc/current/zookeeperOver.html">doc</a> ]。</p> + + + + + + + + + + + + + + + + +
+ + + Java 运行时获取方法参数名 + + https://nullwy.me/2017/05/java-method-parameter/ + 2017-05-02T07:09:51.000Z + 2023-12-05T06:14:57.880Z + + 本文整理 Java 运行时获取方法参数名的两种方法,Java 8 的最新的方法和 Java 8 之前的方法。

Java 8 的新特性

翻阅 Java 8 的新特性,可以看到有这么一条“JEP 118: Access to Parameter Names at Runtime”。这个特性就是为了能运行时获取参数名新加的。这个 JEP 只是功能增强的提案,并没有最终实现的 JDK 相关的 API 的介绍。查看“Enhancements to the Reflection API” 会看到如下介绍:

Enhancements in Java SE 8
Method Parameter Reflection: You can obtain the names of the formal parameters of any method or constructor with the method java.lang.reflect.Executable.getParameters. However, .class files do not store formal parameter names by default. To store formal parameter names in a particular .class file, and thus enable the Reflection API to retrieve formal parameter names, compile the source file with the -parameters option of the javac compiler.

javac 文档中关于 -parameters 的介绍如下 [ doc man ]:

-parameters
Stores formal parameter names of constructors and methods in the generated class file so that the method java.lang.reflect.Executable.getParameters from the Reflection API can retrieve them.

现在试验下这个特性。有如下两个文件:

1
2
3
4
5
6
7
package com.test;

public class TestClass {
public int sum(int num1, int num2) {
return num1 + num2;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.test;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

public class Java8Main {
public static void main(String[] args) throws NoSuchMethodException {
Method method = TestClass.class.getDeclaredMethod("sum", int.class, int.class);
Parameter[] parameters = method.getParameters();
for (Parameter parameter : parameters) {
System.out.println(parameter.getType().getName() + " " + parameter.getName());
}
}
}

先试试 javac 不加 -parameters 编译,结果如下:

1
2
3
4
$ javac -d "target/classes" src/main/java/com/test/*.java
$ java -cp "target/classes" com.test.Java8Main
int arg0
int arg1

加上 -parameters 后,运行结果如下:

1
2
3
4
$ javac -d "target/classes" -parameters src/main/java/com/test/*.java
$ java -cp "target/classes" com.test.Java8Main
int num1
int num2

可以看到,加上 -parameters 后,正确获得了参数名。实际开发中,很少直接用命令行编译 Java 代码,项目一般都会用 maven 管理。在 maven 下,只需修改 pom 文件的 maven-compiler-plugin 插件配置即可,就是加上了 compilerArgs 节点 [ doc ],如下:

1
2
3
4
5
6
7
8
9
10
11
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>

实现原理

“Enhancements in Java SE 8”提到,参数名信息回存储在 class 文件中。现在试试用 javap doc man)命令反编译生成的 class 文件。反编译 class 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
$ javap -v -cp "target/classes" com.test.TestClass
Classfile /Users/yulewei/IdeaProjects/hellojava/target/classes/com/test/TestClass.class
Last modified 2017-5-2; size 305 bytes
MD5 checksum 24b99fec7f3062f5de1c3ca4270a1d36
Compiled from "TestClass.java"
public class com.test.TestClass
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #3.#15 // java/lang/Object."<init>":()V
#2 = Class #16 // com/test/TestClass
#3 = Class #17 // java/lang/Object
#4 = Utf8 <init>
#5 = Utf8 ()V
#6 = Utf8 Code
#7 = Utf8 LineNumberTable
#8 = Utf8 sum
#9 = Utf8 (II)I
#10 = Utf8 MethodParameters
#11 = Utf8 num1
#12 = Utf8 num2
#13 = Utf8 SourceFile
#14 = Utf8 TestClass.java
#15 = NameAndType #4:#5 // "<init>":()V
#16 = Utf8 com/test/TestClass
#17 = Utf8 java/lang/Object
{
public com.test.TestClass();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 3: 0

public int sum(int, int);
descriptor: (II)I
flags: ACC_PUBLIC
Code:
stack=2, locals=3, args_size=3
0: iload_1
1: iload_2
2: iadd
3: ireturn
LineNumberTable:
line 6: 0
MethodParameters:
Name Flags
num1
num2
}
SourceFile: "TestClass.java"

在结尾的 MethodParameters 属性就是,实现运行时获取方法参数的核心。这个属性是 Java 8 的 class 文件新加的,具体介绍可以参考官方“Java 虚拟机官方”文档的介绍,“4.7.24. The MethodParameters Attribute”,doc

class 文件中的调试信息

上文介绍了 Java 8 通过新增的反射 API 运行时获取方法参数名。那么在 Java 8 之前,有没有办法呢?或者在编译时没有开启 -parameters 参数,又如何动态获取方法参数名呢?其实 class 文件中保存的调试信息就可以包含方法参数名。

javac-g 选项可以在 class 文件中生成调试信息,官方文档介绍如下 [ doc man ]:

-g
Generates all debugging information, including local variables. By default, only line number and source file information is generated.
-g:none
Does not generate any debugging information.
-g:[keyword list]
Generates only some kinds of debugging information, specified by a comma separated list of keywords. Valid keywords are:
   source
     Source file debugging information.
   lines
     Line number debugging information.
   vars
     Local variable debugging information.

可以看到默认是包含源代码信息和行号信息的。现在试验下不生成调试信息的情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
$ javac -d "target/classes" src/main/java/com/test/*.java -g:none
$ javap -v -cp "target/classes" com.test.TestClass
Classfile /Users/yulewei/IdeaProjects/hellojava/target/classes/com/test/TestClass.class
Last modified 2017-5-2; size 177 bytes
MD5 checksum 559f5448154e4d7dd089f8155d8d0f55
public class com.test.TestClass
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #3.#9 // java/lang/Object."<init>":()V
#2 = Class #10 // com/test/TestClass
#3 = Class #11 // java/lang/Object
#4 = Utf8 <init>
#5 = Utf8 ()V
#6 = Utf8 Code
#7 = Utf8 sum
#8 = Utf8 (II)I
#9 = NameAndType #4:#5 // "<init>":()V
#10 = Utf8 com/test/TestClass
#11 = Utf8 java/lang/Object
{
public com.test.TestClass();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return

public int sum(int, int);
descriptor: (II)I
flags: ACC_PUBLIC
Code:
stack=2, locals=3, args_size=3
0: iload_1
1: iload_2
2: iadd
3: ireturn
}

对比上文的反编译结果,可以看到,输出结果中的 Compiled from "TestClass.java" 没了,Constant pool 中也不再有 LineNumberTableSourceFilecode 属性里的 LocalVariableTable 属性也没了(当然,因为编译时没加 -parameters 参数,MethodParameters 属性自然也没了)。若选择不生成这两个属性,对程序运行产生的最主要的影响就是,当抛出异常时,堆栈中将不会显示出错代码所属的文件名和出错的行号,并且在调试程序的时候,也无法按照源码行来设置断点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
$ javac -d "target/classes" src/main/java/com/test/*.java -g:vars
$ javap -v -cp "target/classes" com.test.TestClass
Classfile /Users/yulewei/IdeaProjects/hellojava/target/classes/com/test/TestClass.class
Last modified 2017-5-2; size 302 bytes
MD5 checksum d430f817e0e2cfafc9095279c67aaa72
public class com.test.TestClass
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #3.#15 // java/lang/Object."<init>":()V
#2 = Class #16 // com/test/TestClass
#3 = Class #17 // java/lang/Object
#4 = Utf8 <init>
#5 = Utf8 ()V
#6 = Utf8 Code
#7 = Utf8 LocalVariableTable
#8 = Utf8 this
#9 = Utf8 Lcom/test/TestClass;
#10 = Utf8 sum
#11 = Utf8 (II)I
#12 = Utf8 num1
#13 = Utf8 I
#14 = Utf8 num2
#15 = NameAndType #4:#5 // "<init>":()V
#16 = Utf8 com/test/TestClass
#17 = Utf8 java/lang/Object
{
public com.test.TestClass();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/test/TestClass;

public int sum(int, int);
descriptor: (II)I
flags: ACC_PUBLIC
Code:
stack=2, locals=3, args_size=3
0: iload_1
1: iload_2
2: iadd
3: ireturn
LocalVariableTable:
Start Length Slot Name Signature
0 4 0 this Lcom/test/TestClass;
0 4 1 num1 I
0 4 2 num2 I
}

可以看到,code 属性里的出现了 LocalVariableTable 属性,这个属性保存的就是方法参数和方法内的本地变量。在演示代码的 sum 方法中没有定义本地变量,若存在的话,也将会保存在 LocalVariableTable 中。

javap-v 选项会输出全部反编译信息,若只想看行号和本地变量信息,改用 -l 即可。输出结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ javap -l -cp "target/classes" com.test.TestClass
public class com.test.TestClass {
public com.test.TestClass();
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/test/TestClass;

public int sum(int, int);
LocalVariableTable:
Start Length Slot Name Signature
0 4 0 this Lcom/test/TestClass;
0 4 1 num1 I
0 4 2 num2 I
}

若要全部生成全部提示信息,编译参数需要改为 -g:source,lines,vars。一般在 IDE 下调试代码都需要调试信息,所以这三个参数默认都会开启。IDEA 下的 javac 默认参数设置,如图:

IDEA 默认的 javac 设置

若使用 maven,maven 的默认的编译插件 maven-compiler-plugin 也会默认开启这三个参数 [doc],经实际验证也包括了LocalVariableTable

同样的,gradle 默认也会包含调试信息 [ doc ]。

代码如何实现

上文中讲了 class 文件中的调试信息中 LocalVariableTable 属性里就包含方法名参数,这就是运行时获取方法参数名的方法。读取这个属性,JDK 并没有提供 API,只能借助第三方库解析 class 文件实现。

要解析 class 文件典型的工具库有 ObjectWeb 的 ASM(wikihomemvnjavadoc)、Apache 的 Commons BCEL(wikihomemvnjavadoc)、 日本教授开发的 Javassist(wikigithubmvnjavadoc)等。其中 ASM 使用最广,使用 ASM 的知名开源项目有,AspectJ, CGLIB, Clojure, Groovy, JRuby, Jython, TopLink等等 [ ref ]。当然使用 BCEL 的项目也很多 [ ref ]。ASM 相对其他库的 jar 更小,运行速度更快 [ javadoc ]。目前 asm-5.0.1.jar 文件大小 53 KB,BCEL 5.2 版本文件大小 520 KB,javassist-3.20.0-GA.jar 文件大小 751 KB。jar 包文件小,自然意味着代码量更少,提供的功能自然也少了。

BCEL

先来看看用 BCEL 获取方法参数名的写法,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.test;
import org.apache.bcel.Repository;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.LocalVariable;
import org.apache.bcel.classfile.LocalVariableTable;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.Type;

public class BcelMain {

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
java.lang.reflect.Method m = TestClass.class.getDeclaredMethod("sum", int.class, int.class);
JavaClass clazz = Repository.lookupClass("com.test.TestClass");
Method bcelMethod = clazz.getMethod(m);
LocalVariableTable lvt = bcelMethod.getLocalVariableTable();
for (LocalVariable lv : lvt.getLocalVariableTable()) {
System.out.println(lv.getName() + " " + lv.getSignature() + " " + Type.getReturnType(lv.getSignature()));
}
}
}

输出结果:

1
2
3
this  Lcom/test/TestClass;  com.test.TestClass
num1 I int
num2 I int

ASM

ASM 的写法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.test;
import org.objectweb.asm.*;

public class AsmMain {

public static void main(String[] args) throws Exception {
ClassReader classReader = new ClassReader("com.test.TestClass");
classReader.accept(new ParameterNameDiscoveringVisitor("sum", "(II)I"), 0);
}

private static class ParameterNameDiscoveringVisitor extends ClassVisitor {
private final String methodName;
private final String methodDesc;

public ParameterNameDiscoveringVisitor(String name, String desc) {
super(Opcodes.ASM5);
this.methodName = name;
this.methodDesc = desc;
}

@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
if (name.equals(this.methodName) && desc.equals(methodDesc))
return new LocalVariableTableVisitor();
return null;
}
}

private static class LocalVariableTableVisitor extends MethodVisitor {

public LocalVariableTableVisitor() {
super(Opcodes.ASM5);
}

@Override
public void visitLocalVariable(String name, String description, String signature, Label start, Label end, int index) {
System.out.println(name + " " + description);
}
}
}

Spring 框架

若使用 Spring 框架,对于运行时获取参数名,Spring 提供了内建支持,对应的实现类为 DefaultParameterNameDiscovererjavadoc)。该类先尝试用 Java 8 新的反射 API 获取方法参数名,若无法获取,则使用 ASM 库读取 class 文件的 LocalVariableTable,对应的代码分别为 StandardReflectionParameterNameDiscovererLocalVariableTableParameterNameDiscoverer

参考资料

]]>
+ + + <p>本文整理 Java 运行时获取方法参数名的两种方法,Java 8 的最新的方法和 Java 8 之前的方法。</p> +<h1 id="Java-8-的新特性">Java 8 的新特性</h1> +<p>翻阅 Java 8 的<a href="http://openjdk.java.net/projects/jdk8/features">新特性</a>,可以看到有这么一条“<a href="http://openjdk.java.net/jeps/118">JEP 118</a>: Access to Parameter Names at Runtime”。这个特性就是为了能运行时获取参数名新加的。这个 <a href="https://en.wikipedia.org/wiki/JDK_Enhancement_Proposal">JEP</a> 只是功能增强的提案,并没有最终实现的 JDK 相关的 API 的介绍。查看“<a href="http://docs.oracle.com/javase/8/docs/technotes/guides/reflection/enhancements.html">Enhancements to the Reflection API</a>” 会看到如下介绍:</p> + + + + + + + + + + + + +
+ + + Java 编译器 javac 及 Lombok 实现原理解析 + + https://nullwy.me/2017/04/javac-api/ + 2017-04-20T03:53:53.000Z + 2022-10-30T16:55:42.000Z + + javac 是 Java 代码的编译器[1][2],初学 Java 的时候就应该接触过。本文整理一些 javac 相关的高级用法。Lombok 库,大家平常一直在使用,但可能并不知道实现原理解析,其实 Lombok 实现上依赖的是 Java 编译器的注解处理 API(JSR-296[3],本文同时尝试解析 Lombok 的实现原理。

先来看下 javac 命令行工具。javac 命令行工具,官方文档有完整的使用说明[4],当然也可以,运行 javac -helpman javac 查看帮助信息。下面是经典的 hello world 代码:

1
2
3
4
5
6
package com.example;
public class Greeting {
public static void main(String[] args) {
System.out.println("hello world");
}
}

编译与运行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ tree   # 代码目录结构
.
├── pom.xml
└── src
└── main
├── java
│ └── com
│ └── example
   │   └── Greeting.java
└── resources
$ mkdir -p target/classes # 创建 class 文件的存放目录
$ javac -d target/classes src/main/java/com/example/Greeting.java
$ java -cp target/classes com.example.Greeting
hello world

除了使用命令行工具编译 Java 代码,JDK 6 增加了规范“JSR-199: Java Compiler API”和“JSR-296: Pluggable Annotation Processing API”,开始还提供相关的 Java 编译器 API。Java 编译器的实现代码和 API 的整体结构如图所示[2:1][5]

Compiler Package Overview

绿色标注的包是官方 API(Official API),即 JSR-199 和 JSR-296,黄色标注的包为Supported API,紫色标注的包代码全部在 com.sun.tools.javac.* 包下,为内部 API(Internal API)和实现类。完整的包说明如下[2:2][5:1][6]

  • javax.annotation.processing - 注解处理 (JSR-296)
  • javax.lang.model - 注解处理和编译器 Tree API 使用的语言模型 (JSR-296)
  • javax.tools - Java 编译器 API (JSR-199)
  • com.sun.source.* - 编译器的 Tree API,支持对抽象语法树做只读访问
  • com.sun.tools.javac.* - 内部 API 和实现类
    • com.sun.tools.javac.api - javax.tools 包下的 JavaCompiler 和其他 API 的实现
    • com.sun.tools.javac.code - javax.lang.model.* 包下的 API 的实现
    • com.sun.tools.javac.comp - 编译器主要处理阶段的实现
    • com.sun.tools.javac.file - 实现访问文件系统,包括 javax.tools.StandardFileManager 的实现
    • com.sun.tools.javac.jvm - class 文件的读写,编译器的字节码生成阶段的实现
    • com.sun.tools.javac.main - 代码编译的入口实现
    • com.sun.tools.javac.model - javax.lang.model.* 包的其他实现
    • com.sun.tools.javac.parser - 读取 Java 源代码,并生成语法树
    • com.sun.tools.javac.processing - 注解处理 API 的实现
    • com.sun.tools.javac.resources - 本地化文本和版本号的资源文件
    • com.sun.tools.javac.tree - 编译器语法树相关的表示类和工具类,com.sun.source.* 包下的 API 的实现
    • com.sun.tools.javac.util - 基础工具类

全部源码都位于 JDK 源码的 langtools 目录下。对外的 API,被编译到 rt.jarcom.sun.source.*com.sun.tools.javac.* 包,被编译到 tools.jar,在 JDK 下的具体位置是 $JAVA_HOME\lib\tools.jar。值得一提的是,langtools 目录,除了包含 javac 的实现外,还实现了 javadocjavah 等命令,编译后也是在 tools.jar 下。

另外,由于是内部 API 和实现类,com.sun.tools.javac.* 包下全部代码中都有标注警告:

This is NOT part of any supported API. If you write code that depends on this, you do so at your own risk. This code and its internal interfaces are subject to change or deletion without notice.

Java 编译器 API

首先,看下 JSR-199 引入的 Java 编译器 API(Java Compiler API)。在没有引入 JSR-199 之前,如果要通过编程方式编译 Java 代码,只能使用 com.sun.tools.javac.* 包下提供内部 API。上文提到的使用命令 javac 编译 Greeting.java 的等价写法如下:

1
2
3
4
5
6
7
8
import com.sun.tools.javac.main.Main;

public class JavacMain {
public static void main(String[] args) {
Main compiler = new Main("javac");
compiler.compile(new String[]{"src/main/com/example/Greeting.java", "-d", "target/classes"});
}
}

事实上,javac 命令的底层实现就是执行 com.sun.tools.javac.Main 类。执行 javac 命令,等价于执行 java -cp $JAVA_HOME/lib/tools.jar com.sun.tools.javac.Main

1
2
# 直接执行 com.sun.tools.javac.Main 类编译 Java 源代码
java -cp $JAVA_HOME/lib/tools.jar com.sun.tools.javac.Main -d target/classes src/main/java/com/example/Greeting.java

JSR-199,提供了 Java 编译器 API,对应的是 javax.tools.* 包。阅读包的 javadoc 容易发现,API 最核心是 javax.tools.JavaCompiler 接口,该类的 javadoc 阐述了如何使用该类,可以阅读。使用 Java 编译器 API 编译 Java 源代码,示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import javax.tools.*;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;

public class Jsr199Main {
public static void main(String[] args) throws IOException {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();

StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);

File file = new File("src/main/java/com/example/Greeting.java");
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(Arrays.asList(file));
List<String> options = Arrays.asList("-d", "target/classes");

compiler.getTask(null, fileManager, diagnostics, options, null, compilationUnits).call();

fileManager.close();
}
}

上述两种编程方式编译 Java 代码的方式,在 javac 命令的 man[4:1] 文档的 “Programmatic Interface” 小节也有提及,有兴趣可以阅读。

在实际开发过程中,我们基本上都是使用 Maven 或 Gradle 编译 Java 代码。Maven 编译 Java 代码,依赖的是 Maven 的 maven-compiler-plugin 插件。那么 maven-compiler-plugin 插件底层实现是否使用了 javax.tools.JavaCompiler 呢?查阅官网文档后,容易发现实际情况和猜想的一样(其实也是显而易见的结论) [doc]:

The Compiler Plugin is used to compile the sources of your project. Since 3.0, the default compiler is javax.tools.JavaCompiler (if you are using java 1.6) and is used to compile Java sources. If you want to force the plugin using javac, you must configure the plugin option forceJavacCompilerUse.

类似的,Gradle 编译 Java 代码,底层也使用了 Java 编译器 API,可以参见源码 JdkJavaCompiler [github]。

javac 的编译过程

上文提到,JSR-269,可插拔式注解处理 API(Pluggable Annotation Processing API)。注解处理,是编译过程中的其中一个阶段。要理解注解处理,需要先了解 Java 代码的编译过程。完整的编译过程如下图所示[7]

javac-flow.png

整个过程就是:

  1. 源代码经过词法解析和语法解析(parse),生成抽象语法树(abstract syntax tree)。然后遍历抽象语法树,将遇到的符号填充入符号表(enter symbol table)。
  2. 注解处理(annotation processing),所有注解处理器会被处理,若处理器生成新的代码或 class 文件,编译过程会重新开始,直到没有新的文件生成。每一次循环称为一个 round,也就是上图的回环过程。
  3. 语义分析和字节码生成,包括标注(attribute)、数据及控制流分析(flow)、解语法糖(desugar)、字节码生成(generate)。

把上述编译过程对应到代码中,javac 编译动作的入口是 com.sun.tools.javac.main.JavaCompiler 类,上述 3 个过程的代码逻辑集中在这个类的 compile()和 compile2()方法,如下图所示,整个编译过程主要的处理由图中标注的 8 个方法来完成[8]

JavaCompiler compile

具体来看下,词法解析和语法解析。Java 的词法和语法规则,在《Java语言规范》(The Java Language Specification)中定义。从底层实现上来看,com.sun.tools.javac.parser.Scanner 类,按照单个字符的方式读取 Java 源文件中的关键字和标示符等内容,然后将其转换为符合 Java 语法规范(JLS ch3)的 Token 序列。例如,针对语句 int y = x + 1; 的词法解析过程如下图所示[9]

词法解析

然后,com.sun.tools.javac.parser.JavacParser 类,读取 Token 序列,将 Token 序列构造为抽象语法树 com.sun.tools.javac.tree.JCTree。语句 int y = x + 1;,生成的抽象语法树,如下图所示[9:1]

抽象语法树

该语句对应的 JCTree.JCVariableDecl 对象,在 IDEA 的 debug 模式下查看,如下图所示:

IDEA debug

语法树中的每一个语法节点,实际上都直接或者间接地继承了 JCTree 类,并且都以静态内部类的形式定义在 JCTree 类中。Java 源文件的完整的词法解析和语法解析,由 JavacParserparseCompilationUnit 方法完成。解析完成后,方法返回 JCTree.JCCompilationUnit 类。JCTree.JCCompilationUnit 类,为某个 Java 源文件解析后的整个语法树的根节点。

上文提到,com.sun.source.* 包下暴露的 Tree API,提供对语法树只能做只读操作。com.sun.tools.javac.tree 包,是 com.sun.source.* 包下的 API 的实现。com.sun.source.tree.Tree 接口对应的实现类为 JCTreeTree 的子接口的实现类为 JCTree 的子类,并一一对应,比如,com.sun.source.tree.ClassTree 对应的实现类为 JCTree.JCClassDeclTree 接口及其子接口只暴露只读方法,而 JCTree 类及其子类,大部分的内部定义字段都是 public,可以直接读写。

主要的语法树节点 JCTree 子类,如下:

  • JCTree.JCStatement:声明语句的语法树节点。主要的子类包括:
    • JCTree.JCBlock:语句块(JLS 14.2
    • JCTree.JCClassDecl:类声明(JLS 8.1
    • JCTree.JCForLoopfor 语句(JLS 14.14.1
    • JCTree.JCEnhancedForLoop:增强for语句(JLS 14.14.2
    • JCTree.JCIfif 语句(JLS 14.9
    • JCTree.JCReturnreturn 语句(JLS 14.7
    • JCTree.JCVariableDecl:变量声明,比如 int x = 0 语句(JLS 14.4
    • 其他(不一一列举)
  • JCTree.JCExpression:表达式的语法树节点。主要的子类包括:
    • JCAssign:赋值语句表达式,比如 x = 0 语句(JLS 15.26
    • JCIdent:标识符表达式,比如 x 标识符(JLS 3.8
    • JCBinary:二元运算符,比如 x + 1 语句(JLS 15.18
    • JCLiteral:字面量运算符表达式,比如 1 字面量(JLS 3.10
    • JCTree.JCPrimitiveTypeTree:基础类型,比如 int 等类型(JLS 4.2
  • JCTree.JCMethodDecl:方法声明(JLS 8.4
  • JCTree.JCCompilationUnit:编译单元,对应单个源文件内的全部内容(JLS 7.3

全部的各个类型的树节点的类定义,可以参见 JCTreeTree 类的 javadoc 或源代码。

在构造抽象语法树后,就是符号表填充阶段。在符号表填充阶段,会扫描 JCTree 语法树,遇到类型、变量、方法定义时,会它们的信息存储到符号表中,方便后续阶段进行快速查询。符号,对应的是 com.sun.tools.javac.code.Symbol 类。而 Symbol 类,是 javax.lang.model 包下 Element 的实现类,Symbol 子类是对应 Element 子类的实现。

Element 提供 ElementKind getKind() 方法,能获取元素类型(ElementKind)。全部的 ElementKind 共 17 种:ANNOTATION_TYPE(注解)、CLASS(类)、CONSTRUCTOR(构造方法)、ENUM(枚举)、ENUM_CONSTANT(枚举值)、EXCEPTION_PARAMETER(异常参数)、FIELD(字段)、INSTANCE_INIT(实例初始化语句块)、INTERFACE(接口)、LOCAL_VARIABLE(本地变量)、METHOD(方法)、PACKAGE(包)、PARAMETER(参数)、RESOURCE_VARIABLE(资源变量)、STATIC_INIT(静态初始化语句块)、TYPE_PARAMETER(类型参数) 以及 OTHER(其他)。

全部 Element 子类以及对应的 Symbol 子类,如下:

  • PackageElement:表示包 package
    • 实现类:Symbol.PackageSymbol
    • 元素类型 ElementKindPACKAGE(包)
  • TypeElement:表示类 class 或接口 interface 等
    • 实现类:Symbol.ClassSymbol
    • 元素类型 ElementKindANNOTATION_TYPE(注解)、INTERFACE(接口)、ENUM(枚举)、CLASS(类)
  • VariableElement:表示字段、枚举值、方法参数、本地变量、资源变量、异常参数
    • 实现类:Symbol.VarSymbol
    • 元素类型 ElementKindEXCEPTION_PARAMETER(异常参数)、PARAMETER(参数)、ENUM_CONSTANT(枚举值)、RESOURCE_VARIABLE(资源变量)、LOCAL_VARIABLE(本地变量)、FIELD(字段)
  • ExecutableElement:表示方法、构造方法、初始化语句块
    • 实现类:Symbol.MethodSymbol
    • 元素类型 ElementKindCONSTRUCTOR(构造方法)、STATIC_INIT(静态初始化语句块)、INSTANCE_INIT(实例初始化语句块)、METHOD(方法)
  • TypeParameterElement:表示参数化类型,即泛型尖括号内的类型
    • 实现类:Symbol.TypeVariableSymbol
    • 元素类型 ElementKindTYPE_PARAMETER(类型参数)

在填充符号表后,就是语义分析和代码生成,包括标注(attribute)、数据及控制流分析(flow)、解语法糖(desugar)、字节码生成(generate)阶段。

在实际开发时,比如常见的“找不到符号(cannot find symbol)”编译报错,就是在标注阶段的名称消解(name resolution)时触发的。编译报错示例代码,如下:

1
2
3
public class CantResolve {
int foo = bar;
}

编译错误的提示内容:

1
2
3
找不到符号
符号: 变量 bar
位置: 类 CantResolve

编译过程的各个阶段的更详细的阐述可以阅读书籍[8:1][10],本文不再展开。

可插拔式注解处理 API

JSR-296 定义的可插拔式注解处理 API 在 javax.annotation.processing 包下,最核心的接口是 javax.annotation.processing.Processor,通过实现这个接口来定义自己的注解处理器。

编译器工具与 Processor 实现类的交互过程是:

  • 如果存在没有被使用的 Processor 对象,就调用无参构造方法创建一个 Processor 实例。
  • 然后,编译器工具调用注解处理器的 init 方法,初始化注解处理器,方法参数是 ProcessingEnvironment 对象(注解处理的执行环境,从环境中获得相关工具类,比如 Elements)。
  • 之后,编译器工具调用注解处理器的 getSupportedAnnotationTypes(查询该注解处理器支持的注解集合)、getSupportedOptions(查询该注解处理器支持的参数选项集合)、getSupportedSourceVersion(查询该注解处理器支持的源代码版本)方法。
  • 最后,调用注解处理器的 process 方法。

注解处理会执行多轮(round),每轮都会调用 process 方法,调用时传入在上一轮的源代码和 class 文件中找到的该注解处理器支持的注解子集。在处理注解期间,如果任何注解处理器生成了新的源文件或 class 文件,编译器将回到解析、填充符号表、注解处理的过程,直到没有新的文件生成。

init 方法的参数 ProcessingEnvironment 对象,为注解处理的执行环境,从环境中获得相关工具类,比如,Elements 类,用于操作 Element 元素;Filer 类,用于生成新的文件;Messager 类,用于报告编译错误、告警或其他消息。另外,ProcessingEnvironment,也可以获得传递给注解处理器参数选项。

AbstractProcessor 抽象类,实现类了 Processor 接口,用于简化实际的注解处理器类的实现。该类通过读取 @SupportedAnnotationTypes@SupportedOptions@SupportedSourceVersion 注解值,来实现 Processor 接口对应的三个方法。

用命令行编译代码时,javac 编译器,会搜索可用的注解处理器。搜索路径可以通过参数选项 -processorpath 指定,如果未指定,将使用 classpath。注解处理器,可以通过 -processor 参数选项指定。若未通过 -processor 参数选项指定,注解处理器会使用 SPI 方式定位,在搜索路径查找 META-INF/services/javax.annotation.processing.Processor 文件。文件中填写的是注解处理器类名(多个的话,换行填写),编译器就会自动使用这里填写的注解处理器进行注解处理。另外,编译器 API 的 CompilationTasksetProcessors 方法也可以传入注解处理器。

如果注解处理器支持参数选项,编译时,参数选项可以用 -Akey[=value] 的方式传递[4:2]

扫描语法树

JDK 源码的 langtools 目录下,提供了示例注解处理器 CheckNamesProcessor,一个检查命名的注解处理器。CheckNamesProcessor 注解处理器,内部实现了 javax.lang.model.util 包下 ElementScanner,用来扫描 Element 元素符号,然后检查类命名、方法命名、字段命名、参数命名等是否符合命名规范,如果不符合命名规范,就打印编译器告警。

javax.lang.model.util.ElementScanner8 类用于扫描 Element 的核心方法:

1
public final R scan(Element e)

对语法树的扫描,com.sun.source.util 包下,提供了语法树扫描器 TreeScanner,用于扫描语法树上的树节点 Tree。类似的,com.sun.tools.javac.tree.TreeScanner,用于扫描语法树上的树节点 JCTree

com.sun.source.util.TreeScanner 类用于扫描语法树的核心方法:

1
public R scan(Tree node, P p)

com.sun.tools.javac.tree.TreeScanner 类用于扫描语法树的核心方法:

1
public void scan(JCTree tree)

需要注意的是,注解处理器的 process 方法,传递过来的是 Element 对象,需要先获得 Element 对象关联的 TreeJCTree 对象,才能扫描语法树。工具类 com.sun.source.util.Trees 提供了这样的桥接能力,该类的实现类为 com.sun.tools.javac.api.JavacTreesTrees 的相关方法:

1
2
3
4
// 通过 ProcessingEnvironment 获得 Trees 对象
public static Trees instance(ProcessingEnvironment env)
// 通过 Element 获得 Tree
public abstract Tree getTree(Element element);

类似的,JavacTrees 的相关方法:

1
2
3
4
// 通过 ProcessingEnvironment 获得 JavacTrees 对象
public static JavacTrees instance(ProcessingEnvironment env)
// 通过 Element 获得 JCTree
public JCTree getTree(Element element)

使用 ElementScannerTreeScanner 扫描语法树的示例注解处理器,参见 VisitProcessor

修改语法树

在语法解析时,JavacParser 类,底层实现上利用 TreeMaker 类构造的语法树各个节点。TreeMaker 类,封装了创建语法树节点的方法,部分常用的方法举例:

  • TreeMaker.Assign 方法:用于生成赋值语句的语法树节点 JCTree.JCAssign
  • TreeMaker.Binary 方法:用于生成二元操作符的语法树节点 JCTree.JCBinary
  • TreeMaker.Block 方法:用于生成语句块的语法树节点 JCTree.JCBlock
  • TreeMaker.VarDef 方法:用于生成变量定义的语法树节点 JCTree.JCVariableDecl
  • TreeMaker.MethodDef 方法:用于生成方法定义的语法树节点 JCTree.JCMethodDecl
  • 等等

在注解处理阶段,init 方法传入了 ProcessingEnvironment 对象,通过该对象可以获得当前上下文中的 TreeMaker 对象,然后就可以利用 TreeMaker 创建新的语法树节点。

语句 int y = x + 1;,使用 TreeMaker 构造对应的 JCTree.JCVariableDecl,示例代码如下:

1
2
3
4
5
6
Name x = ...
Name y = names.fromString("y");
// x + 1
JCTree.JCBinary binary = maker.Binary(JCTree.Tag.PLUS, maker.Ident(x), maker.Literal(TypeTag.INT, 1));
// int y = x + 1
JCTree.JCVariableDecl decl = maker.VarDef(maker.Modifiers(0), y, maker.TypeIdent(TypeTag.INT), binary);

因为 JCTree 类及其子类的大部分的内部定义字段都是 public,可以直接读写,所以要想修改语法树,可以直接相关字段的值。比如,把 int y = x + 1 语句对应的 JCTree.JCVariableDecl 树节点改为 int y = 42,可以直接修改 JCTree.JCVariableDeclinit 字段,示例代码如下:

1
2
JCTree.JCVariableDecl decl = ...
decl.init = maker.Literal(TypeTag.INT, 42);

修改语法树的示例代码,参见 PlusProcessor 注解处理器。该示例注解处理器,修改 @PlusOne 注解标注的方法的内部实现,改造后的方法的逻辑为,返回请求参数值加 1 后的值。比如,修改语法树前,func 方法实现如下:

1
2
3
4
@PlusOne
public int func(int x) {
return x * x;
}

PlusProcessor 注解处理器修改语法树后,func 方法变成:

1
2
3
public int func(int x) {
return x + 1;
}

修改方法内部实现的核心代码如下:

1
2
3
4
5
6
7
8
private void modifyToPlusOneMethod(JCTree.JCMethodDecl methodDecl) {
JCTree.JCVariableDecl param = methodDecl.params.head;
// x + 1
JCTree.JCBinary binary = maker.Binary(JCTree.Tag.PLUS, maker.Ident(param.name), maker.Literal(TypeTag.INT, 1));
JCTree.JCReturn ret = maker.Return(binary);
// 修改方法内部实现
methodDecl.body.stats = List.of(ret);
}

这个注解处理器仅仅用于示例,没有其他实际用途。实际开发中,Lombok 库被广泛使用,其底层实现就是利用注解处理器修改由 Lombok 注解(@Data@Getter@Setter 等)标注的代码的语法树,自动生成样板代码。针对 Lombok 库实现原理的解析,参见下文。

创建新文件

可插拔式注解处理 API,定义了 javax.annotation.processing.Filer 接口,这个接口提供了让注解处理器创建新文件的能力。createSourceFile 方法,用于创建新的源代码文件,createClassFile,用于创建新的 class 文件。

来看下示例代码,GreetingProcessor 注解处理器。该注解处理器功能就是基于 Filer 自动生成 Greeting 类(打印 "hello world")。核心代码片段如下:

1
2
3
4
5
6
7
8
9
10
private boolean generateGreeting(String className) throws Exception {
byte[] bytes = Files.readAllBytes(Paths.get(this.getClass().getResource("/Greeting.tpl").toURI()));
String greetingTemplate = new String(bytes, StandardCharsets.UTF_8);
String greetingSourceCode = String.format(greetingTemplate, LocalDateTime.now(), className);
JavaFileObject fileObject = filer.createSourceFile(className);
try (PrintWriter writer = new PrintWriter(fileObject.openWriter())) {
writer.println(greetingSourceCode);
}
return true;
}

模板文件 Greeting.tpl 的内容为:

1
2
3
4
5
6
7
8
import javax.annotation.Generated;

@Generated(value = "by GreetingProcessor", date = "%s")
public class %s {
public static void main(String[] args) {
System.out.println("hello world");
}
}

在实际开发中,MapStruct 是流行的用于 Bean 之间映射的工具库之一,其底层实现就是基于注解处理器 API。阅读源码,容易发现 MapStruct 库内部实现的注解处理器是 org.mapstruct.ap.MappingProcessorjavadocgithub)。MappingProcessor 注解处理器生成的 Mapper 实现类,底层调用的就是 Filer 接口的 createSourceFile 方法,参见源代码 github。另外,MapStruct 库的注解处理器生成源代码文件利用了模板引擎 FreeMarker 库,可以参见 javadocgithub

另外值得一提的是,除了模板引擎,生成源代码文件也可以使用 JavaPoet 工具库,JavaPoet 库提供 Java API 来生成 .java 源文件。笔者基于 JavaPoet 库,实现了能处理类似 Lombok 的 @Builder 注解的 BuilderProcessor 注解处理器,有兴趣的话可以查阅(附注:实际的 Lombok 的 @Builder 注解实现原理是修改语法树,并不是生成新的 Builder 类文件)。

Lombok 的实现原理

依赖 JSR-269 实现的第三方工具库有很多[11],比如代码自动生成的 LombokMapStruct 和 Google Auto,代码检查的 Checker 和 Google Error Prone,编译阶段完成依赖注入的 Google Dagger 2 等。笔者在实际开发中就经常使用 Lombok 库和 MapStruct 库。MapStruct 库的实现原理,上文已经做了简单介绍。现在来看下 Lombok 的实现原理。

Lombok 提供 @NonNull@Getter, @Setter, @ToString, @EqualsAndHashCode, @Data 等注解,自动生成常见样板代码 boilerplate,解放开发效率。Lombok 支持 javac 和 ecj (Eclipse Compiler for Java)。对于 javac 编译器对应的注解处理器是 LombokProcessor,然后经过一些处理过程,每个注解都会有特定的 handler 来处理,@NonNull 对应 HandleNonNull@Getter 对应 HandleGetter@Setter 对应 HandleSetter@ToString 对应 HandleToString@EqualsAndHashCode 对应 HandleEqualsAndHashCode@Data 对应 HandleData。如果想要改造 Lombok 项目,让 Lombok 支持新的注解,其实就是添加新的 handler。关于 Lombok 原理以及如何为 Lombok 贡献代码,文档 “Documentation for lombok developers”[12],也有简单介绍,可以阅读。

阅读这些 handler 的实现,可以看到样板代码的生成依赖的就是 com.sun.tools.javac.* 包。最新版的 Lombok 源码太繁杂了,可以从早期版本入手,比如 v0.8.1 版本。

现在来看下如何实现 @Getter 注解。@Getter 注解的功能,就是自动生成类字段的 getter 方法,如果注解加到 class 上,就生成类的全部字段的 getter 方法。假设字段名叫 foo,那边生成的 getter 方法如下所示:

1
2
3
public int getFoo() {
return foo;
}

参考 Lombok v0.8.1 和 v0.9.3 的 HandleGetter 实现源码(从 v0.9.3 版本开始,@Getter 注解支持加到 class 上,之前只能加到字段上),提取出其中的核心代码,实现 @Getter 的示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private void handleGetter(JCTree.JCClassDecl classDecl) {
List<JCTree> methodDecls = List.nil();
for (JCTree tree : classDecl.defs) {
if (tree instanceof JCTree.JCVariableDecl) {
// 创建 getter 方法
JCTree.JCVariableDecl fieldDecl = (JCTree.JCVariableDecl) tree;
String methodGetterName = Utils.toGetterName(fieldDecl);
if (!Utils.methodExists(methodGetterName, classDecl)) {
JCTree.JCMethodDecl methodGetter = this.createGetter(fieldDecl);
methodDecls = methodDecls.append(methodGetter);
}
}
}
classDecl.defs = classDecl.defs.appendList(methodDecls);
}

// 生成 getter 方法
private JCTree.JCMethodDecl createGetter(JCTree.JCVariableDecl field) {
JCTree.JCStatement returnStatement = maker.Return(maker.Ident(field));
JCTree.JCBlock methodBody = maker.Block(0, List.of(returnStatement));
Name methodName = names.fromString(Utils.toGetterName(field));
JCTree.JCExpression methodType = (JCTree.JCExpression) field.getType();

return maker.MethodDef(maker.Modifiers(Flags.PUBLIC), methodName, methodType,
List.nil(), List.nil(), List.nil(), methodBody, null);
}

容易发现,实现 @Getter 注解依赖的 JCTreeTreeMaker 等相关类,这些类在上文都已经提及并介绍,不再复述。

为了加深对 javac 内部 API 的理解,笔者参考 Lombok 的源码,实现了支持类似 Lombok 的 @Data@Getter@Setter@Slf4j 注解的注解处理器MyLombokProcessor,代码参见 GitHub。

附注:本文的示例代码的完整代码,都可以在 GitHub 的 annotation-processor-demo[13] 仓库上找到。

参考资料


  1. OpenJDK: The Java programming language Compiler Group http://openjdk.java.net/groups/compiler/ ↩︎

  2. The Java Programming Language Compiler, javac https://docs.oracle.com/javase/8/docs/technotes/guides/javac/ ↩︎ ↩︎ ↩︎

  3. 2011-05 How does lombok work? http://stackoverflow.com/q/6107197 ↩︎

  4. javac https://docs.oracle.com/javase/8/docs/technotes/tools/unix/javac.html https://www.mankier.com/1/javac ↩︎ ↩︎ ↩︎

  5. OpenJDK: Compiler Package Overview https://openjdk.org/groups/compiler/doc/package-overview/index.html ↩︎ ↩︎

  6. OpenJDK: The Hitchhiker's Guide to javac https://openjdk.org/groups/compiler/doc/hhgtjavac/index.html ↩︎

  7. OpenJDK: Compilation Overview https://openjdk.org/groups/compiler/doc/compilation-overview/index.html ↩︎

  8. 深入理解Java 7虚拟机,周志明 第2版2013:第10章 早期 (编译期) 优化 ↩︎ ↩︎

  9. 莫枢 RednaxelaFX :JVM分享——Java程序的编译、加载与执行 http://www.valleytalk.org/2011/07/28/java-程序的编译,加载-和-执行/ ↩︎ ↩︎

  10. 深入解析Java编译器:源码剖析与实例详解,马智 2019 ↩︎

  11. Awesome Java Annotation Processing https://github.com/gunnarmorling/awesome-annotation-processing ↩︎

  12. Documentation for lombok developers https://projectlombok.org/contributing/ ↩︎

  13. annotation-processor-demo https://github.com/yulewei/annotation-processor-demo ↩︎

]]>
+ + + <p><code>javac</code> 是 Java 代码的编译器<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup><sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup>,初学 Java 的时候就应该接触过。本文整理一些 <code>javac</code> 相关的高级用法。Lombok 库,大家平常一直在使用,但可能并不知道实现原理解析,其实 Lombok 实现上依赖的是 Java 编译器的注解处理 API(<a href="https://www.jcp.org/en/jsr/detail?id=269">JSR-296</a>)<sup class="footnote-ref"><a href="#fn3" id="fnref3">[3]</a></sup>,本文同时尝试解析 Lombok 的实现原理。</p> + + + + + + + + + + + + + + + + +
+ + + Java Executor 框架笔记 + + https://nullwy.me/2017/03/java-executor/ + 2017-03-23T07:09:51.000Z + 2023-12-05T06:14:46.382Z + + 本文整理 Java 并发框架 Executor 的用法,并对结合 JDK 相关的实现源码作简单分析。

任务与线程池

先来看下 Executor 框架的 javadoc 描述 [ ref1 ref2 ]

接口:

  • Executor 是一个简单的标准化接口,用于定义类似于线程的自定义子系统,包括线程池、异步 IO 和轻量级任务框架。根据所使用的具体 Executor 类的不同,可能在新创建的线程中,现有的任务执行线程中,或者调用 execute() 的线程中执行任务,并且可能顺序或并发执行。
  • ExecutorService 提供了多个完整的异步任务执行框架。ExecutorService 管理任务的排队和安排,并允许受控制的关闭。ScheduledExecutorService 子接口及相关的接口添加了对延迟的和定期任务执行的支持。ExecutorService 提供了安排异步执行的方法,可执行由 Callable 表示的任何函数,结果类似于 Runnable。
  • Future 返回函数的结果,允许确定执行是否完成,并提供取消执行的方法。RunnableFuture 是拥有 run 方法的 Future,run 方法执行时将设置其结果。

实现:

涉及到的类与接口的层次结构,如下图所示:

Executor 相关类任务相关类

线程池

Executor,此接口提供一种将任务提交与每个任务将如何运行的机制(包括线程使用的细节、调度等)分离开来的方法。接口只定义唯一一个方法:

1
2
void execute(Runnable command)
在未来某个时间执行给定的命令

实现 Executor 接口,就是定义某种运行任务的机制。最简单的运行任务的机制是,在调用者的线程中立即运行已提交的任务,如下:

1
2
3
4
5
class DirectExecutor implements Executor {
public void execute(Runnable r) {
r.run();
}
}

或者,以下实现将为每个任务生成一个新线程:

1
2
3
4
5
class ThreadPerTaskExecutor implements Executor {
public void execute(Runnable r) {
new Thread(r).start();
}
}

更典型的执行任务的方式是,使用线程池(Thread pool)。

JDK 下的 Executors 类提供创建线程池的静态工厂方法:

  1. newFixedThreadPool:固定大小线程池,创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程
  2. newCachedThreadPool:无界线程池,创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们
  3. newSingleThreadExecutor:单个后台线程池,创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程
  4. newScheduledThreadPool:任务调度线程池,创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行

这 4 个工厂方法返回的类型是 ExecutorService,该接口扩展自 Executor。ExecutorService 提供了管理终止的方法,以及可为跟踪一个或多个异步任务执行状况而生成 Future 的方法。

现在让我们来看看创建线程池的静态工厂方法,对应的实现源码 [ src ]:

1
2
3
4
5
6
7
8
9
10
11
12
13
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
}
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()));
}
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}

可以看到 newFixedThreadPoolnewCachedThreadPoolnewSingleThreadExecutor 内部都是通过类 ThreadPoolExecutor 实现。ThreadPoolExecutor 的构造方法的 javadoc 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue)

用给定的初始参数和默认的线程工厂及被拒绝的执行处理程序创建新的 ThreadPoolExecutor。使用 Executors 工厂方法之一比使用此通用构造方法方便得多。

参数:
corePoolSize - 池中所保存的线程数,包括空闲线程。
maximumPoolSize - 池中允许的最大线程数。
keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
unit - keepAliveTime 参数的时间单位。
workQueue - 执行前用于保持任务的队列。此队列仅保持由 execute 方法提交的 Runnable 任务。

ThreadPoolExecutor 的处理流程如下图所示(参考自《Java并发编程的艺术》第9章 Java中的线程池):
线程池的主要处理流程
ThreadPoolExecutor 执行示意图

基本上预定义的三个线程池已经满足常见的使用需求,若有特殊需求也可以,特殊构造 ThreadPoolExecutor 实例。此类提供 protected 的 beforeExecuteafterExecute 钩子 (hook) 方法,就是预留扩展用的。

ScheduledExecutorService 类提供的方法:

1
2
3
4
5
6
7
8
ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit)
创建并执行在给定延迟后启用的 ScheduledFuture
ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)
创建并执行在给定延迟后启用的一次性操作
ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期
ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
创建并执行一个在给定初始延迟后首次启用的定期操作,随后,在每一次执行终止和下一次执行开始之间都存在给定的延迟

用法就如文档所示,不展开描述。

提交任务

若直接使用线程运行任务,则典型的做法是创建 Runnable 接口实例,然后启动线程,如下:

1
2
3
4
5
Runnable r = ...
Thread worker = new Thread(r);
worker.start();
worker.join();
int result = getSavedValue();

Runnable 实例是没有直接的办法获取运行结果的返回值的,若要获取,需要添加额外的代码,如示例中 getSavedValue

Executor 框架下,使用 ExecutorService 的 submit 方法提交任务。

1
2
<T> Future<T> submit(Callable<T> task)
提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future。该 Future 的 get 方法在成功完成时将会返回该任务的结果。

Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。但是 Callable 会返回结果,并且可以抛出经过检查的异常。 submit 方法也可以接受 Runnable 参数,但阅读内部实现代码的话,就可以看到,最终还是会通过 Executors 类的 callable 方法,将 Runnable 转换成 Callable [ src src ]。Runnable 是为线程设计的,Callable 是为任务设计。任务和线程概念上分离,这样线程如何运用任务,即运行任务的机制,就可以按具体情况定义了。

上文提到 ExecutorService 扩展自 Executor 接口,那么现在就看下 submit 方法实现源码 [ src ]:

1
2
3
4
5
6
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}

可以看到内部实现其实就是调用 execute,但传入参数和返回结果包裹了 Callable 和 Future。execute 方法跟具体实现有关,对于 ThreadPoolExecutor 的实现逻辑,代码会根据线程大小,以及任务队列 workQueue 和工作线程 worker 状况,做出相应选择:[ doc src ]:

  • 如果运行的线程少于 corePoolSize,则 Executor 始终首选添加新的线程,而不进行排队。
  • 如果运行的线程等于或多于 corePoolSize,则 Executor 始终首选将请求加入队列,而不添加新的线程。
  • 如果无法将请求加入队列,则创建新的线程,除非创建此线程超出 maximumPoolSize,在这种情况下,任务将被拒绝。

使用 ExecutorService

ExecutorService 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package concurrent;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

public class ExecutorMain {

public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
ExecutorService pool = Executors.newFixedThreadPool(10);

List<Future<Integer>> futures = new ArrayList<>();
futures.add(pool.submit(() -> {
Thread.sleep(2000);
System.out.println("return 1");
return 1;
}));
futures.add(pool.submit(() -> {
Thread.sleep(1000);
System.out.println("return 2");
return 2;
}));
futures.add(pool.submit(() -> {
Thread.sleep(3000);
System.out.println("return 3");
return 3;
}));

for (Future<Integer> future : futures) {
Integer result = future.get();
System.out.println("get " + result);
}
pool.shutdown();
}
}

输出结果:

1
2
3
4
5
6
return 2
return 1
get 1
get 2
return 3
get 3

为什么输出结果是这样呢?查文档知道,Future 的 get 方法,若已经完成,则直接返回,否则会等待计算完成,然后获取其结果。在示例代码中,任务1 需要 2 秒完成,任务2 需要 1 秒完成,任务3 需要 3 秒完成。自然,在线程池中完成次序是,任务2 - 任务1 - 任务3。main 主线程,先是获取 get 任务1 的执行结果,需要等待 2 秒,在去获取 get 任务2 的执行结果,此时该任务已经完成,直接返回,接下来是获取 get 任务3 的执行结果,任务3 耗时 3 秒,此时时间线是第 2 秒,所以需等 1 秒,才能获取 get 执行结果。

使用 ExecutorService,若想按任务完成次序获取执行结果,可以将代码中 for 循环,修改为轮询方式,就不断地在调用 get 前,先用 isDone 判断是否任务已经完成。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
while (true) {
Iterator<Future<Integer>> iter = futures.iterator();
if (!iter.hasNext()) break;
while (iter.hasNext()) {
Future<Integer> future = iter.next();
if (future.isDone()) {
Integer result = future.get();
System.out.println("get " + result);
iter.remove();
}
}
}

输出结果:

1
2
3
4
5
6
return 2
get 2
return 1
get 1
return 3
get 3

这种实现方式,虽然可行,但相当繁琐。幸运的是,JDK 还提供一种更好的方法,CompletionService

使用 CompletionService

CompletionServiceExecutorBlockingQueue 的功能融合在一起。你可以将 Callable 任务提交给它来执行,然后使用类似于队列操作的 takepoll 等方法来获得已完成的结果,而这些结果会在完成时将被封装为 Future。ExecutorCompletionService 实现了 CompletionService。ExecutorCompletionService 的实现非常简单。在构造函数中创建一个 BlockingQueue 来保存计算完成的结果。当计算完成时,调用 FutureTask 中的 done 方法。当提交某个任务时,该任务将首先包装为一个 QueueingFuture,这是 FutureTask 一个子类,然后再改写子类的 done 方法,并将结果放入 BlockingQueue 中,take 和 poll 方法委托给了 BlockingQueue,这些方法会在得出结果之前阻塞。[ Goetz 2006, 6.3.5 ]

可以看出整个实现逻辑核心在于重写 FutureTask 的 done 方法,正如这个方法的 javadoc 所述,定义该方法的目的就是如此:

1
2
protected void done()
当此任务转换到状态 isDone(不管是正常地还是通过取消)时,调用受保护的方法。默认实现不执行任何操作。子类可以重写此方法,以调用完成回调或执行簿记

再来看下,BlockingQueue 的实现源码 [ src ],以及 submit 任务是对应的实现源码 [ src ]:

1
2
3
4
5
6
public Future<V> submit(Callable<V> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<V> f = newTaskFor(task);
executor.execute(new QueueingFuture(f));
return f;
}
1
2
3
4
5
6
7
8
private class QueueingFuture extends FutureTask<Void> {
QueueingFuture(RunnableFuture<V> task) {
super(task, null);
this.task = task;
}
protected void done() { completionQueue.add(task); }
private final Future<V> task;
}

然后再看下 ExecutorCompletionService 的 take 和 poll 方法的实现源码 [ src ]:

1
2
3
4
5
6
7
public Future<V> take() throws InterruptedException {
return completionQueue.take();
}

public Future<V> poll() {
return completionQueue.poll();
}

整个实现逻辑正如上面文字所述。

上文示例的 ExecutorMain,现在用 CompletionService 重现实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package concurrent;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

public class CompletionServiceMain {

public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService pool = Executors.newFixedThreadPool(10);
CompletionService<Integer> service = new ExecutorCompletionService<>(pool);

List<Future<Integer>> futures = new ArrayList<>();
futures.add(service.submit(() -> {
Thread.sleep(2000);
System.out.println("return 1");
return 1;
}));
futures.add(service.submit(() -> {
Thread.sleep(1000);
System.out.println("return 2");
return 2;
}));
futures.add(service.submit(() -> {
Thread.sleep(3000);
System.out.println("return 3");
return 3;
}));

for (int i = 0; i < futures.size(); i++) {
Integer result = service.take().get();
System.out.println("get " + result);
}
pool.shutdown();
}
}

运行结果,就是依次输出,任务2 - 任务1 - 任务3:

1
2
3
4
5
6
return 2
get 2
return 1
get 1
return 3
get 3

Guava 的 ListenableFuture

CompletionService 的逻辑是,任务完成后,依次添加到完成队列中,然后让主线程主动去获取这些已经完成的任务。其实这种主线程主动模式,也可以修为被动模式,即任务完成后主动以事件回调的形式通知主线程,主动方从主线程换成了任务本身。这种方式就消除了等待任务完成的过程。可惜的是直到 Java 8 新添加的 CompletableFuture 才支持实现这种机制。在 Java 8 之前,需要借助第三方库,比如 Guava 提供的 ListenableFuture。使用 CompletableFuture 需要了解 lambda 以及函数式编程相关知识,本文暂不展开,本文只讨论 ListenableFuture。来看下 Guava 的 ListenableFuture 主要涉及到的类 [ doc ]:

  • ListeningExecutorService:扩展自 ExecutorService 接口,但不同的是,提交 submit 过去的任务返回的是 ListenableFuture 实例。
  • ListenableFuture:扩展自 Future 接口,唯一新增的方法是 addListener,用于添加 Future 完成后的回调监听器。
  • MoreExecutors:工具类,类似于 JDK 的 Executors,主要提供 Executor 的桥接、转换和构造的工具方法。
  • Futures:工具类,提供 Future 接口相关的静态工具方法,如静态方法 addCallback 用于添加任务执行的回调监听器,包括对任务执行成功的 onSuccess 事件和执行失败(抛出异常或被取消)的 onFailure 事件。
  • ListenableFutureTask:实现 ListenableFuture 接口的 FutureTask。

这些类如何使用呢?还是先来看下示例代码吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package concurrent;

import com.google.common.util.concurrent.*;
import java.util.concurrent.Executors;

public class ListenableFutureMain {

public static void main(String[] args) {
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));

ListenableFuture<Integer> task = service.submit(() -> {
Thread.sleep(2000);
return 42;
});
Futures.addCallback(task, new FutureCallback<Integer>() {
public void onSuccess(Integer result) {
System.out.println("onSuccess " + result);
}
public void onFailure(Throwable t) {
System.out.println("onFailure");
}
});

service.shutdown();
}
}

简单解释下。MoreExecutors 工具类的 listeningDecorator 方法将 JDK 创建的 ExecutorService 装饰为 ListeningExecutorService。接下来,创建的任务,并提交 submit 到这个 ExecutorService 里。submit 方法返回 ListenableFuture 接口实例(内部实现其实就是 ListenableFutureTask 对象)。Futures 工具类的 addCallback 方法用于添加在任务执行回调的监听器。

类似于 JDK 的 CompletionService,实现 Guava 的 ListeningExecutorService 也是通过重写 FutureTask 的 done 方法完成的。FutureTask 对应的子类就是 ListenableFutureTask(事实上,Guava 版本 19 开始 ListenableFutureTask 类替换成立了 TrustedListenableFutureTask 类 [ github ],这里暂不展开分析)。实现 ListenableFutureTask 的核心代码如下 [ src ]:

1
2
3
4
5
6
7
8
9
10
11
private final ExecutionList executionList = new ExecutionList();

@Override
public void addListener(Runnable listener, Executor exec) {
executionList.add(listener, exec);
}

@Override
protected void done() {
executionList.execute();
}

之前查看 submit 方法实现源码时,看到该方法内部会调用 newTaskFor 方法创建 FutureTask。相应的 JDK 的 AbstractExecutorService 的 newTaskFor 也 Guava 的 AbstractListeningExecutorService 被重写为 [ src ]:

1
2
3
@Override protected final <T> ListenableFutureTask<T> newTaskFor(Callable<T> callable) {
return ListenableFutureTask.create(callable);
}

这样在线程池中运行任务的不再是 FutureTask,而变成了 ListenableFutureTask。任务完成后调用 done 方法,而 done 方法就去执行该任务关联的监听器列表,即 executionList.execute()

再来看下 Futures 工具类的 addCallback 方法的实现 [ src ]:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public static <V> void addCallback(final ListenableFuture<V> future,
final FutureCallback<? super V> callback, Executor executor) {
Preconditions.checkNotNull(callback);
Runnable callbackListener = new Runnable() {
@Override
public void run() {
final V value;
try {
// TODO(user): (Before Guava release), validate that this
// is the thing for IE.
value = getUninterruptibly(future);
} catch (ExecutionException e) {
callback.onFailure(e.getCause());
return;
} catch (RuntimeException e) {
callback.onFailure(e);
return;
} catch (Error e) {
callback.onFailure(e);
return;
}
callback.onSuccess(value);
}
};
future.addListener(callbackListener, executor);
}

ListenableFuture API 功能的完整介绍参见 ListenableFutureExplained,本文不再展开。

Fork/Join 框架

一个大的任务可能会由多个子任务组成,比如整个任务A,由任务B 和任务C 组成,而任务B 又可以被分解为任务D 和任务E,如下图所示。任务分解组合问题,利用 ListenableFuture 的回调将子任务组合起来是一种解决办法,但还是不够优雅简洁。Java 7 引入的 Fork/Join 框架,就是以这种方式设计的。Fork/Join 框架编程的风格就是,将任务分解为多个子任务,并行执行,然后将结果组合起来,即分而治之。ExecutorService 适合解决相互独立的任务,而 Fork/Join 框架适合解决任务分解组合的情况 [ ref ]。

任务的分治

其实整个 java.util.concurrent 包是由 JSR-166 规范引入的,Fork/Join 框架就是其中的 jsr166y。JSR-166 由 Doug Lea 主导,是主要设计和代码实现者,而 jsr166y 最初源自他发表于 2000 年的论文“A Java Fork/Join Framework”(msa pdf)。

工作窃取

Fork/Join 框架采用工作窃取(work stealing)的任务调度机制 [ ref ]:

  • 每一个工作线程维护自己的调度队列中的可运行任务。
  • 队列以双端队列 deque 的形式被维护,不仅支持 LIFO(last-in-first-out 后进先出)的 push 和 pop 操作,还支持 FIFO(first-in-first-out 先进先出)的 take 操作。
  • 对于一个给定的工作线程来说,任务所产生的子任务将会被放入到工作者自己的双端队列 deque 中。
  • 工作线程使用 LIFO(最早的优先)的顺序,通过弹出任务来处理队列中的任务。
  • 当一个工作线程的本地没有任务去运行的时候,它将使用 FIFO 的规则尝试随机的从别的工作线程中拿(“窃取 steal”)一个任务去运行。
  • 当一个工作线程触及了 join 操作,如果可能的话它将处理其他任务,直到目标任务被告知已经结束(通过 isDone 方法)。所有的任务都会无阻塞的完成。
  • 当一个工作线程无法再从其他线程中获取任务和失败处理的时候,它就会退出(通过 yields, sleeps, 和/或者优先级调整)并经过一段时间之后再度尝试直到所有的工作线程都被告知他们都处于空闲的状态。在这种情况下,他们都会阻塞直到其他的任务再度被上层调用。
work stealing

使用 LIFO 规则来处理每个工作线程的自己任务,窃取别的工作线程的任务却使用 FIFO 规则,这是一种被广泛使用的进行递归 fork/join 设计的一种调优手段。这种模式有以下两个优点:它通过窃取工作线程队列反方向的任务减少了竞争。同时,它利用了递归的分治算法越早的产生大任务这一特点。因此,更早期被窃取的任务有可能会提供一个更大的单元任务,从而使得窃取线程能够在将来进行递归分解。

这些规则的结果是,拥有相对细粒度的基本任务,比那些仅仅使用粗粒度划分或没有使用递归分解的任务运行更快。

使用示例

ForkJoinPool 类是用于执行 ForkJoinTask 的 ExecutorService。在构造过程中,可以在构造函数中指定线程池的大小。如果使用的是默认的无参构造函数,那么会创建大小等同于可用处理器数量的线程池。ForkJoinPool 类的典型方法:

1
2
3
4
5
6
public void execute(ForkJoinTask<?> task)
异步,不需要等待计算结果,只是将任务提交给线程池
public <T> T invoke(ForkJoinTask<T> task)
同步,等待计算结束,并返回计算结果值
public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task)
异步,不需要等待计算结果,只是将任务提交给线程池

提交到 ForkJoinPool 中的任务由 ForkJoinTask 抽象类表示。ForkJoinTask 的实现子类有 RecursiveActionRecursiveTask,以及 Java 8 新增的 CountedCompleter。RecursiveAction 用于没有返回结果的任务,RecursiveTask 用于返回结果的任务。CountedCompleter 用于完成动作会触发另外一个动作的任务 [ javadoc ]。

计算斐波那契数(Fibonacci number)是一个经典的分而治之的问题。Doug Lea 的论文以及 RecursiveTask 的 javadoc 都以斐波那契数为例进行说明。斐波那契数定义公式为:

Fn=Fn1+Fn2F_{n}=F_{n-1}+F_{n-2}

F0=0,F1=1F_{0}=0, F_{1}=1

使用 Fork/Join 框架计算斐波那契数的示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package concurrent;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

public class ForkJoinMain {

public static class Fibonacci extends RecursiveTask<Integer> {
final int n;

public Fibonacci(int n) {
this.n = n;
}

protected Integer compute() {
if (n <= 1)
return n;
Fibonacci f1 = new Fibonacci(n - 1);
Fibonacci f2 = new Fibonacci(n - 2);
f1.fork();
return f2.compute() + f1.join();
}
}

public static void main(String[] args) throws Exception {
ForkJoinPool pool = new ForkJoinPool();
Fibonacci fib = new Fibonacci(3);
pool.invoke(fib); // 等待计算完成
Integer result = fib.get();
System.out.println(result);
}
}

这个计算过程如下图所示:

fork-join

参考资料

  1. Java 并发编程实战,Goetz,2006;第6章 任务执行 https://book.douban.com/subject/10484692/
  2. Java并发编程的艺术,方腾飞,2015 https://book.douban.com/subject/26591326/
  3. ExecutorService vs ExecutorCompletionService in Java https://dzone.com/articles/executorservice-vs
  4. Java's Fork/Join vs ExecutorService - when to use which? https://stackoverflow.com/q/21156599
  5. Java Fork Join框架 (三) 设计 http://ifeve.com/a-java-fork-join-framework-3-2/
]]>
+ + + <p>本文整理 Java 并发框架 Executor 的用法,并对结合 JDK 相关的实现源码作简单分析。</p> +<h1 id="任务与线程池">任务与线程池</h1> +<p>先来看下 Executor 框架的 javadoc 描述 [ <a href="http://www.cjsdn.net/Doc/JDK60/java/util/concurrent/package-summary.html#package_description">ref1</a> <a href="http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/package-summary.html#package.description">ref2</a> ]</p> + + + + + + + + + + +
+ + + MySQL数据库字段类型杂记 + + https://nullwy.me/2017/01/mysql-data-types/ + 2017-01-04T15:26:28.000Z + 2023-12-05T06:16:04.399Z + + 文本整理MySQL字段类型的常见问题和用法。

数值类型

int和int(3)

新手在定义整数字段时,常常想当然通过,如int(3),来限制整数的有效长度,然而这样仅仅只是指定了显示宽度。选择有效长度不同的整数,需要使用tinyint(1个字节)、smallint(2个字节)、mediumint(3个字节)、int(4个字节)或bigint(8个字节)。MySQL的相关文档如下[doc]:

MySQL supports an extension for optionally specifying the display width of integer data types in parentheses following the base keyword for the type. For example, INT(4) specifies an INT with a display width of four digits.

The display width does not constrain the range of values that can be stored in the column. Nor does it prevent values wider than the column display width from being displayed correctly. For example, a column specified as SMALLINT(3) has the usual SMALLINT range of -32768 to 32767, and values outside the range permitted by three digits are displayed in full using more than three digits.

When used in conjunction with the optional (nonstandard) attribute ZEROFILL, the default padding of spaces is replaced with zeros. For example, for a column declared as INT(4) ZEROFILL, a value of 5 is retrieved as 0005.

如下示例,字段bar类型是int(3),但依然能够正确保存数值12345

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> create table test (foo int(3) zerofill, bar int(3) zerofill, baz int);
Query OK, 0 rows affected (0.16 sec)

mysql> insert into test values (42, 12345, 12345);
Query OK, 1 row affected (0.00 sec)

mysql> select * from test;
+------+-------+-------+
| foo | bar | baz |
+------+-------+-------+
| 042 | 12345 | 12345 |
+------+-------+-------+
1 row in set (0.00 sec)

bit和bool

MySQL同时支持bitbool类型,但bool仅仅是tinyint(1)的同义词,创建的字段值的范围并不是01truefalse,而是-128127。如下所示:

1
2
3
4
5
6
7
8
9
10
11
mysql> create table test (foo bool, bar bit);
Query OK, 0 rows affected (0.10 sec)

mysql> desc test;
+---------+------------+--------+-------+-----------+---------+
| Field | Type | Null | Key | Default | Extra |
|---------+------------+--------+-------+-----------+---------|
| foo | tinyint(1) | YES | | <null> | |
| bar | bit(1) | YES | | <null> | |
+---------+------------+--------+-------+-----------+---------+
2 rows in set (0.00 sec)

字符串类型

长度和编码

从MySQL 4.1开始(2004年10月),用字符单位解释在字符列定义中的长度规范。(以前的一些MySQL版本以字节解释长度)。官方文档描述如下[doc]

In MySQL 4.1 and up , string data types include some features that you may not have encountered in working with versions of MySQL prior to 4.1:

MySQL interprets length specifications in character column definitions in character units. (Before MySQL 4.1, column lengths were interpreted in bytes.) This applies to CHAR, VARCHAR, and the TEXT types.

MySQL服务器默认的字符集latin1,使用的校对规则latin1_swedish_ci [doc](校对规则是在字符集内用于比较字符的一套规则)。若要保存中文,典型的做法是使用utf8编码。但MySQL的utf8编码最多只能保存使用utf8编码后长度是3个字节的字符,即只支持基本多文种平面。使用MySQL的utf8保存常见的字符基本上没有问题,但对于生僻字或emoji字符就无能为力了。emoji的中的笑脸(grinning face)的Unicode编码,如下 [ref1][ref2]:

表情UnicodeUTF-16UTF8
😀U+1F6040xD83D 0xDE040xF0 0x9F 0x98 0x84

emoji位于辅助多文种平面,utf8需要4个字节保存。为了解决这个问题,MySQL 5.5.3开始支持utf8mb4,支持辅助多文种平面,每个字符最大4个字节 [doc]。除了utf8,MySQL还支持ucs2utf16utf32等,完整列表如下 [ref]

字符集支持的字符每个字符需要的存储空间
utf8基本多文种平面1, 2, 或 3 个字节
ucs2基本多文种平面2字节
utf8mb4基本多文种平面和辅助多文种平面1, 2, 3,或4字节
utf16基本多文种平面和辅助多文种平面2或4字节
utf16le基本多文种平面和辅助多文种平面2或4字节
utf32基本多文种平面和辅助多文种平面4字节

##varchar和text

MySQL支持多种字符串类型, 如下表所示:

类型最大字节长度最大utf8字符数
char(M)M,M为0~255之间的整数85个utf8字符
varchar(M)M,M为0~65,535之间的整数21,844个utf8字符
tinytext 255 (28−1) 字节85个utf8字符
text65,535 (216−1) 字节 = 64 KB21,844个utf8字符
mediumtext16,777,215 (224−1) 字节 = 16 MB5,592,405个utf8字符
longtext4,294,967,295 (232−1) 字节 = 4 GB1,431,655,765个utf8字符

字符串类型实际支持的最大字符数与编码有关。比如,varchar类型在utf8编码下最大支持保存21,844 (65,535 / 3 = 21,844) 个字符,而utf8mb4编码下最大支持保存16,383 (65,535 / 4 = 16,383) 个字符。

另外,MySQL表行最大总长度为65,535字节 [doc], 所以varchar类型字段的最大字符数会被表中其他字段所占用的存储空间挤掉。blobtext类型的字段不会受表行总长度的限制,因为字段存储的实际内容和表行是分离的,只会占用表行的9到12个字节。

1
2
3
4
5
6
7
mysql> create table test ( foo varchar(21845) character set utf8 );
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
mysql> create table test ( foo varchar(21844) character set utf8 );
Query OK, 0 rows affected (0.19 sec)

mysql> create table test2 ( foo varchar(16384) character set utf8mb4 );
ERROR 1074 (42000): Column length too big for column 'foo' (max = 16383); use BLOB or TEXT instead

日期和时间类型

MySQL支持的日期和时间类型如下表所示 [doc]:

日期和时间类型字节最小值最大值
date41000-01-019999-12-31
datetime81000-01-01 00:00:00.0000009999-12-31 23:59:59.999999
timestamp41970-01-01 00:00:01.0000002038-01-19 03:14:07.999999
time3-838:59:59.000000838:59:59.000000
year119012155

参考资料

  1. MySQL 5.7 Reference Manual, 12 Data Types http://dev.mysql.com/doc/refman/5.7/en/data-types.html
  2. MySQL 5.7 Reference Manual, 10.1 Character Set Support http://dev.mysql.com/doc/refman/5.5/en/charset.html
  3. MySQL 5.7 Reference Manual, C.10.4 Limits on Table Column Count and Row Size http://dev.mysql.com/doc/refman/5.7/en/column-count-limit.html
  4. Difference between “int” and “int(3)” data types in mysql http://stackoverflow.com/q/5562322
  5. Which MySQL Datatype to use for storing boolean values? http://stackoverflow.com/q/289727
  6. MySQL: Large VARCHAR vs. TEXT? http://stackoverflow.com/q/2023481
  7. TINYTEXT, TEXT, MEDIUMTEXT, and LONGTEXT maximum storage sizes http://stackoverflow.com/q/13932750
]]>
+ + + <p>文本整理MySQL字段类型的常见问题和用法。</p> +<h1 id="数值类型">数值类型</h1> +<h2 id="int和int-3">int和int(3)</h2> +<p>新手在定义整数字段时,常常想当然通过,如<code>int(3)</code>,来限制整数的有效长度,然而这样仅仅只是指定了显示宽度。选择有效长度不同的整数,需要使用<code>tinyint</code>(1个字节)、<code>smallint</code>(2个字节)、<code>mediumint</code>(3个字节)、<code>int</code>(4个字节)或<code>bigint</code>(8个字节)。MySQL的相关文档如下[<a href="http://dev.mysql.com/doc/refman/5.7/en/numeric-type-attributes.html">doc</a>]:</p> + + + + + + + + + + +
+ + + MyBatis 生成器的表注释 + + https://nullwy.me/2016/12/mybatis-generator/ + 2016-12-25T13:47:02.000Z + 2023-12-05T06:15:41.870Z + + MyBatis是流行的持久化框架,通过抽象底层的JDBC代码,在类对象和数据库列之间自动映射SQL的参数和结果,以SQL为映射的间接层,实现SQL映射器。MyBatis Generator (MBG) 是一个Mybatis的代码生成器,内省数据库的表,然后自动生成映射表的实体类,并生成CRUD(插入,查询,更新,删除)操作的样板代码。MyBatis,之前所在的公司在用,生成器也在用。虽然生成器大大提供了开发效率,但生成的代码可读性比较低,尤其是自动生成的实体类,如下:

1
2
3
4
5
/**
* This field was generated by MyBatis Generator. This field corresponds to the database column author.book_id
* @mbggenerated Tue Jan 19 13:37:24 CST 2016
*/
private Integer bookId;

这些自动生成注释,没有实质性信息,其实真正有用的是,设计表时,该字段的用途,即表字段的注释。

addRemarkComments选项

庆幸的是,MyBatis生成器在版本1.3.3中添加了,addRemarkComments选项 [github],可以在生成的实体类中附带表字段的注释。addRemarkComments官方文档的介绍 [doc]:

This property is used to specify whether MBG will include table and column remarks from db table in the generated comments. The property supports these values:

  • false: This is the default value When the property is false or unspecified, all generated comments will not include table and column remarks from db table when the element was generated.
  • true: When the property is true, table and columns remarks from db table will be added to the generated comments.

Warning: If suppressAllComments option is true, this option will be ignored.

使用方法很简单,只需将MyBatis生成器的配置文件中的commentGenerator节点修改为:

1
2
3
<commentGenerator>
<property name="addRemarkComments" value="true" />
</commentGenerator>

自定义注释生成器类

通过addRemarkComments选项生成的实体类的注释不够精简。于是笔者参考MyBatis的默认的注释生成器DefaultCommentGenerator[github],对其进行改造成如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package com.test.mbg;

import java.util.Date;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.JavaElement;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.mybatis.generator.config.MergeConstants;
import org.mybatis.generator.internal.DefaultCommentGenerator;
import org.mybatis.generator.internal.util.StringUtility;

/**
* 官方类似的功能见,在版本1.3.3中添加的 addRemarkComments <br>
* http://www.mybatis.org/generator/configreference/commentGenerator.html <br>
* https://github.com/mybatis/generator/issues/23
*
* @see DefaultCommentGenerator#addRemarkComments
*/
public class RemarksCommentGenerator extends DefaultCommentGenerator {

@Override
public void addModelClassComment(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
topLevelClass.addJavaDocLine("/**");

String remarks = introspectedTable.getRemarks();
if (StringUtility.stringHasValue(remarks)) {
String[] remarkLines = remarks.split(System.getProperty("line.separator"));
for (String remarkLine : remarkLines) {
topLevelClass.addJavaDocLine(" * " + remarkLine);
}
}

topLevelClass.addJavaDocLine(" * ");
StringBuilder sb = new StringBuilder();
sb.append(" * ");
sb.append(introspectedTable.getFullyQualifiedTable());
topLevelClass.addJavaDocLine(sb.toString());
topLevelClass.addJavaDocLine(" *");
addJavadocTag(topLevelClass, false);
topLevelClass.addJavaDocLine(" */");
}

public void addFieldComment(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) {
field.addJavaDocLine("/**");

String remarks = introspectedColumn.getRemarks();
if (StringUtility.stringHasValue(remarks)) {
String[] remarkLines = remarks.split(System.getProperty("line.separator"));
for (String remarkLine : remarkLines) {
field.addJavaDocLine(" * " + remarkLine);
}
}

field.addJavaDocLine(" *");
StringBuilder sb = new StringBuilder();
sb.append(" * ");
sb.append(introspectedTable.getFullyQualifiedTable());
sb.append('.');
sb.append(introspectedColumn.getActualColumnName());
field.addJavaDocLine(sb.toString());
field.addJavaDocLine(" *");
addJavadocTag(field, false);
field.addJavaDocLine(" */");
}

public void addFieldComment(Field field, IntrospectedTable introspectedTable) {
field.addJavaDocLine("/**");
addJavadocTag(field, false);
field.addJavaDocLine(" */");
}

public void addGetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) {
method.addJavaDocLine("/**");
addJavadocTag(method, false);
method.addJavaDocLine(" */");
}

public void addSetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) {
method.addJavaDocLine("/**");
addJavadocTag(method, false);
method.addJavaDocLine(" */");
}

protected void addJavadocTag(JavaElement javaElement, boolean markAsDoNotDelete) {
StringBuilder sb = new StringBuilder();
sb.append(" * ");
sb.append(MergeConstants.NEW_ELEMENT_TAG);
if (markAsDoNotDelete) {
sb.append(" do_not_delete_during_merge"); //$NON-NLS-1$
}
String s = getDateString();
if (s != null) {
sb.append(' ');
sb.append(s);
}
javaElement.addJavaDocLine(sb.toString());
}

protected String getDateString() {
return DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
}
}

MyBatis的配置文件修改为:

1
2
<commentGenerator type="com.test.mbg.RemarksCommentGenerator">
</commentGenerator>

运行MyBatis生成器

改用自定义的RemarksCommentGenerator后,运行MyBatis插件可能会报错。需要使用Java来运行MyBatis生成器,代码如下 [doc]:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.test.mbg;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

/**
* 使用Java运行 MyBatis Generator
* http://www.mybatis.org/generator/running/runningWithJava.html
*/
public class MyBatisGen {

public static void main(String[] args) throws Exception {
String fileName = "F:/code/mybatis-generator.xml";
File configFile = new File(fileName);
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
}
}
]]>
+ + + <p><a href="https://en.wikipedia.org/wiki/MyBatis">MyBatis</a>是流行的持久化框架,通过抽象底层的JDBC代码,在类对象和数据库列之间自动映射SQL的参数和结果,以SQL为映射的间接层,实现SQL映射器。<a href="http://www.mybatis.org/generator/">MyBatis Generator</a> (MBG) 是一个Mybatis的代码生成器,内省数据库的表,然后自动生成映射表的实体类,并生成CRUD(插入,查询,更新,删除)操作的样板代码。MyBatis,之前所在的公司在用,生成器也在用。虽然生成器大大提供了开发效率,但生成的代码可读性比较低,尤其是自动生成的实体类,如下:</p> + + + + + + + + + + + + +
+ + + Java 8 的 Stream API 笔记 + + https://nullwy.me/2016/12/java-8-stream-api/ + 2016-12-25T13:10:34.000Z + 2023-12-05T06:14:28.425Z + + Java 8增加了函数式编程的能力,通过流(Stream)API来支持对集合的filter/map/reduce操作。流是Java 8中处理集合的关键抽象概念,实现声明式的集合处理方式。

Java 8流API示例

对集合的filter、map和reduce操作,示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 计算偶数个数
List<Integer> list = Arrays.asList(3, 2, 12, 5, 6, 11, 13);
long count = list.stream()
.filter(x -> x % 2 == 0).count();
System.out.println(count);

// 筛选出偶数列表
List<Integer> evenList = list.stream()
.filter(x -> x % 2 == 0).collect(Collectors.toList());
System.out.println(evenList);

// 筛选出偶数列表, 然后全部元素加1
List<Integer> plusList = list.stream()
.filter(x -> x % 2 == 0)
.map(x -> x + 1).collect(Collectors.toList());
System.out.println(plusList);

// 全部偶数求和
int sum = list.stream()
.filter(x -> x % 2 == 0)
.mapToInt(Integer::intValue).sum();
System.out.println(sum);

// 全部偶数求和
sum = list.stream()
.filter(x -> x % 2 == 0)
.reduce(0, (x, y) -> x + y);
System.out.println(sum);

流与集合的区别

流(Stream)和集合(collection)有以下区别 [doc]:

  • 无存储(no storage)。流并不是存储元素的数据结构。流,通过计算的操作流水线来传输数据源。数据源,比如数据结构、数组、生成器函数或I/O通道。
  • 原生函数式(functional in nature)。对流进行操作会产生结果,但并不会修改数据源。比如,筛选流,是生成一个不包含被筛选掉的元素新流,而不是从原集合中删除元素。
  • 惰性读取(laziness-seeking)。很多对流的操作,比如筛选(filtering)、映射(mapping)或去重(duplicate removal),能够被惰性实现,以便于性能的优化。比如,“找出第一个由三个连续单词组成的String”,并不需要检测全部的输入字符串。流操作被划分为中间操作(用于生成流)和终止操作(用于生成值或副作用)。中间操作总是惰性的。
  • 可能是无界的(possibly unbounded)。集合的大小是必须确定的,但流并不是。像limit(n) 或 findFirst()这样的逻辑短路操作,允许在有限时间内完成对无限流的计算。
  • 可消耗的(consumable)。流的元素在流的生命周期中只能被访问一次。类似于 Iterator,要想重新访问同一个元素,必须生成新的流。

流操作与流水线

当使用Stream时,会通过三个阶段来建立一个操作流水线 [ref]。

  1. 创建一个Stream。
  2. 在一个或多个步骤中,指定将初始Stream转换为另一个Stream的中间操作
  3. 使用一个终止操作来产生一个结果。该操作会强制它之前的延迟操作立即执行。在这之后,该Stream就不会再被使用了。

整个流操作流水线,如图所示 [ref]:

流操作流水线

Java 8的流创建、中间操作和终止操作的API汇总表,如下 [ref]

创建流中间操作终止操作

Collection
stream()
parallelStream()

Stream, IntStream, LongStream, DoubleStream
static generate() 无序
static of(..)
static empty()
static iterate(..)
static concat(..)
static builder()

IntStream, LongStream
static range(..)
static rangeClosed(..)

Arrays
static stream(..)

BufferedReader
lines(..)

Files
static list(..)
static walk(..)
static find(..)

JarFile
stream()

ZipFile
stream()

Pattern
splitAsStream(..)

SplittableRandom
ints(..) 无序
longs(..) 无序
doubles(..) 无序

Random
ints(..)
longs(..)
doubles(..)

ThreadLocalRandom
ints()
longs(..)
doubles(..)

BitSet
stream()

CharSequence (String)
IntStream chars()
IntStream codePoints()

StreamSupport (low level)
static doubleStream(..)
static intStream(..)
static longStream(..)
static stream(..)

BaseStream
sequential()
parallel()
unordered()
onClose(..)

Stream
filter(..)
map(..)
mapToInt(..)
mapToLong(..)
mapToDouble(..)
flatMap(..)
flatMapToInt(..)
flatMapToLong(..)
flatMapToDouble(..)
distinct() 有状态
sorted(..) 有状态
peek(..)
limit(..) 有状态, 逻辑短路
skip(..) 有状态

IntStream、LongStream和DoubleStream方法与Stream类似, 其中额外的方法如下:

IntStream
mapToObj(..)
asLongStream()
asDoubleStream()
boxed()

LongStream
mapToObj(..)
asDoubleStream()
boxed()

DoubleStream
mapToObj(..)
boxed()

BaseStream
iterator()
spliterator()

Stream
forEach(..)
forEachOrdered(..)
toArray(..)
reduce(..)
collect(..)
min(..)
max(..)
count()
anyMatch(..) 逻辑短路
allMatch(..) 逻辑短路
noneMatch(..) 逻辑短路
findFirst() 逻辑短路
findAny() 逻辑短路*, 不确定*

IntStream、LongStream和DoubleStream方法与Stream类似, 其中额外的方法如下:

IntStream, LongStream, DoubleStream
sum()
average()
summaryStatistics()

筛选与映射操作

筛选与映射操作,即上文所说的中间操作。相关的API如下:

1
2
3
Stream<T> filter(Predicate<? super T> predicate)
<R> Stream<R> map(Function<? super T,? extends R> mapper)
<R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)

filter(..),筛选出元素符合某个条件的新流。map(..),用于对元素作某种形式的转换。flatMap(..),用于将多个子流合并为一个新流。

其他的中间操作有,提取子流,limit(..)(提取前n个)和skip(..)(丢弃前n个);有状态的转换,distinct()(过滤重复元素)和sorted(..)(排序),以及主要用于日志调试的peek(..)

1
2
3
4
5
Stream<T> limit(long maxSize)
Stream<T> skip(long n)
Stream<T> distinct()
Stream<T> sorted(Comparator<? super T> comparator)
Stream<T> peek(Consumer<? super T> action)

归约操作与收集器

流有多种形式的通用的归约操作,reduce(..)collect(..),同时也有多种特化的归约形式,比如 sum()min(..)max(..)count()等。reduce(..)collect(..)的方法签名如下:

1
2
3
4
5
Optional<T> reduce(BinaryOperator<T> accumulator)
T reduce(T identity, BinaryOperator<T> accumulator)
<U> U reduce(U identity, BiFunction<U,? super T,U> accumulator,
BinaryOperator<U> combiner)
<R,A> R collect(Collector<? super T,A,R> collector)

sum()min(..)max(..)count()等特化的归约操作,是reduce(..)归约操作的特殊化,内部实现依赖reduce(..),相应JDK的实现源码可以作为印证。

IntStream的sum(..)的JDK现实源码为 [github]:

1
2
3
4
@Override
public final int sum() {
return reduce(0, Integer::sum);
}

IntStream的min(..)的JDK现实源码为 [github]:

1
2
3
4
@Override
public final OptionalInt min() {
return reduce(Math::min);
}

Stream的count()的JDK现实源码为 [github]:

1
2
3
4
@Override
public final long count() {
return mapToLong(e -> 1L).sum();
}

如果不想将流归约为单个值,而只要查看集合被流操作后的结果,需要使用收集器(collector)。上文已经见到,将流收集为List:

1
2
List<Integer> evenList = list.stream()
.filter(..).collect(Collectors.toList());

Collectors是收集器工具类,提供获取预定义收集器(实现接口Collector)的静态方法。Collectors类,除了将流收集为List,还可以是Map、Set、String,或者也能进行统计操作,如求和、计算平均值、最大值、最小值。Collectors的全部静态方法列表如下:

  • averaging[Double|Int|Long]
  • collectingAndThen
  • counting
  • groupingBy
  • groupingByConcurrent
  • joining
  • mapping
  • maxBy
  • minBy
  • partitioningBy
  • reducing
  • summarizing[Double|Int|Long]
  • summing[Double|Int|Long]
  • toCollection
  • toConcurrentMap
  • toList
  • toMap
  • toSet
]]>
+ + + <p>Java 8增加了函数式编程的能力,通过流(Stream)API来支持对集合的<a href="https://en.wikipedia.org/wiki/Filter_%28higher-order_function%29">filter</a>/<a href="https://en.wikipedia.org/wiki/Map_%28higher-order_function%29">map</a>/<a href="https://en.wikipedia.org/wiki/Fold_%28higher-order_function%29">reduce</a>操作。流是Java 8中处理集合的关键抽象概念,实现声明式的集合处理方式。</p> + + + + + + + + +
+ + + iText处理pdf书签和标注代码乱记 + + https://nullwy.me/2016/12/itext-pdf/ + 2016-12-23T14:59:09.000Z + 2023-12-04T15:12:41.466Z + + 将文档1中的书签转存到文档2​:

1
2
3
4
5
6
7
PdfReader reader1 = new PdfReader("in1.pdf");
List<HashMap<String, Object>> bookmarks = SimpleBookmark.getBookmark(reader1);

PdfReader reader2 = new PdfReader("in2.pdf");
PdfStamper stamper = new PdfStamper(reader2, new FileOutputStream("out.pdf"));
stamper.getWriter().setOutlines(bookmarks);
stamper.close();

导出书签文件​:

1
2
3
4
5
6
7
8
9
10
PdfReader reader = new PdfReader("in.pdf");
List<HashMap<String, Object>> bookmarks = SimpleBookmark.getBookmark(reader);
SimpleBookmark.exportToXML(bookmarks, new FileWriter("out.xml"), "utf-8", false);

导入书签到文件​:
PdfReader reader = new PdfReader("in.pdf");
List<HashMap<String, Object>> bookmarks = SimpleBookmark.importFromXML(new FileReader("out.xml"));
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("out.pdf"));
stamper.getWriter().setOutlines(bookmarks);
stamper.close();

将文档1中的标注(包括超链接)转存到文档2​:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
PdfReader reader1 = new PdfReader("in1.pdf");
PdfReader reader2 = new PdfReader("in2.pdf");
Document document = new Document(reader2.getPageSize(3));
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("out.pdf"));
document.open();

List<HashMap<String, Object>> bookmarks = SimpleBookmark.getBookmark(reader1);
writer.setOutlines(bookmarks);

int num = reader1.getNumberOfPages();
for (int i = 1; i <= num; i++) {
PdfImportedPage page = writer.getImportedPage(reader2, i);
PdfContentByte content = writer.getDirectContent();
content.addTemplate(page, 0, 0);

PdfDictionary pageDict = reader1.getPageN(i);
PdfArray annotArray = pageDict.getAsArray(PdfName.ANNOTS);
for (int j = 0; annotArray != null && j < annotArray.size(); ++j) {
PdfDictionary curAnnot = annotArray.getAsDict(j);
PdfAnnotation pdfAnnot = new PdfAnnotation(writer, null);
pdfAnnot.putAll(curAnnot);
writer.addAnnotation(pdfAnnot);
}
document.newPage();
}

document.close();
reader1.close();
reader2.close();

如果仅仅读取全部链接,只需将上述代码18行开始的for循环修改为:

1
2
3
4
5
6
7
8
for (int j = 0; annotArray != null && j < annotArray.size(); ++j) {
PdfDictionary curAnnot = annotArray.getAsDict(j);
if (PdfName.LINK.equals(curAnnot.getAsName(PdfName.SUBTYPE))) {
PdfAnnotation pdfAnnot = new PdfAnnotation(writer, null);
pdfAnnot.putAll(curAnnot);
writer.addAnnotation(pdfAnnot);
}
}

参考资料:

  1. iText 5 examples - iText 5 actions and annotations http://developers.itextpdf.com/content/itext-5-examples
  2. iText in Action, 2nd 2010, 7. Making documents interactive https://www.manning.com/books/itext-in-action-second-edition
]]>
+ + + <p>将文档1中的书签转存到文档2​:</p> + + + + + + + + + + + + +
+ +
diff --git a/categories/Java/index.html b/categories/Java/index.html new file mode 100644 index 00000000..6a5cb097 --- /dev/null +++ b/categories/Java/index.html @@ -0,0 +1,675 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 分类: Java | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+

Java + 分类 +

+
+ + +
+ 2018 +
+ + + + +
+ 2017 +
+ + + + + + +
+ 2016 +
+ + + + + + + + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/categories/MySQL/index.html b/categories/MySQL/index.html new file mode 100644 index 00000000..2eccb605 --- /dev/null +++ b/categories/MySQL/index.html @@ -0,0 +1,558 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 分类: MySQL | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+

MySQL + 分类 +

+
+ + +
+ 2023 +
+ + +
+ 2019 +
+ + +
+ 2018 +
+ + +
+ 2017 +
+ + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/categories/index.html b/categories/index.html new file mode 100644 index 00000000..e862d27f --- /dev/null +++ b/categories/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + categories | nullwy's blog + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + + + +
+ + + + + +
+
+ +

categories +

+ + + +
+ + + + +
+
+
+ 目前共计 5 个分类 +
+ +
+ +
+ + + +
+ + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/categories/\346\236\266\346\236\204/index.html" "b/categories/\346\236\266\346\236\204/index.html" new file mode 100644 index 00000000..9d47305e --- /dev/null +++ "b/categories/\346\236\266\346\236\204/index.html" @@ -0,0 +1,618 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 分类: 架构 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+

架构 + 分类 +

+
+ + +
+ 2023 +
+ + + + + + + + +
+ 2020 +
+ + +
+ 2019 +
+ + +
+ 2017 +
+ + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/categories/\347\274\226\347\250\213/index.html" "b/categories/\347\274\226\347\250\213/index.html" new file mode 100644 index 00000000..73b7ac52 --- /dev/null +++ "b/categories/\347\274\226\347\250\213/index.html" @@ -0,0 +1,509 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 分类: 编程 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+

编程 + 分类 +

+
+ + +
+ 2016 +
+ + + + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/categories/\350\256\241\347\256\227\346\234\272\347\263\273\347\273\237/index.html" "b/categories/\350\256\241\347\256\227\346\234\272\347\263\273\347\273\237/index.html" new file mode 100644 index 00000000..45edc7c4 --- /dev/null +++ "b/categories/\350\256\241\347\256\227\346\234\272\347\263\273\347\273\237/index.html" @@ -0,0 +1,512 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 分类: 计算机系统 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + + +
+
+
+

计算机系统 + 分类 +

+
+ + +
+ 2018 +
+ + +
+ 2016 +
+ + + +
+
+ + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/css/main.css b/css/main.css new file mode 100644 index 00000000..eeff2f38 --- /dev/null +++ b/css/main.css @@ -0,0 +1,2572 @@ +:root { + --body-bg-color: #fff; + --content-bg-color: #f5f5f5; + --card-bg-color: #f5f5f5; + --text-color: #555; + --blockquote-color: #666; + --link-color: #555; + --link-hover-color: #222; + --brand-color: #222; + --brand-hover-color: #222; + --table-row-odd-bg-color: #f9f9f9; + --table-row-hover-bg-color: #f5f5f5; + --menu-item-bg-color: #ddd; + --btn-default-bg: transparent; + --btn-default-color: var(--link-color); + --btn-default-border-color: var(--link-color); + --btn-default-hover-bg: transparent; + --btn-default-hover-color: var(--link-hover-color); + --btn-default-hover-border-color: var(--link-hover-color); +} +html { + line-height: 1.15; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} +body { + margin: 0; +} +main { + display: block; +} +h1 { + font-size: 2em; + margin: 0.67em 0; +} +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} +a { + background: transparent; +} +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} +b, +strong { + font-weight: bolder; +} +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sub { + bottom: -0.25em; +} +sup { + top: -0.5em; +} +img { + border-style: none; +} +button, +input, +optgroup, +select, +textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} +button, +input { +/* 1 */ + overflow: visible; +} +button, +select { +/* 1 */ + text-transform: none; +} +button, +[type='button'], +[type='reset'], +[type='submit'] { + -webkit-appearance: button; +} +button::-moz-focus-inner, +[type='button']::-moz-focus-inner, +[type='reset']::-moz-focus-inner, +[type='submit']::-moz-focus-inner { + border-style: none; + padding: 0; +} +button:-moz-focusring, +[type='button']:-moz-focusring, +[type='reset']:-moz-focusring, +[type='submit']:-moz-focusring { + outline: 1px dotted ButtonText; +} +fieldset { + padding: 0.35em 0.75em 0.625em; +} +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} +progress { + vertical-align: baseline; +} +textarea { + overflow: auto; +} +[type='checkbox'], +[type='radio'] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} +[type='number']::-webkit-inner-spin-button, +[type='number']::-webkit-outer-spin-button { + height: auto; +} +[type='search'] { + outline-offset: -2px; /* 2 */ + -webkit-appearance: textfield; /* 1 */ +} +[type='search']::-webkit-search-decoration { + -webkit-appearance: none; +} +::-webkit-file-upload-button { + font: inherit; /* 2 */ + -webkit-appearance: button; /* 1 */ +} +details { + display: block; +} +summary { + display: list-item; +} +template { + display: none; +} +[hidden] { + display: none; +} +::selection { + background: #262a30; + color: #eee; +} +html, +body { + height: 100%; +} +body { + background: var(--body-bg-color); + color: var(--text-color); + font-family: 'Consolas', "PingFang SC", "Microsoft YaHei", sans-serif; + font-size: 1em; + line-height: 2; +} +@media (max-width: 991px) { + body { + padding-left: 0 !important; + padding-right: 0 !important; + } +} +h1, +h2, +h3, +h4, +h5, +h6 { + font-family: 'Consolas', "PingFang SC", "Microsoft YaHei", sans-serif; + font-weight: bold; + line-height: 1.5; + margin: 20px 0 15px; +} +h1 { + font-size: 1.5em; +} +h2 { + font-size: 1.375em; +} +h3 { + font-size: 1.25em; +} +h4 { + font-size: 1.125em; +} +h5 { + font-size: 1em; +} +h6 { + font-size: 0.875em; +} +p { + margin: 0 0 20px 0; +} +a, +span.exturl { + border-bottom: 1px solid #ccc; + color: var(--link-color); + outline: 0; + text-decoration: none; + overflow-wrap: break-word; + word-wrap: break-word; + cursor: pointer; +} +a:hover, +span.exturl:hover { + border-bottom-color: var(--link-hover-color); + color: var(--link-hover-color); +} +iframe, +img, +video { + display: block; + margin-left: auto; + margin-right: auto; + max-width: 100%; +} +hr { + background-image: repeating-linear-gradient(-45deg, #ddd, #ddd 4px, transparent 4px, transparent 8px); + border: 0; + height: 3px; + margin: 40px 0; +} +blockquote { + border-left: 4px solid #ddd; + color: var(--blockquote-color); + margin: 0; + padding: 0 15px; +} +blockquote cite::before { + content: '-'; + padding: 0 5px; +} +dt { + font-weight: bold; +} +dd { + margin: 0; + padding: 0; +} +kbd { + background-color: #f5f5f5; + background-image: linear-gradient(#eee, #fff, #eee); + border: 1px solid #ccc; + border-radius: 0.2em; + box-shadow: 0.1em 0.1em 0.2em rgba(0,0,0,0.1); + color: #555; + font-family: inherit; + padding: 0.1em 0.3em; + white-space: nowrap; +} +.table-container { + overflow: auto; +} +table { + border-collapse: collapse; + border-spacing: 0; + font-size: 0.875em; + margin: 0 0 20px 0; + width: 100%; +} +tbody tr:nth-of-type(odd) { + background: var(--table-row-odd-bg-color); +} +tbody tr:hover { + background: var(--table-row-hover-bg-color); +} +caption, +th, +td { + font-weight: normal; + padding: 8px; + vertical-align: middle; +} +th, +td { + border: 1px solid #ddd; + border-bottom: 3px solid #ddd; +} +th { + font-weight: 700; + padding-bottom: 10px; +} +td { + border-bottom-width: 1px; +} +.btn { + background: var(--btn-default-bg); + border: 2px solid var(--btn-default-border-color); + border-radius: 0; + color: var(--btn-default-color); + display: inline-block; + font-size: 0.875em; + line-height: 2; + padding: 0 20px; + text-decoration: none; + transition-property: background-color; + transition-delay: 0s; + transition-duration: 0.2s; + transition-timing-function: ease-in-out; +} +.btn:hover { + background: var(--btn-default-hover-bg); + border-color: var(--btn-default-hover-border-color); + color: var(--btn-default-hover-color); +} +.btn + .btn { + margin: 0 0 8px 8px; +} +.btn .fa-fw { + text-align: left; + width: 1.285714285714286em; +} +.toggle { + line-height: 0; +} +.toggle .toggle-line { + background: #fff; + display: inline-block; + height: 2px; + left: 0; + position: relative; + top: 0; + transition: all 0.4s; + vertical-align: top; + width: 100%; +} +.toggle .toggle-line:not(:first-child) { + margin-top: 3px; +} +.toggle.toggle-arrow .toggle-line-first { + top: 2px; + transform: rotate(-45deg); + width: 50%; +} +.toggle.toggle-arrow .toggle-line-middle { + width: 90%; +} +.toggle.toggle-arrow .toggle-line-last { + top: -2px; + transform: rotate(45deg); + width: 50%; +} +.toggle.toggle-close .toggle-line-first { + top: 5px; + transform: rotate(-45deg); +} +.toggle.toggle-close .toggle-line-middle { + opacity: 0; +} +.toggle.toggle-close .toggle-line-last { + top: -5px; + transform: rotate(45deg); +} +.highlight-container { + position: relative; +} +.highlight-container:hover .copy-btn, +.highlight-container .copy-btn:focus { + opacity: 1; +} +.copy-btn { + color: #333; + cursor: pointer; + line-height: 1.6; + opacity: 0; + padding: 2px 6px; + position: absolute; + transition-delay: 0s; + transition-duration: 0.2s; + transition-timing-function: ease-in-out; + background-color: #eee; + background-image: linear-gradient(#fcfcfc, #eee); + border: 1px solid #d5d5d5; + border-radius: 3px; + font-size: 0.8125em; + right: 4px; + top: 8px; +} +.highlight, +pre { + background: #f7f7f7; + color: #4d4d4c; + line-height: 1.6; + margin: 0 auto 20px; +} +pre, +code { + font-family: consolas, Menlo, monospace, "PingFang SC", "Microsoft YaHei"; +} +code { + background: #eee; + border-radius: 3px; + color: #555; + padding: 2px 4px; + overflow-wrap: break-word; + word-wrap: break-word; +} +.highlight *::selection { + background: #d6d6d6; +} +.highlight pre { + border: 0; + margin: 0; + padding: 10px 0; +} +.highlight table { + border: 0; + margin: 0; + width: auto; +} +.highlight td { + border: 0; + padding: 0; +} +.highlight figcaption { + background: #eff2f3; + color: #4d4d4c; + display: flex; + font-size: 0.875em; + justify-content: space-between; + line-height: 1.2; + padding: 0.5em; +} +.highlight figcaption a { + color: #4d4d4c; +} +.highlight figcaption a:hover { + border-bottom-color: #4d4d4c; +} +.highlight .gutter { + -moz-user-select: none; + -ms-user-select: none; + -webkit-user-select: none; + user-select: none; +} +.highlight .gutter pre { + background: #eff2f3; + color: #869194; + padding-left: 10px; + padding-right: 10px; + text-align: right; +} +.highlight .code pre { + background: #f7f7f7; + padding-left: 10px; + width: 100%; +} +.gist table { + width: auto; +} +.gist table td { + border: 0; +} +pre { + overflow: auto; + padding: 10px; +} +pre code { + background: none; + color: #4d4d4c; + font-size: 0.875em; + padding: 0; + text-shadow: none; +} +pre .deletion { + background: #fdd; +} +pre .addition { + background: #dfd; +} +pre .meta { + color: #eab700; + -moz-user-select: none; + -ms-user-select: none; + -webkit-user-select: none; + user-select: none; +} +pre .comment { + color: #8e908c; +} +pre .variable, +pre .attribute, +pre .tag, +pre .name, +pre .regexp, +pre .ruby .constant, +pre .xml .tag .title, +pre .xml .pi, +pre .xml .doctype, +pre .html .doctype, +pre .css .id, +pre .css .class, +pre .css .pseudo { + color: #c82829; +} +pre .number, +pre .preprocessor, +pre .built_in, +pre .builtin-name, +pre .literal, +pre .params, +pre .constant, +pre .command { + color: #f5871f; +} +pre .ruby .class .title, +pre .css .rules .attribute, +pre .string, +pre .symbol, +pre .value, +pre .inheritance, +pre .header, +pre .ruby .symbol, +pre .xml .cdata, +pre .special, +pre .formula { + color: #718c00; +} +pre .title, +pre .css .hexcolor { + color: #3e999f; +} +pre .function, +pre .python .decorator, +pre .python .title, +pre .ruby .function .title, +pre .ruby .title .keyword, +pre .perl .sub, +pre .javascript .title, +pre .coffeescript .title { + color: #4271ae; +} +pre .keyword, +pre .javascript .function { + color: #8959a8; +} +.blockquote-center { + border-left: none; + margin: 40px 0; + padding: 0; + position: relative; + text-align: center; +} +.blockquote-center .fa { + display: block; + opacity: 0.6; + position: absolute; + width: 100%; +} +.blockquote-center .fa-quote-left { + border-top: 1px solid #ccc; + text-align: left; + top: -20px; +} +.blockquote-center .fa-quote-right { + border-bottom: 1px solid #ccc; + text-align: right; + bottom: -20px; +} +.blockquote-center p, +.blockquote-center div { + text-align: center; +} +.post-body .group-picture img { + margin: 0 auto; + padding: 0 3px; +} +.group-picture-row { + margin-bottom: 6px; + overflow: hidden; +} +.group-picture-column { + float: left; + margin-bottom: 10px; +} +.post-body .label { + color: #555; + display: inline; + padding: 0 2px; +} +.post-body .label.default { + background: #f0f0f0; +} +.post-body .label.primary { + background: #efe6f7; +} +.post-body .label.info { + background: #e5f2f8; +} +.post-body .label.success { + background: #e7f4e9; +} +.post-body .label.warning { + background: #fcf6e1; +} +.post-body .label.danger { + background: #fae8eb; +} +.post-body .tabs { + margin-bottom: 20px; +} +.post-body .tabs, +.tabs-comment { + display: block; + padding-top: 10px; + position: relative; +} +.post-body .tabs ul.nav-tabs, +.tabs-comment ul.nav-tabs { + display: flex; + flex-wrap: wrap; + margin: 0; + margin-bottom: -1px; + padding: 0; +} +@media (max-width: 413px) { + .post-body .tabs ul.nav-tabs, + .tabs-comment ul.nav-tabs { + display: block; + margin-bottom: 5px; + } +} +.post-body .tabs ul.nav-tabs li.tab, +.tabs-comment ul.nav-tabs li.tab { + border-bottom: 1px solid #ddd; + border-left: 1px solid transparent; + border-right: 1px solid transparent; + border-top: 3px solid transparent; + flex-grow: 1; + list-style-type: none; + border-radius: 0 0 0 0; +} +@media (max-width: 413px) { + .post-body .tabs ul.nav-tabs li.tab, + .tabs-comment ul.nav-tabs li.tab { + border-bottom: 1px solid transparent; + border-left: 3px solid transparent; + border-right: 1px solid transparent; + border-top: 1px solid transparent; + } +} +@media (max-width: 413px) { + .post-body .tabs ul.nav-tabs li.tab, + .tabs-comment ul.nav-tabs li.tab { + border-radius: 0; + } +} +.post-body .tabs ul.nav-tabs li.tab a, +.tabs-comment ul.nav-tabs li.tab a { + border-bottom: initial; + display: block; + line-height: 1.8; + outline: 0; + padding: 0.25em 0.75em; + text-align: center; + transition-delay: 0s; + transition-duration: 0.2s; + transition-timing-function: ease-out; +} +.post-body .tabs ul.nav-tabs li.tab a i, +.tabs-comment ul.nav-tabs li.tab a i { + width: 1.285714285714286em; +} +.post-body .tabs ul.nav-tabs li.tab.active, +.tabs-comment ul.nav-tabs li.tab.active { + border-bottom: 1px solid transparent; + border-left: 1px solid #ddd; + border-right: 1px solid #ddd; + border-top: 3px solid #fc6423; +} +@media (max-width: 413px) { + .post-body .tabs ul.nav-tabs li.tab.active, + .tabs-comment ul.nav-tabs li.tab.active { + border-bottom: 1px solid #ddd; + border-left: 3px solid #fc6423; + border-right: 1px solid #ddd; + border-top: 1px solid #ddd; + } +} +.post-body .tabs ul.nav-tabs li.tab.active a, +.tabs-comment ul.nav-tabs li.tab.active a { + color: var(--link-color); + cursor: default; +} +.post-body .tabs .tab-content .tab-pane, +.tabs-comment .tab-content .tab-pane { + border: 1px solid #ddd; + border-top: 0; + padding: 20px 20px 0 20px; + border-radius: 0; +} +.post-body .tabs .tab-content .tab-pane:not(.active), +.tabs-comment .tab-content .tab-pane:not(.active) { + display: none; +} +.post-body .tabs .tab-content .tab-pane.active, +.tabs-comment .tab-content .tab-pane.active { + display: block; +} +.post-body .tabs .tab-content .tab-pane.active:nth-of-type(1), +.tabs-comment .tab-content .tab-pane.active:nth-of-type(1) { + border-radius: 0 0 0 0; +} +@media (max-width: 413px) { + .post-body .tabs .tab-content .tab-pane.active:nth-of-type(1), + .tabs-comment .tab-content .tab-pane.active:nth-of-type(1) { + border-radius: 0; + } +} +.post-body .note { + border-radius: 3px; + margin-bottom: 20px; + padding: 1em; + position: relative; + border: 1px solid #eee; + border-left-width: 5px; +} +.post-body .note h2, +.post-body .note h3, +.post-body .note h4, +.post-body .note h5, +.post-body .note h6 { + margin-top: 0; + border-bottom: initial; + margin-bottom: 0; + padding-top: 0; +} +.post-body .note p:first-child, +.post-body .note ul:first-child, +.post-body .note ol:first-child, +.post-body .note table:first-child, +.post-body .note pre:first-child, +.post-body .note blockquote:first-child, +.post-body .note img:first-child { + margin-top: 0; +} +.post-body .note p:last-child, +.post-body .note ul:last-child, +.post-body .note ol:last-child, +.post-body .note table:last-child, +.post-body .note pre:last-child, +.post-body .note blockquote:last-child, +.post-body .note img:last-child { + margin-bottom: 0; +} +.post-body .note.default { + border-left-color: #777; +} +.post-body .note.default h2, +.post-body .note.default h3, +.post-body .note.default h4, +.post-body .note.default h5, +.post-body .note.default h6 { + color: #777; +} +.post-body .note.primary { + border-left-color: #6f42c1; +} +.post-body .note.primary h2, +.post-body .note.primary h3, +.post-body .note.primary h4, +.post-body .note.primary h5, +.post-body .note.primary h6 { + color: #6f42c1; +} +.post-body .note.info { + border-left-color: #428bca; +} +.post-body .note.info h2, +.post-body .note.info h3, +.post-body .note.info h4, +.post-body .note.info h5, +.post-body .note.info h6 { + color: #428bca; +} +.post-body .note.success { + border-left-color: #5cb85c; +} +.post-body .note.success h2, +.post-body .note.success h3, +.post-body .note.success h4, +.post-body .note.success h5, +.post-body .note.success h6 { + color: #5cb85c; +} +.post-body .note.warning { + border-left-color: #f0ad4e; +} +.post-body .note.warning h2, +.post-body .note.warning h3, +.post-body .note.warning h4, +.post-body .note.warning h5, +.post-body .note.warning h6 { + color: #f0ad4e; +} +.post-body .note.danger { + border-left-color: #d9534f; +} +.post-body .note.danger h2, +.post-body .note.danger h3, +.post-body .note.danger h4, +.post-body .note.danger h5, +.post-body .note.danger h6 { + color: #d9534f; +} +.pagination .prev, +.pagination .next, +.pagination .page-number, +.pagination .space { + display: inline-block; + margin: 0 10px; + padding: 0 11px; + position: relative; + top: -1px; +} +@media (max-width: 767px) { + .pagination .prev, + .pagination .next, + .pagination .page-number, + .pagination .space { + margin: 0 5px; + } +} +.pagination { + border-top: 1px solid #eee; + margin: 120px 0 0; + text-align: center; +} +.pagination .prev, +.pagination .next, +.pagination .page-number { + border-bottom: 0; + border-top: 1px solid #eee; + transition-property: border-color; + transition-delay: 0s; + transition-duration: 0.2s; + transition-timing-function: ease-in-out; +} +.pagination .prev:hover, +.pagination .next:hover, +.pagination .page-number:hover { + border-top-color: #222; +} +.pagination .space { + margin: 0; + padding: 0; +} +.pagination .prev { + margin-left: 0; +} +.pagination .next { + margin-right: 0; +} +.pagination .page-number.current { + background: #ccc; + border-top-color: #ccc; + color: #fff; +} +@media (max-width: 767px) { + .pagination { + border-top: none; + } + .pagination .prev, + .pagination .next, + .pagination .page-number { + border-bottom: 1px solid #eee; + border-top: 0; + margin-bottom: 10px; + padding: 0 10px; + } + .pagination .prev:hover, + .pagination .next:hover, + .pagination .page-number:hover { + border-bottom-color: #222; + } +} +.comments { + margin-top: 60px; + overflow: hidden; +} +.comment-button-group { + display: flex; + flex-wrap: wrap-reverse; + justify-content: center; + margin: 1em 0; +} +.comment-button-group .comment-button { + margin: 0.1em 0.2em; +} +.comment-button-group .comment-button.active { + background: var(--btn-default-hover-bg); + border-color: var(--btn-default-hover-border-color); + color: var(--btn-default-hover-color); +} +.comment-position { + display: none; +} +.comment-position.active { + display: block; +} +.tabs-comment { + background: var(--content-bg-color); + margin-top: 4em; + padding-top: 0; +} +.tabs-comment .comments { + border: 0; + box-shadow: none; + margin-top: 0; + padding-top: 0; +} +.container { + min-height: 100%; + position: relative; +} +.main-inner { + margin: 0 auto; + width: 700px; +} +@media (min-width: 1200px) { + .main-inner { + width: 800px; + } +} +@media (min-width: 1600px) { + .main-inner { + width: 900px; + } +} +@media (max-width: 767px) { + .content-wrap { + padding: 0 20px; + } +} +.header { + background: transparent; +} +.header-inner { + margin: 0 auto; + width: 700px; +} +@media (min-width: 1200px) { + .header-inner { + width: 800px; + } +} +@media (min-width: 1600px) { + .header-inner { + width: 900px; + } +} +.site-brand-container { + display: flex; + flex-shrink: 0; + padding: 0 10px; +} +.headband { + background: #222; + height: 3px; +} +.site-meta { + flex-grow: 1; + text-align: left; +} +@media (max-width: 767px) { + .site-meta { + text-align: center; + } +} +.brand { + border-bottom: none; + color: var(--brand-color); + display: inline-block; + line-height: 1.7em; + padding: 0 40px; + position: relative; +} +.brand:hover { + color: var(--brand-hover-color); +} +.site-title { + font-family: 'Consolas', "PingFang SC", "Microsoft YaHei", sans-serif; + font-size: 1.7em; + font-weight: normal; + margin: 0; +} +.site-subtitle { + color: #999; + font-size: 0.8125em; + margin: 10px 0; +} +.use-motion .brand { + opacity: 0; +} +.use-motion .site-title, +.use-motion .site-subtitle, +.use-motion .custom-logo-image { + opacity: 0; + position: relative; + top: -10px; +} +.site-nav-toggle, +.site-nav-right { + display: none; +} +@media (max-width: 767px) { + .site-nav-toggle, + .site-nav-right { + display: flex; + flex-direction: column; + justify-content: center; + } +} +.site-nav-toggle .toggle, +.site-nav-right .toggle { + color: var(--text-color); + padding: 10px; + width: 22px; +} +.site-nav-toggle .toggle .toggle-line, +.site-nav-right .toggle .toggle-line { + background: var(--text-color); + border-radius: 1px; +} +.site-nav { + display: block; +} +@media (max-width: 767px) { + .site-nav { + clear: both; + display: none; + } +} +.site-nav.site-nav-on { + display: block; +} +.menu { + margin-top: 20px; + padding-left: 0; + text-align: center; +} +.menu-item { + display: inline-block; + list-style: none; + margin: 0 10px; +} +@media (max-width: 767px) { + .menu-item { + display: block; + margin-top: 10px; + } + .menu-item.menu-item-search { + display: none; + } +} +.menu-item a, +.menu-item span.exturl { + border-bottom: 0; + display: block; + font-size: 0.8125em; + transition-property: border-color; + transition-delay: 0s; + transition-duration: 0.2s; + transition-timing-function: ease-in-out; +} +@media (hover: none) { + .menu-item a:hover, + .menu-item span.exturl:hover { + border-bottom-color: transparent !important; + } +} +.menu-item .fa, +.menu-item .fab, +.menu-item .far, +.menu-item .fas { + margin-right: 8px; +} +.menu-item .badge { + display: inline-block; + font-weight: bold; + line-height: 1; + margin-left: 0.35em; + margin-top: 0.35em; + text-align: center; + white-space: nowrap; +} +@media (max-width: 767px) { + .menu-item .badge { + float: right; + margin-left: 0; + } +} +.menu-item-active a, +.menu .menu-item a:hover, +.menu .menu-item span.exturl:hover { + background: var(--menu-item-bg-color); +} +.use-motion .menu-item { + opacity: 0; +} +.sidebar { + background: #222; + bottom: 0; + box-shadow: inset 0 2px 6px #000; + position: fixed; + top: 0; +} +@media (max-width: 991px) { + .sidebar { + display: none; + } +} +.sidebar-inner { + color: #999; + padding: 18px 10px; + text-align: center; +} +.cc-license { + margin-top: 10px; + text-align: center; +} +.cc-license .cc-opacity { + border-bottom: none; + opacity: 0.7; +} +.cc-license .cc-opacity:hover { + opacity: 0.9; +} +.cc-license img { + display: inline-block; +} +.site-author-image { + border: 2px solid #333; + display: block; + margin: 0 auto; + max-width: 96px; + padding: 2px; +} +.site-author-name { + color: #f5f5f5; + font-weight: normal; + margin: 5px 0 0; + text-align: center; +} +.site-description { + color: #999; + font-size: 0.95em; + margin-top: 5px; + text-align: center; +} +.links-of-author { + margin-top: 15px; +} +.links-of-author a, +.links-of-author span.exturl { + border-bottom-color: #555; + display: inline-block; + font-size: 0.8125em; + margin-bottom: 10px; + margin-right: 10px; + vertical-align: middle; +} +.links-of-author a::before, +.links-of-author span.exturl::before { + background: #584408; + border-radius: 50%; + content: ' '; + display: inline-block; + height: 4px; + margin-right: 3px; + vertical-align: middle; + width: 4px; +} +.sidebar-button { + margin-top: 15px; +} +.sidebar-button a { + border: 1px solid #fc6423; + border-radius: 4px; + color: #fc6423; + display: inline-block; + padding: 0 15px; +} +.sidebar-button a .fa, +.sidebar-button a .fab, +.sidebar-button a .far, +.sidebar-button a .fas { + margin-right: 5px; +} +.sidebar-button a:hover { + background: #fc6423; + border: 1px solid #fc6423; + color: #fff; +} +.sidebar-button a:hover .fa, +.sidebar-button a:hover .fab, +.sidebar-button a:hover .far, +.sidebar-button a:hover .fas { + color: #fff; +} +.links-of-blogroll { + font-size: 0.8125em; + margin-top: 10px; +} +.links-of-blogroll-title { + font-size: 0.875em; + font-weight: 600; + margin-top: 0; +} +.links-of-blogroll-list { + list-style: none; + margin: 0; + padding: 0; +} +#sidebar-dimmer { + display: none; +} +@media (max-width: 767px) { + #sidebar-dimmer { + background: #000; + display: block; + height: 100%; + left: 100%; + opacity: 0; + position: fixed; + top: 0; + width: 100%; + z-index: 1100; + } + .sidebar-active + #sidebar-dimmer { + opacity: 0.7; + transform: translateX(-100%); + transition: opacity 0.5s; + } +} +.sidebar-nav { + margin: 0; + padding-bottom: 20px; + padding-left: 0; +} +.sidebar-nav li { + border-bottom: 1px solid transparent; + color: #666; + cursor: pointer; + display: inline-block; + font-size: 0.875em; +} +.sidebar-nav li.sidebar-nav-overview { + margin-left: 10px; +} +.sidebar-nav li:hover { + color: #f5f5f5; +} +.sidebar-nav .sidebar-nav-active { + border-bottom-color: #87daff; + color: #87daff; +} +.sidebar-nav .sidebar-nav-active:hover { + color: #87daff; +} +.sidebar-panel { + display: none; + overflow-x: hidden; + overflow-y: auto; +} +.sidebar-panel-active { + display: block; +} +.sidebar-toggle { + background: #222; + bottom: 45px; + cursor: pointer; + height: 14px; + left: 30px; + padding: 5px; + position: fixed; + width: 14px; + z-index: 1300; +} +@media (max-width: 991px) { + .sidebar-toggle { + left: 20px; + opacity: 0.8; + display: none; + } +} +.sidebar-toggle:hover .toggle-line { + background: #87daff; +} +.post-toc { + font-size: 0.875em; +} +.post-toc ol { + list-style: none; + margin: 0; + padding: 0 2px 5px 15px; + text-align: left; +} +.post-toc ol > ol { + padding-left: 0; +} +.post-toc ol a { + transition-property: all; + transition-delay: 0s; + transition-duration: 0.2s; + transition-timing-function: ease-in-out; +} +.post-toc .nav-item { + line-height: 1.8; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.post-toc .nav .nav-child { + display: block; +} +.post-toc .nav .active > .nav-child { + display: block; +} +.post-toc .nav .active-current > .nav-child { + display: block; +} +.post-toc .nav .active-current > .nav-child > .nav-item { + display: block; +} +.post-toc .nav .active > a { + border-bottom-color: #87daff; + color: #87daff; +} +.post-toc .nav .active-current > a { + color: #87daff; +} +.post-toc .nav .active-current > a:hover { + color: #87daff; +} +.site-state { + display: flex; + justify-content: center; + line-height: 1.4; + margin-top: 10px; + overflow: hidden; + text-align: center; + white-space: nowrap; +} +.site-state-item { + padding: 0 15px; +} +.site-state-item:not(:first-child) { + border-left: 1px solid #333; +} +.site-state-item a { + border-bottom: none; +} +.site-state-item-count { + display: block; + font-size: 1em; + font-weight: 600; + text-align: center; +} +.site-state-item-name { + color: inherit; + font-size: 0.875em; +} +.footer { + color: #999; + font-size: 0.875em; + padding: 20px 0; +} +.footer.footer-fixed { + bottom: 0; + left: 0; + position: absolute; + right: 0; +} +.footer-inner { + box-sizing: border-box; + margin: 0 auto; + text-align: center; + width: 700px; +} +@media (min-width: 1200px) { + .footer-inner { + width: 800px; + } +} +@media (min-width: 1600px) { + .footer-inner { + width: 900px; + } +} +.languages { + display: inline-block; + font-size: 0.975em; + position: relative; +} +.languages .lang-select-label span { + margin: 0 0.5em; +} +.languages .lang-select { + height: 100%; + left: 0; + opacity: 0; + position: absolute; + top: 0; + width: 100%; +} +.with-love { + color: #ff0000; + display: inline-block; + margin: 0 5px; +} +.powered-by, +.theme-info { + display: inline-block; +} +@-moz-keyframes iconAnimate { + 0%, 100% { + transform: scale(1); + } + 10%, 30% { + transform: scale(0.9); + } + 20%, 40%, 60%, 80% { + transform: scale(1.1); + } + 50%, 70% { + transform: scale(1.1); + } +} +@-webkit-keyframes iconAnimate { + 0%, 100% { + transform: scale(1); + } + 10%, 30% { + transform: scale(0.9); + } + 20%, 40%, 60%, 80% { + transform: scale(1.1); + } + 50%, 70% { + transform: scale(1.1); + } +} +@-o-keyframes iconAnimate { + 0%, 100% { + transform: scale(1); + } + 10%, 30% { + transform: scale(0.9); + } + 20%, 40%, 60%, 80% { + transform: scale(1.1); + } + 50%, 70% { + transform: scale(1.1); + } +} +@keyframes iconAnimate { + 0%, 100% { + transform: scale(1); + } + 10%, 30% { + transform: scale(0.9); + } + 20%, 40%, 60%, 80% { + transform: scale(1.1); + } + 50%, 70% { + transform: scale(1.1); + } +} +.back-to-top { + font-size: 12px; + text-align: center; + transition-delay: 0s; + transition-duration: 0.2s; + transition-timing-function: ease-in-out; +} +.back-to-top { + background: #222; + bottom: -100px; + box-sizing: border-box; + color: #fff; + cursor: pointer; + left: 30px; + opacity: 1; + padding: 0 6px; + position: fixed; + transition-property: bottom; + z-index: 1300; + width: 24px; +} +.back-to-top span { + display: none; +} +.back-to-top:hover { + color: #87daff; +} +.back-to-top.back-to-top-on { + bottom: 19px; +} +@media (max-width: 991px) { + .back-to-top { + left: 20px; + opacity: 0.8; + } +} +.post-body { + font-family: 'Consolas', "PingFang SC", "Microsoft YaHei", sans-serif; + overflow-wrap: break-word; + word-wrap: break-word; +} +@media (min-width: 1200px) { + .post-body { + font-size: 0.975em; + } +} +.post-body .exturl .fa { + font-size: 0.875em; + margin-left: 4px; +} +.post-body .image-caption, +.post-body .figure .caption { + color: #999; + font-size: 0.875em; + font-weight: bold; + line-height: 1; + margin: -20px auto 15px; + text-align: center; +} +.post-sticky-flag { + display: inline-block; + transform: rotate(30deg); +} +.post-button { + margin-top: 40px; + text-align: center; +} +.use-motion .post-block, +.use-motion .pagination, +.use-motion .comments { + opacity: 0; +} +.use-motion .post-header { + opacity: 0; +} +.use-motion .post-body { + opacity: 0; +} +.use-motion .collection-header { + opacity: 0; +} +.posts-collapse { + margin-left: 35px; + position: relative; +} +@media (max-width: 767px) { + .posts-collapse { + margin-left: 0px; + margin-right: 0px; + } +} +.posts-collapse .collection-title { + font-size: 0.975em; + position: relative; +} +.posts-collapse .collection-title::before { + background: #999; + border: 1px solid #fff; + border-radius: 50%; + content: ' '; + height: 10px; + left: 0; + margin-left: -6px; + margin-top: -4px; + position: absolute; + top: 50%; + width: 10px; +} +.posts-collapse .collection-year { + font-size: 1.7em; + font-weight: bold; + margin: 60px 0; + position: relative; +} +.posts-collapse .collection-year::before { + background: #bbb; + border-radius: 50%; + content: ' '; + height: 8px; + left: 0; + margin-left: -4px; + margin-top: -4px; + position: absolute; + top: 50%; + width: 8px; +} +.posts-collapse .collection-header { + display: block; + margin: 0 0 0 20px; +} +.posts-collapse .collection-header small { + color: #bbb; + margin-left: 5px; +} +.posts-collapse .post-header { + border-bottom: 1px dashed #ccc; + margin: 30px 0; + padding-left: 15px; + position: relative; + transition-property: border; + transition-delay: 0s; + transition-duration: 0.2s; + transition-timing-function: ease-in-out; +} +.posts-collapse .post-header::before { + background: #bbb; + border: 1px solid #fff; + border-radius: 50%; + content: ' '; + height: 6px; + left: 0; + margin-left: -4px; + position: absolute; + top: 0.75em; + transition-property: background; + width: 6px; + transition-delay: 0s; + transition-duration: 0.2s; + transition-timing-function: ease-in-out; +} +.posts-collapse .post-header:hover { + border-bottom-color: #666; +} +.posts-collapse .post-header:hover::before { + background: #222; +} +.posts-collapse .post-meta { + display: inline; + font-size: 0.75em; + margin-right: 10px; +} +.posts-collapse .post-title { + display: inline; +} +.posts-collapse .post-title a, +.posts-collapse .post-title span.exturl { + border-bottom: none; + color: var(--link-color); +} +.posts-collapse .post-title .fa-external-link-alt { + font-size: 0.875em; + margin-left: 5px; +} +.posts-collapse::before { + background: #f5f5f5; + content: ' '; + height: 100%; + left: 0; + margin-left: -2px; + position: absolute; + top: 1.25em; + width: 4px; +} +.post-eof { + background: #ccc; + height: 1px; + margin: 80px auto 60px; + text-align: center; + width: 8%; +} +.post-block:last-of-type .post-eof { + display: none; +} +.content { + padding-top: 40px; +} +@media (min-width: 992px) { + .post-body { + text-align: start; + } +} +@media (max-width: 991px) { + .post-body { + text-align: start; + } +} +.post-body h1, +.post-body h2, +.post-body h3, +.post-body h4, +.post-body h5, +.post-body h6 { + padding-top: 10px; +} +.post-body h1 .header-anchor, +.post-body h2 .header-anchor, +.post-body h3 .header-anchor, +.post-body h4 .header-anchor, +.post-body h5 .header-anchor, +.post-body h6 .header-anchor { + border-bottom-style: none; + color: #ccc; + float: right; + margin-left: 10px; + visibility: hidden; +} +.post-body h1 .header-anchor:hover, +.post-body h2 .header-anchor:hover, +.post-body h3 .header-anchor:hover, +.post-body h4 .header-anchor:hover, +.post-body h5 .header-anchor:hover, +.post-body h6 .header-anchor:hover { + color: inherit; +} +.post-body h1:hover .header-anchor, +.post-body h2:hover .header-anchor, +.post-body h3:hover .header-anchor, +.post-body h4:hover .header-anchor, +.post-body h5:hover .header-anchor, +.post-body h6:hover .header-anchor { + visibility: visible; +} +.post-body iframe, +.post-body img, +.post-body video { + margin-bottom: 20px; +} +.post-body .video-container { + height: 0; + margin-bottom: 20px; + overflow: hidden; + padding-top: 75%; + position: relative; + width: 100%; +} +.post-body .video-container iframe, +.post-body .video-container object, +.post-body .video-container embed { + height: 100%; + left: 0; + margin: 0; + position: absolute; + top: 0; + width: 100%; +} +.post-gallery { + align-items: center; + display: grid; + grid-gap: 10px; + grid-template-columns: 1fr 1fr 1fr; + margin-bottom: 20px; +} +@media (max-width: 767px) { + .post-gallery { + grid-template-columns: 1fr 1fr; + } +} +.post-gallery a { + border: 0; +} +.post-gallery img { + margin: 0; +} +.posts-expand .post-header { + font-size: 0.975em; +} +.posts-expand .post-title { + font-size: 1.7em; + font-weight: normal; + margin: initial; + text-align: center; + overflow-wrap: break-word; + word-wrap: break-word; +} +.posts-expand .post-title-link { + border-bottom: none; + color: var(--link-color); + display: inline-block; + position: relative; + vertical-align: top; +} +.posts-expand .post-title-link::before { + background: var(--link-color); + bottom: 0; + content: ''; + height: 2px; + left: 0; + position: absolute; + transform: scaleX(0); + visibility: hidden; + width: 100%; + transition-delay: 0s; + transition-duration: 0.2s; + transition-timing-function: ease-in-out; +} +.posts-expand .post-title-link:hover::before { + transform: scaleX(1); + visibility: visible; +} +.posts-expand .post-title-link .fa-external-link-alt { + font-size: 0.875em; + margin-left: 5px; +} +.posts-expand .post-meta { + color: #999; + font-family: 'Consolas', "PingFang SC", "Microsoft YaHei", sans-serif; + font-size: 0.75em; + margin: 3px 0 60px 0; + text-align: center; +} +.posts-expand .post-meta .post-description { + font-size: 0.875em; + margin-top: 2px; +} +.posts-expand .post-meta time { + border-bottom: 1px dashed #999; + cursor: pointer; +} +.post-meta .post-meta-item + .post-meta-item::before { + content: '|'; + margin: 0 0.5em; +} +.post-meta-divider { + margin: 0 0.5em; +} +.post-meta-item-icon { + margin-right: 3px; +} +@media (max-width: 991px) { + .post-meta-item-icon { + display: inline-block; + } +} +@media (max-width: 991px) { + .post-meta-item-text { + display: none; + } +} +.post-nav { + border-top: 1px solid #eee; + display: flex; + justify-content: space-between; + margin-top: 15px; + padding: 10px 5px 0; +} +.post-nav-item { + flex: 1; +} +.post-nav-item a { + border-bottom: none; + display: block; + font-size: 0.875em; + line-height: 1.6; + position: relative; +} +.post-nav-item a:active { + top: 2px; +} +.post-nav-item .fa { + font-size: 0.75em; +} +.post-nav-item:first-child { + margin-right: 15px; +} +.post-nav-item:first-child .fa { + margin-right: 5px; +} +.post-nav-item:last-child { + margin-left: 15px; + text-align: right; +} +.post-nav-item:last-child .fa { + margin-left: 5px; +} +.rtl.post-body p, +.rtl.post-body a, +.rtl.post-body h1, +.rtl.post-body h2, +.rtl.post-body h3, +.rtl.post-body h4, +.rtl.post-body h5, +.rtl.post-body h6, +.rtl.post-body li, +.rtl.post-body ul, +.rtl.post-body ol { + direction: rtl; + font-family: UKIJ Ekran; +} +.rtl.post-title { + font-family: UKIJ Ekran; +} +.post-tags { + margin-top: 40px; + text-align: center; +} +.post-tags a { + display: inline-block; + font-size: 0.8125em; +} +.post-tags a:not(:last-child) { + margin-right: 10px; +} +.post-widgets { + border-top: 1px solid #eee; + margin-top: 15px; + text-align: center; +} +.wp_rating { + height: 20px; + line-height: 20px; + margin-top: 10px; + padding-top: 6px; + text-align: center; +} +.social-like { + display: flex; + font-size: 0.875em; + justify-content: center; + text-align: center; +} +.reward-container { + margin: 20px auto; + padding: 10px 0; + text-align: center; + width: 90%; +} +.reward-container button { + background: transparent; + border: 1px solid #fc6423; + border-radius: 0; + color: #fc6423; + cursor: pointer; + line-height: 2; + outline: 0; + padding: 0 15px; + vertical-align: text-top; +} +.reward-container button:hover { + background: #fc6423; + border: 1px solid transparent; + color: #fa9366; +} +#qr { + padding-top: 20px; +} +#qr a { + border: 0; +} +#qr img { + display: inline-block; + margin: 0.8em 2em 0 2em; + max-width: 100%; + width: 180px; +} +#qr p { + text-align: center; +} +.post-copyright { + background: var(--card-bg-color); + border-left: 3px solid #ff2a2a; + list-style: none; + margin: 2em 0 0; + padding: 0.5em 1em; +} +.category-all-page .category-all-title { + text-align: center; +} +.category-all-page .category-all { + margin-top: 20px; +} +.category-all-page .category-list { + list-style: none; + margin: 0; + padding: 0; +} +.category-all-page .category-list-item { + margin: 5px 10px; +} +.category-all-page .category-list-count { + color: #bbb; +} +.category-all-page .category-list-count::before { + content: ' ('; + display: inline; +} +.category-all-page .category-list-count::after { + content: ') '; + display: inline; +} +.category-all-page .category-list-child { + padding-left: 10px; +} +.event-list { + padding: 0; +} +.event-list hr { + background: #222; + margin: 20px 0 45px 0; +} +.event-list hr::after { + background: #222; + color: #fff; + content: 'NOW'; + display: inline-block; + font-weight: bold; + padding: 0 5px; + text-align: right; +} +.event-list .event { + background: #222; + margin: 20px 0; + min-height: 40px; + padding: 15px 0 15px 10px; +} +.event-list .event .event-summary { + color: #fff; + margin: 0; + padding-bottom: 3px; +} +.event-list .event .event-summary::before { + animation: dot-flash 1s alternate infinite ease-in-out; + color: #fff; + content: '\f111'; + display: inline-block; + font-size: 10px; + margin-right: 25px; + vertical-align: middle; + font-family: 'Font Awesome 5 Free'; + font-weight: 900; +} +.event-list .event .event-relative-time { + color: #bbb; + display: inline-block; + font-size: 12px; + font-weight: normal; + padding-left: 12px; +} +.event-list .event .event-details { + color: #fff; + display: block; + line-height: 18px; + margin-left: 56px; + padding-bottom: 6px; + padding-top: 3px; + text-indent: -24px; +} +.event-list .event .event-details::before { + color: #fff; + display: inline-block; + margin-right: 9px; + text-align: center; + text-indent: 0; + width: 14px; + font-family: 'Font Awesome 5 Free'; + font-weight: 900; +} +.event-list .event .event-details.event-location::before { + content: '\f041'; +} +.event-list .event .event-details.event-duration::before { + content: '\f017'; +} +.event-list .event-past { + background: #f5f5f5; +} +.event-list .event-past .event-summary, +.event-list .event-past .event-details { + color: #bbb; + opacity: 0.9; +} +.event-list .event-past .event-summary::before, +.event-list .event-past .event-details::before { + animation: none; + color: #bbb; +} +@-moz-keyframes dot-flash { + from { + opacity: 1; + transform: scale(1); + } + to { + opacity: 0; + transform: scale(0.8); + } +} +@-webkit-keyframes dot-flash { + from { + opacity: 1; + transform: scale(1); + } + to { + opacity: 0; + transform: scale(0.8); + } +} +@-o-keyframes dot-flash { + from { + opacity: 1; + transform: scale(1); + } + to { + opacity: 0; + transform: scale(0.8); + } +} +@keyframes dot-flash { + from { + opacity: 1; + transform: scale(1); + } + to { + opacity: 0; + transform: scale(0.8); + } +} +ul.breadcrumb { + font-size: 0.75em; + list-style: none; + margin: 1em 0; + padding: 0 2em; + text-align: center; +} +ul.breadcrumb li { + display: inline; +} +ul.breadcrumb li + li::before { + content: '/\00a0'; + font-weight: normal; + padding: 0.5em; +} +ul.breadcrumb li + li:last-child { + font-weight: bold; +} +.tag-cloud { + text-align: center; +} +.tag-cloud a { + display: inline-block; + margin: 10px; +} +.tag-cloud a:hover { + color: var(--link-hover-color) !important; +} +.search-pop-overlay { + background: rgba(0,0,0,0); + height: 100%; + left: 0; + position: fixed; + top: 0; + transition: visibility 0s linear 0.2s, background 0.2s; + visibility: hidden; + width: 100%; + z-index: 1400; +} +.search-pop-overlay.search-active { + background: rgba(0,0,0,0.3); + transition: background 0.2s; + visibility: visible; +} +.search-popup { + background: var(--card-bg-color); + border-radius: 5px; + height: 80%; + left: calc(50% - 350px); + position: fixed; + top: 10%; + transform: scale(0); + transition: transform 0.2s; + width: 700px; + z-index: 1500; +} +.search-active .search-popup { + transform: scale(1); +} +@media (max-width: 767px) { + .search-popup { + border-radius: 0; + height: 100%; + left: 0; + margin: 0; + top: 0; + width: 100%; + } +} +.search-popup .search-icon, +.search-popup .popup-btn-close { + color: #999; + font-size: 18px; + padding: 0 10px; +} +.search-popup .popup-btn-close { + cursor: pointer; +} +.search-popup .popup-btn-close:hover .fa { + color: #222; +} +.search-popup .search-header { + background: #eee; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + display: flex; + padding: 5px; +} +.search-popup input.search-input { + background: transparent; + border: 0; + outline: 0; + width: 100%; +} +.search-popup input.search-input::-webkit-search-cancel-button { + display: none; +} +.search-popup .search-input-container { + flex-grow: 1; + padding: 2px; +} +.search-popup ul.search-result-list { + margin: 0 5px; + padding: 0; + width: 100%; +} +.search-popup p.search-result { + border-bottom: 1px dashed #ccc; + padding: 5px 0; +} +.search-popup a.search-result-title { + font-weight: bold; +} +.search-popup .search-keyword { + border-bottom: 1px dashed #ff2a2a; + color: #ff2a2a; + font-weight: bold; +} +.search-popup #search-result { + display: flex; + height: calc(100% - 55px); + overflow: auto; + padding: 5px 25px; +} +.search-popup #no-result { + color: #ccc; + margin: auto; +} +hr { + height: 2px; + margin: 20px 0; +} +.btn { + padding: 0 10px; +} +.headband { + display: none; +} +.main-inner { + padding-bottom: 80px; +} +@media (max-width: 767px) { + .main-inner { + width: auto; + } +} +.content { + padding-top: 80px; +} +@media (max-width: 767px) { + .content { + padding-top: 60px; + } +} +.pagination { + margin: 120px 0 0; + text-align: left; +} +@media (max-width: 767px) { + .pagination { + margin: 80px 10px 0; + text-align: center; + } +} +.footer { + background: var(--content-bg-color); + color: var(--text-color); + padding: 10px 0; +} +.footer-inner { + text-align: left; +} +@media (max-width: 767px) { + .footer-inner { + text-align: center; + width: auto; + } +} +.header { + background: var(--content-bg-color); +} +.header-inner { + align-items: center; + display: flex; + padding: 20px 0; +} +@media (max-width: 767px) { + .header-inner { + display: block; + padding: 10px 0; + width: auto; + } +} +.site-meta { + line-height: normal; +} +.site-meta .brand { + padding: 2px 1px; +} +@media (max-width: 767px) { + .site-meta .brand { + display: block; + } +} +.site-meta .site-title { + font-weight: bolder; +} +.logo-line-before, +.logo-line-after { + display: block; + margin: 0 auto; + overflow: hidden; + width: 75%; +} +@media (max-width: 767px) { + .logo-line-before, + .logo-line-after { + display: none; + } +} +.logo-line-before i, +.logo-line-after i { + background: var(--brand-color); + display: block; + height: 2px; + position: relative; +} +.use-motion .logo-line-before i { + left: -100%; +} +.use-motion .logo-line-after i { + right: -100%; +} +.site-subtitle { + display: none; +} +.site-nav { + flex-grow: 1; +} +@media (max-width: 767px) { + .site-nav { + padding: 10px 10px 0; + } +} +.menu { + margin: 0; +} +.menu .menu-item { + margin: 0; +} +@media (max-width: 767px) { + .menu .menu-item { + margin-top: 5px; + } +} +.menu .menu-item a, +.menu .menu-item span.exturl { + border-radius: 2px; + padding: 0 10px; + transition-property: background; +} +@media (max-width: 767px) { + .menu .menu-item a, + .menu .menu-item span.exturl { + text-align: left; + } +} +.menu .menu-item .badge { + background: #fff; + border-radius: 10px; + color: #555; + padding: 1px 4px; + text-shadow: 1px 1px 0 rgba(0,0,0,0.1); +} +.posts-expand.index .post-title, +.posts-expand.index .post-meta { + text-align: left; +} +@media (max-width: 767px) { + .posts-expand.index .post-title, + .posts-expand.index .post-meta { + text-align: center; + } +} +.posts-expand.index .post-meta { + margin: 5px 0 20px 0; +} +.posts-expand .post-eof { + display: none; +} +.posts-expand .post-block:not(:first-child) { + margin-top: 120px; +} +.posts-expand .post-title, +.posts-expand .post-meta { + text-align: center; +} +.posts-expand .post-body img { + margin-left: 0; +} +.posts-expand .post-tags { + text-align: left; +} +.posts-expand .post-tags a { + background: #f5f5f5; + border-bottom: none; + padding: 1px 5px; +} +.posts-expand .post-tags a:hover { + background: #ccc; +} +.posts-expand .post-nav { + margin-top: 40px; +} +.post-button { + margin-top: 20px; + text-align: left; +} +.post-button .btn { + background: none; + border: 0; + border-bottom: 2px solid var(--btn-default-border-color); + padding: 0; + transition-property: border; +} +.post-button .btn:hover { + border-bottom-color: var(--btn-default-hover-border-color); +} +.post-block:not(:first-child) { + margin-top: 80px !important; +} +.content { + padding-top: 60px !important; +} +.posts-expand .post-meta { + margin: 3px 0 30px 0 !important; +} +.post-body a { + color: #0366d6; +} +.post-body li p { + margin: 0; +} +.posts-expand .post-body img { + margin: 0 auto 30px; +} +.post-body .footnotes-sep { + display: none; +} +.post-body .footnotes { + font-size: 0.9em; +} +.post-body p + ul { + margin-top: -15px; +} +.post-body p + blockquote { + margin-top: -10px; +} +.post-body ul { + padding-left: 30px; +} +.post-body blockquote { + opacity: 0.85; +} +.post-body .highlight pre { + font-size: 0.975em; +} +.post-body .highlight *::selection { + background: #262a30 !important; +} +.post-copyright { + font-size: 0.95em; +} +.sidebar { + right: -320px; +} +.sidebar.sidebar-active { + right: 0; +} +.sidebar-toggle, +.back-to-top { + left: auto; + right: 30px; +} +@media (max-width: 991px) { + .sidebar-toggle, + .back-to-top { + right: 20px; + } +} +.book-mark-link { + left: 30px; +} +.sidebar { + width: 320px; + z-index: 1200; + transition-delay: 0s; + transition-duration: 0.2s; + transition-timing-function: ease-out; +} +.sidebar a, +.sidebar span.exturl { + border-bottom-color: #555; + color: #999; +} +.sidebar a:hover, +.sidebar span.exturl:hover { + border-bottom-color: #eee; + color: #eee; +} +.links-of-blogroll-item { + padding: 2px 10px; +} +.links-of-blogroll-item a, +.links-of-blogroll-item span.exturl { + box-sizing: border-box; + display: inline-block; + max-width: 280px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.sub-menu { + margin: 10px 0; +} +.sub-menu .menu-item { + display: inline-block; +} diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 00000000..49c965ac Binary files /dev/null and b/favicon.ico differ diff --git a/favicon.png b/favicon.png new file mode 100644 index 00000000..07546777 Binary files /dev/null and b/favicon.png differ diff --git a/images/algolia_logo.svg b/images/algolia_logo.svg new file mode 100644 index 00000000..47024234 --- /dev/null +++ b/images/algolia_logo.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/images/apple-touch-icon-next.png b/images/apple-touch-icon-next.png new file mode 100644 index 00000000..86a0d1d3 Binary files /dev/null and b/images/apple-touch-icon-next.png differ diff --git a/images/avatar.gif b/images/avatar.gif new file mode 100644 index 00000000..28411fd0 Binary files /dev/null and b/images/avatar.gif differ diff --git a/images/cc-by-nc-nd.svg b/images/cc-by-nc-nd.svg new file mode 100644 index 00000000..79a4f2e0 --- /dev/null +++ b/images/cc-by-nc-nd.svg @@ -0,0 +1,121 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/images/cc-by-nc-sa.svg b/images/cc-by-nc-sa.svg new file mode 100644 index 00000000..bf6bc26f --- /dev/null +++ b/images/cc-by-nc-sa.svg @@ -0,0 +1,121 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/images/cc-by-nc.svg b/images/cc-by-nc.svg new file mode 100644 index 00000000..36973490 --- /dev/null +++ b/images/cc-by-nc.svg @@ -0,0 +1,121 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/images/cc-by-nd.svg b/images/cc-by-nd.svg new file mode 100644 index 00000000..934c61e1 --- /dev/null +++ b/images/cc-by-nd.svg @@ -0,0 +1,117 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/images/cc-by-sa.svg b/images/cc-by-sa.svg new file mode 100644 index 00000000..463276a8 --- /dev/null +++ b/images/cc-by-sa.svg @@ -0,0 +1,121 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/images/cc-by.svg b/images/cc-by.svg new file mode 100644 index 00000000..4bccd14f --- /dev/null +++ b/images/cc-by.svg @@ -0,0 +1,121 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/images/cc-zero.svg b/images/cc-zero.svg new file mode 100644 index 00000000..0f866392 --- /dev/null +++ b/images/cc-zero.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/favicon-16x16-next.png b/images/favicon-16x16-next.png new file mode 100644 index 00000000..de8c5d3a Binary files /dev/null and b/images/favicon-16x16-next.png differ diff --git a/images/favicon-32x32-next.png b/images/favicon-32x32-next.png new file mode 100644 index 00000000..e02f5f4d Binary files /dev/null and b/images/favicon-32x32-next.png differ diff --git a/images/logo.svg b/images/logo.svg new file mode 100644 index 00000000..cbb3937e --- /dev/null +++ b/images/logo.svg @@ -0,0 +1,23 @@ + +image/svg+xml diff --git a/index.html b/index.html new file mode 100644 index 00000000..949b9df0 --- /dev/null +++ b/index.html @@ -0,0 +1,2410 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + nullwy's blog + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + +
+ + + + + + + + +
+ +
+ +
+
+ + +
+ + 0% +
+ + +
+
+
+ + +
+ + + + +
+ + + + + +
+

+ + +

+ + +
+ + + + +
+ + +

技术栈是构建应用的技术集合,由编程语言、框架、库、服务器、数据库、工具等组合而成。组成技术栈的技术是与具体业务无关的基础软件。互联网公司选择的技术栈,倾向于使用开源软件,相对于专有软件,开源软件具有高质量、免费、开放、灵活等优势。互联网的早期开拓者 Yahoo 的技术栈选择是经典案例,受开源运动的影响,在 2000 左右 Yahoo 从最初基于自定义的专属软件迁移了到 LAMP 技术栈。

+ +
+ + 阅读全文 » + +
+ + + +
+ + + + +
+
+
+
+ + + + + + + +
+ + + + + +
+

+ + +

+ + +
+ + + + +
+ + +

SOA 与微服务

+

Amazon,1994 年创立,早期网站是单服务、单数据库的单体架构的系统[1][2][3],全部代码由 C++ 编写,编译成单个二进制文件,整个代码仓库被命名为 Obidos。Obidos 是底层是一个 Web 页面渲染引擎,是一个框架,业务逻辑基于这个框架开发,Obidos 渲染引擎和业务逻辑共同组成整个代码仓库。随着时间的推移,Obidos 变得越来越复杂,编译 Obidos 整个代码库耗时 12 小时,开发调试效率低下[2:1]。另外,全部业务逻辑在单个二进制文件中,导致紧耦合,新功能特性无法快速发布上线。1995 年,Amazon 网站的技术架构,如下图所示[3:1]

+ +
+ + 阅读全文 » + +
+ + + +
+ + + + +
+
+
+
+ + + + + + + +
+ + + + + +
+

+ + +

+ + +
+ + + + +
+ + +

为了应对负载的增长,目前大型网站普遍都采用分布式架构。相对于采用单体架构的系统,分布式系统中有大量的服务器及设备,各模块之间存在错综复杂的依赖关系,存在更多的不确定性。整个系统的故障率会随设备的增加而呈指数级增加,单一节点问题可能会被无限放大,日常运行过程中一定会伴随故障发生。所以,可靠性开始成为大型网站关注的最重要的质量属性之一,并因此发展出了站点可靠性工程(Site reliability engineering,SRE)。站点可靠性工程,是从可靠性工程发展而来的,从可靠性工程中借鉴了概念和成果。本文溯本求源,内容主要是总结概括,可靠性工程的历史演进和核心概念,软件可靠性工程的核心概念,以及可靠性设计的方法。

+ +
+ + 阅读全文 » + +
+ + + +
+ + + + +
+
+
+
+ + + + + + + +
+ + + + + +
+

+ + +

+ + +
+ + + + +
+ + +

目前主流的网络服务器,网络 I/O 相关的底层最核心的技术都是 I/O 多路复用(I/O Multiplexing),比如 Apache HTTP Server、Nginx、Redis 等。本文尝试解释各种 I/O 模型,包括解释什么是 I/O 多路复用,同时也总结 I/O 多路复用底层的系统调用 select、poll、kqueue 和 epoll 的演进和区别,并编写了使用这些函数的示例代码。另外,本文还总结了各种基于 I/O 多路复用实现的网络服务器的并发策略的三种模式,包括对 Apache HTTP Server、Nginx 和 Redis 等网络服务器的并发策略的具体案例的解析。

+ +
+ + 阅读全文 » + +
+ + + +
+ + + + +
+
+
+
+ + + + + + + +
+ + + + + +
+

+ + +

+ + +
+ + + + +
+ + +

目前主流数据库事务的并发控制实现,如 MySQL InnoDB、PostgreSQL、Oracle,都使用两阶段封锁 2PLMVCC 技术,但具体实现细节上存在差异。InnoDB 是在以封锁技术为主体的情况下,用 MVCC 技术辅助实现读-写、写-读操作的并发。PostgreSQL 的并发控制技术是以 MVCC 技术为主,封锁技术为辅。本文主要关注 InnoDB 事务的并发控制实现。

+ +
+ + 阅读全文 » + +
+ + + +
+ + + + +
+
+
+
+ + + + + + + +
+ + + + + +
+

+ + +

+ + +
+ + + + +
+ + +

Kong 简介

+

Kong 是云原生、高效、可扩展、分布式的微服务抽象层,被称为 API 网关,或者 API 中间件。Kong 在 2015 年 4 月由 Mashape 公司开源,基于 OpenResty 和 Apache Cassandra/PostgreSQL 构建,提供易于使用的 RESTful API 来操作和配置 API 系统[1][2]

+ +
+ + 阅读全文 » + +
+ + + +
+ + + + +
+
+
+
+ + + + + + + +
+ + + + + +
+

+ + +

+ + +
+ + + + +
+ + +

2015 年 8 月,MySQL 5.7.8 开始提供对 JSON 的原生支持[1][2]。MySQL 对 JSON 的支持可以说是千呼万唤始出来。2009 年开始 NoSQL 逐渐流行起来,相继出现了键值对数据库、文档数据库、列族数据库、图数据库等各类 NoSQL,解决经典关系型数据库无法解决的痛点。其中,对灵活存储半结构化数据的需求,使得类似 MongoDB 这类文档数据库涌现出来。各大主流关系型数据库也在响应趋势,开始支持半结构化数据。早在 2012 年,PostgreSQL 9.2 就已经添加了 JSON 数据类型[3]。Oracle 也在 2014 年 7 月发布 12c Release 1 后开始支持 JSON[4][5]。Facebook 在 MySQL 5.7 没发布之前,对 5.6 版本的 MySQL 添加了存储 JSON 功能,这个特性被 Facebook 命名为 DocStore (Document Database for MySQL at Facebook)[6][7]。另外,SQL 标准组织行动也很快,在 2014 年 3 月已经完成了 SQL/JSON 标准草案(SQL/JSON Proposals)[8][9][10]。完整的草案在 2016 年 12 月正式被采纳为标准,即 SQL:2016。

+ +
+ + 阅读全文 » + +
+ + + +
+ + + + +
+
+
+
+ + + + + + + +
+ + + + + +
+

+ + +

+ + +
+ + + + +
+ + +

Elastic Stack(旧称 ELK Stack)是最受欢迎的开源日志平台 [ ref ]。Elastic Stack 由 Elasticsearch、Logstash、Kibana 和 Beats 四个组件组成:

+
    +
  • Beats,是轻量型采集器的平台,从边缘机器向 Logstash 和 Elasticsearch 发送数据。
  • +
  • Logstash,集中、转换和存储数据,是动态数据收集管道,拥有可扩展的插件生态系统,能够与 Elasticsearch 产生强大的协同作用。
  • +
  • Elasticsearch,搜索、分析和存储您的数据,是基于 JSON 的分布式搜索和分析引擎,专为实现水平扩展、高可靠性和管理便捷性而设计。
  • +
  • Kibana,实现数据可视化,导览 Elastic Stack。能够以图表的形式呈现数据,并且具有可扩展的用户界面,供您全方位配置和管理 Elastic Stack。
  • +
+ +
+ + 阅读全文 » + +
+ + + +
+ + + + +
+
+
+
+ + + + + + + +
+ + + + + +
+

+ + +

+ + +
+ + + + +
+ + +

Java 从 1.5 开始提供了 java.lang.instrumentdoc)包,该包为检测(instrument) Java 程序提供 API,比如用于监控、收集性能信息、诊断问题。通过 java.lang.instrument 实现工具被称为 Java Agent。Java Agent 可以修改类文件的字节码,通常是,在字节码方法插入额外的字节码来完成检测。关于如何使用 java.lang.instrument 包,可以参考 javadoc 的包描述(en, zh)。

+ +
+ + 阅读全文 » + +
+ + + +
+ + + + +
+
+
+
+ + + + + + + +
+ + + + + +
+

+ + +

+ + +
+ + + + +
+ + +

MySQL 的 binlog 日志文件,记录了数据库表的全部修改操作。本文简单整理 MySQL binlog 相关知识,以及如何使用 binlog 恢复或闪回数据库数据。

+

STATEMENT 格式的 binlog

+

要想开启 binlog,需要在启动 MySQL 时传入 --log-bin 参数。或者也可以在 MySQL 配置文件 /etc/my.cnf,设置 log_bin 开启 binlog。MySQL 5.7 开始,开启 binlog 后,--server-id 参数也必须指定,否则 MySQL 服务器会启动失败。

+ +
+ + 阅读全文 » + +
+ + + +
+ + + + +
+
+
+
+ + + + + + + +
+ + + + + +
+

+ + +

+ + +
+ + + + +
+ + +

栈与栈帧

+

要想知道函数是怎么被调用的,需要了解栈帧和调用惯例相关知识。俞甲子2009 的“第10章 内存: 栈与堆”对相关概念有很好的介绍。本文是对相关知识的学习笔记。

+ +
+ + 阅读全文 » + +
+ + + +
+ + + + +
+
+
+
+ + + + + + + +
+ + + + + +
+

+ + +

+ + +
+ + + + +
+ + +

遇到的问题

+

前段时间开发的时候,遇到一个问题,就是如何用 Java 实现 chdir?网上搜索一番,发现了 JNR-POSIX 项目 [ stackoverflow ]。俗话说,好记性不如烂笔头。现在将涉及到的相关知识点总结成笔记。

+ +
+ + 阅读全文 » + +
+ + + +
+ + + + +
+
+
+
+ + + + + + + +
+ + + + + +
+

+ + +

+ + +
+ + + + +
+ + +

ZooKeeper 介绍

+

ZooKeeper(wikihomegithub) 是用于分布式应用的开源的分布式协调服务。通过暴露简单的原语,分布式应用能在之上构建更高层的服务,如同步、配置管理和组成员管理等。在设计上易于编程开发,并且数据模型使用了熟知的文件系统目录树结构 [ doc ]。

+ +
+ + 阅读全文 » + +
+ + + +
+ + + + +
+
+
+
+ + + + + + + +
+ + + + + +
+

+ + +

+ + +
+ + + + +
+ + +

本文整理 Java 运行时获取方法参数名的两种方法,Java 8 的最新的方法和 Java 8 之前的方法。

+

Java 8 的新特性

+

翻阅 Java 8 的新特性,可以看到有这么一条“JEP 118: Access to Parameter Names at Runtime”。这个特性就是为了能运行时获取参数名新加的。这个 JEP 只是功能增强的提案,并没有最终实现的 JDK 相关的 API 的介绍。查看“Enhancements to the Reflection API” 会看到如下介绍:

+ +
+ + 阅读全文 » + +
+ + + +
+ + + + +
+
+
+
+ + + + + + + +
+ + + + + +
+

+ + +

+ + +
+ + + + +
+ + +

javac 是 Java 代码的编译器[1][2],初学 Java 的时候就应该接触过。本文整理一些 javac 相关的高级用法。Lombok 库,大家平常一直在使用,但可能并不知道实现原理解析,其实 Lombok 实现上依赖的是 Java 编译器的注解处理 API(JSR-296[3],本文同时尝试解析 Lombok 的实现原理。

+ +
+ + 阅读全文 » + +
+ + + +
+ + + + +
+
+
+
+ + + + + + + +
+ + + + + +
+

+ + +

+ + +
+ + + + +
+ + +

本文整理 Java 并发框架 Executor 的用法,并对结合 JDK 相关的实现源码作简单分析。

+

任务与线程池

+

先来看下 Executor 框架的 javadoc 描述 [ ref1 ref2 ]

+ +
+ + 阅读全文 » + +
+ + + +
+ + + + +
+
+
+
+ + + + + + + +
+ + + + + +
+

+ + +

+ + +
+ + + + +
+ + +

文本整理MySQL字段类型的常见问题和用法。

+

数值类型

+

int和int(3)

+

新手在定义整数字段时,常常想当然通过,如int(3),来限制整数的有效长度,然而这样仅仅只是指定了显示宽度。选择有效长度不同的整数,需要使用tinyint(1个字节)、smallint(2个字节)、mediumint(3个字节)、int(4个字节)或bigint(8个字节)。MySQL的相关文档如下[doc]:

+ +
+ + 阅读全文 » + +
+ + + +
+ + + + +
+
+
+
+ + + + + + + +
+ + + + + +
+

+ + +

+ + +
+ + + + +
+ + +

MyBatis是流行的持久化框架,通过抽象底层的JDBC代码,在类对象和数据库列之间自动映射SQL的参数和结果,以SQL为映射的间接层,实现SQL映射器。MyBatis Generator (MBG) 是一个Mybatis的代码生成器,内省数据库的表,然后自动生成映射表的实体类,并生成CRUD(插入,查询,更新,删除)操作的样板代码。MyBatis,之前所在的公司在用,生成器也在用。虽然生成器大大提供了开发效率,但生成的代码可读性比较低,尤其是自动生成的实体类,如下:

+ +
+ + 阅读全文 » + +
+ + + +
+ + + + +
+
+
+
+ + + + + + + +
+ + + + + +
+

+ + +

+ + +
+ + + + +
+ + +

Java 8增加了函数式编程的能力,通过流(Stream)API来支持对集合的filter/map/reduce操作。流是Java 8中处理集合的关键抽象概念,实现声明式的集合处理方式。

+ +
+ + 阅读全文 » + +
+ + + +
+ + + + +
+
+
+
+ + + + + + + +
+ + + + + +
+

+ + +

+ + +
+ + + + +
+ + +

将文档1中的书签转存到文档2​:

+ +
+ + 阅读全文 » + +
+ + + +
+ + + + +
+
+
+
+ + + + + + + + + + +
+ + + + +
+ + + + + + + + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/js/algolia-search.js b/js/algolia-search.js new file mode 100644 index 00000000..01a5f0b0 --- /dev/null +++ b/js/algolia-search.js @@ -0,0 +1,124 @@ +/* global instantsearch, algoliasearch, CONFIG */ + +document.addEventListener('DOMContentLoaded', () => { + const algoliaSettings = CONFIG.algolia; + const { indexName, appID, apiKey } = algoliaSettings; + + let search = instantsearch({ + indexName, + searchClient : algoliasearch(appID, apiKey), + searchFunction: helper => { + let searchInput = document.querySelector('.search-input'); + if (searchInput.value) { + helper.search(); + } + } + }); + + window.pjax && search.on('render', () => { + window.pjax.refresh(document.getElementById('algolia-hits')); + }); + + // Registering Widgets + search.addWidgets([ + instantsearch.widgets.configure({ + hitsPerPage: algoliaSettings.hits.per_page || 10 + }), + + instantsearch.widgets.searchBox({ + container : '.search-input-container', + placeholder : algoliaSettings.labels.input_placeholder, + // Hide default icons of algolia search + showReset : false, + showSubmit : false, + showLoadingIndicator: false, + cssClasses : { + input: 'search-input' + } + }), + + instantsearch.widgets.stats({ + container: '#algolia-stats', + templates: { + text: data => { + let stats = algoliaSettings.labels.hits_stats + .replace(/\$\{hits}/, data.nbHits) + .replace(/\$\{time}/, data.processingTimeMS); + return `${stats} + + Algolia + +
`; + } + } + }), + + instantsearch.widgets.hits({ + container: '#algolia-hits', + templates: { + item: data => { + let link = data.permalink ? data.permalink : CONFIG.root + data.path; + return `${data._highlightResult.title.value}`; + }, + empty: data => { + return `
+ ${algoliaSettings.labels.hits_empty.replace(/\$\{query}/, data.query)} +
`; + } + }, + cssClasses: { + item: 'algolia-hit-item' + } + }), + + instantsearch.widgets.pagination({ + container: '#algolia-pagination', + scrollTo : false, + showFirst: false, + showLast : false, + templates: { + first : '', + last : '', + previous: '', + next : '' + }, + cssClasses: { + root : 'pagination', + item : 'pagination-item', + link : 'page-number', + selectedItem: 'current', + disabledItem: 'disabled-item' + } + }) + ]); + + search.start(); + + // Handle and trigger popup window + document.querySelectorAll('.popup-trigger').forEach(element => { + element.addEventListener('click', () => { + document.body.style.overflow = 'hidden'; + document.querySelector('.search-pop-overlay').classList.add('search-active'); + document.querySelector('.search-input').focus(); + }); + }); + + // Monitor main search box + const onPopupClose = () => { + document.body.style.overflow = ''; + document.querySelector('.search-pop-overlay').classList.remove('search-active'); + }; + + document.querySelector('.search-pop-overlay').addEventListener('click', event => { + if (event.target === document.querySelector('.search-pop-overlay')) { + onPopupClose(); + } + }); + document.querySelector('.popup-btn-close').addEventListener('click', onPopupClose); + window.addEventListener('pjax:success', onPopupClose); + window.addEventListener('keyup', event => { + if (event.key === 'Escape') { + onPopupClose(); + } + }); +}); diff --git a/js/bookmark.js b/js/bookmark.js new file mode 100644 index 00000000..7c2438e1 --- /dev/null +++ b/js/bookmark.js @@ -0,0 +1,56 @@ +/* global CONFIG */ + +document.addEventListener('DOMContentLoaded', () => { + 'use strict'; + + var doSaveScroll = () => { + localStorage.setItem('bookmark' + location.pathname, window.scrollY); + }; + + var scrollToMark = () => { + var top = localStorage.getItem('bookmark' + location.pathname); + top = parseInt(top, 10); + // If the page opens with a specific hash, just jump out + if (!isNaN(top) && location.hash === '') { + // Auto scroll to the position + window.anime({ + targets : document.scrollingElement, + duration : 200, + easing : 'linear', + scrollTop: top + }); + } + }; + // Register everything + var init = function(trigger) { + // Create a link element + var link = document.querySelector('.book-mark-link'); + // Scroll event + window.addEventListener('scroll', () => link.classList.toggle('book-mark-link-fixed', window.scrollY === 0)); + // Register beforeunload event when the trigger is auto + if (trigger === 'auto') { + // Register beforeunload event + window.addEventListener('beforeunload', doSaveScroll); + window.addEventListener('pjax:send', doSaveScroll); + } + // Save the position by clicking the icon + link.addEventListener('click', () => { + doSaveScroll(); + window.anime({ + targets : link, + duration: 200, + easing : 'linear', + top : -30, + complete: () => { + setTimeout(() => { + link.style.top = ''; + }, 400); + } + }); + }); + scrollToMark(); + window.addEventListener('pjax:success', scrollToMark); + }; + + init(CONFIG.bookmark.save); +}); diff --git a/js/local-search.js b/js/local-search.js new file mode 100644 index 00000000..31f945fd --- /dev/null +++ b/js/local-search.js @@ -0,0 +1,278 @@ +/* global CONFIG */ + +document.addEventListener('DOMContentLoaded', () => { + // Popup Window + let isfetched = false; + let datas; + let isXml = true; + // Search DB path + let searchPath = CONFIG.path; + if (searchPath.length === 0) { + searchPath = 'search.xml'; + } else if (searchPath.endsWith('json')) { + isXml = false; + } + const input = document.querySelector('.search-input'); + const resultContent = document.getElementById('search-result'); + + const getIndexByWord = (word, text, caseSensitive) => { + if (CONFIG.localsearch.unescape) { + let div = document.createElement('div'); + div.innerText = word; + word = div.innerHTML; + } + let wordLen = word.length; + if (wordLen === 0) return []; + let startPosition = 0; + let position = []; + let index = []; + if (!caseSensitive) { + text = text.toLowerCase(); + word = word.toLowerCase(); + } + while ((position = text.indexOf(word, startPosition)) > -1) { + index.push({ position, word }); + startPosition = position + wordLen; + } + return index; + }; + + // Merge hits into slices + const mergeIntoSlice = (start, end, index, searchText) => { + let item = index[index.length - 1]; + let { position, word } = item; + let hits = []; + let searchTextCountInSlice = 0; + while (position + word.length <= end && index.length !== 0) { + if (word === searchText) { + searchTextCountInSlice++; + } + hits.push({ + position, + length: word.length + }); + let wordEnd = position + word.length; + + // Move to next position of hit + index.pop(); + while (index.length !== 0) { + item = index[index.length - 1]; + position = item.position; + word = item.word; + if (wordEnd > position) { + index.pop(); + } else { + break; + } + } + } + return { + hits, + start, + end, + searchTextCount: searchTextCountInSlice + }; + }; + + // Highlight title and content + const highlightKeyword = (text, slice) => { + let result = ''; + let prevEnd = slice.start; + slice.hits.forEach(hit => { + result += text.substring(prevEnd, hit.position); + let end = hit.position + hit.length; + result += `${text.substring(hit.position, end)}`; + prevEnd = end; + }); + result += text.substring(prevEnd, slice.end); + return result; + }; + + const inputEventFunction = () => { + if (!isfetched) return; + let searchText = input.value.trim().toLowerCase(); + let keywords = searchText.split(/[-\s]+/); + if (keywords.length > 1) { + keywords.push(searchText); + } + let resultItems = []; + if (searchText.length > 0) { + // Perform local searching + datas.forEach(({ title, content, url }) => { + let titleInLowerCase = title.toLowerCase(); + let contentInLowerCase = content.toLowerCase(); + let indexOfTitle = []; + let indexOfContent = []; + let searchTextCount = 0; + keywords.forEach(keyword => { + indexOfTitle = indexOfTitle.concat(getIndexByWord(keyword, titleInLowerCase, false)); + indexOfContent = indexOfContent.concat(getIndexByWord(keyword, contentInLowerCase, false)); + }); + + // Show search results + if (indexOfTitle.length > 0 || indexOfContent.length > 0) { + let hitCount = indexOfTitle.length + indexOfContent.length; + // Sort index by position of keyword + [indexOfTitle, indexOfContent].forEach(index => { + index.sort((itemLeft, itemRight) => { + if (itemRight.position !== itemLeft.position) { + return itemRight.position - itemLeft.position; + } + return itemLeft.word.length - itemRight.word.length; + }); + }); + + let slicesOfTitle = []; + if (indexOfTitle.length !== 0) { + let tmp = mergeIntoSlice(0, title.length, indexOfTitle, searchText); + searchTextCount += tmp.searchTextCountInSlice; + slicesOfTitle.push(tmp); + } + + let slicesOfContent = []; + while (indexOfContent.length !== 0) { + let item = indexOfContent[indexOfContent.length - 1]; + let { position, word } = item; + // Cut out 100 characters + let start = position - 20; + let end = position + 80; + if (start < 0) { + start = 0; + } + if (end < position + word.length) { + end = position + word.length; + } + if (end > content.length) { + end = content.length; + } + let tmp = mergeIntoSlice(start, end, indexOfContent, searchText); + searchTextCount += tmp.searchTextCountInSlice; + slicesOfContent.push(tmp); + } + + // Sort slices in content by search text's count and hits' count + slicesOfContent.sort((sliceLeft, sliceRight) => { + if (sliceLeft.searchTextCount !== sliceRight.searchTextCount) { + return sliceRight.searchTextCount - sliceLeft.searchTextCount; + } else if (sliceLeft.hits.length !== sliceRight.hits.length) { + return sliceRight.hits.length - sliceLeft.hits.length; + } + return sliceLeft.start - sliceRight.start; + }); + + // Select top N slices in content + let upperBound = parseInt(CONFIG.localsearch.top_n_per_article, 10); + if (upperBound >= 0) { + slicesOfContent = slicesOfContent.slice(0, upperBound); + } + + let resultItem = ''; + + if (slicesOfTitle.length !== 0) { + resultItem += `
  • ${highlightKeyword(title, slicesOfTitle[0])}`; + } else { + resultItem += `
  • ${title}`; + } + + slicesOfContent.forEach(slice => { + resultItem += `

    ${highlightKeyword(content, slice)}...

    `; + }); + + resultItem += '
  • '; + resultItems.push({ + item: resultItem, + id : resultItems.length, + hitCount, + searchTextCount + }); + } + }); + } + if (keywords.length === 1 && keywords[0] === '') { + resultContent.innerHTML = '
    '; + } else if (resultItems.length === 0) { + resultContent.innerHTML = '
    '; + } else { + resultItems.sort((resultLeft, resultRight) => { + if (resultLeft.searchTextCount !== resultRight.searchTextCount) { + return resultRight.searchTextCount - resultLeft.searchTextCount; + } else if (resultLeft.hitCount !== resultRight.hitCount) { + return resultRight.hitCount - resultLeft.hitCount; + } + return resultRight.id - resultLeft.id; + }); + resultContent.innerHTML = ``; + window.pjax && window.pjax.refresh(resultContent); + } + }; + + const fetchData = () => { + fetch(CONFIG.root + searchPath) + .then(response => response.text()) + .then(res => { + // Get the contents from search data + isfetched = true; + datas = isXml ? [...new DOMParser().parseFromString(res, 'text/xml').querySelectorAll('entry')].map(element => { + return { + title : element.querySelector('title').textContent, + content: element.querySelector('content').textContent, + url : element.querySelector('url').textContent + }; + }) : JSON.parse(res); + // Only match articles with not empty titles + datas = datas.filter(data => data.title).map(data => { + data.title = data.title.trim(); + data.content = data.content ? data.content.trim().replace(/<[^>]+>/g, '') : ''; + data.url = decodeURIComponent(data.url).replace(/\/{2,}/g, '/'); + return data; + }); + // Remove loading animation + document.getElementById('no-result').innerHTML = ''; + inputEventFunction(); + }); + }; + + if (CONFIG.localsearch.preload) { + fetchData(); + } + + if (CONFIG.localsearch.trigger === 'auto') { + input.addEventListener('input', inputEventFunction); + } else { + document.querySelector('.search-icon').addEventListener('click', inputEventFunction); + input.addEventListener('keypress', event => { + if (event.key === 'Enter') { + inputEventFunction(); + } + }); + } + + // Handle and trigger popup window + document.querySelectorAll('.popup-trigger').forEach(element => { + element.addEventListener('click', () => { + document.body.style.overflow = 'hidden'; + document.querySelector('.search-pop-overlay').classList.add('search-active'); + input.focus(); + if (!isfetched) fetchData(); + }); + }); + + // Monitor main search box + const onPopupClose = () => { + document.body.style.overflow = ''; + document.querySelector('.search-pop-overlay').classList.remove('search-active'); + }; + + document.querySelector('.search-pop-overlay').addEventListener('click', event => { + if (event.target === document.querySelector('.search-pop-overlay')) { + onPopupClose(); + } + }); + document.querySelector('.popup-btn-close').addEventListener('click', onPopupClose); + window.addEventListener('pjax:success', onPopupClose); + window.addEventListener('keyup', event => { + if (event.key === 'Escape') { + onPopupClose(); + } + }); +}); diff --git a/js/motion.js b/js/motion.js new file mode 100644 index 00000000..026199aa --- /dev/null +++ b/js/motion.js @@ -0,0 +1,177 @@ +/* global NexT, CONFIG, Velocity */ + +if (window.$ && window.$.Velocity) window.Velocity = window.$.Velocity; + +NexT.motion = {}; + +NexT.motion.integrator = { + queue : [], + cursor: -1, + init : function() { + this.queue = []; + this.cursor = -1; + return this; + }, + add: function(fn) { + this.queue.push(fn); + return this; + }, + next: function() { + this.cursor++; + var fn = this.queue[this.cursor]; + typeof fn === 'function' && fn(NexT.motion.integrator); + }, + bootstrap: function() { + this.next(); + } +}; + +NexT.motion.middleWares = { + logo: function(integrator) { + var sequence = []; + var brand = document.querySelector('.brand'); + var image = document.querySelector('.custom-logo-image'); + var title = document.querySelector('.site-title'); + var subtitle = document.querySelector('.site-subtitle'); + var logoLineTop = document.querySelector('.logo-line-before i'); + var logoLineBottom = document.querySelector('.logo-line-after i'); + + brand && sequence.push({ + e: brand, + p: {opacity: 1}, + o: {duration: 200} + }); + + function getMistLineSettings(element, translateX) { + return { + e: element, + p: {translateX}, + o: { + duration : 500, + sequenceQueue: false + } + }; + } + + function pushImageToSequence() { + sequence.push({ + e: image, + p: {opacity: 1, top: 0}, + o: {duration: 200} + }); + } + + CONFIG.scheme === 'Mist' && logoLineTop && logoLineBottom + && sequence.push( + getMistLineSettings(logoLineTop, '100%'), + getMistLineSettings(logoLineBottom, '-100%') + ); + + CONFIG.scheme === 'Muse' && image && pushImageToSequence(); + + title && sequence.push({ + e: title, + p: {opacity: 1, top: 0}, + o: {duration: 200} + }); + + subtitle && sequence.push({ + e: subtitle, + p: {opacity: 1, top: 0}, + o: {duration: 200} + }); + + (CONFIG.scheme === 'Pisces' || CONFIG.scheme === 'Gemini') && image && pushImageToSequence(); + + if (sequence.length > 0) { + sequence[sequence.length - 1].o.complete = function() { + integrator.next(); + }; + Velocity.RunSequence(sequence); + } else { + integrator.next(); + } + + if (CONFIG.motion.async) { + integrator.next(); + } + }, + + menu: function(integrator) { + Velocity(document.querySelectorAll('.menu-item'), 'transition.slideDownIn', { + display : null, + duration: 200, + complete: function() { + integrator.next(); + } + }); + + if (CONFIG.motion.async) { + integrator.next(); + } + }, + + subMenu: function(integrator) { + var subMenuItem = document.querySelectorAll('.sub-menu .menu-item'); + if (subMenuItem.length > 0) { + subMenuItem.forEach(element => { + element.style.opacity = 1; + }); + } + integrator.next(); + }, + + postList: function(integrator) { + var postBlock = document.querySelectorAll('.post-block, .pagination, .comments'); + var postBlockTransition = CONFIG.motion.transition.post_block; + var postHeader = document.querySelectorAll('.post-header'); + var postHeaderTransition = CONFIG.motion.transition.post_header; + var postBody = document.querySelectorAll('.post-body'); + var postBodyTransition = CONFIG.motion.transition.post_body; + var collHeader = document.querySelectorAll('.collection-header'); + var collHeaderTransition = CONFIG.motion.transition.coll_header; + + if (postBlock.length > 0) { + var postMotionOptions = window.postMotionOptions || { + stagger : 100, + drag : true, + complete: function() { + integrator.next(); + } + }; + + if (CONFIG.motion.transition.post_block) { + Velocity(postBlock, 'transition.' + postBlockTransition, postMotionOptions); + } + if (CONFIG.motion.transition.post_header) { + Velocity(postHeader, 'transition.' + postHeaderTransition, postMotionOptions); + } + if (CONFIG.motion.transition.post_body) { + Velocity(postBody, 'transition.' + postBodyTransition, postMotionOptions); + } + if (CONFIG.motion.transition.coll_header) { + Velocity(collHeader, 'transition.' + collHeaderTransition, postMotionOptions); + } + } + if (CONFIG.scheme === 'Pisces' || CONFIG.scheme === 'Gemini') { + integrator.next(); + } + }, + + sidebar: function(integrator) { + var sidebarAffix = document.querySelector('.sidebar-inner'); + var sidebarAffixTransition = CONFIG.motion.transition.sidebar; + // Only for Pisces | Gemini. + if (sidebarAffixTransition && (CONFIG.scheme === 'Pisces' || CONFIG.scheme === 'Gemini')) { + Velocity(sidebarAffix, 'transition.' + sidebarAffixTransition, { + display : null, + duration: 200, + complete: function() { + // After motion complete need to remove transform from sidebar to let affix work on Pisces | Gemini. + sidebarAffix.style.transform = 'initial'; + } + }); + } + integrator.next(); + } +}; diff --git a/js/next-boot.js b/js/next-boot.js new file mode 100644 index 00000000..52ec9aec --- /dev/null +++ b/js/next-boot.js @@ -0,0 +1,114 @@ +/* global NexT, CONFIG, Velocity */ + +NexT.boot = {}; + +NexT.boot.registerEvents = function() { + + NexT.utils.registerScrollPercent(); + NexT.utils.registerCanIUseTag(); + + // Mobile top menu bar. + document.querySelector('.site-nav-toggle .toggle').addEventListener('click', () => { + event.currentTarget.classList.toggle('toggle-close'); + var siteNav = document.querySelector('.site-nav'); + var animateAction = siteNav.classList.contains('site-nav-on') ? 'slideUp' : 'slideDown'; + + if (typeof Velocity === 'function') { + Velocity(siteNav, animateAction, { + duration: 200, + complete: function() { + siteNav.classList.toggle('site-nav-on'); + } + }); + } else { + siteNav.classList.toggle('site-nav-on'); + } + }); + + var TAB_ANIMATE_DURATION = 200; + document.querySelectorAll('.sidebar-nav li').forEach((element, index) => { + element.addEventListener('click', event => { + var item = event.currentTarget; + var activeTabClassName = 'sidebar-nav-active'; + var activePanelClassName = 'sidebar-panel-active'; + if (item.classList.contains(activeTabClassName)) return; + + var targets = document.querySelectorAll('.sidebar-panel'); + var target = targets[index]; + var currentTarget = targets[1 - index]; + window.anime({ + targets : currentTarget, + duration: TAB_ANIMATE_DURATION, + easing : 'linear', + opacity : 0, + complete: () => { + // Prevent adding TOC to Overview if Overview was selected when close & open sidebar. + currentTarget.classList.remove(activePanelClassName); + target.style.opacity = 0; + target.classList.add(activePanelClassName); + window.anime({ + targets : target, + duration: TAB_ANIMATE_DURATION, + easing : 'linear', + opacity : 1 + }); + } + }); + + [...item.parentNode.children].forEach(element => { + element.classList.remove(activeTabClassName); + }); + item.classList.add(activeTabClassName); + }); + }); + + window.addEventListener('resize', NexT.utils.initSidebarDimension); + + window.addEventListener('hashchange', () => { + var tHash = location.hash; + if (tHash !== '' && !tHash.match(/%\S{2}/)) { + var target = document.querySelector(`.tabs ul.nav-tabs li a[href="${tHash}"]`); + target && target.click(); + } + }); +}; + +NexT.boot.refresh = function() { + + /** + * Register JS handlers by condition option. + * Need to add config option in Front-End at 'layout/_partials/head.swig' file. + */ + CONFIG.fancybox && NexT.utils.wrapImageWithFancyBox(); + CONFIG.mediumzoom && window.mediumZoom('.post-body :not(a) > img, .post-body > img'); + CONFIG.lazyload && window.lozad('.post-body img').observe(); + CONFIG.pangu && window.pangu.spacingPage(); + + CONFIG.exturl && NexT.utils.registerExtURL(); + CONFIG.copycode.enable && NexT.utils.registerCopyCode(); + NexT.utils.registerTabsTag(); + NexT.utils.registerActiveMenuItem(); + NexT.utils.registerLangSelect(); + NexT.utils.registerSidebarTOC(); + NexT.utils.wrapTableWithBox(); + NexT.utils.registerVideoIframe(); +}; + +NexT.boot.motion = function() { + // Define Motion Sequence & Bootstrap Motion. + if (CONFIG.motion.enable) { + NexT.motion.integrator + .add(NexT.motion.middleWares.logo) + .add(NexT.motion.middleWares.menu) + .add(NexT.motion.middleWares.postList) + .add(NexT.motion.middleWares.sidebar) + .bootstrap(); + } + NexT.utils.updateSidebarPosition(); +}; + +document.addEventListener('DOMContentLoaded', () => { + NexT.boot.registerEvents(); + NexT.boot.refresh(); + NexT.boot.motion(); +}); diff --git a/js/schemes/muse.js b/js/schemes/muse.js new file mode 100644 index 00000000..3ad14b13 --- /dev/null +++ b/js/schemes/muse.js @@ -0,0 +1,114 @@ +/* global NexT, CONFIG, Velocity */ + +document.addEventListener('DOMContentLoaded', () => { + + var isRight = CONFIG.sidebar.position === 'right'; + var SIDEBAR_WIDTH = CONFIG.sidebar.width || 320; + var SIDEBAR_DISPLAY_DURATION = 200; + var mousePos = {}; + + var sidebarToggleLines = { + lines: document.querySelector('.sidebar-toggle'), + init : function() { + this.lines.classList.remove('toggle-arrow', 'toggle-close'); + }, + arrow: function() { + this.lines.classList.remove('toggle-close'); + this.lines.classList.add('toggle-arrow'); + }, + close: function() { + this.lines.classList.remove('toggle-arrow'); + this.lines.classList.add('toggle-close'); + } + }; + + var sidebarToggleMotion = { + sidebarEl : document.querySelector('.sidebar'), + isSidebarVisible: false, + init : function() { + sidebarToggleLines.init(); + + window.addEventListener('mousedown', this.mousedownHandler.bind(this)); + window.addEventListener('mouseup', this.mouseupHandler.bind(this)); + document.querySelector('#sidebar-dimmer').addEventListener('click', this.clickHandler.bind(this)); + document.querySelector('.sidebar-toggle').addEventListener('click', this.clickHandler.bind(this)); + document.querySelector('.sidebar-toggle').addEventListener('mouseenter', this.mouseEnterHandler.bind(this)); + document.querySelector('.sidebar-toggle').addEventListener('mouseleave', this.mouseLeaveHandler.bind(this)); + window.addEventListener('sidebar:show', this.showSidebar.bind(this)); + window.addEventListener('sidebar:hide', this.hideSidebar.bind(this)); + }, + mousedownHandler: function(event) { + mousePos.X = event.pageX; + mousePos.Y = event.pageY; + }, + mouseupHandler: function(event) { + var deltaX = event.pageX - mousePos.X; + var deltaY = event.pageY - mousePos.Y; + var clickingBlankPart = Math.sqrt((deltaX * deltaX) + (deltaY * deltaY)) < 20 && event.target.matches('.main'); + if (this.isSidebarVisible && (clickingBlankPart || event.target.matches('img.medium-zoom-image, .fancybox img'))) { + // 点击文章内容的空白区域时,是否隐藏 sidebar + // this.hideSidebar(); + } + }, + clickHandler: function() { + this.isSidebarVisible ? this.hideSidebar() : this.showSidebar(); + }, + mouseEnterHandler: function() { + if (!this.isSidebarVisible) { + sidebarToggleLines.arrow(); + } + }, + mouseLeaveHandler: function() { + if (!this.isSidebarVisible) { + sidebarToggleLines.init(); + } + }, + showSidebar: function() { + this.isSidebarVisible = true; + this.sidebarEl.classList.add('sidebar-active'); + if (typeof Velocity === 'function') { + Velocity(document.querySelectorAll('.sidebar .motion-element'), isRight ? 'transition.slideRightIn' : 'transition.slideLeftIn', { + stagger: 50, + drag : true + }); + } + + sidebarToggleLines.close(); + NexT.utils.isDesktop() && window.anime(Object.assign({ + targets : document.body, + duration: SIDEBAR_DISPLAY_DURATION, + easing : 'linear' + }, isRight ? { + 'padding-right': SIDEBAR_WIDTH + } : { + 'padding-left': SIDEBAR_WIDTH + })); + }, + hideSidebar: function() { + this.isSidebarVisible = false; + this.sidebarEl.classList.remove('sidebar-active'); + + sidebarToggleLines.init(); + NexT.utils.isDesktop() && window.anime(Object.assign({ + targets : document.body, + duration: SIDEBAR_DISPLAY_DURATION, + easing : 'linear' + }, isRight ? { + 'padding-right': 0 + } : { + 'padding-left': 0 + })); + } + }; + sidebarToggleMotion.init(); + + function updateFooterPosition() { + var footer = document.querySelector('.footer'); + var containerHeight = document.querySelector('.header').offsetHeight + document.querySelector('.main').offsetHeight + footer.offsetHeight; + footer.classList.toggle('footer-fixed', containerHeight <= window.innerHeight); + } + + updateFooterPosition(); + window.addEventListener('resize', updateFooterPosition); + window.addEventListener('scroll', updateFooterPosition); +}); diff --git a/js/schemes/pisces.js b/js/schemes/pisces.js new file mode 100644 index 00000000..41633eac --- /dev/null +++ b/js/schemes/pisces.js @@ -0,0 +1,86 @@ +/* global NexT, CONFIG */ + +var Affix = { + init: function(element, options) { + this.element = element; + this.offset = options || 0; + this.affixed = null; + this.unpin = null; + this.pinnedOffset = null; + this.checkPosition(); + window.addEventListener('scroll', this.checkPosition.bind(this)); + window.addEventListener('click', this.checkPositionWithEventLoop.bind(this)); + window.matchMedia('(min-width: 992px)').addListener(event => { + if (event.matches) { + this.offset = NexT.utils.getAffixParam(); + this.checkPosition(); + } + }); + }, + getState: function(scrollHeight, height, offsetTop, offsetBottom) { + let scrollTop = window.scrollY; + let targetHeight = window.innerHeight; + if (offsetTop != null && this.affixed === 'top') { + if (document.querySelector('.content-wrap').offsetHeight < offsetTop) return 'top'; + return scrollTop < offsetTop ? 'top' : false; + } + if (this.affixed === 'bottom') { + if (offsetTop != null) return this.unpin <= this.element.getBoundingClientRect().top ? false : 'bottom'; + return scrollTop + targetHeight <= scrollHeight - offsetBottom ? false : 'bottom'; + } + let initializing = this.affixed === null; + let colliderTop = initializing ? scrollTop : this.element.getBoundingClientRect().top + scrollTop; + let colliderHeight = initializing ? targetHeight : height; + if (offsetTop != null && scrollTop <= offsetTop) return 'top'; + if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'; + return false; + }, + getPinnedOffset: function() { + if (this.pinnedOffset) return this.pinnedOffset; + this.element.classList.remove('affix-top', 'affix-bottom'); + this.element.classList.add('affix'); + return (this.pinnedOffset = this.element.getBoundingClientRect().top); + }, + checkPositionWithEventLoop() { + setTimeout(this.checkPosition.bind(this), 1); + }, + checkPosition: function() { + if (window.getComputedStyle(this.element).display === 'none') return; + let height = this.element.offsetHeight; + let { offset } = this; + let offsetTop = offset.top; + let offsetBottom = offset.bottom; + let { scrollHeight } = document.body; + let affix = this.getState(scrollHeight, height, offsetTop, offsetBottom); + if (this.affixed !== affix) { + if (this.unpin != null) this.element.style.top = ''; + let affixType = 'affix' + (affix ? '-' + affix : ''); + this.affixed = affix; + this.unpin = affix === 'bottom' ? this.getPinnedOffset() : null; + this.element.classList.remove('affix', 'affix-top', 'affix-bottom'); + this.element.classList.add(affixType); + } + if (affix === 'bottom') { + this.element.style.top = scrollHeight - height - offsetBottom + 'px'; + } + } +}; + +NexT.utils.getAffixParam = function() { + const sidebarOffset = CONFIG.sidebar.offset || 12; + + let headerOffset = document.querySelector('.header-inner').offsetHeight; + let footerOffset = document.querySelector('.footer').offsetHeight; + + document.querySelector('.sidebar').style.marginTop = headerOffset + sidebarOffset + 'px'; + + return { + top : headerOffset, + bottom: footerOffset + }; +}; + +document.addEventListener('DOMContentLoaded', () => { + + Affix.init(document.querySelector('.sidebar-inner'), NexT.utils.getAffixParam()); +}); diff --git a/js/utils.js b/js/utils.js new file mode 100644 index 00000000..26153e7c --- /dev/null +++ b/js/utils.js @@ -0,0 +1,419 @@ +/* global NexT, CONFIG */ + +HTMLElement.prototype.wrap = function(wrapper) { + this.parentNode.insertBefore(wrapper, this); + this.parentNode.removeChild(this); + wrapper.appendChild(this); +}; + +NexT.utils = { + + /** + * Wrap images with fancybox. + */ + wrapImageWithFancyBox: function() { + document.querySelectorAll('.post-body :not(a) > img, .post-body > img').forEach(element => { + var $image = $(element); + var imageLink = $image.attr('data-src') || $image.attr('src'); + var $imageWrapLink = $image.wrap(``).parent('a'); + if ($image.is('.post-gallery img')) { + $imageWrapLink.attr('data-fancybox', 'gallery').attr('rel', 'gallery'); + } else if ($image.is('.group-picture img')) { + $imageWrapLink.attr('data-fancybox', 'group').attr('rel', 'group'); + } else { + $imageWrapLink.attr('data-fancybox', 'default').attr('rel', 'default'); + } + + var imageTitle = $image.attr('title') || $image.attr('alt'); + if (imageTitle) { + $imageWrapLink.append(`

    ${imageTitle}

    `); + // Make sure img title tag will show correctly in fancybox + $imageWrapLink.attr('title', imageTitle).attr('data-caption', imageTitle); + } + }); + + $.fancybox.defaults.hash = false; + $('.fancybox').fancybox({ + loop : true, + // 点击图片内容时,默认交互是缩放,改为关闭 + clickContent : function( current, event ) { + return current.type === 'image' ? 'close' : false; + }, + helpers: { + overlay: { + locked: false + } + } + }); + }, + + registerExtURL: function() { + document.querySelectorAll('span.exturl').forEach(element => { + let link = document.createElement('a'); + // https://stackoverflow.com/questions/30106476/using-javascripts-atob-to-decode-base64-doesnt-properly-decode-utf-8-strings + link.href = decodeURIComponent(atob(element.dataset.url).split('').map(c => { + return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); + }).join('')); + link.rel = 'noopener external nofollow noreferrer'; + link.target = '_blank'; + link.className = element.className; + link.title = element.title; + link.innerHTML = element.innerHTML; + element.parentNode.replaceChild(link, element); + }); + }, + + /** + * One-click copy code support. + */ + registerCopyCode: function() { + document.querySelectorAll('figure.highlight').forEach(element => { + const box = document.createElement('div'); + element.wrap(box); + box.classList.add('highlight-container'); + box.insertAdjacentHTML('beforeend', '
    '); + var button = element.parentNode.querySelector('.copy-btn'); + button.addEventListener('click', event => { + var target = event.currentTarget; + var code = [...target.parentNode.querySelectorAll('.code .line')].map(line => line.innerText).join('\n'); + var ta = document.createElement('textarea'); + ta.style.top = window.scrollY + 'px'; // Prevent page scrolling + ta.style.position = 'absolute'; + ta.style.opacity = '0'; + ta.readOnly = true; + ta.value = code; + document.body.append(ta); + const selection = document.getSelection(); + const selected = selection.rangeCount > 0 ? selection.getRangeAt(0) : false; + ta.select(); + ta.setSelectionRange(0, code.length); + ta.readOnly = false; + var result = document.execCommand('copy'); + if (CONFIG.copycode.show_result) { + target.querySelector('i').className = result ? 'fa fa-check fa-fw' : 'fa fa-times fa-fw'; + } + ta.blur(); // For iOS + target.blur(); + if (selected) { + selection.removeAllRanges(); + selection.addRange(selected); + } + document.body.removeChild(ta); + }); + button.addEventListener('mouseleave', event => { + setTimeout(() => { + event.target.querySelector('i').className = 'fa fa-clipboard fa-fw'; + }, 300); + }); + }); + }, + + wrapTableWithBox: function() { + document.querySelectorAll('table').forEach(element => { + const box = document.createElement('div'); + box.className = 'table-container'; + element.wrap(box); + }); + }, + + registerVideoIframe: function() { + document.querySelectorAll('iframe').forEach(element => { + const supported = [ + 'www.youtube.com', + 'player.vimeo.com', + 'player.youku.com', + 'player.bilibili.com', + 'www.tudou.com' + ].some(host => element.src.includes(host)); + if (supported && !element.parentNode.matches('.video-container')) { + const box = document.createElement('div'); + box.className = 'video-container'; + element.wrap(box); + let width = Number(element.width); + let height = Number(element.height); + if (width && height) { + element.parentNode.style.paddingTop = (height / width * 100) + '%'; + } + } + }); + }, + + registerScrollPercent: function() { + var THRESHOLD = 50; + var backToTop = document.querySelector('.back-to-top'); + var readingProgressBar = document.querySelector('.reading-progress-bar'); + // For init back to top in sidebar if page was scrolled after page refresh. + window.addEventListener('scroll', () => { + if (backToTop || readingProgressBar) { + var docHeight = document.querySelector('.container').offsetHeight; + var winHeight = window.innerHeight; + var contentVisibilityHeight = docHeight > winHeight ? docHeight - winHeight : document.body.scrollHeight - winHeight; + var scrollPercent = Math.min(100 * window.scrollY / contentVisibilityHeight, 100); + if (backToTop) { + backToTop.classList.toggle('back-to-top-on', window.scrollY > THRESHOLD); + backToTop.querySelector('span').innerText = Math.round(scrollPercent) + '%'; + } + if (readingProgressBar) { + readingProgressBar.style.width = scrollPercent.toFixed(2) + '%'; + } + } + }); + + backToTop && backToTop.addEventListener('click', () => { + window.anime({ + targets : document.scrollingElement, + duration : 500, + easing : 'linear', + scrollTop: 0 + }); + }); + }, + + /** + * Tabs tag listener (without twitter bootstrap). + */ + registerTabsTag: function() { + // Binding `nav-tabs` & `tab-content` by real time permalink changing. + document.querySelectorAll('.tabs ul.nav-tabs .tab').forEach(element => { + element.addEventListener('click', event => { + event.preventDefault(); + var target = event.currentTarget; + // Prevent selected tab to select again. + if (!target.classList.contains('active')) { + // Add & Remove active class on `nav-tabs` & `tab-content`. + [...target.parentNode.children].forEach(element => { + element.classList.remove('active'); + }); + target.classList.add('active'); + var tActive = document.getElementById(target.querySelector('a').getAttribute('href').replace('#', '')); + [...tActive.parentNode.children].forEach(element => { + element.classList.remove('active'); + }); + tActive.classList.add('active'); + // Trigger event + tActive.dispatchEvent(new Event('tabs:click', { + bubbles: true + })); + } + }); + }); + + window.dispatchEvent(new Event('tabs:register')); + }, + + registerCanIUseTag: function() { + // Get responsive height passed from iframe. + window.addEventListener('message', ({ data }) => { + if ((typeof data === 'string') && data.includes('ciu_embed')) { + var featureID = data.split(':')[1]; + var height = data.split(':')[2]; + document.querySelector(`iframe[data-feature=${featureID}]`).style.height = parseInt(height, 10) + 5 + 'px'; + } + }, false); + }, + + registerActiveMenuItem: function() { + document.querySelectorAll('.menu-item').forEach(element => { + var target = element.querySelector('a[href]'); + if (!target) return; + var isSamePath = target.pathname === location.pathname || target.pathname === location.pathname.replace('index.html', ''); + var isSubPath = !CONFIG.root.startsWith(target.pathname) && location.pathname.startsWith(target.pathname); + element.classList.toggle('menu-item-active', target.hostname === location.hostname && (isSamePath || isSubPath)); + }); + }, + + registerLangSelect: function() { + let selects = document.querySelectorAll('.lang-select'); + selects.forEach(sel => { + sel.value = CONFIG.page.lang; + sel.addEventListener('change', () => { + let target = sel.options[sel.selectedIndex]; + document.querySelectorAll('.lang-select-label span').forEach(span => span.innerText = target.text); + let url = target.dataset.href; + window.pjax ? window.pjax.loadUrl(url) : window.location.href = url; + }); + }); + }, + + registerSidebarTOC: function() { + const navItems = document.querySelectorAll('.post-toc li'); + const sections = [...navItems].map(element => { + var link = element.querySelector('a.nav-link'); + var target = document.getElementById(decodeURI(link.getAttribute('href')).replace('#', '')); + // TOC item animation navigate. + link.addEventListener('click', event => { + event.preventDefault(); + var offset = target.getBoundingClientRect().top + window.scrollY; + window.anime({ + targets : document.scrollingElement, + duration : 500, + easing : 'linear', + scrollTop: offset + 10 + }); + }); + return target; + }); + + var tocElement = document.querySelector('.post-toc-wrap'); + function activateNavByIndex(target) { + if (target.classList.contains('active-current')) return; + + document.querySelectorAll('.post-toc .active').forEach(element => { + element.classList.remove('active', 'active-current'); + }); + target.classList.add('active', 'active-current'); + var parent = target.parentNode; + while (!parent.matches('.post-toc')) { + if (parent.matches('li')) parent.classList.add('active'); + parent = parent.parentNode; + } + // Scrolling to center active TOC element if TOC content is taller then viewport. + window.anime({ + targets : tocElement, + duration : 200, + easing : 'linear', + scrollTop: tocElement.scrollTop - (tocElement.offsetHeight / 2) + target.getBoundingClientRect().top - tocElement.getBoundingClientRect().top + }); + } + + function findIndex(entries) { + let index = 0; + let entry = entries[index]; + if (entry.boundingClientRect.top > 0) { + index = sections.indexOf(entry.target); + return index === 0 ? 0 : index - 1; + } + for (; index < entries.length; index++) { + if (entries[index].boundingClientRect.top <= 0) { + entry = entries[index]; + } else { + return sections.indexOf(entry.target); + } + } + return sections.indexOf(entry.target); + } + + function createIntersectionObserver(marginTop) { + marginTop = Math.floor(marginTop + 10000); + let intersectionObserver = new IntersectionObserver((entries, observe) => { + let scrollHeight = document.documentElement.scrollHeight + 100; + if (scrollHeight > marginTop) { + observe.disconnect(); + createIntersectionObserver(scrollHeight); + return; + } + let index = findIndex(entries); + activateNavByIndex(navItems[index]); + }, { + rootMargin: marginTop + 'px 0px -100% 0px', + threshold : 0 + }); + sections.forEach(element => { + element && intersectionObserver.observe(element); + }); + } + createIntersectionObserver(document.documentElement.scrollHeight); + }, + + hasMobileUA: function() { + let ua = navigator.userAgent; + let pa = /iPad|iPhone|Android|Opera Mini|BlackBerry|webOS|UCWEB|Blazer|PSP|IEMobile|Symbian/g; + return pa.test(ua); + }, + + isTablet: function() { + return window.screen.width < 992 && window.screen.width > 767 && this.hasMobileUA(); + }, + + isMobile: function() { + return window.screen.width < 767 && this.hasMobileUA(); + }, + + isDesktop: function() { + return !this.isTablet() && !this.isMobile(); + }, + + supportsPDFs: function() { + let ua = navigator.userAgent; + let isFirefoxWithPDFJS = ua.includes('irefox') && parseInt(ua.split('rv:')[1].split('.')[0], 10) > 18; + let supportsPdfMimeType = typeof navigator.mimeTypes['application/pdf'] !== 'undefined'; + let isIOS = /iphone|ipad|ipod/i.test(ua.toLowerCase()); + return isFirefoxWithPDFJS || (supportsPdfMimeType && !isIOS); + }, + + /** + * Init Sidebar & TOC inner dimensions on all pages and for all schemes. + * Need for Sidebar/TOC inner scrolling if content taller then viewport. + */ + initSidebarDimension: function() { + var sidebarNav = document.querySelector('.sidebar-nav'); + var sidebarNavHeight = sidebarNav.style.display !== 'none' ? sidebarNav.offsetHeight : 0; + var sidebarOffset = CONFIG.sidebar.offset || 12; + var sidebarb2tHeight = CONFIG.back2top.enable && CONFIG.back2top.sidebar ? document.querySelector('.back-to-top').offsetHeight : 0; + var sidebarSchemePadding = (CONFIG.sidebar.padding * 2) + sidebarNavHeight + sidebarb2tHeight; + // Margin of sidebar b2t: -4px -10px -18px, brings a different of 22px. + if (CONFIG.scheme === 'Pisces' || CONFIG.scheme === 'Gemini') sidebarSchemePadding += (sidebarOffset * 2) - 22; + // Initialize Sidebar & TOC Height. + var sidebarWrapperHeight = document.body.offsetHeight - sidebarSchemePadding + 'px'; + document.querySelector('.site-overview-wrap').style.maxHeight = sidebarWrapperHeight; + document.querySelector('.post-toc-wrap').style.maxHeight = sidebarWrapperHeight; + }, + + updateSidebarPosition: function() { + var sidebarNav = document.querySelector('.sidebar-nav'); + var hasTOC = document.querySelector('.post-toc'); + if (hasTOC) { + sidebarNav.style.display = ''; + sidebarNav.classList.add('motion-element'); + document.querySelector('.sidebar-nav-toc').click(); + } else { + sidebarNav.style.display = 'none'; + sidebarNav.classList.remove('motion-element'); + document.querySelector('.sidebar-nav-overview').click(); + } + NexT.utils.initSidebarDimension(); + if (!this.isDesktop() || CONFIG.scheme === 'Pisces' || CONFIG.scheme === 'Gemini') return; + // Expand sidebar on post detail page by default, when post has a toc. + var display = CONFIG.page.sidebar; + if (typeof display !== 'boolean') { + // There's no definition sidebar in the page front-matter. + display = CONFIG.sidebar.display === 'always' || (CONFIG.sidebar.display === 'post' && hasTOC); + } + if (display) { + window.dispatchEvent(new Event('sidebar:show')); + } + }, + + getScript: function(url, callback, condition) { + if (condition) { + callback(); + } else { + var script = document.createElement('script'); + script.onload = script.onreadystatechange = function(_, isAbort) { + if (isAbort || !script.readyState || /loaded|complete/.test(script.readyState)) { + script.onload = script.onreadystatechange = null; + script = undefined; + if (!isAbort && callback) setTimeout(callback, 0); + } + }; + script.src = url; + document.head.appendChild(script); + } + }, + + loadComments: function(element, callback) { + if (!CONFIG.comments.lazyload || !element) { + callback(); + return; + } + let intersectionObserver = new IntersectionObserver((entries, observer) => { + let entry = entries[0]; + if (entry.isIntersecting) { + callback(); + observer.disconnect(); + } + }); + intersectionObserver.observe(element); + return intersectionObserver; + } +}; diff --git a/lib/anime.min.js b/lib/anime.min.js new file mode 100644 index 00000000..99b263aa --- /dev/null +++ b/lib/anime.min.js @@ -0,0 +1,8 @@ +/* + * anime.js v3.1.0 + * (c) 2019 Julian Garnier + * Released under the MIT license + * animejs.com + */ + +!function(n,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):n.anime=e()}(this,function(){"use strict";var n={update:null,begin:null,loopBegin:null,changeBegin:null,change:null,changeComplete:null,loopComplete:null,complete:null,loop:1,direction:"normal",autoplay:!0,timelineOffset:0},e={duration:1e3,delay:0,endDelay:0,easing:"easeOutElastic(1, .5)",round:0},r=["translateX","translateY","translateZ","rotate","rotateX","rotateY","rotateZ","scale","scaleX","scaleY","scaleZ","skew","skewX","skewY","perspective"],t={CSS:{},springs:{}};function a(n,e,r){return Math.min(Math.max(n,e),r)}function o(n,e){return n.indexOf(e)>-1}function u(n,e){return n.apply(null,e)}var i={arr:function(n){return Array.isArray(n)},obj:function(n){return o(Object.prototype.toString.call(n),"Object")},pth:function(n){return i.obj(n)&&n.hasOwnProperty("totalLength")},svg:function(n){return n instanceof SVGElement},inp:function(n){return n instanceof HTMLInputElement},dom:function(n){return n.nodeType||i.svg(n)},str:function(n){return"string"==typeof n},fnc:function(n){return"function"==typeof n},und:function(n){return void 0===n},hex:function(n){return/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(n)},rgb:function(n){return/^rgb/.test(n)},hsl:function(n){return/^hsl/.test(n)},col:function(n){return i.hex(n)||i.rgb(n)||i.hsl(n)},key:function(r){return!n.hasOwnProperty(r)&&!e.hasOwnProperty(r)&&"targets"!==r&&"keyframes"!==r}};function c(n){var e=/\(([^)]+)\)/.exec(n);return e?e[1].split(",").map(function(n){return parseFloat(n)}):[]}function s(n,e){var r=c(n),o=a(i.und(r[0])?1:r[0],.1,100),u=a(i.und(r[1])?100:r[1],.1,100),s=a(i.und(r[2])?10:r[2],.1,100),f=a(i.und(r[3])?0:r[3],.1,100),l=Math.sqrt(u/o),d=s/(2*Math.sqrt(u*o)),p=d<1?l*Math.sqrt(1-d*d):0,h=1,v=d<1?(d*l-f)/p:-f+l;function g(n){var r=e?e*n/1e3:n;return r=d<1?Math.exp(-r*d*l)*(h*Math.cos(p*r)+v*Math.sin(p*r)):(h+v*r)*Math.exp(-r*l),0===n||1===n?n:1-r}return e?g:function(){var e=t.springs[n];if(e)return e;for(var r=0,a=0;;)if(1===g(r+=1/6)){if(++a>=16)break}else a=0;var o=r*(1/6)*1e3;return t.springs[n]=o,o}}function f(n){return void 0===n&&(n=10),function(e){return Math.round(e*n)*(1/n)}}var l,d,p=function(){var n=11,e=1/(n-1);function r(n,e){return 1-3*e+3*n}function t(n,e){return 3*e-6*n}function a(n){return 3*n}function o(n,e,o){return((r(e,o)*n+t(e,o))*n+a(e))*n}function u(n,e,o){return 3*r(e,o)*n*n+2*t(e,o)*n+a(e)}return function(r,t,a,i){if(0<=r&&r<=1&&0<=a&&a<=1){var c=new Float32Array(n);if(r!==t||a!==i)for(var s=0;s=.001?function(n,e,r,t){for(var a=0;a<4;++a){var i=u(e,r,t);if(0===i)return e;e-=(o(e,r,t)-n)/i}return e}(t,l,r,a):0===d?l:function(n,e,r,t,a){for(var u,i,c=0;(u=o(i=e+(r-e)/2,t,a)-n)>0?r=i:e=i,Math.abs(u)>1e-7&&++c<10;);return i}(t,i,i+e,r,a)}}}(),h=(l={linear:function(){return function(n){return n}}},d={Sine:function(){return function(n){return 1-Math.cos(n*Math.PI/2)}},Circ:function(){return function(n){return 1-Math.sqrt(1-n*n)}},Back:function(){return function(n){return n*n*(3*n-2)}},Bounce:function(){return function(n){for(var e,r=4;n<((e=Math.pow(2,--r))-1)/11;);return 1/Math.pow(4,3-r)-7.5625*Math.pow((3*e-2)/22-n,2)}},Elastic:function(n,e){void 0===n&&(n=1),void 0===e&&(e=.5);var r=a(n,1,10),t=a(e,.1,2);return function(n){return 0===n||1===n?n:-r*Math.pow(2,10*(n-1))*Math.sin((n-1-t/(2*Math.PI)*Math.asin(1/r))*(2*Math.PI)/t)}}},["Quad","Cubic","Quart","Quint","Expo"].forEach(function(n,e){d[n]=function(){return function(n){return Math.pow(n,e+2)}}}),Object.keys(d).forEach(function(n){var e=d[n];l["easeIn"+n]=e,l["easeOut"+n]=function(n,r){return function(t){return 1-e(n,r)(1-t)}},l["easeInOut"+n]=function(n,r){return function(t){return t<.5?e(n,r)(2*t)/2:1-e(n,r)(-2*t+2)/2}}}),l);function v(n,e){if(i.fnc(n))return n;var r=n.split("(")[0],t=h[r],a=c(n);switch(r){case"spring":return s(n,e);case"cubicBezier":return u(p,a);case"steps":return u(f,a);default:return u(t,a)}}function g(n){try{return document.querySelectorAll(n)}catch(n){return}}function m(n,e){for(var r=n.length,t=arguments.length>=2?arguments[1]:void 0,a=[],o=0;o1&&(r-=1),r<1/6?n+6*(e-n)*r:r<.5?e:r<2/3?n+(e-n)*(2/3-r)*6:n}if(0==u)e=r=t=i;else{var f=i<.5?i*(1+u):i+u-i*u,l=2*i-f;e=s(l,f,o+1/3),r=s(l,f,o),t=s(l,f,o-1/3)}return"rgba("+255*e+","+255*r+","+255*t+","+c+")"}(n):void 0;var e,r,t,a}function C(n){var e=/[+-]?\d*\.?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?(%|px|pt|em|rem|in|cm|mm|ex|ch|pc|vw|vh|vmin|vmax|deg|rad|turn)?$/.exec(n);if(e)return e[1]}function B(n,e){return i.fnc(n)?n(e.target,e.id,e.total):n}function P(n,e){return n.getAttribute(e)}function I(n,e,r){if(M([r,"deg","rad","turn"],C(e)))return e;var a=t.CSS[e+r];if(!i.und(a))return a;var o=document.createElement(n.tagName),u=n.parentNode&&n.parentNode!==document?n.parentNode:document.body;u.appendChild(o),o.style.position="absolute",o.style.width=100+r;var c=100/o.offsetWidth;u.removeChild(o);var s=c*parseFloat(e);return t.CSS[e+r]=s,s}function T(n,e,r){if(e in n.style){var t=e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase(),a=n.style[e]||getComputedStyle(n).getPropertyValue(t)||"0";return r?I(n,a,r):a}}function D(n,e){return i.dom(n)&&!i.inp(n)&&(P(n,e)||i.svg(n)&&n[e])?"attribute":i.dom(n)&&M(r,e)?"transform":i.dom(n)&&"transform"!==e&&T(n,e)?"css":null!=n[e]?"object":void 0}function E(n){if(i.dom(n)){for(var e,r=n.style.transform||"",t=/(\w+)\(([^)]*)\)/g,a=new Map;e=t.exec(r);)a.set(e[1],e[2]);return a}}function F(n,e,r,t){var a,u=o(e,"scale")?1:0+(o(a=e,"translate")||"perspective"===a?"px":o(a,"rotate")||o(a,"skew")?"deg":void 0),i=E(n).get(e)||u;return r&&(r.transforms.list.set(e,i),r.transforms.last=e),t?I(n,i,t):i}function N(n,e,r,t){switch(D(n,e)){case"transform":return F(n,e,t,r);case"css":return T(n,e,r);case"attribute":return P(n,e);default:return n[e]||0}}function A(n,e){var r=/^(\*=|\+=|-=)/.exec(n);if(!r)return n;var t=C(n)||0,a=parseFloat(e),o=parseFloat(n.replace(r[0],""));switch(r[0][0]){case"+":return a+o+t;case"-":return a-o+t;case"*":return a*o+t}}function L(n,e){if(i.col(n))return O(n);if(/\s/g.test(n))return n;var r=C(n),t=r?n.substr(0,n.length-r.length):n;return e?t+e:t}function j(n,e){return Math.sqrt(Math.pow(e.x-n.x,2)+Math.pow(e.y-n.y,2))}function S(n){for(var e,r=n.points,t=0,a=0;a0&&(t+=j(e,o)),e=o}return t}function q(n){if(n.getTotalLength)return n.getTotalLength();switch(n.tagName.toLowerCase()){case"circle":return o=n,2*Math.PI*P(o,"r");case"rect":return 2*P(a=n,"width")+2*P(a,"height");case"line":return j({x:P(t=n,"x1"),y:P(t,"y1")},{x:P(t,"x2"),y:P(t,"y2")});case"polyline":return S(n);case"polygon":return r=(e=n).points,S(e)+j(r.getItem(r.numberOfItems-1),r.getItem(0))}var e,r,t,a,o}function $(n,e){var r=e||{},t=r.el||function(n){for(var e=n.parentNode;i.svg(e)&&i.svg(e.parentNode);)e=e.parentNode;return e}(n),a=t.getBoundingClientRect(),o=P(t,"viewBox"),u=a.width,c=a.height,s=r.viewBox||(o?o.split(" "):[0,0,u,c]);return{el:t,viewBox:s,x:s[0]/1,y:s[1]/1,w:u/s[2],h:c/s[3]}}function X(n,e){function r(r){void 0===r&&(r=0);var t=e+r>=1?e+r:0;return n.el.getPointAtLength(t)}var t=$(n.el,n.svg),a=r(),o=r(-1),u=r(1);switch(n.property){case"x":return(a.x-t.x)*t.w;case"y":return(a.y-t.y)*t.h;case"angle":return 180*Math.atan2(u.y-o.y,u.x-o.x)/Math.PI}}function Y(n,e){var r=/[+-]?\d*\.?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/g,t=L(i.pth(n)?n.totalLength:n,e)+"";return{original:t,numbers:t.match(r)?t.match(r).map(Number):[0],strings:i.str(n)||e?t.split(r):[]}}function Z(n){return m(n?y(i.arr(n)?n.map(b):b(n)):[],function(n,e,r){return r.indexOf(n)===e})}function Q(n){var e=Z(n);return e.map(function(n,r){return{target:n,id:r,total:e.length,transforms:{list:E(n)}}})}function V(n,e){var r=x(e);if(/^spring/.test(r.easing)&&(r.duration=s(r.easing)),i.arr(n)){var t=n.length;2===t&&!i.obj(n[0])?n={value:n}:i.fnc(e.duration)||(r.duration=e.duration/t)}var a=i.arr(n)?n:[n];return a.map(function(n,r){var t=i.obj(n)&&!i.pth(n)?n:{value:n};return i.und(t.delay)&&(t.delay=r?0:e.delay),i.und(t.endDelay)&&(t.endDelay=r===a.length-1?e.endDelay:0),t}).map(function(n){return k(n,r)})}function z(n,e){var r=[],t=e.keyframes;for(var a in t&&(e=k(function(n){for(var e=m(y(n.map(function(n){return Object.keys(n)})),function(n){return i.key(n)}).reduce(function(n,e){return n.indexOf(e)<0&&n.push(e),n},[]),r={},t=function(t){var a=e[t];r[a]=n.map(function(n){var e={};for(var r in n)i.key(r)?r==a&&(e.value=n[r]):e[r]=n[r];return e})},a=0;a-1&&(_.splice(o,1),r=_.length)}else a.tick(e);t++}n()}else U=cancelAnimationFrame(U)}return n}();function rn(r){void 0===r&&(r={});var t,o=0,u=0,i=0,c=0,s=null;function f(n){var e=window.Promise&&new Promise(function(n){return s=n});return n.finished=e,e}var l,d,p,h,v,g,y,b,M=(d=w(n,l=r),p=w(e,l),h=z(p,l),v=Q(l.targets),g=W(v,h),y=J(g,p),b=K,K++,k(d,{id:b,children:[],animatables:v,animations:g,duration:y.duration,delay:y.delay,endDelay:y.endDelay}));f(M);function x(){var n=M.direction;"alternate"!==n&&(M.direction="normal"!==n?"normal":"reverse"),M.reversed=!M.reversed,t.forEach(function(n){return n.reversed=M.reversed})}function O(n){return M.reversed?M.duration-n:n}function C(){o=0,u=O(M.currentTime)*(1/rn.speed)}function B(n,e){e&&e.seek(n-e.timelineOffset)}function P(n){for(var e=0,r=M.animations,t=r.length;e2||(b=Math.round(b*p)/p)),h.push(b)}var k=d.length;if(k){g=d[0];for(var O=0;O0&&(M.began=!0,I("begin")),!M.loopBegan&&M.currentTime>0&&(M.loopBegan=!0,I("loopBegin")),d<=r&&0!==M.currentTime&&P(0),(d>=l&&M.currentTime!==e||!e)&&P(e),d>r&&d=e&&(u=0,M.remaining&&!0!==M.remaining&&M.remaining--,M.remaining?(o=i,I("loopComplete"),M.loopBegan=!1,"alternate"===M.direction&&x()):(M.paused=!0,M.completed||(M.completed=!0,I("loopComplete"),I("complete"),!M.passThrough&&"Promise"in window&&(s(),f(M)))))}return M.reset=function(){var n=M.direction;M.passThrough=!1,M.currentTime=0,M.progress=0,M.paused=!0,M.began=!1,M.loopBegan=!1,M.changeBegan=!1,M.completed=!1,M.changeCompleted=!1,M.reversePlayback=!1,M.reversed="reverse"===n,M.remaining=M.loop,t=M.children;for(var e=c=t.length;e--;)M.children[e].reset();(M.reversed&&!0!==M.loop||"alternate"===n&&1===M.loop)&&M.remaining++,P(M.reversed?M.duration:0)},M.set=function(n,e){return R(n,e),M},M.tick=function(n){i=n,o||(o=i),T((i+(u-o))*rn.speed)},M.seek=function(n){T(O(n))},M.pause=function(){M.paused=!0,C()},M.play=function(){M.paused&&(M.completed&&M.reset(),M.paused=!1,_.push(M),C(),U||en())},M.reverse=function(){x(),C()},M.restart=function(){M.reset(),M.play()},M.reset(),M.autoplay&&M.play(),M}function tn(n,e){for(var r=e.length;r--;)M(n,e[r].animatable.target)&&e.splice(r,1)}return"undefined"!=typeof document&&document.addEventListener("visibilitychange",function(){document.hidden?(_.forEach(function(n){return n.pause()}),nn=_.slice(0),rn.running=_=[]):nn.forEach(function(n){return n.play()})}),rn.version="3.1.0",rn.speed=1,rn.running=_,rn.remove=function(n){for(var e=Z(n),r=_.length;r--;){var t=_[r],a=t.animations,o=t.children;tn(e,a);for(var u=o.length;u--;){var i=o[u],c=i.animations;tn(e,c),c.length||i.children.length||o.splice(u,1)}a.length||o.length||t.pause()}},rn.get=N,rn.set=R,rn.convertPx=I,rn.path=function(n,e){var r=i.str(n)?g(n)[0]:n,t=e||100;return function(n){return{property:n,el:r,svg:$(r),totalLength:q(r)*(t/100)}}},rn.setDashoffset=function(n){var e=q(n);return n.setAttribute("stroke-dasharray",e),e},rn.stagger=function(n,e){void 0===e&&(e={});var r=e.direction||"normal",t=e.easing?v(e.easing):null,a=e.grid,o=e.axis,u=e.from||0,c="first"===u,s="center"===u,f="last"===u,l=i.arr(n),d=l?parseFloat(n[0]):parseFloat(n),p=l?parseFloat(n[1]):0,h=C(l?n[1]:n)||0,g=e.start||0+(l?d:0),m=[],y=0;return function(n,e,i){if(c&&(u=0),s&&(u=(i-1)/2),f&&(u=i-1),!m.length){for(var v=0;v-1&&_.splice(o,1);for(var s=0;sli{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:.08em solid #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-webkit-transform:scaleY(-1);transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical,.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1);transform:scale(-1)}:root .fa-flip-both,:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-500px:before{content:"\f26e"}.fa-accessible-icon:before{content:"\f368"}.fa-accusoft:before{content:"\f369"}.fa-acquisitions-incorporated:before{content:"\f6af"}.fa-ad:before{content:"\f641"}.fa-address-book:before{content:"\f2b9"}.fa-address-card:before{content:"\f2bb"}.fa-adjust:before{content:"\f042"}.fa-adn:before{content:"\f170"}.fa-adobe:before{content:"\f778"}.fa-adversal:before{content:"\f36a"}.fa-affiliatetheme:before{content:"\f36b"}.fa-air-freshener:before{content:"\f5d0"}.fa-airbnb:before{content:"\f834"}.fa-algolia:before{content:"\f36c"}.fa-align-center:before{content:"\f037"}.fa-align-justify:before{content:"\f039"}.fa-align-left:before{content:"\f036"}.fa-align-right:before{content:"\f038"}.fa-alipay:before{content:"\f642"}.fa-allergies:before{content:"\f461"}.fa-amazon:before{content:"\f270"}.fa-amazon-pay:before{content:"\f42c"}.fa-ambulance:before{content:"\f0f9"}.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-amilia:before{content:"\f36d"}.fa-anchor:before{content:"\f13d"}.fa-android:before{content:"\f17b"}.fa-angellist:before{content:"\f209"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-down:before{content:"\f107"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angry:before{content:"\f556"}.fa-angrycreative:before{content:"\f36e"}.fa-angular:before{content:"\f420"}.fa-ankh:before{content:"\f644"}.fa-app-store:before{content:"\f36f"}.fa-app-store-ios:before{content:"\f370"}.fa-apper:before{content:"\f371"}.fa-apple:before{content:"\f179"}.fa-apple-alt:before{content:"\f5d1"}.fa-apple-pay:before{content:"\f415"}.fa-archive:before{content:"\f187"}.fa-archway:before{content:"\f557"}.fa-arrow-alt-circle-down:before{content:"\f358"}.fa-arrow-alt-circle-left:before{content:"\f359"}.fa-arrow-alt-circle-right:before{content:"\f35a"}.fa-arrow-alt-circle-up:before{content:"\f35b"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrows-alt:before{content:"\f0b2"}.fa-arrows-alt-h:before{content:"\f337"}.fa-arrows-alt-v:before{content:"\f338"}.fa-artstation:before{content:"\f77a"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asterisk:before{content:"\f069"}.fa-asymmetrik:before{content:"\f372"}.fa-at:before{content:"\f1fa"}.fa-atlas:before{content:"\f558"}.fa-atlassian:before{content:"\f77b"}.fa-atom:before{content:"\f5d2"}.fa-audible:before{content:"\f373"}.fa-audio-description:before{content:"\f29e"}.fa-autoprefixer:before{content:"\f41c"}.fa-avianex:before{content:"\f374"}.fa-aviato:before{content:"\f421"}.fa-award:before{content:"\f559"}.fa-aws:before{content:"\f375"}.fa-baby:before{content:"\f77c"}.fa-baby-carriage:before{content:"\f77d"}.fa-backspace:before{content:"\f55a"}.fa-backward:before{content:"\f04a"}.fa-bacon:before{content:"\f7e5"}.fa-bahai:before{content:"\f666"}.fa-balance-scale:before{content:"\f24e"}.fa-balance-scale-left:before{content:"\f515"}.fa-balance-scale-right:before{content:"\f516"}.fa-ban:before{content:"\f05e"}.fa-band-aid:before{content:"\f462"}.fa-bandcamp:before{content:"\f2d5"}.fa-barcode:before{content:"\f02a"}.fa-bars:before{content:"\f0c9"}.fa-baseball-ball:before{content:"\f433"}.fa-basketball-ball:before{content:"\f434"}.fa-bath:before{content:"\f2cd"}.fa-battery-empty:before{content:"\f244"}.fa-battery-full:before{content:"\f240"}.fa-battery-half:before{content:"\f242"}.fa-battery-quarter:before{content:"\f243"}.fa-battery-three-quarters:before{content:"\f241"}.fa-battle-net:before{content:"\f835"}.fa-bed:before{content:"\f236"}.fa-beer:before{content:"\f0fc"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-bell:before{content:"\f0f3"}.fa-bell-slash:before{content:"\f1f6"}.fa-bezier-curve:before{content:"\f55b"}.fa-bible:before{content:"\f647"}.fa-bicycle:before{content:"\f206"}.fa-biking:before{content:"\f84a"}.fa-bimobject:before{content:"\f378"}.fa-binoculars:before{content:"\f1e5"}.fa-biohazard:before{content:"\f780"}.fa-birthday-cake:before{content:"\f1fd"}.fa-bitbucket:before{content:"\f171"}.fa-bitcoin:before{content:"\f379"}.fa-bity:before{content:"\f37a"}.fa-black-tie:before{content:"\f27e"}.fa-blackberry:before{content:"\f37b"}.fa-blender:before{content:"\f517"}.fa-blender-phone:before{content:"\f6b6"}.fa-blind:before{content:"\f29d"}.fa-blog:before{content:"\f781"}.fa-blogger:before{content:"\f37c"}.fa-blogger-b:before{content:"\f37d"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-bold:before{content:"\f032"}.fa-bolt:before{content:"\f0e7"}.fa-bomb:before{content:"\f1e2"}.fa-bone:before{content:"\f5d7"}.fa-bong:before{content:"\f55c"}.fa-book:before{content:"\f02d"}.fa-book-dead:before{content:"\f6b7"}.fa-book-medical:before{content:"\f7e6"}.fa-book-open:before{content:"\f518"}.fa-book-reader:before{content:"\f5da"}.fa-bookmark:before{content:"\f02e"}.fa-bootstrap:before{content:"\f836"}.fa-border-all:before{content:"\f84c"}.fa-border-none:before{content:"\f850"}.fa-border-style:before{content:"\f853"}.fa-bowling-ball:before{content:"\f436"}.fa-box:before{content:"\f466"}.fa-box-open:before{content:"\f49e"}.fa-box-tissue:before{content:"\f95b"}.fa-boxes:before{content:"\f468"}.fa-braille:before{content:"\f2a1"}.fa-brain:before{content:"\f5dc"}.fa-bread-slice:before{content:"\f7ec"}.fa-briefcase:before{content:"\f0b1"}.fa-briefcase-medical:before{content:"\f469"}.fa-broadcast-tower:before{content:"\f519"}.fa-broom:before{content:"\f51a"}.fa-brush:before{content:"\f55d"}.fa-btc:before{content:"\f15a"}.fa-buffer:before{content:"\f837"}.fa-bug:before{content:"\f188"}.fa-building:before{content:"\f1ad"}.fa-bullhorn:before{content:"\f0a1"}.fa-bullseye:before{content:"\f140"}.fa-burn:before{content:"\f46a"}.fa-buromobelexperte:before{content:"\f37f"}.fa-bus:before{content:"\f207"}.fa-bus-alt:before{content:"\f55e"}.fa-business-time:before{content:"\f64a"}.fa-buy-n-large:before{content:"\f8a6"}.fa-buysellads:before{content:"\f20d"}.fa-calculator:before{content:"\f1ec"}.fa-calendar:before{content:"\f133"}.fa-calendar-alt:before{content:"\f073"}.fa-calendar-check:before{content:"\f274"}.fa-calendar-day:before{content:"\f783"}.fa-calendar-minus:before{content:"\f272"}.fa-calendar-plus:before{content:"\f271"}.fa-calendar-times:before{content:"\f273"}.fa-calendar-week:before{content:"\f784"}.fa-camera:before{content:"\f030"}.fa-camera-retro:before{content:"\f083"}.fa-campground:before{content:"\f6bb"}.fa-canadian-maple-leaf:before{content:"\f785"}.fa-candy-cane:before{content:"\f786"}.fa-cannabis:before{content:"\f55f"}.fa-capsules:before{content:"\f46b"}.fa-car:before{content:"\f1b9"}.fa-car-alt:before{content:"\f5de"}.fa-car-battery:before{content:"\f5df"}.fa-car-crash:before{content:"\f5e1"}.fa-car-side:before{content:"\f5e4"}.fa-caravan:before{content:"\f8ff"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-caret-square-down:before{content:"\f150"}.fa-caret-square-left:before{content:"\f191"}.fa-caret-square-right:before{content:"\f152"}.fa-caret-square-up:before{content:"\f151"}.fa-caret-up:before{content:"\f0d8"}.fa-carrot:before{content:"\f787"}.fa-cart-arrow-down:before{content:"\f218"}.fa-cart-plus:before{content:"\f217"}.fa-cash-register:before{content:"\f788"}.fa-cat:before{content:"\f6be"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-apple-pay:before{content:"\f416"}.fa-cc-diners-club:before{content:"\f24c"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-cc-visa:before{content:"\f1f0"}.fa-centercode:before{content:"\f380"}.fa-centos:before{content:"\f789"}.fa-certificate:before{content:"\f0a3"}.fa-chair:before{content:"\f6c0"}.fa-chalkboard:before{content:"\f51b"}.fa-chalkboard-teacher:before{content:"\f51c"}.fa-charging-station:before{content:"\f5e7"}.fa-chart-area:before{content:"\f1fe"}.fa-chart-bar:before{content:"\f080"}.fa-chart-line:before{content:"\f201"}.fa-chart-pie:before{content:"\f200"}.fa-check:before{content:"\f00c"}.fa-check-circle:before{content:"\f058"}.fa-check-double:before{content:"\f560"}.fa-check-square:before{content:"\f14a"}.fa-cheese:before{content:"\f7ef"}.fa-chess:before{content:"\f439"}.fa-chess-bishop:before{content:"\f43a"}.fa-chess-board:before{content:"\f43c"}.fa-chess-king:before{content:"\f43f"}.fa-chess-knight:before{content:"\f441"}.fa-chess-pawn:before{content:"\f443"}.fa-chess-queen:before{content:"\f445"}.fa-chess-rook:before{content:"\f447"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-down:before{content:"\f078"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-chevron-up:before{content:"\f077"}.fa-child:before{content:"\f1ae"}.fa-chrome:before{content:"\f268"}.fa-chromecast:before{content:"\f838"}.fa-church:before{content:"\f51d"}.fa-circle:before{content:"\f111"}.fa-circle-notch:before{content:"\f1ce"}.fa-city:before{content:"\f64f"}.fa-clinic-medical:before{content:"\f7f2"}.fa-clipboard:before{content:"\f328"}.fa-clipboard-check:before{content:"\f46c"}.fa-clipboard-list:before{content:"\f46d"}.fa-clock:before{content:"\f017"}.fa-clone:before{content:"\f24d"}.fa-closed-captioning:before{content:"\f20a"}.fa-cloud:before{content:"\f0c2"}.fa-cloud-download-alt:before{content:"\f381"}.fa-cloud-meatball:before{content:"\f73b"}.fa-cloud-moon:before{content:"\f6c3"}.fa-cloud-moon-rain:before{content:"\f73c"}.fa-cloud-rain:before{content:"\f73d"}.fa-cloud-showers-heavy:before{content:"\f740"}.fa-cloud-sun:before{content:"\f6c4"}.fa-cloud-sun-rain:before{content:"\f743"}.fa-cloud-upload-alt:before{content:"\f382"}.fa-cloudscale:before{content:"\f383"}.fa-cloudsmith:before{content:"\f384"}.fa-cloudversify:before{content:"\f385"}.fa-cocktail:before{content:"\f561"}.fa-code:before{content:"\f121"}.fa-code-branch:before{content:"\f126"}.fa-codepen:before{content:"\f1cb"}.fa-codiepie:before{content:"\f284"}.fa-coffee:before{content:"\f0f4"}.fa-cog:before{content:"\f013"}.fa-cogs:before{content:"\f085"}.fa-coins:before{content:"\f51e"}.fa-columns:before{content:"\f0db"}.fa-comment:before{content:"\f075"}.fa-comment-alt:before{content:"\f27a"}.fa-comment-dollar:before{content:"\f651"}.fa-comment-dots:before{content:"\f4ad"}.fa-comment-medical:before{content:"\f7f5"}.fa-comment-slash:before{content:"\f4b3"}.fa-comments:before{content:"\f086"}.fa-comments-dollar:before{content:"\f653"}.fa-compact-disc:before{content:"\f51f"}.fa-compass:before{content:"\f14e"}.fa-compress:before{content:"\f066"}.fa-compress-alt:before{content:"\f422"}.fa-compress-arrows-alt:before{content:"\f78c"}.fa-concierge-bell:before{content:"\f562"}.fa-confluence:before{content:"\f78d"}.fa-connectdevelop:before{content:"\f20e"}.fa-contao:before{content:"\f26d"}.fa-cookie:before{content:"\f563"}.fa-cookie-bite:before{content:"\f564"}.fa-copy:before{content:"\f0c5"}.fa-copyright:before{content:"\f1f9"}.fa-cotton-bureau:before{content:"\f89e"}.fa-couch:before{content:"\f4b8"}.fa-cpanel:before{content:"\f388"}.fa-creative-commons:before{content:"\f25e"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-credit-card:before{content:"\f09d"}.fa-critical-role:before{content:"\f6c9"}.fa-crop:before{content:"\f125"}.fa-crop-alt:before{content:"\f565"}.fa-cross:before{content:"\f654"}.fa-crosshairs:before{content:"\f05b"}.fa-crow:before{content:"\f520"}.fa-crown:before{content:"\f521"}.fa-crutch:before{content:"\f7f7"}.fa-css3:before{content:"\f13c"}.fa-css3-alt:before{content:"\f38b"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-cut:before{content:"\f0c4"}.fa-cuttlefish:before{content:"\f38c"}.fa-d-and-d:before{content:"\f38d"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-dailymotion:before{content:"\f952"}.fa-dashcube:before{content:"\f210"}.fa-database:before{content:"\f1c0"}.fa-deaf:before{content:"\f2a4"}.fa-delicious:before{content:"\f1a5"}.fa-democrat:before{content:"\f747"}.fa-deploydog:before{content:"\f38e"}.fa-deskpro:before{content:"\f38f"}.fa-desktop:before{content:"\f108"}.fa-dev:before{content:"\f6cc"}.fa-deviantart:before{content:"\f1bd"}.fa-dharmachakra:before{content:"\f655"}.fa-dhl:before{content:"\f790"}.fa-diagnoses:before{content:"\f470"}.fa-diaspora:before{content:"\f791"}.fa-dice:before{content:"\f522"}.fa-dice-d20:before{content:"\f6cf"}.fa-dice-d6:before{content:"\f6d1"}.fa-dice-five:before{content:"\f523"}.fa-dice-four:before{content:"\f524"}.fa-dice-one:before{content:"\f525"}.fa-dice-six:before{content:"\f526"}.fa-dice-three:before{content:"\f527"}.fa-dice-two:before{content:"\f528"}.fa-digg:before{content:"\f1a6"}.fa-digital-ocean:before{content:"\f391"}.fa-digital-tachograph:before{content:"\f566"}.fa-directions:before{content:"\f5eb"}.fa-discord:before{content:"\f392"}.fa-discourse:before{content:"\f393"}.fa-disease:before{content:"\f7fa"}.fa-divide:before{content:"\f529"}.fa-dizzy:before{content:"\f567"}.fa-dna:before{content:"\f471"}.fa-dochub:before{content:"\f394"}.fa-docker:before{content:"\f395"}.fa-dog:before{content:"\f6d3"}.fa-dollar-sign:before{content:"\f155"}.fa-dolly:before{content:"\f472"}.fa-dolly-flatbed:before{content:"\f474"}.fa-donate:before{content:"\f4b9"}.fa-door-closed:before{content:"\f52a"}.fa-door-open:before{content:"\f52b"}.fa-dot-circle:before{content:"\f192"}.fa-dove:before{content:"\f4ba"}.fa-download:before{content:"\f019"}.fa-draft2digital:before{content:"\f396"}.fa-drafting-compass:before{content:"\f568"}.fa-dragon:before{content:"\f6d5"}.fa-draw-polygon:before{content:"\f5ee"}.fa-dribbble:before{content:"\f17d"}.fa-dribbble-square:before{content:"\f397"}.fa-dropbox:before{content:"\f16b"}.fa-drum:before{content:"\f569"}.fa-drum-steelpan:before{content:"\f56a"}.fa-drumstick-bite:before{content:"\f6d7"}.fa-drupal:before{content:"\f1a9"}.fa-dumbbell:before{content:"\f44b"}.fa-dumpster:before{content:"\f793"}.fa-dumpster-fire:before{content:"\f794"}.fa-dungeon:before{content:"\f6d9"}.fa-dyalog:before{content:"\f399"}.fa-earlybirds:before{content:"\f39a"}.fa-ebay:before{content:"\f4f4"}.fa-edge:before{content:"\f282"}.fa-edit:before{content:"\f044"}.fa-egg:before{content:"\f7fb"}.fa-eject:before{content:"\f052"}.fa-elementor:before{content:"\f430"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-ello:before{content:"\f5f1"}.fa-ember:before{content:"\f423"}.fa-empire:before{content:"\f1d1"}.fa-envelope:before{content:"\f0e0"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-text:before{content:"\f658"}.fa-envelope-square:before{content:"\f199"}.fa-envira:before{content:"\f299"}.fa-equals:before{content:"\f52c"}.fa-eraser:before{content:"\f12d"}.fa-erlang:before{content:"\f39d"}.fa-ethereum:before{content:"\f42e"}.fa-ethernet:before{content:"\f796"}.fa-etsy:before{content:"\f2d7"}.fa-euro-sign:before{content:"\f153"}.fa-evernote:before{content:"\f839"}.fa-exchange-alt:before{content:"\f362"}.fa-exclamation:before{content:"\f12a"}.fa-exclamation-circle:before{content:"\f06a"}.fa-exclamation-triangle:before{content:"\f071"}.fa-expand:before{content:"\f065"}.fa-expand-alt:before{content:"\f424"}.fa-expand-arrows-alt:before{content:"\f31e"}.fa-expeditedssl:before{content:"\f23e"}.fa-external-link-alt:before{content:"\f35d"}.fa-external-link-square-alt:before{content:"\f360"}.fa-eye:before{content:"\f06e"}.fa-eye-dropper:before{content:"\f1fb"}.fa-eye-slash:before{content:"\f070"}.fa-facebook:before{content:"\f09a"}.fa-facebook-f:before{content:"\f39e"}.fa-facebook-messenger:before{content:"\f39f"}.fa-facebook-square:before{content:"\f082"}.fa-fan:before{content:"\f863"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-fast-backward:before{content:"\f049"}.fa-fast-forward:before{content:"\f050"}.fa-faucet:before{content:"\f905"}.fa-fax:before{content:"\f1ac"}.fa-feather:before{content:"\f52d"}.fa-feather-alt:before{content:"\f56b"}.fa-fedex:before{content:"\f797"}.fa-fedora:before{content:"\f798"}.fa-female:before{content:"\f182"}.fa-fighter-jet:before{content:"\f0fb"}.fa-figma:before{content:"\f799"}.fa-file:before{content:"\f15b"}.fa-file-alt:before{content:"\f15c"}.fa-file-archive:before{content:"\f1c6"}.fa-file-audio:before{content:"\f1c7"}.fa-file-code:before{content:"\f1c9"}.fa-file-contract:before{content:"\f56c"}.fa-file-csv:before{content:"\f6dd"}.fa-file-download:before{content:"\f56d"}.fa-file-excel:before{content:"\f1c3"}.fa-file-export:before{content:"\f56e"}.fa-file-image:before{content:"\f1c5"}.fa-file-import:before{content:"\f56f"}.fa-file-invoice:before{content:"\f570"}.fa-file-invoice-dollar:before{content:"\f571"}.fa-file-medical:before{content:"\f477"}.fa-file-medical-alt:before{content:"\f478"}.fa-file-pdf:before{content:"\f1c1"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-file-prescription:before{content:"\f572"}.fa-file-signature:before{content:"\f573"}.fa-file-upload:before{content:"\f574"}.fa-file-video:before{content:"\f1c8"}.fa-file-word:before{content:"\f1c2"}.fa-fill:before{content:"\f575"}.fa-fill-drip:before{content:"\f576"}.fa-film:before{content:"\f008"}.fa-filter:before{content:"\f0b0"}.fa-fingerprint:before{content:"\f577"}.fa-fire:before{content:"\f06d"}.fa-fire-alt:before{content:"\f7e4"}.fa-fire-extinguisher:before{content:"\f134"}.fa-firefox:before{content:"\f269"}.fa-firefox-browser:before{content:"\f907"}.fa-first-aid:before{content:"\f479"}.fa-first-order:before{content:"\f2b0"}.fa-first-order-alt:before{content:"\f50a"}.fa-firstdraft:before{content:"\f3a1"}.fa-fish:before{content:"\f578"}.fa-fist-raised:before{content:"\f6de"}.fa-flag:before{content:"\f024"}.fa-flag-checkered:before{content:"\f11e"}.fa-flag-usa:before{content:"\f74d"}.fa-flask:before{content:"\f0c3"}.fa-flickr:before{content:"\f16e"}.fa-flipboard:before{content:"\f44d"}.fa-flushed:before{content:"\f579"}.fa-fly:before{content:"\f417"}.fa-folder:before{content:"\f07b"}.fa-folder-minus:before{content:"\f65d"}.fa-folder-open:before{content:"\f07c"}.fa-folder-plus:before{content:"\f65e"}.fa-font:before{content:"\f031"}.fa-font-awesome:before{content:"\f2b4"}.fa-font-awesome-alt:before{content:"\f35c"}.fa-font-awesome-flag:before{content:"\f425"}.fa-font-awesome-logo-full:before{content:"\f4e6"}.fa-fonticons:before{content:"\f280"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-football-ball:before{content:"\f44e"}.fa-fort-awesome:before{content:"\f286"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-forumbee:before{content:"\f211"}.fa-forward:before{content:"\f04e"}.fa-foursquare:before{content:"\f180"}.fa-free-code-camp:before{content:"\f2c5"}.fa-freebsd:before{content:"\f3a4"}.fa-frog:before{content:"\f52e"}.fa-frown:before{content:"\f119"}.fa-frown-open:before{content:"\f57a"}.fa-fulcrum:before{content:"\f50b"}.fa-funnel-dollar:before{content:"\f662"}.fa-futbol:before{content:"\f1e3"}.fa-galactic-republic:before{content:"\f50c"}.fa-galactic-senate:before{content:"\f50d"}.fa-gamepad:before{content:"\f11b"}.fa-gas-pump:before{content:"\f52f"}.fa-gavel:before{content:"\f0e3"}.fa-gem:before{content:"\f3a5"}.fa-genderless:before{content:"\f22d"}.fa-get-pocket:before{content:"\f265"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-ghost:before{content:"\f6e2"}.fa-gift:before{content:"\f06b"}.fa-gifts:before{content:"\f79c"}.fa-git:before{content:"\f1d3"}.fa-git-alt:before{content:"\f841"}.fa-git-square:before{content:"\f1d2"}.fa-github:before{content:"\f09b"}.fa-github-alt:before{content:"\f113"}.fa-github-square:before{content:"\f092"}.fa-gitkraken:before{content:"\f3a6"}.fa-gitlab:before{content:"\f296"}.fa-gitter:before{content:"\f426"}.fa-glass-cheers:before{content:"\f79f"}.fa-glass-martini:before{content:"\f000"}.fa-glass-martini-alt:before{content:"\f57b"}.fa-glass-whiskey:before{content:"\f7a0"}.fa-glasses:before{content:"\f530"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-globe:before{content:"\f0ac"}.fa-globe-africa:before{content:"\f57c"}.fa-globe-americas:before{content:"\f57d"}.fa-globe-asia:before{content:"\f57e"}.fa-globe-europe:before{content:"\f7a2"}.fa-gofore:before{content:"\f3a7"}.fa-golf-ball:before{content:"\f450"}.fa-goodreads:before{content:"\f3a8"}.fa-goodreads-g:before{content:"\f3a9"}.fa-google:before{content:"\f1a0"}.fa-google-drive:before{content:"\f3aa"}.fa-google-play:before{content:"\f3ab"}.fa-google-plus:before{content:"\f2b3"}.fa-google-plus-g:before{content:"\f0d5"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-wallet:before{content:"\f1ee"}.fa-gopuram:before{content:"\f664"}.fa-graduation-cap:before{content:"\f19d"}.fa-gratipay:before{content:"\f184"}.fa-grav:before{content:"\f2d6"}.fa-greater-than:before{content:"\f531"}.fa-greater-than-equal:before{content:"\f532"}.fa-grimace:before{content:"\f57f"}.fa-grin:before{content:"\f580"}.fa-grin-alt:before{content:"\f581"}.fa-grin-beam:before{content:"\f582"}.fa-grin-beam-sweat:before{content:"\f583"}.fa-grin-hearts:before{content:"\f584"}.fa-grin-squint:before{content:"\f585"}.fa-grin-squint-tears:before{content:"\f586"}.fa-grin-stars:before{content:"\f587"}.fa-grin-tears:before{content:"\f588"}.fa-grin-tongue:before{content:"\f589"}.fa-grin-tongue-squint:before{content:"\f58a"}.fa-grin-tongue-wink:before{content:"\f58b"}.fa-grin-wink:before{content:"\f58c"}.fa-grip-horizontal:before{content:"\f58d"}.fa-grip-lines:before{content:"\f7a4"}.fa-grip-lines-vertical:before{content:"\f7a5"}.fa-grip-vertical:before{content:"\f58e"}.fa-gripfire:before{content:"\f3ac"}.fa-grunt:before{content:"\f3ad"}.fa-guitar:before{content:"\f7a6"}.fa-gulp:before{content:"\f3ae"}.fa-h-square:before{content:"\f0fd"}.fa-hacker-news:before{content:"\f1d4"}.fa-hacker-news-square:before{content:"\f3af"}.fa-hackerrank:before{content:"\f5f7"}.fa-hamburger:before{content:"\f805"}.fa-hammer:before{content:"\f6e3"}.fa-hamsa:before{content:"\f665"}.fa-hand-holding:before{content:"\f4bd"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-hand-holding-medical:before{content:"\f95c"}.fa-hand-holding-usd:before{content:"\f4c0"}.fa-hand-holding-water:before{content:"\f4c1"}.fa-hand-lizard:before{content:"\f258"}.fa-hand-middle-finger:before{content:"\f806"}.fa-hand-paper:before{content:"\f256"}.fa-hand-peace:before{content:"\f25b"}.fa-hand-point-down:before{content:"\f0a7"}.fa-hand-point-left:before{content:"\f0a5"}.fa-hand-point-right:before{content:"\f0a4"}.fa-hand-point-up:before{content:"\f0a6"}.fa-hand-pointer:before{content:"\f25a"}.fa-hand-rock:before{content:"\f255"}.fa-hand-scissors:before{content:"\f257"}.fa-hand-sparkles:before{content:"\f95d"}.fa-hand-spock:before{content:"\f259"}.fa-hands:before{content:"\f4c2"}.fa-hands-helping:before{content:"\f4c4"}.fa-hands-wash:before{content:"\f95e"}.fa-handshake:before{content:"\f2b5"}.fa-handshake-alt-slash:before{content:"\f95f"}.fa-handshake-slash:before{content:"\f960"}.fa-hanukiah:before{content:"\f6e6"}.fa-hard-hat:before{content:"\f807"}.fa-hashtag:before{content:"\f292"}.fa-hat-cowboy:before{content:"\f8c0"}.fa-hat-cowboy-side:before{content:"\f8c1"}.fa-hat-wizard:before{content:"\f6e8"}.fa-hdd:before{content:"\f0a0"}.fa-head-side-cough:before{content:"\f961"}.fa-head-side-cough-slash:before{content:"\f962"}.fa-head-side-mask:before{content:"\f963"}.fa-head-side-virus:before{content:"\f964"}.fa-heading:before{content:"\f1dc"}.fa-headphones:before{content:"\f025"}.fa-headphones-alt:before{content:"\f58f"}.fa-headset:before{content:"\f590"}.fa-heart:before{content:"\f004"}.fa-heart-broken:before{content:"\f7a9"}.fa-heartbeat:before{content:"\f21e"}.fa-helicopter:before{content:"\f533"}.fa-highlighter:before{content:"\f591"}.fa-hiking:before{content:"\f6ec"}.fa-hippo:before{content:"\f6ed"}.fa-hips:before{content:"\f452"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-history:before{content:"\f1da"}.fa-hockey-puck:before{content:"\f453"}.fa-holly-berry:before{content:"\f7aa"}.fa-home:before{content:"\f015"}.fa-hooli:before{content:"\f427"}.fa-hornbill:before{content:"\f592"}.fa-horse:before{content:"\f6f0"}.fa-horse-head:before{content:"\f7ab"}.fa-hospital:before{content:"\f0f8"}.fa-hospital-alt:before{content:"\f47d"}.fa-hospital-symbol:before{content:"\f47e"}.fa-hospital-user:before{content:"\f80d"}.fa-hot-tub:before{content:"\f593"}.fa-hotdog:before{content:"\f80f"}.fa-hotel:before{content:"\f594"}.fa-hotjar:before{content:"\f3b1"}.fa-hourglass:before{content:"\f254"}.fa-hourglass-end:before{content:"\f253"}.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-start:before{content:"\f251"}.fa-house-damage:before{content:"\f6f1"}.fa-house-user:before{content:"\f965"}.fa-houzz:before{content:"\f27c"}.fa-hryvnia:before{content:"\f6f2"}.fa-html5:before{content:"\f13b"}.fa-hubspot:before{content:"\f3b2"}.fa-i-cursor:before{content:"\f246"}.fa-ice-cream:before{content:"\f810"}.fa-icicles:before{content:"\f7ad"}.fa-icons:before{content:"\f86d"}.fa-id-badge:before{content:"\f2c1"}.fa-id-card:before{content:"\f2c2"}.fa-id-card-alt:before{content:"\f47f"}.fa-ideal:before{content:"\f913"}.fa-igloo:before{content:"\f7ae"}.fa-image:before{content:"\f03e"}.fa-images:before{content:"\f302"}.fa-imdb:before{content:"\f2d8"}.fa-inbox:before{content:"\f01c"}.fa-indent:before{content:"\f03c"}.fa-industry:before{content:"\f275"}.fa-infinity:before{content:"\f534"}.fa-info:before{content:"\f129"}.fa-info-circle:before{content:"\f05a"}.fa-instagram:before{content:"\f16d"}.fa-instagram-square:before{content:"\f955"}.fa-intercom:before{content:"\f7af"}.fa-internet-explorer:before{content:"\f26b"}.fa-invision:before{content:"\f7b0"}.fa-ioxhost:before{content:"\f208"}.fa-italic:before{content:"\f033"}.fa-itch-io:before{content:"\f83a"}.fa-itunes:before{content:"\f3b4"}.fa-itunes-note:before{content:"\f3b5"}.fa-java:before{content:"\f4e4"}.fa-jedi:before{content:"\f669"}.fa-jedi-order:before{content:"\f50e"}.fa-jenkins:before{content:"\f3b6"}.fa-jira:before{content:"\f7b1"}.fa-joget:before{content:"\f3b7"}.fa-joint:before{content:"\f595"}.fa-joomla:before{content:"\f1aa"}.fa-journal-whills:before{content:"\f66a"}.fa-js:before{content:"\f3b8"}.fa-js-square:before{content:"\f3b9"}.fa-jsfiddle:before{content:"\f1cc"}.fa-kaaba:before{content:"\f66b"}.fa-kaggle:before{content:"\f5fa"}.fa-key:before{content:"\f084"}.fa-keybase:before{content:"\f4f5"}.fa-keyboard:before{content:"\f11c"}.fa-keycdn:before{content:"\f3ba"}.fa-khanda:before{content:"\f66d"}.fa-kickstarter:before{content:"\f3bb"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-kiss:before{content:"\f596"}.fa-kiss-beam:before{content:"\f597"}.fa-kiss-wink-heart:before{content:"\f598"}.fa-kiwi-bird:before{content:"\f535"}.fa-korvue:before{content:"\f42f"}.fa-landmark:before{content:"\f66f"}.fa-language:before{content:"\f1ab"}.fa-laptop:before{content:"\f109"}.fa-laptop-code:before{content:"\f5fc"}.fa-laptop-house:before{content:"\f966"}.fa-laptop-medical:before{content:"\f812"}.fa-laravel:before{content:"\f3bd"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-laugh:before{content:"\f599"}.fa-laugh-beam:before{content:"\f59a"}.fa-laugh-squint:before{content:"\f59b"}.fa-laugh-wink:before{content:"\f59c"}.fa-layer-group:before{content:"\f5fd"}.fa-leaf:before{content:"\f06c"}.fa-leanpub:before{content:"\f212"}.fa-lemon:before{content:"\f094"}.fa-less:before{content:"\f41d"}.fa-less-than:before{content:"\f536"}.fa-less-than-equal:before{content:"\f537"}.fa-level-down-alt:before{content:"\f3be"}.fa-level-up-alt:before{content:"\f3bf"}.fa-life-ring:before{content:"\f1cd"}.fa-lightbulb:before{content:"\f0eb"}.fa-line:before{content:"\f3c0"}.fa-link:before{content:"\f0c1"}.fa-linkedin:before{content:"\f08c"}.fa-linkedin-in:before{content:"\f0e1"}.fa-linode:before{content:"\f2b8"}.fa-linux:before{content:"\f17c"}.fa-lira-sign:before{content:"\f195"}.fa-list:before{content:"\f03a"}.fa-list-alt:before{content:"\f022"}.fa-list-ol:before{content:"\f0cb"}.fa-list-ul:before{content:"\f0ca"}.fa-location-arrow:before{content:"\f124"}.fa-lock:before{content:"\f023"}.fa-lock-open:before{content:"\f3c1"}.fa-long-arrow-alt-down:before{content:"\f309"}.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-long-arrow-alt-right:before{content:"\f30b"}.fa-long-arrow-alt-up:before{content:"\f30c"}.fa-low-vision:before{content:"\f2a8"}.fa-luggage-cart:before{content:"\f59d"}.fa-lungs:before{content:"\f604"}.fa-lungs-virus:before{content:"\f967"}.fa-lyft:before{content:"\f3c3"}.fa-magento:before{content:"\f3c4"}.fa-magic:before{content:"\f0d0"}.fa-magnet:before{content:"\f076"}.fa-mail-bulk:before{content:"\f674"}.fa-mailchimp:before{content:"\f59e"}.fa-male:before{content:"\f183"}.fa-mandalorian:before{content:"\f50f"}.fa-map:before{content:"\f279"}.fa-map-marked:before{content:"\f59f"}.fa-map-marked-alt:before{content:"\f5a0"}.fa-map-marker:before{content:"\f041"}.fa-map-marker-alt:before{content:"\f3c5"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-markdown:before{content:"\f60f"}.fa-marker:before{content:"\f5a1"}.fa-mars:before{content:"\f222"}.fa-mars-double:before{content:"\f227"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mask:before{content:"\f6fa"}.fa-mastodon:before{content:"\f4f6"}.fa-maxcdn:before{content:"\f136"}.fa-mdb:before{content:"\f8ca"}.fa-medal:before{content:"\f5a2"}.fa-medapps:before{content:"\f3c6"}.fa-medium:before{content:"\f23a"}.fa-medium-m:before{content:"\f3c7"}.fa-medkit:before{content:"\f0fa"}.fa-medrt:before{content:"\f3c8"}.fa-meetup:before{content:"\f2e0"}.fa-megaport:before{content:"\f5a3"}.fa-meh:before{content:"\f11a"}.fa-meh-blank:before{content:"\f5a4"}.fa-meh-rolling-eyes:before{content:"\f5a5"}.fa-memory:before{content:"\f538"}.fa-mendeley:before{content:"\f7b3"}.fa-menorah:before{content:"\f676"}.fa-mercury:before{content:"\f223"}.fa-meteor:before{content:"\f753"}.fa-microblog:before{content:"\f91a"}.fa-microchip:before{content:"\f2db"}.fa-microphone:before{content:"\f130"}.fa-microphone-alt:before{content:"\f3c9"}.fa-microphone-alt-slash:before{content:"\f539"}.fa-microphone-slash:before{content:"\f131"}.fa-microscope:before{content:"\f610"}.fa-microsoft:before{content:"\f3ca"}.fa-minus:before{content:"\f068"}.fa-minus-circle:before{content:"\f056"}.fa-minus-square:before{content:"\f146"}.fa-mitten:before{content:"\f7b5"}.fa-mix:before{content:"\f3cb"}.fa-mixcloud:before{content:"\f289"}.fa-mixer:before{content:"\f956"}.fa-mizuni:before{content:"\f3cc"}.fa-mobile:before{content:"\f10b"}.fa-mobile-alt:before{content:"\f3cd"}.fa-modx:before{content:"\f285"}.fa-monero:before{content:"\f3d0"}.fa-money-bill:before{content:"\f0d6"}.fa-money-bill-alt:before{content:"\f3d1"}.fa-money-bill-wave:before{content:"\f53a"}.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-money-check:before{content:"\f53c"}.fa-money-check-alt:before{content:"\f53d"}.fa-monument:before{content:"\f5a6"}.fa-moon:before{content:"\f186"}.fa-mortar-pestle:before{content:"\f5a7"}.fa-mosque:before{content:"\f678"}.fa-motorcycle:before{content:"\f21c"}.fa-mountain:before{content:"\f6fc"}.fa-mouse:before{content:"\f8cc"}.fa-mouse-pointer:before{content:"\f245"}.fa-mug-hot:before{content:"\f7b6"}.fa-music:before{content:"\f001"}.fa-napster:before{content:"\f3d2"}.fa-neos:before{content:"\f612"}.fa-network-wired:before{content:"\f6ff"}.fa-neuter:before{content:"\f22c"}.fa-newspaper:before{content:"\f1ea"}.fa-nimblr:before{content:"\f5a8"}.fa-node:before{content:"\f419"}.fa-node-js:before{content:"\f3d3"}.fa-not-equal:before{content:"\f53e"}.fa-notes-medical:before{content:"\f481"}.fa-npm:before{content:"\f3d4"}.fa-ns8:before{content:"\f3d5"}.fa-nutritionix:before{content:"\f3d6"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-oil-can:before{content:"\f613"}.fa-old-republic:before{content:"\f510"}.fa-om:before{content:"\f679"}.fa-opencart:before{content:"\f23d"}.fa-openid:before{content:"\f19b"}.fa-opera:before{content:"\f26a"}.fa-optin-monster:before{content:"\f23c"}.fa-orcid:before{content:"\f8d2"}.fa-osi:before{content:"\f41a"}.fa-otter:before{content:"\f700"}.fa-outdent:before{content:"\f03b"}.fa-page4:before{content:"\f3d7"}.fa-pagelines:before{content:"\f18c"}.fa-pager:before{content:"\f815"}.fa-paint-brush:before{content:"\f1fc"}.fa-paint-roller:before{content:"\f5aa"}.fa-palette:before{content:"\f53f"}.fa-palfed:before{content:"\f3d8"}.fa-pallet:before{content:"\f482"}.fa-paper-plane:before{content:"\f1d8"}.fa-paperclip:before{content:"\f0c6"}.fa-parachute-box:before{content:"\f4cd"}.fa-paragraph:before{content:"\f1dd"}.fa-parking:before{content:"\f540"}.fa-passport:before{content:"\f5ab"}.fa-pastafarianism:before{content:"\f67b"}.fa-paste:before{content:"\f0ea"}.fa-patreon:before{content:"\f3d9"}.fa-pause:before{content:"\f04c"}.fa-pause-circle:before{content:"\f28b"}.fa-paw:before{content:"\f1b0"}.fa-paypal:before{content:"\f1ed"}.fa-peace:before{content:"\f67c"}.fa-pen:before{content:"\f304"}.fa-pen-alt:before{content:"\f305"}.fa-pen-fancy:before{content:"\f5ac"}.fa-pen-nib:before{content:"\f5ad"}.fa-pen-square:before{content:"\f14b"}.fa-pencil-alt:before{content:"\f303"}.fa-pencil-ruler:before{content:"\f5ae"}.fa-penny-arcade:before{content:"\f704"}.fa-people-arrows:before{content:"\f968"}.fa-people-carry:before{content:"\f4ce"}.fa-pepper-hot:before{content:"\f816"}.fa-percent:before{content:"\f295"}.fa-percentage:before{content:"\f541"}.fa-periscope:before{content:"\f3da"}.fa-person-booth:before{content:"\f756"}.fa-phabricator:before{content:"\f3db"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-phoenix-squadron:before{content:"\f511"}.fa-phone:before{content:"\f095"}.fa-phone-alt:before{content:"\f879"}.fa-phone-slash:before{content:"\f3dd"}.fa-phone-square:before{content:"\f098"}.fa-phone-square-alt:before{content:"\f87b"}.fa-phone-volume:before{content:"\f2a0"}.fa-photo-video:before{content:"\f87c"}.fa-php:before{content:"\f457"}.fa-pied-piper:before{content:"\f2ae"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-square:before{content:"\f91e"}.fa-piggy-bank:before{content:"\f4d3"}.fa-pills:before{content:"\f484"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-p:before{content:"\f231"}.fa-pinterest-square:before{content:"\f0d3"}.fa-pizza-slice:before{content:"\f818"}.fa-place-of-worship:before{content:"\f67f"}.fa-plane:before{content:"\f072"}.fa-plane-arrival:before{content:"\f5af"}.fa-plane-departure:before{content:"\f5b0"}.fa-plane-slash:before{content:"\f969"}.fa-play:before{content:"\f04b"}.fa-play-circle:before{content:"\f144"}.fa-playstation:before{content:"\f3df"}.fa-plug:before{content:"\f1e6"}.fa-plus:before{content:"\f067"}.fa-plus-circle:before{content:"\f055"}.fa-plus-square:before{content:"\f0fe"}.fa-podcast:before{content:"\f2ce"}.fa-poll:before{content:"\f681"}.fa-poll-h:before{content:"\f682"}.fa-poo:before{content:"\f2fe"}.fa-poo-storm:before{content:"\f75a"}.fa-poop:before{content:"\f619"}.fa-portrait:before{content:"\f3e0"}.fa-pound-sign:before{content:"\f154"}.fa-power-off:before{content:"\f011"}.fa-pray:before{content:"\f683"}.fa-praying-hands:before{content:"\f684"}.fa-prescription:before{content:"\f5b1"}.fa-prescription-bottle:before{content:"\f485"}.fa-prescription-bottle-alt:before{content:"\f486"}.fa-print:before{content:"\f02f"}.fa-procedures:before{content:"\f487"}.fa-product-hunt:before{content:"\f288"}.fa-project-diagram:before{content:"\f542"}.fa-pump-medical:before{content:"\f96a"}.fa-pump-soap:before{content:"\f96b"}.fa-pushed:before{content:"\f3e1"}.fa-puzzle-piece:before{content:"\f12e"}.fa-python:before{content:"\f3e2"}.fa-qq:before{content:"\f1d6"}.fa-qrcode:before{content:"\f029"}.fa-question:before{content:"\f128"}.fa-question-circle:before{content:"\f059"}.fa-quidditch:before{content:"\f458"}.fa-quinscape:before{content:"\f459"}.fa-quora:before{content:"\f2c4"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-quran:before{content:"\f687"}.fa-r-project:before{content:"\f4f7"}.fa-radiation:before{content:"\f7b9"}.fa-radiation-alt:before{content:"\f7ba"}.fa-rainbow:before{content:"\f75b"}.fa-random:before{content:"\f074"}.fa-raspberry-pi:before{content:"\f7bb"}.fa-ravelry:before{content:"\f2d9"}.fa-react:before{content:"\f41b"}.fa-reacteurope:before{content:"\f75d"}.fa-readme:before{content:"\f4d5"}.fa-rebel:before{content:"\f1d0"}.fa-receipt:before{content:"\f543"}.fa-record-vinyl:before{content:"\f8d9"}.fa-recycle:before{content:"\f1b8"}.fa-red-river:before{content:"\f3e3"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-alien:before{content:"\f281"}.fa-reddit-square:before{content:"\f1a2"}.fa-redhat:before{content:"\f7bc"}.fa-redo:before{content:"\f01e"}.fa-redo-alt:before{content:"\f2f9"}.fa-registered:before{content:"\f25d"}.fa-remove-format:before{content:"\f87d"}.fa-renren:before{content:"\f18b"}.fa-reply:before{content:"\f3e5"}.fa-reply-all:before{content:"\f122"}.fa-replyd:before{content:"\f3e6"}.fa-republican:before{content:"\f75e"}.fa-researchgate:before{content:"\f4f8"}.fa-resolving:before{content:"\f3e7"}.fa-restroom:before{content:"\f7bd"}.fa-retweet:before{content:"\f079"}.fa-rev:before{content:"\f5b2"}.fa-ribbon:before{content:"\f4d6"}.fa-ring:before{content:"\f70b"}.fa-road:before{content:"\f018"}.fa-robot:before{content:"\f544"}.fa-rocket:before{content:"\f135"}.fa-rocketchat:before{content:"\f3e8"}.fa-rockrms:before{content:"\f3e9"}.fa-route:before{content:"\f4d7"}.fa-rss:before{content:"\f09e"}.fa-rss-square:before{content:"\f143"}.fa-ruble-sign:before{content:"\f158"}.fa-ruler:before{content:"\f545"}.fa-ruler-combined:before{content:"\f546"}.fa-ruler-horizontal:before{content:"\f547"}.fa-ruler-vertical:before{content:"\f548"}.fa-running:before{content:"\f70c"}.fa-rupee-sign:before{content:"\f156"}.fa-sad-cry:before{content:"\f5b3"}.fa-sad-tear:before{content:"\f5b4"}.fa-safari:before{content:"\f267"}.fa-salesforce:before{content:"\f83b"}.fa-sass:before{content:"\f41e"}.fa-satellite:before{content:"\f7bf"}.fa-satellite-dish:before{content:"\f7c0"}.fa-save:before{content:"\f0c7"}.fa-schlix:before{content:"\f3ea"}.fa-school:before{content:"\f549"}.fa-screwdriver:before{content:"\f54a"}.fa-scribd:before{content:"\f28a"}.fa-scroll:before{content:"\f70e"}.fa-sd-card:before{content:"\f7c2"}.fa-search:before{content:"\f002"}.fa-search-dollar:before{content:"\f688"}.fa-search-location:before{content:"\f689"}.fa-search-minus:before{content:"\f010"}.fa-search-plus:before{content:"\f00e"}.fa-searchengin:before{content:"\f3eb"}.fa-seedling:before{content:"\f4d8"}.fa-sellcast:before{content:"\f2da"}.fa-sellsy:before{content:"\f213"}.fa-server:before{content:"\f233"}.fa-servicestack:before{content:"\f3ec"}.fa-shapes:before{content:"\f61f"}.fa-share:before{content:"\f064"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-share-square:before{content:"\f14d"}.fa-shekel-sign:before{content:"\f20b"}.fa-shield-alt:before{content:"\f3ed"}.fa-shield-virus:before{content:"\f96c"}.fa-ship:before{content:"\f21a"}.fa-shipping-fast:before{content:"\f48b"}.fa-shirtsinbulk:before{content:"\f214"}.fa-shoe-prints:before{content:"\f54b"}.fa-shopify:before{content:"\f957"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-shopping-cart:before{content:"\f07a"}.fa-shopware:before{content:"\f5b5"}.fa-shower:before{content:"\f2cc"}.fa-shuttle-van:before{content:"\f5b6"}.fa-sign:before{content:"\f4d9"}.fa-sign-in-alt:before{content:"\f2f6"}.fa-sign-language:before{content:"\f2a7"}.fa-sign-out-alt:before{content:"\f2f5"}.fa-signal:before{content:"\f012"}.fa-signature:before{content:"\f5b7"}.fa-sim-card:before{content:"\f7c4"}.fa-simplybuilt:before{content:"\f215"}.fa-sistrix:before{content:"\f3ee"}.fa-sitemap:before{content:"\f0e8"}.fa-sith:before{content:"\f512"}.fa-skating:before{content:"\f7c5"}.fa-sketch:before{content:"\f7c6"}.fa-skiing:before{content:"\f7c9"}.fa-skiing-nordic:before{content:"\f7ca"}.fa-skull:before{content:"\f54c"}.fa-skull-crossbones:before{content:"\f714"}.fa-skyatlas:before{content:"\f216"}.fa-skype:before{content:"\f17e"}.fa-slack:before{content:"\f198"}.fa-slack-hash:before{content:"\f3ef"}.fa-slash:before{content:"\f715"}.fa-sleigh:before{content:"\f7cc"}.fa-sliders-h:before{content:"\f1de"}.fa-slideshare:before{content:"\f1e7"}.fa-smile:before{content:"\f118"}.fa-smile-beam:before{content:"\f5b8"}.fa-smile-wink:before{content:"\f4da"}.fa-smog:before{content:"\f75f"}.fa-smoking:before{content:"\f48d"}.fa-smoking-ban:before{content:"\f54d"}.fa-sms:before{content:"\f7cd"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-snowboarding:before{content:"\f7ce"}.fa-snowflake:before{content:"\f2dc"}.fa-snowman:before{content:"\f7d0"}.fa-snowplow:before{content:"\f7d2"}.fa-soap:before{content:"\f96e"}.fa-socks:before{content:"\f696"}.fa-solar-panel:before{content:"\f5ba"}.fa-sort:before{content:"\f0dc"}.fa-sort-alpha-down:before{content:"\f15d"}.fa-sort-alpha-down-alt:before{content:"\f881"}.fa-sort-alpha-up:before{content:"\f15e"}.fa-sort-alpha-up-alt:before{content:"\f882"}.fa-sort-amount-down:before{content:"\f160"}.fa-sort-amount-down-alt:before{content:"\f884"}.fa-sort-amount-up:before{content:"\f161"}.fa-sort-amount-up-alt:before{content:"\f885"}.fa-sort-down:before{content:"\f0dd"}.fa-sort-numeric-down:before{content:"\f162"}.fa-sort-numeric-down-alt:before{content:"\f886"}.fa-sort-numeric-up:before{content:"\f163"}.fa-sort-numeric-up-alt:before{content:"\f887"}.fa-sort-up:before{content:"\f0de"}.fa-soundcloud:before{content:"\f1be"}.fa-sourcetree:before{content:"\f7d3"}.fa-spa:before{content:"\f5bb"}.fa-space-shuttle:before{content:"\f197"}.fa-speakap:before{content:"\f3f3"}.fa-speaker-deck:before{content:"\f83c"}.fa-spell-check:before{content:"\f891"}.fa-spider:before{content:"\f717"}.fa-spinner:before{content:"\f110"}.fa-splotch:before{content:"\f5bc"}.fa-spotify:before{content:"\f1bc"}.fa-spray-can:before{content:"\f5bd"}.fa-square:before{content:"\f0c8"}.fa-square-full:before{content:"\f45c"}.fa-square-root-alt:before{content:"\f698"}.fa-squarespace:before{content:"\f5be"}.fa-stack-exchange:before{content:"\f18d"}.fa-stack-overflow:before{content:"\f16c"}.fa-stackpath:before{content:"\f842"}.fa-stamp:before{content:"\f5bf"}.fa-star:before{content:"\f005"}.fa-star-and-crescent:before{content:"\f699"}.fa-star-half:before{content:"\f089"}.fa-star-half-alt:before{content:"\f5c0"}.fa-star-of-david:before{content:"\f69a"}.fa-star-of-life:before{content:"\f621"}.fa-staylinked:before{content:"\f3f5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-steam-symbol:before{content:"\f3f6"}.fa-step-backward:before{content:"\f048"}.fa-step-forward:before{content:"\f051"}.fa-stethoscope:before{content:"\f0f1"}.fa-sticker-mule:before{content:"\f3f7"}.fa-sticky-note:before{content:"\f249"}.fa-stop:before{content:"\f04d"}.fa-stop-circle:before{content:"\f28d"}.fa-stopwatch:before{content:"\f2f2"}.fa-stopwatch-20:before{content:"\f96f"}.fa-store:before{content:"\f54e"}.fa-store-alt:before{content:"\f54f"}.fa-store-alt-slash:before{content:"\f970"}.fa-store-slash:before{content:"\f971"}.fa-strava:before{content:"\f428"}.fa-stream:before{content:"\f550"}.fa-street-view:before{content:"\f21d"}.fa-strikethrough:before{content:"\f0cc"}.fa-stripe:before{content:"\f429"}.fa-stripe-s:before{content:"\f42a"}.fa-stroopwafel:before{content:"\f551"}.fa-studiovinari:before{content:"\f3f8"}.fa-stumbleupon:before{content:"\f1a4"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-subscript:before{content:"\f12c"}.fa-subway:before{content:"\f239"}.fa-suitcase:before{content:"\f0f2"}.fa-suitcase-rolling:before{content:"\f5c1"}.fa-sun:before{content:"\f185"}.fa-superpowers:before{content:"\f2dd"}.fa-superscript:before{content:"\f12b"}.fa-supple:before{content:"\f3f9"}.fa-surprise:before{content:"\f5c2"}.fa-suse:before{content:"\f7d6"}.fa-swatchbook:before{content:"\f5c3"}.fa-swift:before{content:"\f8e1"}.fa-swimmer:before{content:"\f5c4"}.fa-swimming-pool:before{content:"\f5c5"}.fa-symfony:before{content:"\f83d"}.fa-synagogue:before{content:"\f69b"}.fa-sync:before{content:"\f021"}.fa-sync-alt:before{content:"\f2f1"}.fa-syringe:before{content:"\f48e"}.fa-table:before{content:"\f0ce"}.fa-table-tennis:before{content:"\f45d"}.fa-tablet:before{content:"\f10a"}.fa-tablet-alt:before{content:"\f3fa"}.fa-tablets:before{content:"\f490"}.fa-tachometer-alt:before{content:"\f3fd"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-tape:before{content:"\f4db"}.fa-tasks:before{content:"\f0ae"}.fa-taxi:before{content:"\f1ba"}.fa-teamspeak:before{content:"\f4f9"}.fa-teeth:before{content:"\f62e"}.fa-teeth-open:before{content:"\f62f"}.fa-telegram:before{content:"\f2c6"}.fa-telegram-plane:before{content:"\f3fe"}.fa-temperature-high:before{content:"\f769"}.fa-temperature-low:before{content:"\f76b"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-tenge:before{content:"\f7d7"}.fa-terminal:before{content:"\f120"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-th:before{content:"\f00a"}.fa-th-large:before{content:"\f009"}.fa-th-list:before{content:"\f00b"}.fa-the-red-yeti:before{content:"\f69d"}.fa-theater-masks:before{content:"\f630"}.fa-themeco:before{content:"\f5c6"}.fa-themeisle:before{content:"\f2b2"}.fa-thermometer:before{content:"\f491"}.fa-thermometer-empty:before{content:"\f2cb"}.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-think-peaks:before{content:"\f731"}.fa-thumbs-down:before{content:"\f165"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbtack:before{content:"\f08d"}.fa-ticket-alt:before{content:"\f3ff"}.fa-times:before{content:"\f00d"}.fa-times-circle:before{content:"\f057"}.fa-tint:before{content:"\f043"}.fa-tint-slash:before{content:"\f5c7"}.fa-tired:before{content:"\f5c8"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-toilet:before{content:"\f7d8"}.fa-toilet-paper:before{content:"\f71e"}.fa-toilet-paper-slash:before{content:"\f972"}.fa-toolbox:before{content:"\f552"}.fa-tools:before{content:"\f7d9"}.fa-tooth:before{content:"\f5c9"}.fa-torah:before{content:"\f6a0"}.fa-torii-gate:before{content:"\f6a1"}.fa-tractor:before{content:"\f722"}.fa-trade-federation:before{content:"\f513"}.fa-trademark:before{content:"\f25c"}.fa-traffic-light:before{content:"\f637"}.fa-trailer:before{content:"\f941"}.fa-train:before{content:"\f238"}.fa-tram:before{content:"\f7da"}.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-trash:before{content:"\f1f8"}.fa-trash-alt:before{content:"\f2ed"}.fa-trash-restore:before{content:"\f829"}.fa-trash-restore-alt:before{content:"\f82a"}.fa-tree:before{content:"\f1bb"}.fa-trello:before{content:"\f181"}.fa-tripadvisor:before{content:"\f262"}.fa-trophy:before{content:"\f091"}.fa-truck:before{content:"\f0d1"}.fa-truck-loading:before{content:"\f4de"}.fa-truck-monster:before{content:"\f63b"}.fa-truck-moving:before{content:"\f4df"}.fa-truck-pickup:before{content:"\f63c"}.fa-tshirt:before{content:"\f553"}.fa-tty:before{content:"\f1e4"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-tv:before{content:"\f26c"}.fa-twitch:before{content:"\f1e8"}.fa-twitter:before{content:"\f099"}.fa-twitter-square:before{content:"\f081"}.fa-typo3:before{content:"\f42b"}.fa-uber:before{content:"\f402"}.fa-ubuntu:before{content:"\f7df"}.fa-uikit:before{content:"\f403"}.fa-umbraco:before{content:"\f8e8"}.fa-umbrella:before{content:"\f0e9"}.fa-umbrella-beach:before{content:"\f5ca"}.fa-underline:before{content:"\f0cd"}.fa-undo:before{content:"\f0e2"}.fa-undo-alt:before{content:"\f2ea"}.fa-uniregistry:before{content:"\f404"}.fa-unity:before{content:"\f949"}.fa-universal-access:before{content:"\f29a"}.fa-university:before{content:"\f19c"}.fa-unlink:before{content:"\f127"}.fa-unlock:before{content:"\f09c"}.fa-unlock-alt:before{content:"\f13e"}.fa-untappd:before{content:"\f405"}.fa-upload:before{content:"\f093"}.fa-ups:before{content:"\f7e0"}.fa-usb:before{content:"\f287"}.fa-user:before{content:"\f007"}.fa-user-alt:before{content:"\f406"}.fa-user-alt-slash:before{content:"\f4fa"}.fa-user-astronaut:before{content:"\f4fb"}.fa-user-check:before{content:"\f4fc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-clock:before{content:"\f4fd"}.fa-user-cog:before{content:"\f4fe"}.fa-user-edit:before{content:"\f4ff"}.fa-user-friends:before{content:"\f500"}.fa-user-graduate:before{content:"\f501"}.fa-user-injured:before{content:"\f728"}.fa-user-lock:before{content:"\f502"}.fa-user-md:before{content:"\f0f0"}.fa-user-minus:before{content:"\f503"}.fa-user-ninja:before{content:"\f504"}.fa-user-nurse:before{content:"\f82f"}.fa-user-plus:before{content:"\f234"}.fa-user-secret:before{content:"\f21b"}.fa-user-shield:before{content:"\f505"}.fa-user-slash:before{content:"\f506"}.fa-user-tag:before{content:"\f507"}.fa-user-tie:before{content:"\f508"}.fa-user-times:before{content:"\f235"}.fa-users:before{content:"\f0c0"}.fa-users-cog:before{content:"\f509"}.fa-usps:before{content:"\f7e1"}.fa-ussunnah:before{content:"\f407"}.fa-utensil-spoon:before{content:"\f2e5"}.fa-utensils:before{content:"\f2e7"}.fa-vaadin:before{content:"\f408"}.fa-vector-square:before{content:"\f5cb"}.fa-venus:before{content:"\f221"}.fa-venus-double:before{content:"\f226"}.fa-venus-mars:before{content:"\f228"}.fa-viacoin:before{content:"\f237"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-vial:before{content:"\f492"}.fa-vials:before{content:"\f493"}.fa-viber:before{content:"\f409"}.fa-video:before{content:"\f03d"}.fa-video-slash:before{content:"\f4e2"}.fa-vihara:before{content:"\f6a7"}.fa-vimeo:before{content:"\f40a"}.fa-vimeo-square:before{content:"\f194"}.fa-vimeo-v:before{content:"\f27d"}.fa-vine:before{content:"\f1ca"}.fa-virus:before{content:"\f974"}.fa-virus-slash:before{content:"\f975"}.fa-viruses:before{content:"\f976"}.fa-vk:before{content:"\f189"}.fa-vnv:before{content:"\f40b"}.fa-voicemail:before{content:"\f897"}.fa-volleyball-ball:before{content:"\f45f"}.fa-volume-down:before{content:"\f027"}.fa-volume-mute:before{content:"\f6a9"}.fa-volume-off:before{content:"\f026"}.fa-volume-up:before{content:"\f028"}.fa-vote-yea:before{content:"\f772"}.fa-vr-cardboard:before{content:"\f729"}.fa-vuejs:before{content:"\f41f"}.fa-walking:before{content:"\f554"}.fa-wallet:before{content:"\f555"}.fa-warehouse:before{content:"\f494"}.fa-water:before{content:"\f773"}.fa-wave-square:before{content:"\f83e"}.fa-waze:before{content:"\f83f"}.fa-weebly:before{content:"\f5cc"}.fa-weibo:before{content:"\f18a"}.fa-weight:before{content:"\f496"}.fa-weight-hanging:before{content:"\f5cd"}.fa-weixin:before{content:"\f1d7"}.fa-whatsapp:before{content:"\f232"}.fa-whatsapp-square:before{content:"\f40c"}.fa-wheelchair:before{content:"\f193"}.fa-whmcs:before{content:"\f40d"}.fa-wifi:before{content:"\f1eb"}.fa-wikipedia-w:before{content:"\f266"}.fa-wind:before{content:"\f72e"}.fa-window-close:before{content:"\f410"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-windows:before{content:"\f17a"}.fa-wine-bottle:before{content:"\f72f"}.fa-wine-glass:before{content:"\f4e3"}.fa-wine-glass-alt:before{content:"\f5ce"}.fa-wix:before{content:"\f5cf"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-won-sign:before{content:"\f159"}.fa-wordpress:before{content:"\f19a"}.fa-wordpress-simple:before{content:"\f411"}.fa-wpbeginner:before{content:"\f297"}.fa-wpexplorer:before{content:"\f2de"}.fa-wpforms:before{content:"\f298"}.fa-wpressr:before{content:"\f3e4"}.fa-wrench:before{content:"\f0ad"}.fa-x-ray:before{content:"\f497"}.fa-xbox:before{content:"\f412"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-y-combinator:before{content:"\f23b"}.fa-yahoo:before{content:"\f19e"}.fa-yammer:before{content:"\f840"}.fa-yandex:before{content:"\f413"}.fa-yandex-international:before{content:"\f414"}.fa-yarn:before{content:"\f7e3"}.fa-yelp:before{content:"\f1e9"}.fa-yen-sign:before{content:"\f157"}.fa-yin-yang:before{content:"\f6ad"}.fa-yoast:before{content:"\f2b1"}.fa-youtube:before{content:"\f167"}.fa-youtube-square:before{content:"\f431"}.fa-zhihu:before{content:"\f63f"}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}@font-face{font-family:"Font Awesome 5 Brands";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:"Font Awesome 5 Brands"}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-regular-400.eot);src:url(../webfonts/fa-regular-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.woff) format("woff"),url(../webfonts/fa-regular-400.ttf) format("truetype"),url(../webfonts/fa-regular-400.svg#fontawesome) format("svg")}.fab,.far{font-weight:400}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.far,.fas{font-family:"Font Awesome 5 Free"}.fa,.fas{font-weight:900} \ No newline at end of file diff --git a/lib/font-awesome/webfonts/fa-brands-400.woff2 b/lib/font-awesome/webfonts/fa-brands-400.woff2 new file mode 100644 index 00000000..141a90a9 Binary files /dev/null and b/lib/font-awesome/webfonts/fa-brands-400.woff2 differ diff --git a/lib/font-awesome/webfonts/fa-regular-400.woff2 b/lib/font-awesome/webfonts/fa-regular-400.woff2 new file mode 100644 index 00000000..7e0118e5 Binary files /dev/null and b/lib/font-awesome/webfonts/fa-regular-400.woff2 differ diff --git a/lib/font-awesome/webfonts/fa-solid-900.woff2 b/lib/font-awesome/webfonts/fa-solid-900.woff2 new file mode 100644 index 00000000..978a681a Binary files /dev/null and b/lib/font-awesome/webfonts/fa-solid-900.woff2 differ diff --git a/lib/velocity/velocity.min.js b/lib/velocity/velocity.min.js new file mode 100644 index 00000000..58244c80 --- /dev/null +++ b/lib/velocity/velocity.min.js @@ -0,0 +1,4 @@ +/*! VelocityJS.org (1.2.2). (C) 2014 Julian Shapiro. MIT @license: en.wikipedia.org/wiki/MIT_License */ +/*! VelocityJS.org jQuery Shim (1.0.1). (C) 2014 The jQuery Foundation. MIT @license: en.wikipedia.org/wiki/MIT_License. */ +!function(e){function t(e){var t=e.length,r=$.type(e);return"function"===r||$.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===r||0===t||"number"==typeof t&&t>0&&t-1 in e}if(!e.jQuery){var $=function(e,t){return new $.fn.init(e,t)};$.isWindow=function(e){return null!=e&&e==e.window},$.type=function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?a[o.call(e)]||"object":typeof e},$.isArray=Array.isArray||function(e){return"array"===$.type(e)},$.isPlainObject=function(e){var t;if(!e||"object"!==$.type(e)||e.nodeType||$.isWindow(e))return!1;try{if(e.constructor&&!n.call(e,"constructor")&&!n.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(r){return!1}for(t in e);return void 0===t||n.call(e,t)},$.each=function(e,r,a){var n,o=0,i=e.length,s=t(e);if(a){if(s)for(;i>o&&(n=r.apply(e[o],a),n!==!1);o++);else for(o in e)if(n=r.apply(e[o],a),n===!1)break}else if(s)for(;i>o&&(n=r.call(e[o],o,e[o]),n!==!1);o++);else for(o in e)if(n=r.call(e[o],o,e[o]),n===!1)break;return e},$.data=function(e,t,a){if(void 0===a){var n=e[$.expando],o=n&&r[n];if(void 0===t)return o;if(o&&t in o)return o[t]}else if(void 0!==t){var n=e[$.expando]||(e[$.expando]=++$.uuid);return r[n]=r[n]||{},r[n][t]=a,a}},$.removeData=function(e,t){var a=e[$.expando],n=a&&r[a];n&&$.each(t,function(e,t){delete n[t]})},$.extend=function(){var e,t,r,a,n,o,i=arguments[0]||{},s=1,l=arguments.length,u=!1;for("boolean"==typeof i&&(u=i,i=arguments[s]||{},s++),"object"!=typeof i&&"function"!==$.type(i)&&(i={}),s===l&&(i=this,s--);l>s;s++)if(null!=(n=arguments[s]))for(a in n)e=i[a],r=n[a],i!==r&&(u&&r&&($.isPlainObject(r)||(t=$.isArray(r)))?(t?(t=!1,o=e&&$.isArray(e)?e:[]):o=e&&$.isPlainObject(e)?e:{},i[a]=$.extend(u,o,r)):void 0!==r&&(i[a]=r));return i},$.queue=function(e,r,a){function n(e,r){var a=r||[];return null!=e&&(t(Object(e))?!function(e,t){for(var r=+t.length,a=0,n=e.length;r>a;)e[n++]=t[a++];if(r!==r)for(;void 0!==t[a];)e[n++]=t[a++];return e.length=n,e}(a,"string"==typeof e?[e]:e):[].push.call(a,e)),a}if(e){r=(r||"fx")+"queue";var o=$.data(e,r);return a?(!o||$.isArray(a)?o=$.data(e,r,n(a)):o.push(a),o):o||[]}},$.dequeue=function(e,t){$.each(e.nodeType?[e]:e,function(e,r){t=t||"fx";var a=$.queue(r,t),n=a.shift();"inprogress"===n&&(n=a.shift()),n&&("fx"===t&&a.unshift("inprogress"),n.call(r,function(){$.dequeue(r,t)}))})},$.fn=$.prototype={init:function(e){if(e.nodeType)return this[0]=e,this;throw new Error("Not a DOM node.")},offset:function(){var t=this[0].getBoundingClientRect?this[0].getBoundingClientRect():{top:0,left:0};return{top:t.top+(e.pageYOffset||document.scrollTop||0)-(document.clientTop||0),left:t.left+(e.pageXOffset||document.scrollLeft||0)-(document.clientLeft||0)}},position:function(){function e(){for(var e=this.offsetParent||document;e&&"html"===!e.nodeType.toLowerCase&&"static"===e.style.position;)e=e.offsetParent;return e||document}var t=this[0],e=e.apply(t),r=this.offset(),a=/^(?:body|html)$/i.test(e.nodeName)?{top:0,left:0}:$(e).offset();return r.top-=parseFloat(t.style.marginTop)||0,r.left-=parseFloat(t.style.marginLeft)||0,e.style&&(a.top+=parseFloat(e.style.borderTopWidth)||0,a.left+=parseFloat(e.style.borderLeftWidth)||0),{top:r.top-a.top,left:r.left-a.left}}};var r={};$.expando="velocity"+(new Date).getTime(),$.uuid=0;for(var a={},n=a.hasOwnProperty,o=a.toString,i="Boolean Number String Function Array Date RegExp Object Error".split(" "),s=0;sn;++n){var o=u(r,e,a);if(0===o)return r;var i=l(r,e,a)-t;r-=i/o}return r}function p(){for(var t=0;b>t;++t)w[t]=l(t*x,e,a)}function f(t,r,n){var o,i,s=0;do i=r+(n-r)/2,o=l(i,e,a)-t,o>0?n=i:r=i;while(Math.abs(o)>h&&++s=y?c(t,s):0==l?s:f(t,r,r+x)}function g(){V=!0,(e!=r||a!=n)&&p()}var m=4,y=.001,h=1e-7,v=10,b=11,x=1/(b-1),S="Float32Array"in t;if(4!==arguments.length)return!1;for(var P=0;4>P;++P)if("number"!=typeof arguments[P]||isNaN(arguments[P])||!isFinite(arguments[P]))return!1;e=Math.min(e,1),a=Math.min(a,1),e=Math.max(e,0),a=Math.max(a,0);var w=S?new Float32Array(b):new Array(b),V=!1,C=function(t){return V||g(),e===r&&a===n?t:0===t?0:1===t?1:l(d(t),r,n)};C.getControlPoints=function(){return[{x:e,y:r},{x:a,y:n}]};var T="generateBezier("+[e,r,a,n]+")";return C.toString=function(){return T},C}function u(e,t){var r=e;return g.isString(e)?v.Easings[e]||(r=!1):r=g.isArray(e)&&1===e.length?s.apply(null,e):g.isArray(e)&&2===e.length?b.apply(null,e.concat([t])):g.isArray(e)&&4===e.length?l.apply(null,e):!1,r===!1&&(r=v.Easings[v.defaults.easing]?v.defaults.easing:h),r}function c(e){if(e){var t=(new Date).getTime(),r=v.State.calls.length;r>1e4&&(v.State.calls=n(v.State.calls));for(var o=0;r>o;o++)if(v.State.calls[o]){var s=v.State.calls[o],l=s[0],u=s[2],f=s[3],d=!!f,m=null;f||(f=v.State.calls[o][3]=t-16);for(var y=Math.min((t-f)/u.duration,1),h=0,b=l.length;b>h;h++){var S=l[h],w=S.element;if(i(w)){var V=!1;if(u.display!==a&&null!==u.display&&"none"!==u.display){if("flex"===u.display){var C=["-webkit-box","-moz-box","-ms-flexbox","-webkit-flex"];$.each(C,function(e,t){x.setPropertyValue(w,"display",t)})}x.setPropertyValue(w,"display",u.display)}u.visibility!==a&&"hidden"!==u.visibility&&x.setPropertyValue(w,"visibility",u.visibility);for(var T in S)if("element"!==T){var k=S[T],A,F=g.isString(k.easing)?v.Easings[k.easing]:k.easing;if(1===y)A=k.endValue;else{var E=k.endValue-k.startValue;if(A=k.startValue+E*F(y,u,E),!d&&A===k.currentValue)continue}if(k.currentValue=A,"tween"===T)m=A;else{if(x.Hooks.registered[T]){var j=x.Hooks.getRoot(T),H=i(w).rootPropertyValueCache[j];H&&(k.rootPropertyValue=H)}var N=x.setPropertyValue(w,T,k.currentValue+(0===parseFloat(A)?"":k.unitType),k.rootPropertyValue,k.scrollData);x.Hooks.registered[T]&&(i(w).rootPropertyValueCache[j]=x.Normalizations.registered[j]?x.Normalizations.registered[j]("extract",null,N[1]):N[1]),"transform"===N[0]&&(V=!0)}}u.mobileHA&&i(w).transformCache.translate3d===a&&(i(w).transformCache.translate3d="(0px, 0px, 0px)",V=!0),V&&x.flushTransformCache(w)}}u.display!==a&&"none"!==u.display&&(v.State.calls[o][2].display=!1),u.visibility!==a&&"hidden"!==u.visibility&&(v.State.calls[o][2].visibility=!1),u.progress&&u.progress.call(s[1],s[1],y,Math.max(0,f+u.duration-t),f,m),1===y&&p(o)}}v.State.isTicking&&P(c)}function p(e,t){if(!v.State.calls[e])return!1;for(var r=v.State.calls[e][0],n=v.State.calls[e][1],o=v.State.calls[e][2],s=v.State.calls[e][4],l=!1,u=0,c=r.length;c>u;u++){var p=r[u].element;if(t||o.loop||("none"===o.display&&x.setPropertyValue(p,"display",o.display),"hidden"===o.visibility&&x.setPropertyValue(p,"visibility",o.visibility)),o.loop!==!0&&($.queue(p)[1]===a||!/\.velocityQueueEntryFlag/i.test($.queue(p)[1]))&&i(p)){i(p).isAnimating=!1,i(p).rootPropertyValueCache={};var f=!1;$.each(x.Lists.transforms3D,function(e,t){var r=/^scale/.test(t)?1:0,n=i(p).transformCache[t];i(p).transformCache[t]!==a&&new RegExp("^\\("+r+"[^.]").test(n)&&(f=!0,delete i(p).transformCache[t])}),o.mobileHA&&(f=!0,delete i(p).transformCache.translate3d),f&&x.flushTransformCache(p),x.Values.removeClass(p,"velocity-animating")}if(!t&&o.complete&&!o.loop&&u===c-1)try{o.complete.call(n,n)}catch(d){setTimeout(function(){throw d},1)}s&&o.loop!==!0&&s(n),i(p)&&o.loop===!0&&!t&&($.each(i(p).tweensContainer,function(e,t){/^rotate/.test(e)&&360===parseFloat(t.endValue)&&(t.endValue=0,t.startValue=360),/^backgroundPosition/.test(e)&&100===parseFloat(t.endValue)&&"%"===t.unitType&&(t.endValue=0,t.startValue=100)}),v(p,"reverse",{loop:!0,delay:o.delay})),o.queue!==!1&&$.dequeue(p,o.queue)}v.State.calls[e]=!1;for(var g=0,m=v.State.calls.length;m>g;g++)if(v.State.calls[g]!==!1){l=!0;break}l===!1&&(v.State.isTicking=!1,delete v.State.calls,v.State.calls=[])}var f=function(){if(r.documentMode)return r.documentMode;for(var e=7;e>4;e--){var t=r.createElement("div");if(t.innerHTML="",t.getElementsByTagName("span").length)return t=null,e}return a}(),d=function(){var e=0;return t.webkitRequestAnimationFrame||t.mozRequestAnimationFrame||function(t){var r=(new Date).getTime(),a;return a=Math.max(0,16-(r-e)),e=r+a,setTimeout(function(){t(r+a)},a)}}(),g={isString:function(e){return"string"==typeof e},isArray:Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)},isFunction:function(e){return"[object Function]"===Object.prototype.toString.call(e)},isNode:function(e){return e&&e.nodeType},isNodeList:function(e){return"object"==typeof e&&/^\[object (HTMLCollection|NodeList|Object)\]$/.test(Object.prototype.toString.call(e))&&e.length!==a&&(0===e.length||"object"==typeof e[0]&&e[0].nodeType>0)},isWrapped:function(e){return e&&(e.jquery||t.Zepto&&t.Zepto.zepto.isZ(e))},isSVG:function(e){return t.SVGElement&&e instanceof t.SVGElement},isEmptyObject:function(e){for(var t in e)return!1;return!0}},$,m=!1;if(e.fn&&e.fn.jquery?($=e,m=!0):$=t.Velocity.Utilities,8>=f&&!m)throw new Error("Velocity: IE8 and below require jQuery to be loaded before Velocity.");if(7>=f)return void(jQuery.fn.velocity=jQuery.fn.animate);var y=400,h="swing",v={State:{isMobile:/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),isAndroid:/Android/i.test(navigator.userAgent),isGingerbread:/Android 2\.3\.[3-7]/i.test(navigator.userAgent),isChrome:t.chrome,isFirefox:/Firefox/i.test(navigator.userAgent),prefixElement:r.createElement("div"),prefixMatches:{},scrollAnchor:null,scrollPropertyLeft:null,scrollPropertyTop:null,isTicking:!1,calls:[]},CSS:{},Utilities:$,Redirects:{},Easings:{},Promise:t.Promise,defaults:{queue:"",duration:y,easing:h,begin:a,complete:a,progress:a,display:a,visibility:a,loop:!1,delay:!1,mobileHA:!0,_cacheValues:!0},init:function(e){$.data(e,"velocity",{isSVG:g.isSVG(e),isAnimating:!1,computedStyle:null,tweensContainer:null,rootPropertyValueCache:{},transformCache:{}})},hook:null,mock:!1,version:{major:1,minor:2,patch:2},debug:!1};t.pageYOffset!==a?(v.State.scrollAnchor=t,v.State.scrollPropertyLeft="pageXOffset",v.State.scrollPropertyTop="pageYOffset"):(v.State.scrollAnchor=r.documentElement||r.body.parentNode||r.body,v.State.scrollPropertyLeft="scrollLeft",v.State.scrollPropertyTop="scrollTop");var b=function(){function e(e){return-e.tension*e.x-e.friction*e.v}function t(t,r,a){var n={x:t.x+a.dx*r,v:t.v+a.dv*r,tension:t.tension,friction:t.friction};return{dx:n.v,dv:e(n)}}function r(r,a){var n={dx:r.v,dv:e(r)},o=t(r,.5*a,n),i=t(r,.5*a,o),s=t(r,a,i),l=1/6*(n.dx+2*(o.dx+i.dx)+s.dx),u=1/6*(n.dv+2*(o.dv+i.dv)+s.dv);return r.x=r.x+l*a,r.v=r.v+u*a,r}return function a(e,t,n){var o={x:-1,v:0,tension:null,friction:null},i=[0],s=0,l=1e-4,u=.016,c,p,f;for(e=parseFloat(e)||500,t=parseFloat(t)||20,n=n||null,o.tension=e,o.friction=t,c=null!==n,c?(s=a(e,t),p=s/n*u):p=u;;)if(f=r(f||o,p),i.push(1+f.x),s+=16,!(Math.abs(f.x)>l&&Math.abs(f.v)>l))break;return c?function(e){return i[e*(i.length-1)|0]}:s}}();v.Easings={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},spring:function(e){return 1-Math.cos(4.5*e*Math.PI)*Math.exp(6*-e)}},$.each([["ease",[.25,.1,.25,1]],["ease-in",[.42,0,1,1]],["ease-out",[0,0,.58,1]],["ease-in-out",[.42,0,.58,1]],["easeInSine",[.47,0,.745,.715]],["easeOutSine",[.39,.575,.565,1]],["easeInOutSine",[.445,.05,.55,.95]],["easeInQuad",[.55,.085,.68,.53]],["easeOutQuad",[.25,.46,.45,.94]],["easeInOutQuad",[.455,.03,.515,.955]],["easeInCubic",[.55,.055,.675,.19]],["easeOutCubic",[.215,.61,.355,1]],["easeInOutCubic",[.645,.045,.355,1]],["easeInQuart",[.895,.03,.685,.22]],["easeOutQuart",[.165,.84,.44,1]],["easeInOutQuart",[.77,0,.175,1]],["easeInQuint",[.755,.05,.855,.06]],["easeOutQuint",[.23,1,.32,1]],["easeInOutQuint",[.86,0,.07,1]],["easeInExpo",[.95,.05,.795,.035]],["easeOutExpo",[.19,1,.22,1]],["easeInOutExpo",[1,0,0,1]],["easeInCirc",[.6,.04,.98,.335]],["easeOutCirc",[.075,.82,.165,1]],["easeInOutCirc",[.785,.135,.15,.86]]],function(e,t){v.Easings[t[0]]=l.apply(null,t[1])});var x=v.CSS={RegEx:{isHex:/^#([A-f\d]{3}){1,2}$/i,valueUnwrap:/^[A-z]+\((.*)\)$/i,wrappedValueAlreadyExtracted:/[0-9.]+ [0-9.]+ [0-9.]+( [0-9.]+)?/,valueSplit:/([A-z]+\(.+\))|(([A-z0-9#-.]+?)(?=\s|$))/gi},Lists:{colors:["fill","stroke","stopColor","color","backgroundColor","borderColor","borderTopColor","borderRightColor","borderBottomColor","borderLeftColor","outlineColor"],transformsBase:["translateX","translateY","scale","scaleX","scaleY","skewX","skewY","rotateZ"],transforms3D:["transformPerspective","translateZ","scaleZ","rotateX","rotateY"]},Hooks:{templates:{textShadow:["Color X Y Blur","black 0px 0px 0px"],boxShadow:["Color X Y Blur Spread","black 0px 0px 0px 0px"],clip:["Top Right Bottom Left","0px 0px 0px 0px"],backgroundPosition:["X Y","0% 0%"],transformOrigin:["X Y Z","50% 50% 0px"],perspectiveOrigin:["X Y","50% 50%"]},registered:{},register:function(){for(var e=0;e=f)switch(e){case"name":return"filter";case"extract":var a=r.toString().match(/alpha\(opacity=(.*)\)/i);return r=a?a[1]/100:1;case"inject":return t.style.zoom=1,parseFloat(r)>=1?"":"alpha(opacity="+parseInt(100*parseFloat(r),10)+")"}else switch(e){case"name":return"opacity";case"extract":return r;case"inject":return r}}},register:function(){9>=f||v.State.isGingerbread||(x.Lists.transformsBase=x.Lists.transformsBase.concat(x.Lists.transforms3D));for(var e=0;en&&(n=1),o=!/(\d)$/i.test(n);break;case"skew":o=!/(deg|\d)$/i.test(n);break;case"rotate":o=!/(deg|\d)$/i.test(n)}return o||(i(r).transformCache[t]="("+n+")"),i(r).transformCache[t]}}}();for(var e=0;e=f||3!==o.split(" ").length||(o+=" 1"),o;case"inject":return 8>=f?4===n.split(" ").length&&(n=n.split(/\s+/).slice(0,3).join(" ")):3===n.split(" ").length&&(n+=" 1"),(8>=f?"rgb":"rgba")+"("+n.replace(/\s+/g,",").replace(/\.(\d)+(?=,)/g,"")+")"}}}()}},Names:{camelCase:function(e){return e.replace(/-(\w)/g,function(e,t){return t.toUpperCase()})},SVGAttribute:function(e){var t="width|height|x|y|cx|cy|r|rx|ry|x1|x2|y1|y2";return(f||v.State.isAndroid&&!v.State.isChrome)&&(t+="|transform"),new RegExp("^("+t+")$","i").test(e)},prefixCheck:function(e){if(v.State.prefixMatches[e])return[v.State.prefixMatches[e],!0];for(var t=["","Webkit","Moz","ms","O"],r=0,a=t.length;a>r;r++){var n;if(n=0===r?e:t[r]+e.replace(/^\w/,function(e){return e.toUpperCase()}),g.isString(v.State.prefixElement.style[n]))return v.State.prefixMatches[e]=n,[n,!0]}return[e,!1]}},Values:{hexToRgb:function(e){var t=/^#?([a-f\d])([a-f\d])([a-f\d])$/i,r=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,a;return e=e.replace(t,function(e,t,r,a){return t+t+r+r+a+a}),a=r.exec(e),a?[parseInt(a[1],16),parseInt(a[2],16),parseInt(a[3],16)]:[0,0,0]},isCSSNullValue:function(e){return 0==e||/^(none|auto|transparent|(rgba\(0, ?0, ?0, ?0\)))$/i.test(e)},getUnitType:function(e){return/^(rotate|skew)/i.test(e)?"deg":/(^(scale|scaleX|scaleY|scaleZ|alpha|flexGrow|flexHeight|zIndex|fontWeight)$)|((opacity|red|green|blue|alpha)$)/i.test(e)?"":"px"},getDisplayType:function(e){var t=e&&e.tagName.toString().toLowerCase();return/^(b|big|i|small|tt|abbr|acronym|cite|code|dfn|em|kbd|strong|samp|var|a|bdo|br|img|map|object|q|script|span|sub|sup|button|input|label|select|textarea)$/i.test(t)?"inline":/^(li)$/i.test(t)?"list-item":/^(tr)$/i.test(t)?"table-row":/^(table)$/i.test(t)?"table":/^(tbody)$/i.test(t)?"table-row-group":"block"},addClass:function(e,t){e.classList?e.classList.add(t):e.className+=(e.className.length?" ":"")+t},removeClass:function(e,t){e.classList?e.classList.remove(t):e.className=e.className.toString().replace(new RegExp("(^|\\s)"+t.split(" ").join("|")+"(\\s|$)","gi")," ")}},getPropertyValue:function(e,r,n,o){function s(e,r){function n(){u&&x.setPropertyValue(e,"display","none")}var l=0;if(8>=f)l=$.css(e,r);else{var u=!1;if(/^(width|height)$/.test(r)&&0===x.getPropertyValue(e,"display")&&(u=!0,x.setPropertyValue(e,"display",x.Values.getDisplayType(e))),!o){if("height"===r&&"border-box"!==x.getPropertyValue(e,"boxSizing").toString().toLowerCase()){var c=e.offsetHeight-(parseFloat(x.getPropertyValue(e,"borderTopWidth"))||0)-(parseFloat(x.getPropertyValue(e,"borderBottomWidth"))||0)-(parseFloat(x.getPropertyValue(e,"paddingTop"))||0)-(parseFloat(x.getPropertyValue(e,"paddingBottom"))||0);return n(),c}if("width"===r&&"border-box"!==x.getPropertyValue(e,"boxSizing").toString().toLowerCase()){var p=e.offsetWidth-(parseFloat(x.getPropertyValue(e,"borderLeftWidth"))||0)-(parseFloat(x.getPropertyValue(e,"borderRightWidth"))||0)-(parseFloat(x.getPropertyValue(e,"paddingLeft"))||0)-(parseFloat(x.getPropertyValue(e,"paddingRight"))||0);return n(),p}}var d;d=i(e)===a?t.getComputedStyle(e,null):i(e).computedStyle?i(e).computedStyle:i(e).computedStyle=t.getComputedStyle(e,null),"borderColor"===r&&(r="borderTopColor"),l=9===f&&"filter"===r?d.getPropertyValue(r):d[r],(""===l||null===l)&&(l=e.style[r]),n()}if("auto"===l&&/^(top|right|bottom|left)$/i.test(r)){var g=s(e,"position");("fixed"===g||"absolute"===g&&/top|left/i.test(r))&&(l=$(e).position()[r]+"px")}return l}var l;if(x.Hooks.registered[r]){var u=r,c=x.Hooks.getRoot(u);n===a&&(n=x.getPropertyValue(e,x.Names.prefixCheck(c)[0])),x.Normalizations.registered[c]&&(n=x.Normalizations.registered[c]("extract",e,n)),l=x.Hooks.extractValue(u,n)}else if(x.Normalizations.registered[r]){var p,d;p=x.Normalizations.registered[r]("name",e),"transform"!==p&&(d=s(e,x.Names.prefixCheck(p)[0]),x.Values.isCSSNullValue(d)&&x.Hooks.templates[r]&&(d=x.Hooks.templates[r][1])),l=x.Normalizations.registered[r]("extract",e,d)}if(!/^[\d-]/.test(l))if(i(e)&&i(e).isSVG&&x.Names.SVGAttribute(r))if(/^(height|width)$/i.test(r))try{l=e.getBBox()[r]}catch(g){l=0}else l=e.getAttribute(r);else l=s(e,x.Names.prefixCheck(r)[0]);return x.Values.isCSSNullValue(l)&&(l=0),v.debug>=2&&console.log("Get "+r+": "+l),l},setPropertyValue:function(e,r,a,n,o){var s=r;if("scroll"===r)o.container?o.container["scroll"+o.direction]=a:"Left"===o.direction?t.scrollTo(a,o.alternateValue):t.scrollTo(o.alternateValue,a);else if(x.Normalizations.registered[r]&&"transform"===x.Normalizations.registered[r]("name",e))x.Normalizations.registered[r]("inject",e,a),s="transform",a=i(e).transformCache[r];else{if(x.Hooks.registered[r]){var l=r,u=x.Hooks.getRoot(r);n=n||x.getPropertyValue(e,u),a=x.Hooks.injectValue(l,a,n),r=u}if(x.Normalizations.registered[r]&&(a=x.Normalizations.registered[r]("inject",e,a),r=x.Normalizations.registered[r]("name",e)),s=x.Names.prefixCheck(r)[0],8>=f)try{e.style[s]=a}catch(c){v.debug&&console.log("Browser does not support ["+a+"] for ["+s+"]")}else i(e)&&i(e).isSVG&&x.Names.SVGAttribute(r)?e.setAttribute(r,a):e.style[s]=a;v.debug>=2&&console.log("Set "+r+" ("+s+"): "+a)}return[s,a]},flushTransformCache:function(e){function t(t){return parseFloat(x.getPropertyValue(e,t))}var r="";if((f||v.State.isAndroid&&!v.State.isChrome)&&i(e).isSVG){var a={translate:[t("translateX"),t("translateY")],skewX:[t("skewX")],skewY:[t("skewY")],scale:1!==t("scale")?[t("scale"),t("scale")]:[t("scaleX"),t("scaleY")],rotate:[t("rotateZ"),0,0]};$.each(i(e).transformCache,function(e){/^translate/i.test(e)?e="translate":/^scale/i.test(e)?e="scale":/^rotate/i.test(e)&&(e="rotate"),a[e]&&(r+=e+"("+a[e].join(" ")+") ",delete a[e])})}else{var n,o;$.each(i(e).transformCache,function(t){return n=i(e).transformCache[t],"transformPerspective"===t?(o=n,!0):(9===f&&"rotateZ"===t&&(t="rotate"),void(r+=t+n+" "))}),o&&(r="perspective"+o+" "+r)}x.setPropertyValue(e,"transform",r)}};x.Hooks.register(),x.Normalizations.register(),v.hook=function(e,t,r){var n=a;return e=o(e),$.each(e,function(e,o){if(i(o)===a&&v.init(o),r===a)n===a&&(n=v.CSS.getPropertyValue(o,t));else{var s=v.CSS.setPropertyValue(o,t,r);"transform"===s[0]&&v.CSS.flushTransformCache(o),n=s}}),n};var S=function(){function e(){return l?T.promise||null:f}function n(){function e(e){function p(e,t){var r=a,i=a,s=a;return g.isArray(e)?(r=e[0],!g.isArray(e[1])&&/^[\d-]/.test(e[1])||g.isFunction(e[1])||x.RegEx.isHex.test(e[1])?s=e[1]:(g.isString(e[1])&&!x.RegEx.isHex.test(e[1])||g.isArray(e[1]))&&(i=t?e[1]:u(e[1],o.duration),e[2]!==a&&(s=e[2]))):r=e,t||(i=i||o.easing),g.isFunction(r)&&(r=r.call(n,w,P)),g.isFunction(s)&&(s=s.call(n,w,P)),[r||0,i,s]}function f(e,t){var r,a;return a=(t||"0").toString().toLowerCase().replace(/[%A-z]+$/,function(e){return r=e,""}),r||(r=x.Values.getUnitType(e)),[a,r]}function d(){var e={myParent:n.parentNode||r.body,position:x.getPropertyValue(n,"position"),fontSize:x.getPropertyValue(n,"fontSize")},a=e.position===N.lastPosition&&e.myParent===N.lastParent,o=e.fontSize===N.lastFontSize;N.lastParent=e.myParent,N.lastPosition=e.position,N.lastFontSize=e.fontSize;var s=100,l={};if(o&&a)l.emToPx=N.lastEmToPx,l.percentToPxWidth=N.lastPercentToPxWidth,l.percentToPxHeight=N.lastPercentToPxHeight;else{var u=i(n).isSVG?r.createElementNS("http://www.w3.org/2000/svg","rect"):r.createElement("div");v.init(u),e.myParent.appendChild(u),$.each(["overflow","overflowX","overflowY"],function(e,t){v.CSS.setPropertyValue(u,t,"hidden")}),v.CSS.setPropertyValue(u,"position",e.position),v.CSS.setPropertyValue(u,"fontSize",e.fontSize),v.CSS.setPropertyValue(u,"boxSizing","content-box"),$.each(["minWidth","maxWidth","width","minHeight","maxHeight","height"],function(e,t){v.CSS.setPropertyValue(u,t,s+"%")}),v.CSS.setPropertyValue(u,"paddingLeft",s+"em"),l.percentToPxWidth=N.lastPercentToPxWidth=(parseFloat(x.getPropertyValue(u,"width",null,!0))||1)/s,l.percentToPxHeight=N.lastPercentToPxHeight=(parseFloat(x.getPropertyValue(u,"height",null,!0))||1)/s,l.emToPx=N.lastEmToPx=(parseFloat(x.getPropertyValue(u,"paddingLeft"))||1)/s,e.myParent.removeChild(u)}return null===N.remToPx&&(N.remToPx=parseFloat(x.getPropertyValue(r.body,"fontSize"))||16),null===N.vwToPx&&(N.vwToPx=parseFloat(t.innerWidth)/100,N.vhToPx=parseFloat(t.innerHeight)/100),l.remToPx=N.remToPx,l.vwToPx=N.vwToPx,l.vhToPx=N.vhToPx,v.debug>=1&&console.log("Unit ratios: "+JSON.stringify(l),n),l}if(o.begin&&0===w)try{o.begin.call(m,m)}catch(y){setTimeout(function(){throw y},1)}if("scroll"===k){var S=/^x$/i.test(o.axis)?"Left":"Top",V=parseFloat(o.offset)||0,C,A,F;o.container?g.isWrapped(o.container)||g.isNode(o.container)?(o.container=o.container[0]||o.container,C=o.container["scroll"+S],F=C+$(n).position()[S.toLowerCase()]+V):o.container=null:(C=v.State.scrollAnchor[v.State["scrollProperty"+S]],A=v.State.scrollAnchor[v.State["scrollProperty"+("Left"===S?"Top":"Left")]],F=$(n).offset()[S.toLowerCase()]+V),s={scroll:{rootPropertyValue:!1,startValue:C,currentValue:C,endValue:F,unitType:"",easing:o.easing,scrollData:{container:o.container,direction:S,alternateValue:A}},element:n},v.debug&&console.log("tweensContainer (scroll): ",s.scroll,n)}else if("reverse"===k){if(!i(n).tweensContainer)return void $.dequeue(n,o.queue);"none"===i(n).opts.display&&(i(n).opts.display="auto"),"hidden"===i(n).opts.visibility&&(i(n).opts.visibility="visible"),i(n).opts.loop=!1,i(n).opts.begin=null,i(n).opts.complete=null,b.easing||delete o.easing,b.duration||delete o.duration,o=$.extend({},i(n).opts,o);var E=$.extend(!0,{},i(n).tweensContainer);for(var j in E)if("element"!==j){var H=E[j].startValue;E[j].startValue=E[j].currentValue=E[j].endValue,E[j].endValue=H,g.isEmptyObject(b)||(E[j].easing=o.easing),v.debug&&console.log("reverse tweensContainer ("+j+"): "+JSON.stringify(E[j]),n)}s=E}else if("start"===k){var E;i(n).tweensContainer&&i(n).isAnimating===!0&&(E=i(n).tweensContainer),$.each(h,function(e,t){if(RegExp("^"+x.Lists.colors.join("$|^")+"$").test(e)){var r=p(t,!0),n=r[0],o=r[1],i=r[2];if(x.RegEx.isHex.test(n)){for(var s=["Red","Green","Blue"],l=x.Values.hexToRgb(n),u=i?x.Values.hexToRgb(i):a,c=0;cO;O++){var z={delay:F.delay,progress:F.progress};O===R-1&&(z.display=F.display,z.visibility=F.visibility,z.complete=F.complete),S(m,"reverse",z)}return e()}};v=$.extend(S,v),v.animate=S;var P=t.requestAnimationFrame||d;return v.State.isMobile||r.hidden===a||r.addEventListener("visibilitychange",function(){r.hidden?(P=function(e){return setTimeout(function(){e(!0)},16)},c()):P=t.requestAnimationFrame||d}),e.Velocity=v,e!==t&&(e.fn.velocity=S,e.fn.velocity.defaults=v.defaults),$.each(["Down","Up"],function(e,t){v.Redirects["slide"+t]=function(e,r,n,o,i,s){var l=$.extend({},r),u=l.begin,c=l.complete,p={height:"",marginTop:"",marginBottom:"",paddingTop:"",paddingBottom:""},f={};l.display===a&&(l.display="Down"===t?"inline"===v.CSS.Values.getDisplayType(e)?"inline-block":"block":"none"),l.begin=function(){u&&u.call(i,i);for(var r in p){f[r]=e.style[r];var a=v.CSS.getPropertyValue(e,r);p[r]="Down"===t?[a,0]:[0,a]}f.overflow=e.style.overflow,e.style.overflow="hidden"},l.complete=function(){for(var t in f)e.style[t]=f[t];c&&c.call(i,i),s&&s.resolver(i)},v(e,p,l)}}),$.each(["In","Out"],function(e,t){v.Redirects["fade"+t]=function(e,r,n,o,i,s){var l=$.extend({},r),u={opacity:"In"===t?1:0},c=l.complete;l.complete=n!==o-1?l.begin=null:function(){c&&c.call(i,i),s&&s.resolver(i)},l.display===a&&(l.display="In"===t?"auto":"none"),v(this,u,l)}}),v}(window.jQuery||window.Zepto||window,window,document)}); \ No newline at end of file diff --git a/lib/velocity/velocity.ui.min.js b/lib/velocity/velocity.ui.min.js new file mode 100644 index 00000000..87069453 --- /dev/null +++ b/lib/velocity/velocity.ui.min.js @@ -0,0 +1,2 @@ +/* VelocityJS.org UI Pack (5.0.4). (C) 2014 Julian Shapiro. MIT @license: en.wikipedia.org/wiki/MIT_License. Portions copyright Daniel Eden, Christian Pucci. */ +!function(t){"function"==typeof require&&"object"==typeof exports?module.exports=t():"function"==typeof define&&define.amd?define(["velocity"],t):t()}(function(){return function(t,a,e,r){function n(t,a){var e=[];return t&&a?($.each([t,a],function(t,a){var r=[];$.each(a,function(t,a){for(;a.toString().length<5;)a="0"+a;r.push(a)}),e.push(r.join(""))}),parseFloat(e[0])>parseFloat(e[1])):!1}if(!t.Velocity||!t.Velocity.Utilities)return void(a.console&&console.log("Velocity UI Pack: Velocity must be loaded first. Aborting."));var i=t.Velocity,$=i.Utilities,s=i.version,o={major:1,minor:1,patch:0};if(n(o,s)){var l="Velocity UI Pack: You need to update Velocity (jquery.velocity.js) to a newer version. Visit http://github.com/julianshapiro/velocity.";throw alert(l),new Error(l)}i.RegisterEffect=i.RegisterUI=function(t,a){function e(t,a,e,r){var n=0,s;$.each(t.nodeType?[t]:t,function(t,a){r&&(e+=t*r),s=a.parentNode,$.each(["height","paddingTop","paddingBottom","marginTop","marginBottom"],function(t,e){n+=parseFloat(i.CSS.getPropertyValue(a,e))})}),i.animate(s,{height:("In"===a?"+":"-")+"="+n},{queue:!1,easing:"ease-in-out",duration:e*("In"===a?.6:1)})}return i.Redirects[t]=function(n,s,o,l,c,u){function f(){s.display!==r&&"none"!==s.display||!/Out$/.test(t)||$.each(c.nodeType?[c]:c,function(t,a){i.CSS.setPropertyValue(a,"display","none")}),s.complete&&s.complete.call(c,c),u&&u.resolver(c||n)}var p=o===l-1;a.defaultDuration="function"==typeof a.defaultDuration?a.defaultDuration.call(c,c):parseFloat(a.defaultDuration);for(var d=0;d1&&($.each(a.reverse(),function(t,e){var r=a[t+1];if(r){var n=e.o||e.options,s=r.o||r.options,o=n&&n.sequenceQueue===!1?"begin":"complete",l=s&&s[o],c={};c[o]=function(){var t=r.e||r.elements,a=t.nodeType?[t]:t;l&&l.call(a,a),i(e)},r.o?r.o=$.extend({},s,c):r.options=$.extend({},s,c)}}),a.reverse()),i(a[0])}}(window.jQuery||window.Zepto||window,window,document)}); \ No newline at end of file diff --git a/misc/btrace/BTrace_BOF-5552_J12008.pdf b/misc/btrace/BTrace_BOF-5552_J12008.pdf new file mode 100644 index 00000000..a38f036e Binary files /dev/null and b/misc/btrace/BTrace_BOF-5552_J12008.pdf differ diff --git a/misc/btrace/developersguide.html b/misc/btrace/developersguide.html new file mode 100644 index 00000000..228f7561 --- /dev/null +++ b/misc/btrace/developersguide.html @@ -0,0 +1,150 @@ + + + +BTrace Developer's Guide + + + + +

    BTrace Developer's Guide

    +

    +BTrace is a safe, dynamic tracing tool for Java. Please +refer to user's guide for BTrace usage +information. +

    + +

    BTrace Development Tools

    + +

    +

      +
    • BTrace requires JDK 6 or above. +
    • BTrace can be built using ant or +NetBeans IDE. +
    +

    + +

    BTrace Components

    + +

    +BTrace accepts a tracing program written in (subset) of +the Java programming language. BTrace compiles the trace class +into bytecode and submits the same to a java.lang.instrument agent that +runs inside the target program. The BTrace agent is dynamically +loaded into the target program if it is not already loaded (using +"attach-on-demand" API). +

    +BTrace Components: +
      +
    • BTrace Client Tool - compiles, validates and submits BTrace program to +BTrace VM agent. And receives trace messages and prints to stdout. +
    • BTrace java.lang.instrument Agent to bytecode instrument classes +and hotswap them. Also, this agent verifies the bytecodes of BTrace +class for safety [read-only, boundedness] rules. This way we don't need +to trust the client to enforce the safety rules at compile time. +
    • Wire Protocol between the client and the agent. +
    +

    + +

    BTrace Packages

    +
      +
    • com.sun.btrace.agent. This package contains +classes for BTrace's java.lang.instrument agent. +This agent uses simple socket protocol to communicate with the client. +Multiple BTrace clients are supported. For each client, an instance +of com.sun.btrace.agent.Client is created. +
    • com.sun.btrace.annotations. This package +contains annotations and enumeration classes used by BTrace author +as well as agent to specify/infer "probed locations" of the traced +program. These classes are loaded by bootstrap loader (agent +adds classes containing these classes to bootstrap path). +
    • com.sun.btrace.client. This package contains +BTrace client tool main class. +
    • com.sun.btrace.dtrace. This package contains +BTrace and DTrace integration classes. The classes that wrap DTrace/Java +API are here. Please refer to /use/share/lib/java/javadoc/dtrace for DTrace/Java +API. +
    • com.sun.btrace.comm. This package contains +wire protocol messages between BTrace agent and client tool. BTrace +agent and client communicate by object serializing the instances of +Message classes. +
    • com.sun.btrace.compiler. This package +has classes for compiling a BTrace program into bytecode after +safety verification. Because BTrace accepts subset of Java, it uses +javac's APIs (JSR 199 - compiler tool API, JSR 269 - Annotation +Processing API and javac Tree API to access AST of compiled Java +program) to compile and enforce BTrace safety rules. +
    • com.sun.btrace.resources. This package contains +error messages resource used by BTrace compiler and bytecode verifier. +
    • com.sun.btrace.runtime. This package contains +various bytecode instrumentation classes used by BTrace. These +instrumentation classes use Objectweb's ASM +package to do actual class file parsing and writing. ASM version 3.0 +is used. This package contains BTrace bytecode verifier and jvmstat reader as well. +
    • com.sun.btrace. This package contains classes loaded +by bootstrap loader (agent adds classes containing these classes to bootstrap path). +com.sun.btrace.BTraceUtils class contains built-in "functions" that can be called +by any BTrace program (these are read-only and bounded methods can +be called by trace program). com.sun.btrace.BTraceRuntime class contains +per-client state for each BTrace client and helps implementing certain methods +of BTraceUtils. Also, BTraceRuntime makes sure that BTrace agent's own +method invocations and BTrace built-in "function" calls are not +traced [there by leading to infinite recursion!]. +
    + +

    BTrace jar files

    + +
      +
    • btrace-boot.jar - loaded by bootstrap loader in the traced +JVM. Contains BTrace annotation classes in com.sun.btrace.annotations +package and classes in com.sun.btrace package. +
    • btrace-agent.jar - contains classes for java.lang.instrument +agent and instrumentation classes. This uses asm-3.0 +jar for instrumentation and tools.jar for reading +jvmstat counter values [sun.jvmstat.monitor classes]. +
    • btrace-client.jar - contains BTrace client classes. This +uses tools.jar for javac's classes. +
    + +

    BTrace "To Do"s

    +
      +
    • Remove instrumentation when a client leaves tracing session. +Right now, we "disable" trace calls when a BTrace client leaves +the session. It would be better to remove the instrumentation and +re-hotswap the classes to avoid the "disabled" calls completely. +
    + +

    Debugging BTrace

    +

    +BTrace can be debugged by setting few System properties. All these properties are +set at the BTrace client. +

      +
    • com.sun.btrace.debug - this boolean valued property makes +BTrace to print debug messages (set at client - but debug mode is propagated +to BTrace agent as well). +
    • com.sun.btrace.dumpClasses - this boolean valued property +may be set to force BTrace agent dump every .class that is +intrumented. +
    • com.sun.btrace.dumpDir - this is a String valued property +that sets the directory where the instrumened .class files are dumped. +
    +It is better to run the traced JVM with -Xverify:all to force +bytecode verification of all classes. This is to make sure that BTrace does not produce +bad classes thereby crashing the JVM. After dumping instrumeted classes, it is possible +(offline) analyze those using javap tool. The BTrace action methods look like +the form: "btrace$<trace-class-name>$<trace-action-method-name>" - where "."s +in the trace class name are replaced by "$". +

    + +

    Known Issues and Limitations

    + +
      +
    • BTrace requires JDK 6. There are API dependencies [for example, javac's new APIs]. +And BTrace uses certain recent changes with java.lang.instrument and hotswap. In particular, +BTrace adds private methods while hotswapping classes. This feature (of +adding private methods while hotswapping classes) is not available in earlier +JDK versions. Also, retranformantion is used to avoid fetching .class bytes from +the file system. Again, this is a new feature of java.lang.instrument API since JDK 6. +
    + + + diff --git a/misc/btrace/index.html b/misc/btrace/index.html new file mode 100644 index 00000000..87a39fc5 --- /dev/null +++ b/misc/btrace/index.html @@ -0,0 +1,16 @@ + + + +BTrace + + + +

    BTrace

    + + + + + diff --git a/misc/btrace/javadoc/allclasses-frame.html b/misc/btrace/javadoc/allclasses-frame.html new file mode 100644 index 00000000..349eed45 --- /dev/null +++ b/misc/btrace/javadoc/allclasses-frame.html @@ -0,0 +1,212 @@ + + + + + +All Classes (btrace 1.3.11 API) + + + + + +

    All Classes

    +
    + +
    + + diff --git a/misc/btrace/javadoc/allclasses-noframe.html b/misc/btrace/javadoc/allclasses-noframe.html new file mode 100644 index 00000000..c6079439 --- /dev/null +++ b/misc/btrace/javadoc/allclasses-noframe.html @@ -0,0 +1,212 @@ + + + + + +All Classes (btrace 1.3.11 API) + + + + + +

    All Classes

    +
    + +
    + + diff --git a/misc/btrace/javadoc/com/sun/btrace/AnyType.html b/misc/btrace/javadoc/com/sun/btrace/AnyType.html new file mode 100644 index 00000000..94604657 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/AnyType.html @@ -0,0 +1,220 @@ + + + + + +AnyType (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Interface AnyType

    +
    +
    +
    +
      +
    • +
      +
      +
      public interface AnyType
      +
      This interface type is used in BTrace programs + to tell that any reference type [object or array] + is allowed in the place where it is used. We use + that for method signature matching when signature + needs to be specified loosely. Note that we don't + want to use java.lang.Object - because user may + want to match java.lang.Object exactly.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Summary

        + + + + + + + + + + +
        Fields 
        Modifier and TypeField and Description
        static AnyTypeVOID 
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + + +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/ArgsMap.html b/misc/btrace/javadoc/com/sun/btrace/ArgsMap.html new file mode 100644 index 00000000..d614a695 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/ArgsMap.html @@ -0,0 +1,498 @@ + + + + + +ArgsMap (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class ArgsMap

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.ArgsMap
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.lang.Iterable<java.util.Map.Entry<java.lang.String,java.lang.String>>
      +
      +
      +
      +
      public final class ArgsMap
      +extends java.lang.Object
      +implements java.lang.Iterable<java.util.Map.Entry<java.lang.String,java.lang.String>>
      +
      A simple argument map wrapper allowing indexed access
      +
    • +
    +
    +
    +
      +
    • + + + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        voidclear() 
        booleancontainsKey(java.lang.String key) 
        booleanequals(java.lang.Object o) 
        java.lang.Stringget(int idx) 
        java.lang.Stringget(java.lang.String key) 
        inthashCode() 
        booleanisEmpty() 
        java.util.Iterator<java.util.Map.Entry<java.lang.String,java.lang.String>>iterator() 
        static ArgsMapmerge(ArgsMap... maps) 
        java.lang.Stringput(java.lang.String key, + java.lang.String value) 
        intsize() 
        java.lang.Stringtemplate(java.lang.String value) 
        java.lang.StringtoString() 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, finalize, getClass, notify, notifyAll, wait, wait, wait
        • +
        +
          +
        • + + +

          Methods inherited from interface java.lang.Iterable

          +forEach, spliterator
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          ArgsMap

          +
          public ArgsMap(java.util.Map<java.lang.String,java.lang.String> args,
          +               DebugSupport debug)
          +
        • +
        + + + +
          +
        • +

          ArgsMap

          +
          public ArgsMap(java.lang.String[] argLine,
          +               DebugSupport debug)
          +
        • +
        + + + +
          +
        • +

          ArgsMap

          +
          public ArgsMap()
          +
        • +
        + + + +
          +
        • +

          ArgsMap

          +
          public ArgsMap(int initialCapacity,
          +               DebugSupport debug)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          get

          +
          public java.lang.String get(java.lang.String key)
          +
        • +
        + + + +
          +
        • +

          get

          +
          public java.lang.String get(int idx)
          +
        • +
        + + + +
          +
        • +

          clear

          +
          public void clear()
          +
        • +
        + + + +
          +
        • +

          size

          +
          public int size()
          +
        • +
        + + + +
          +
        • +

          isEmpty

          +
          public boolean isEmpty()
          +
        • +
        + + + +
          +
        • +

          put

          +
          public java.lang.String put(java.lang.String key,
          +                            java.lang.String value)
          +
        • +
        + + + +
          +
        • +

          iterator

          +
          public java.util.Iterator<java.util.Map.Entry<java.lang.String,java.lang.String>> iterator()
          +
          +
          Specified by:
          +
          iterator in interface java.lang.Iterable<java.util.Map.Entry<java.lang.String,java.lang.String>>
          +
          +
        • +
        + + + +
          +
        • +

          containsKey

          +
          public boolean containsKey(java.lang.String key)
          +
        • +
        + + + +
          +
        • +

          equals

          +
          public boolean equals(java.lang.Object o)
          +
          +
          Overrides:
          +
          equals in class java.lang.Object
          +
          +
        • +
        + + + +
          +
        • +

          hashCode

          +
          public int hashCode()
          +
          +
          Overrides:
          +
          hashCode in class java.lang.Object
          +
          +
        • +
        + + + +
          +
        • +

          toString

          +
          public java.lang.String toString()
          +
          +
          Overrides:
          +
          toString in class java.lang.Object
          +
          +
        • +
        + + + + + + + +
          +
        • +

          template

          +
          public java.lang.String template(java.lang.String value)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/BTraceCollection.html b/misc/btrace/javadoc/com/sun/btrace/BTraceCollection.html new file mode 100644 index 00000000..7b49bbdf --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/BTraceCollection.html @@ -0,0 +1,203 @@ + + + + + +BTraceCollection (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Interface BTraceCollection<T>

    +
    +
    +
    +
      +
    • +
      +
      All Superinterfaces:
      +
      java.util.Collection<T>, java.lang.Iterable<T>
      +
      +
      +
      All Known Implementing Classes:
      +
      BTraceDeque
      +
      +
      +
      +
      public interface BTraceCollection<T>
      +extends java.util.Collection<T>
      +
      Marker interface for BTrace defined collections
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Method Summary

        +
          +
        • + + +

          Methods inherited from interface java.util.Collection

          +add, addAll, clear, contains, containsAll, equals, hashCode, isEmpty, iterator, parallelStream, remove, removeAll, removeIf, retainAll, size, spliterator, stream, toArray, toArray
        • +
        +
          +
        • + + +

          Methods inherited from interface java.lang.Iterable

          +forEach
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/BTraceDeque.html b/misc/btrace/javadoc/com/sun/btrace/BTraceDeque.html new file mode 100644 index 00000000..015f846a --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/BTraceDeque.html @@ -0,0 +1,985 @@ + + + + + +BTraceDeque (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class BTraceDeque<V>

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.BTraceDeque<V>
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      BTraceCollection<V>, java.lang.Cloneable, java.lang.Iterable<V>, java.util.Collection<V>, java.util.Deque<V>, java.util.Queue<V>
      +
      +
      +
      +
      public class BTraceDeque<V>
      +extends java.lang.Object
      +implements java.util.Deque<V>, BTraceCollection<V>, java.lang.Cloneable
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          BTraceDeque

          +
          public BTraceDeque(java.util.Deque<V> delegate)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          toString

          +
          public java.lang.String toString()
          +
          +
          Overrides:
          +
          toString in class java.lang.Object
          +
          +
        • +
        + + + + + +
          +
        • +

          toArray

          +
          public <T> T[] toArray(T[] a)
          +
          +
          Specified by:
          +
          toArray in interface java.util.Collection<V>
          +
          +
        • +
        + + + +
          +
        • +

          toArray

          +
          public java.lang.Object[] toArray()
          +
          +
          Specified by:
          +
          toArray in interface java.util.Collection<V>
          +
          +
        • +
        + + + +
          +
        • +

          retainAll

          +
          public boolean retainAll(java.util.Collection<?> c)
          +
          +
          Specified by:
          +
          retainAll in interface java.util.Collection<V>
          +
          +
        • +
        + + + +
          +
        • +

          removeAll

          +
          public boolean removeAll(java.util.Collection<?> c)
          +
          +
          Specified by:
          +
          removeAll in interface java.util.Collection<V>
          +
          +
        • +
        + + + +
          +
        • +

          isEmpty

          +
          public boolean isEmpty()
          +
          +
          Specified by:
          +
          isEmpty in interface java.util.Collection<V>
          +
          +
        • +
        + + + +
          +
        • +

          containsAll

          +
          public boolean containsAll(java.util.Collection<?> c)
          +
          +
          Specified by:
          +
          containsAll in interface java.util.Collection<V>
          +
          +
        • +
        + + + +
          +
        • +

          clear

          +
          public void clear()
          +
          +
          Specified by:
          +
          clear in interface java.util.Collection<V>
          +
          +
        • +
        + + + +
          +
        • +

          addAll

          +
          public boolean addAll(java.util.Collection<? extends V> c)
          +
          +
          Specified by:
          +
          addAll in interface java.util.Collection<V>
          +
          +
        • +
        + + + +
          +
        • +

          size

          +
          public int size()
          +
          +
          Specified by:
          +
          size in interface java.util.Collection<V>
          +
          Specified by:
          +
          size in interface java.util.Deque<V>
          +
          +
        • +
        + + + +
          +
        • +

          removeLastOccurrence

          +
          public boolean removeLastOccurrence(java.lang.Object o)
          +
          +
          Specified by:
          +
          removeLastOccurrence in interface java.util.Deque<V>
          +
          +
        • +
        + + + +
          +
        • +

          removeLast

          +
          public V removeLast()
          +
          +
          Specified by:
          +
          removeLast in interface java.util.Deque<V>
          +
          +
        • +
        + + + +
          +
        • +

          removeFirstOccurrence

          +
          public boolean removeFirstOccurrence(java.lang.Object o)
          +
          +
          Specified by:
          +
          removeFirstOccurrence in interface java.util.Deque<V>
          +
          +
        • +
        + + + +
          +
        • +

          removeFirst

          +
          public V removeFirst()
          +
          +
          Specified by:
          +
          removeFirst in interface java.util.Deque<V>
          +
          +
        • +
        + + + +
          +
        • +

          remove

          +
          public boolean remove(java.lang.Object o)
          +
          +
          Specified by:
          +
          remove in interface java.util.Collection<V>
          +
          Specified by:
          +
          remove in interface java.util.Deque<V>
          +
          +
        • +
        + + + +
          +
        • +

          remove

          +
          public V remove()
          +
          +
          Specified by:
          +
          remove in interface java.util.Deque<V>
          +
          Specified by:
          +
          remove in interface java.util.Queue<V>
          +
          +
        • +
        + + + + + +
          +
        • +

          push

          +
          public void push(V e)
          +
          +
          Specified by:
          +
          push in interface java.util.Deque<V>
          +
          +
        • +
        + + + +
          +
        • +

          pop

          +
          public V pop()
          +
          +
          Specified by:
          +
          pop in interface java.util.Deque<V>
          +
          +
        • +
        + + + +
          +
        • +

          pollLast

          +
          public V pollLast()
          +
          +
          Specified by:
          +
          pollLast in interface java.util.Deque<V>
          +
          +
        • +
        + + + +
          +
        • +

          pollFirst

          +
          public V pollFirst()
          +
          +
          Specified by:
          +
          pollFirst in interface java.util.Deque<V>
          +
          +
        • +
        + + + +
          +
        • +

          poll

          +
          public V poll()
          +
          +
          Specified by:
          +
          poll in interface java.util.Deque<V>
          +
          Specified by:
          +
          poll in interface java.util.Queue<V>
          +
          +
        • +
        + + + +
          +
        • +

          peekLast

          +
          public V peekLast()
          +
          +
          Specified by:
          +
          peekLast in interface java.util.Deque<V>
          +
          +
        • +
        + + + +
          +
        • +

          peekFirst

          +
          public V peekFirst()
          +
          +
          Specified by:
          +
          peekFirst in interface java.util.Deque<V>
          +
          +
        • +
        + + + +
          +
        • +

          peek

          +
          public V peek()
          +
          +
          Specified by:
          +
          peek in interface java.util.Deque<V>
          +
          Specified by:
          +
          peek in interface java.util.Queue<V>
          +
          +
        • +
        + + + + + +
          +
        • +

          offerLast

          +
          public boolean offerLast(V e)
          +
          +
          Specified by:
          +
          offerLast in interface java.util.Deque<V>
          +
          +
        • +
        + + + + + +
          +
        • +

          offerFirst

          +
          public boolean offerFirst(V e)
          +
          +
          Specified by:
          +
          offerFirst in interface java.util.Deque<V>
          +
          +
        • +
        + + + + + +
          +
        • +

          offer

          +
          public boolean offer(V e)
          +
          +
          Specified by:
          +
          offer in interface java.util.Deque<V>
          +
          Specified by:
          +
          offer in interface java.util.Queue<V>
          +
          +
        • +
        + + + +
          +
        • +

          iterator

          +
          public java.util.Iterator<V> iterator()
          +
          +
          Specified by:
          +
          iterator in interface java.lang.Iterable<V>
          +
          Specified by:
          +
          iterator in interface java.util.Collection<V>
          +
          Specified by:
          +
          iterator in interface java.util.Deque<V>
          +
          +
        • +
        + + + +
          +
        • +

          getLast

          +
          public V getLast()
          +
          +
          Specified by:
          +
          getLast in interface java.util.Deque<V>
          +
          +
        • +
        + + + +
          +
        • +

          getFirst

          +
          public V getFirst()
          +
          +
          Specified by:
          +
          getFirst in interface java.util.Deque<V>
          +
          +
        • +
        + + + +
          +
        • +

          element

          +
          public V element()
          +
          +
          Specified by:
          +
          element in interface java.util.Deque<V>
          +
          Specified by:
          +
          element in interface java.util.Queue<V>
          +
          +
        • +
        + + + +
          +
        • +

          descendingIterator

          +
          public java.util.Iterator<V> descendingIterator()
          +
          +
          Specified by:
          +
          descendingIterator in interface java.util.Deque<V>
          +
          +
        • +
        + + + +
          +
        • +

          contains

          +
          public boolean contains(java.lang.Object o)
          +
          +
          Specified by:
          +
          contains in interface java.util.Collection<V>
          +
          Specified by:
          +
          contains in interface java.util.Deque<V>
          +
          +
        • +
        + + + + + +
          +
        • +

          addLast

          +
          public void addLast(V e)
          +
          +
          Specified by:
          +
          addLast in interface java.util.Deque<V>
          +
          +
        • +
        + + + + + +
          +
        • +

          addFirst

          +
          public void addFirst(V e)
          +
          +
          Specified by:
          +
          addFirst in interface java.util.Deque<V>
          +
          +
        • +
        + + + + + +
          +
        • +

          add

          +
          public boolean add(V e)
          +
          +
          Specified by:
          +
          add in interface java.util.Collection<V>
          +
          Specified by:
          +
          add in interface java.util.Deque<V>
          +
          Specified by:
          +
          add in interface java.util.Queue<V>
          +
          +
        • +
        + + + +
          +
        • +

          hashCode

          +
          public int hashCode()
          +
          +
          Specified by:
          +
          hashCode in interface java.util.Collection<V>
          +
          Overrides:
          +
          hashCode in class java.lang.Object
          +
          +
        • +
        + + + +
          +
        • +

          equals

          +
          public boolean equals(java.lang.Object obj)
          +
          +
          Specified by:
          +
          equals in interface java.util.Collection<V>
          +
          Overrides:
          +
          equals in class java.lang.Object
          +
          +
        • +
        + + + +
          +
        • +

          clone

          +
          protected java.lang.Object clone()
          +                          throws java.lang.CloneNotSupportedException
          +
          +
          Overrides:
          +
          clone in class java.lang.Object
          +
          Throws:
          +
          java.lang.CloneNotSupportedException
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/BTraceMBean.html b/misc/btrace/javadoc/com/sun/btrace/BTraceMBean.html new file mode 100644 index 00000000..6b9ed82b --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/BTraceMBean.html @@ -0,0 +1,411 @@ + + + + + +BTraceMBean (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class BTraceMBean

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.BTraceMBean
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      javax.management.DynamicMBean
      +
      +
      +
      +
      public class BTraceMBean
      +extends java.lang.Object
      +implements javax.management.DynamicMBean
      +
      This is a simple DynamicMBean implementation that exposes the static + fields of BTrace class as attributes. The fields exposed should be + annotated as Property.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        BTraceMBean(java.lang.Class clazz) 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        java.lang.ObjectgetAttribute(java.lang.String name) 
        javax.management.AttributeListgetAttributes(java.lang.String[] names) 
        javax.management.MBeanInfogetMBeanInfo() 
        java.lang.Objectinvoke(java.lang.String name, + java.lang.Object[] args, + java.lang.String[] sig) 
        static booleanisMBean(java.lang.Class clazz) 
        static voidregisterMBean(java.lang.Class clazz) 
        voidsetAttribute(javax.management.Attribute attribute) 
        javax.management.AttributeListsetAttributes(javax.management.AttributeList list) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          BTraceMBean

          +
          public BTraceMBean(java.lang.Class clazz)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getAttribute

          +
          public java.lang.Object getAttribute(java.lang.String name)
          +                              throws javax.management.AttributeNotFoundException
          +
          +
          Specified by:
          +
          getAttribute in interface javax.management.DynamicMBean
          +
          Throws:
          +
          javax.management.AttributeNotFoundException
          +
          +
        • +
        + + + +
          +
        • +

          setAttribute

          +
          public void setAttribute(javax.management.Attribute attribute)
          +                  throws javax.management.InvalidAttributeValueException,
          +                         javax.management.MBeanException,
          +                         javax.management.AttributeNotFoundException
          +
          +
          Specified by:
          +
          setAttribute in interface javax.management.DynamicMBean
          +
          Throws:
          +
          javax.management.InvalidAttributeValueException
          +
          javax.management.MBeanException
          +
          javax.management.AttributeNotFoundException
          +
          +
        • +
        + + + +
          +
        • +

          getAttributes

          +
          public javax.management.AttributeList getAttributes(java.lang.String[] names)
          +
          +
          Specified by:
          +
          getAttributes in interface javax.management.DynamicMBean
          +
          +
        • +
        + + + +
          +
        • +

          setAttributes

          +
          public javax.management.AttributeList setAttributes(javax.management.AttributeList list)
          +
          +
          Specified by:
          +
          setAttributes in interface javax.management.DynamicMBean
          +
          +
        • +
        + + + +
          +
        • +

          invoke

          +
          public java.lang.Object invoke(java.lang.String name,
          +                               java.lang.Object[] args,
          +                               java.lang.String[] sig)
          +                        throws javax.management.MBeanException,
          +                               javax.management.ReflectionException
          +
          +
          Specified by:
          +
          invoke in interface javax.management.DynamicMBean
          +
          Throws:
          +
          javax.management.MBeanException
          +
          javax.management.ReflectionException
          +
          +
        • +
        + + + +
          +
        • +

          getMBeanInfo

          +
          public javax.management.MBeanInfo getMBeanInfo()
          +
          +
          Specified by:
          +
          getMBeanInfo in interface javax.management.DynamicMBean
          +
          +
        • +
        + + + +
          +
        • +

          registerMBean

          +
          public static void registerMBean(java.lang.Class clazz)
          +
        • +
        + + + +
          +
        • +

          isMBean

          +
          public static boolean isMBean(java.lang.Class clazz)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/BTraceRuntime.html b/misc/btrace/javadoc/com/sun/btrace/BTraceRuntime.html new file mode 100644 index 00000000..70853a04 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/BTraceRuntime.html @@ -0,0 +1,997 @@ + + + + + +BTraceRuntime (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class BTraceRuntime

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.BTraceRuntime
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class BTraceRuntime
      +extends java.lang.Object
      +
      Helper class used by BTrace built-in functions and + also acts runtime "manager" for a specific BTrace client + and sends Commands to the CommandListener passed.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Summary

        + + + + + + + + + + +
        Fields 
        Modifier and TypeField and Description
        static java.lang.StringCMD_QUEUE_LIMIT_KEY 
        +
      • +
      + + + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static <V> voidaddLast(java.util.Deque<V> queue, + V value) 
        static java.lang.Appendableappend(java.lang.Appendable buffer, + java.lang.String strToAppend) 
        static <V> voidclear(java.util.Deque<V> queue) 
        java.lang.ClassdefineClass(byte[] code) 
        java.lang.ClassdefineClass(byte[] code, + boolean mustBeBootstrap) 
        static booleanenter() 
        static booleanenter(BTraceRuntime current) +
        Enter method is called by every probed method just + before the probe actions start.
        +
        static BTraceRuntimeforClass(java.lang.Class cl, + TimerHandler[] tHandlers, + EventHandler[] evHandlers, + ErrorHandler[] errHandlers, + ExitHandler[] eHandlers, + LowMemoryHandler[] lmHandlers) +
        One instance of BTraceRuntime is created per-client.
        +
        static java.lang.StringgetClientName(java.lang.String forClassName) 
        static doublegetPerfDouble(java.lang.String name) +
        Return the value of double perf.
        +
        static floatgetPerfFloat(java.lang.String name) +
        Return the value of float perf.
        +
        static intgetPerfInt(java.lang.String name) +
        Return the value of integer perf.
        +
        static longgetPerfLong(java.lang.String name) +
        Return the value of long perf.
        +
        static java.lang.StringgetPerfString(java.lang.String name) +
        Return the value of String perf.
        +
        voidhandleEvent(EventCommand ecmd) 
        static voidhandleException(java.lang.Throwable th) +
        Handles exception from BTrace probe actions.
        +
        voidhandleExit(int exitCode) 
        static voidinit(PerfReader perfRead) 
        static voidinitUnsafe() 
        static <E> booleanisEmpty(java.util.Collection<E> coll) 
        static voidleave() +
        Leave method is called by every probed method just + before the probe actions end (and actual probed + method continues).
        +
        static intlength(java.lang.Appendable buffer) 
        static voidnewPerfCounter(java.lang.Object value, + java.lang.String name, + java.lang.String desc) 
        static voidnewPerfCounter(java.lang.String name, + java.lang.String desc, + java.lang.Object value) +
        Utility to create a new jvmstat perf counter.
        +
        static java.lang.ThreadLocalnewThreadLocal(java.lang.Object initValue) +
        Utility to create a new ThreadLocal object.
        +
        static intparseInt(java.lang.String value, + int deflt) 
        static longparseLong(java.lang.String value, + long deflt) 
        static <V> Vpeek(java.util.Deque<V> queue) 
        static <V> VpeekFirst(java.util.Deque<V> queue) 
        static <V> VpeekLast(java.util.Deque<V> queue) 
        static <V> Vpoll(java.util.Deque<V> queue) 
        static <V> voidpush(java.util.Deque<V> queue, + V value) 
        static voidputPerfDouble(double value, + java.lang.String name) +
        write the value of double perf.
        +
        static voidputPerfFloat(float value, + java.lang.String name) +
        Write the value of float perf.
        +
        static voidputPerfInt(int value, + java.lang.String name) +
        Write the value of integer perf.
        +
        static voidputPerfLong(long value, + java.lang.String name) +
        Write the value of float perf.
        +
        static voidputPerfString(java.lang.String value, + java.lang.String name) +
        Write the value of float perf.
        +
        static <V> VremoveFirst(java.util.Deque<V> queue) 
        static <V> VremoveLast(java.util.Deque<V> queue) 
        static voidretransform(java.lang.String runtimeName, + java.lang.Class<?> clazz) 
        static java.lang.StringsafeStr(java.lang.Object obj) 
        voidsend(Command cmd) 
        voidshutdownCmdLine() 
        static voidstart() +
        start method is called by every BTrace (preprocesed) class + just at the end of it's class initializer.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Detail

        + + + +
          +
        • +

          CMD_QUEUE_LIMIT_KEY

          +
          public static final java.lang.String CMD_QUEUE_LIMIT_KEY
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          BTraceRuntime

          +
          public BTraceRuntime(java.lang.String className,
          +                     ArgsMap args,
          +                     CommandListener cmdListener,
          +                     DebugSupport ds,
          +                     java.lang.instrument.Instrumentation inst)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          parseLong

          +
          public static long parseLong(java.lang.String value,
          +                             long deflt)
          +
        • +
        + + + +
          +
        • +

          parseInt

          +
          public static int parseInt(java.lang.String value,
          +                           int deflt)
          +
        • +
        + + + +
          +
        • +

          initUnsafe

          +
          public static void initUnsafe()
          +
        • +
        + + + +
          +
        • +

          getClientName

          +
          public static java.lang.String getClientName(java.lang.String forClassName)
          +
        • +
        + + + +
          +
        • +

          init

          +
          public static void init(PerfReader perfRead)
          +
        • +
        + + + +
          +
        • +

          defineClass

          +
          public java.lang.Class defineClass(byte[] code)
          +
        • +
        + + + +
          +
        • +

          defineClass

          +
          public java.lang.Class defineClass(byte[] code,
          +                                   boolean mustBeBootstrap)
          +
        • +
        + + + +
          +
        • +

          shutdownCmdLine

          +
          public void shutdownCmdLine()
          +
        • +
        + + + +
          +
        • +

          enter

          +
          public static boolean enter(BTraceRuntime current)
          +
          Enter method is called by every probed method just + before the probe actions start.
          +
        • +
        + + + +
          +
        • +

          enter

          +
          public static boolean enter()
          +
        • +
        + + + +
          +
        • +

          leave

          +
          public static void leave()
          +
          Leave method is called by every probed method just + before the probe actions end (and actual probed + method continues).
          +
        • +
        + + + +
          +
        • +

          start

          +
          public static void start()
          +
          start method is called by every BTrace (preprocesed) class + just at the end of it's class initializer.
          +
        • +
        + + + +
          +
        • +

          handleExit

          +
          public void handleExit(int exitCode)
          +
        • +
        + + + +
          +
        • +

          handleEvent

          +
          public void handleEvent(EventCommand ecmd)
          +
        • +
        + + + +
          +
        • +

          forClass

          +
          public static BTraceRuntime forClass(java.lang.Class cl,
          +                                     TimerHandler[] tHandlers,
          +                                     EventHandler[] evHandlers,
          +                                     ErrorHandler[] errHandlers,
          +                                     ExitHandler[] eHandlers,
          +                                     LowMemoryHandler[] lmHandlers)
          +
          One instance of BTraceRuntime is created per-client. + This forClass method creates it. Class passed is the + preprocessed BTrace program of the client.
          +
        • +
        + + + +
          +
        • +

          newThreadLocal

          +
          public static java.lang.ThreadLocal newThreadLocal(java.lang.Object initValue)
          +
          Utility to create a new ThreadLocal object. Called + by preprocessed BTrace class to create ThreadLocal + for each @TLS variable.
          +
          +
          Parameters:
          +
          initValue - Initial value. + This value must be either a boxed primitive or Cloneable. + In case a Cloneable value is provided the value is never used directly + - instead, a new clone of the value is created per thread.
          +
          +
        • +
        + + + +
          +
        • +

          newPerfCounter

          +
          public static void newPerfCounter(java.lang.String name,
          +                                  java.lang.String desc,
          +                                  java.lang.Object value)
          +
          Utility to create a new jvmstat perf counter. Called + by preprocessed BTrace class to create perf counter + for each @Export variable.
          +
        • +
        + + + +
          +
        • +

          newPerfCounter

          +
          public static void newPerfCounter(java.lang.Object value,
          +                                  java.lang.String name,
          +                                  java.lang.String desc)
          +
        • +
        + + + +
          +
        • +

          getPerfInt

          +
          public static int getPerfInt(java.lang.String name)
          +
          Return the value of integer perf. counter of given name.
          +
        • +
        + + + +
          +
        • +

          putPerfInt

          +
          public static void putPerfInt(int value,
          +                              java.lang.String name)
          +
          Write the value of integer perf. counter of given name.
          +
        • +
        + + + +
          +
        • +

          getPerfFloat

          +
          public static float getPerfFloat(java.lang.String name)
          +
          Return the value of float perf. counter of given name.
          +
        • +
        + + + +
          +
        • +

          putPerfFloat

          +
          public static void putPerfFloat(float value,
          +                                java.lang.String name)
          +
          Write the value of float perf. counter of given name.
          +
        • +
        + + + +
          +
        • +

          getPerfLong

          +
          public static long getPerfLong(java.lang.String name)
          +
          Return the value of long perf. counter of given name.
          +
        • +
        + + + +
          +
        • +

          putPerfLong

          +
          public static void putPerfLong(long value,
          +                               java.lang.String name)
          +
          Write the value of float perf. counter of given name.
          +
        • +
        + + + +
          +
        • +

          getPerfDouble

          +
          public static double getPerfDouble(java.lang.String name)
          +
          Return the value of double perf. counter of given name.
          +
        • +
        + + + +
          +
        • +

          putPerfDouble

          +
          public static void putPerfDouble(double value,
          +                                 java.lang.String name)
          +
          write the value of double perf. counter of given name.
          +
        • +
        + + + +
          +
        • +

          getPerfString

          +
          public static java.lang.String getPerfString(java.lang.String name)
          +
          Return the value of String perf. counter of given name.
          +
        • +
        + + + +
          +
        • +

          putPerfString

          +
          public static void putPerfString(java.lang.String value,
          +                                 java.lang.String name)
          +
          Write the value of float perf. counter of given name.
          +
        • +
        + + + +
          +
        • +

          handleException

          +
          public static void handleException(java.lang.Throwable th)
          +
          Handles exception from BTrace probe actions.
          +
        • +
        + + + +
          +
        • +

          safeStr

          +
          public static java.lang.String safeStr(java.lang.Object obj)
          +
        • +
        + + + +
          +
        • +

          isEmpty

          +
          public static <E> boolean isEmpty(java.util.Collection<E> coll)
          +
        • +
        + + + + + +
          +
        • +

          push

          +
          public static <V> void push(java.util.Deque<V> queue,
          +                            V value)
          +
        • +
        + + + + + +
          +
        • +

          addLast

          +
          public static <V> void addLast(java.util.Deque<V> queue,
          +                               V value)
          +
        • +
        + + + +
          +
        • +

          peekFirst

          +
          public static <V> V peekFirst(java.util.Deque<V> queue)
          +
        • +
        + + + +
          +
        • +

          peekLast

          +
          public static <V> V peekLast(java.util.Deque<V> queue)
          +
        • +
        + + + +
          +
        • +

          removeLast

          +
          public static <V> V removeLast(java.util.Deque<V> queue)
          +
        • +
        + + + +
          +
        • +

          removeFirst

          +
          public static <V> V removeFirst(java.util.Deque<V> queue)
          +
        • +
        + + + +
          +
        • +

          poll

          +
          public static <V> V poll(java.util.Deque<V> queue)
          +
        • +
        + + + +
          +
        • +

          peek

          +
          public static <V> V peek(java.util.Deque<V> queue)
          +
        • +
        + + + +
          +
        • +

          clear

          +
          public static <V> void clear(java.util.Deque<V> queue)
          +
        • +
        + + + +
          +
        • +

          append

          +
          public static java.lang.Appendable append(java.lang.Appendable buffer,
          +                                          java.lang.String strToAppend)
          +
        • +
        + + + +
          +
        • +

          length

          +
          public static int length(java.lang.Appendable buffer)
          +
        • +
        + + + +
          +
        • +

          retransform

          +
          public static void retransform(java.lang.String runtimeName,
          +                               java.lang.Class<?> clazz)
          +
        • +
        + + + +
          +
        • +

          send

          +
          public void send(Command cmd)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Aggregations.html b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Aggregations.html new file mode 100644 index 00000000..59b5963d --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Aggregations.html @@ -0,0 +1,529 @@ + + + + + +BTraceUtils.Aggregations (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class BTraceUtils.Aggregations

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.BTraceUtils.Aggregations
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing class:
      +
      BTraceUtils
      +
      +
      +
      +
      public static class BTraceUtils.Aggregations
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        Aggregations() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static voidaddToAggregation(Aggregation aggregation, + AggregationKey key, + long value) +
        Adds a value to the aggregation with a grouping key.
        +
        static voidaddToAggregation(Aggregation aggregation, + long value) +
        Adds a value to the aggregation with no grouping key.
        +
        static voidclearAggregation(Aggregation aggregation) +
        Resets values within the aggregation to the default.
        +
        static AggregationnewAggregation(AggregationFunction type) +
        Creates a new aggregation based on the given aggregation function type.
        +
        static AggregationKeynewAggregationKey(java.lang.Object element1) +
        Creates a grouping aggregation key with the provided value.
        +
        static AggregationKeynewAggregationKey(java.lang.Object element1, + java.lang.Object element2) +
        Creates a composite grouping aggregation key with the provided values.
        +
        static AggregationKeynewAggregationKey(java.lang.Object element1, + java.lang.Object element2, + java.lang.Object element3) +
        Creates a composite grouping aggregation key with the provided values.
        +
        static AggregationKeynewAggregationKey(java.lang.Object element1, + java.lang.Object element2, + java.lang.Object element3, + java.lang.Object element4) +
        Creates a composite grouping aggregation key with the provided values.
        +
        static voidprintAggregation(java.lang.String name, + Aggregation aggregation) 
        static voidprintAggregation(java.lang.String name, + Aggregation aggregation, + java.lang.String format) 
        static voidprintAggregation(java.lang.String name, + java.lang.String format, + java.util.Collection<Aggregation> aggregationList) 
        static voidtruncateAggregation(Aggregation aggregation, + int count) +
        Removes all aggregated values from the aggregation except for the largest or smallest + abs(count) elements.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Aggregations

          +
          public Aggregations()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          newAggregation

          +
          public static Aggregation newAggregation(AggregationFunction type)
          +
          Creates a new aggregation based on the given aggregation function type.
          +
          +
          Parameters:
          +
          type - the aggregating function to be performed on the data being added to the aggregation.
          +
          +
        • +
        + + + +
          +
        • +

          newAggregationKey

          +
          public static AggregationKey newAggregationKey(java.lang.Object element1)
          +
          Creates a grouping aggregation key with the provided value. The value must be a String or Number type.
          +
          +
          Parameters:
          +
          element1 - the value of the aggregation key
          +
          +
        • +
        + + + +
          +
        • +

          newAggregationKey

          +
          public static AggregationKey newAggregationKey(java.lang.Object element1,
          +                                               java.lang.Object element2)
          +
          Creates a composite grouping aggregation key with the provided values. The values must be String or Number types.
          +
          +
          Parameters:
          +
          element1 - the first element of the composite aggregation key
          +
          element2 - the second element of the composite aggregation key
          +
          +
        • +
        + + + +
          +
        • +

          newAggregationKey

          +
          public static AggregationKey newAggregationKey(java.lang.Object element1,
          +                                               java.lang.Object element2,
          +                                               java.lang.Object element3)
          +
          Creates a composite grouping aggregation key with the provided values. The values must be String or Number types.
          +
          +
          Parameters:
          +
          element1 - the first element of the composite aggregation key
          +
          element2 - the second element of the composite aggregation key
          +
          element3 - the third element of the composite aggregation key
          +
          +
        • +
        + + + +
          +
        • +

          newAggregationKey

          +
          public static AggregationKey newAggregationKey(java.lang.Object element1,
          +                                               java.lang.Object element2,
          +                                               java.lang.Object element3,
          +                                               java.lang.Object element4)
          +
          Creates a composite grouping aggregation key with the provided values. The values must be String or Number types.
          +
          +
          Parameters:
          +
          element1 - the first element of the composite aggregation key
          +
          element2 - the second element of the composite aggregation key
          +
          element3 - the third element of the composite aggregation key
          +
          element4 - the fourth element of the composite aggregation key
          +
          +
        • +
        + + + +
          +
        • +

          addToAggregation

          +
          public static void addToAggregation(Aggregation aggregation,
          +                                    long value)
          +
          Adds a value to the aggregation with no grouping key. This method should be used when the aggregation + is to calculate only a single aggregated value.
          +
          +
          Parameters:
          +
          aggregation - the aggregation to which the value should be added
          +
          +
        • +
        + + + +
          +
        • +

          addToAggregation

          +
          public static void addToAggregation(Aggregation aggregation,
          +                                    AggregationKey key,
          +                                    long value)
          +
          Adds a value to the aggregation with a grouping key. This method should be used when the aggregation + should effectively perform a "group by" on the key value. The aggregation will calculate a separate + aggregated value for each unique aggregation key.
          +
          +
          Parameters:
          +
          aggregation - the aggregation to which the value should be added
          +
          key - the grouping aggregation key
          +
          +
        • +
        + + + +
          +
        • +

          clearAggregation

          +
          public static void clearAggregation(Aggregation aggregation)
          +
          Resets values within the aggregation to the default. This will affect all values within the aggregation + when multiple aggregation keys have been used.
          +
          +
          Parameters:
          +
          aggregation - the aggregation to be cleared
          +
          +
        • +
        + + + +
          +
        • +

          truncateAggregation

          +
          public static void truncateAggregation(Aggregation aggregation,
          +                                       int count)
          +
          Removes all aggregated values from the aggregation except for the largest or smallest + abs(count) elements. + +

          If count is positive, the largest aggregated values in the aggregation will be + preserved. If count is negative the smallest values will be preserved. If count + is zero then all elements will be removed. + +

          Behavior is intended to be similar to the dtrace trunc() function.

          +
          +
          Parameters:
          +
          aggregation - the aggregation to be truncated
          +
          count - the number of elements to preserve. If negative, the smallest abs(count) elements are preserved.
          +
          +
        • +
        + + + +
          +
        • +

          printAggregation

          +
          public static void printAggregation(java.lang.String name,
          +                                    Aggregation aggregation)
          +
        • +
        + + + +
          +
        • +

          printAggregation

          +
          public static void printAggregation(java.lang.String name,
          +                                    Aggregation aggregation,
          +                                    java.lang.String format)
          +
        • +
        + + + +
          +
        • +

          printAggregation

          +
          public static void printAggregation(java.lang.String name,
          +                                    java.lang.String format,
          +                                    java.util.Collection<Aggregation> aggregationList)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Atomic.html b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Atomic.html new file mode 100644 index 00000000..018cc369 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Atomic.html @@ -0,0 +1,892 @@ + + + + + +BTraceUtils.Atomic (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class BTraceUtils.Atomic

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.BTraceUtils.Atomic
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing class:
      +
      BTraceUtils
      +
      +
      +
      +
      public static class BTraceUtils.Atomic
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        Atomic() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static intaddAndGet(java.util.concurrent.atomic.AtomicInteger ai, + int delta) +
        Atomically adds the given value to the current value.
        +
        static longaddAndGet(java.util.concurrent.atomic.AtomicLong al, + long delta) +
        Atomically adds the given value to the current value.
        +
        static booleancompareAndSet(java.util.concurrent.atomic.AtomicInteger ai, + int expect, + int update) +
        Atomically sets the value of given AtomitInteger to the given + updated value if the current value == the expected value.
        +
        static booleancompareAndSet(java.util.concurrent.atomic.AtomicLong al, + long expect, + long update) +
        Atomically sets the value to the given updated value + if the current value == the expected value.
        +
        static intdecrementAndGet(java.util.concurrent.atomic.AtomicInteger ai) +
        Atomically decrements by one the current value of given AtomicInteger.
        +
        static longdecrementAndGet(java.util.concurrent.atomic.AtomicLong al) +
        Atomically decrements by one the current value.
        +
        static intget(java.util.concurrent.atomic.AtomicInteger ai) +
        Gets the current value of the given AtomicInteger.
        +
        static longget(java.util.concurrent.atomic.AtomicLong al) +
        Gets the current value the given AtomicLong.
        +
        static intgetAndAdd(java.util.concurrent.atomic.AtomicInteger ai, + int delta) +
        Atomically adds the given value to the current value.
        +
        static longgetAndAdd(java.util.concurrent.atomic.AtomicLong al, + long delta) +
        Atomically adds the given value to the current value.
        +
        static intgetAndDecrement(java.util.concurrent.atomic.AtomicInteger ai) +
        Atomically decrements by one the current value of given AtomicInteger.
        +
        static longgetAndDecrement(java.util.concurrent.atomic.AtomicLong al) +
        Atomically decrements by one the current value.
        +
        static intgetAndIncrement(java.util.concurrent.atomic.AtomicInteger ai) +
        Atomically increments by one the current value of given AtomicInteger.
        +
        static longgetAndIncrement(java.util.concurrent.atomic.AtomicLong al) +
        Atomically increments by one the current value.
        +
        static intgetAndSet(java.util.concurrent.atomic.AtomicInteger ai, + int newValue) +
        Atomically sets to the given value and returns the old value.
        +
        static longgetAndSet(java.util.concurrent.atomic.AtomicLong al, + long newValue) +
        Atomically sets to the given value and returns the old value.
        +
        static intincrementAndGet(java.util.concurrent.atomic.AtomicInteger ai) +
        Atomically increments by one the current value of given AtomicInteger.
        +
        static longincrementAndGet(java.util.concurrent.atomic.AtomicLong al) +
        Atomically increments by one the current value.
        +
        static voidlazySet(java.util.concurrent.atomic.AtomicInteger ai, + int newValue) +
        Eventually sets to the given value to the given AtomicInteger.
        +
        static voidlazySet(java.util.concurrent.atomic.AtomicLong al, + long newValue) +
        Eventually sets to the given value to the given AtomicLong.
        +
        static java.util.concurrent.atomic.AtomicIntegernewAtomicInteger(int initialValue) +
        Creates a new AtomicInteger with the given initial value.
        +
        static java.util.concurrent.atomic.AtomicLongnewAtomicLong(long initialValue) +
        Creates a new AtomicLong with the given initial value.
        +
        static voidset(java.util.concurrent.atomic.AtomicInteger ai, + int newValue) +
        Sets to the given value to the given AtomicInteger.
        +
        static voidset(java.util.concurrent.atomic.AtomicLong al, + long newValue) +
        Sets to the given value.
        +
        static booleanweakCompareAndSet(java.util.concurrent.atomic.AtomicInteger ai, + int expect, + int update) +
        Atomically sets the value to the given updated value + if the current value == the expected value.
        +
        static booleanweakCompareAndSet(java.util.concurrent.atomic.AtomicLong al, + long expect, + long update) +
        Atomically sets the value to the given updated value + if the current value == the expected value.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Atomic

          +
          public Atomic()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          newAtomicInteger

          +
          public static java.util.concurrent.atomic.AtomicInteger newAtomicInteger(int initialValue)
          +
          Creates a new AtomicInteger with the given initial value.
          +
          +
          Parameters:
          +
          initialValue - the initial value
          +
          +
        • +
        + + + +
          +
        • +

          get

          +
          public static int get(java.util.concurrent.atomic.AtomicInteger ai)
          +
          Gets the current value of the given AtomicInteger.
          +
          +
          Parameters:
          +
          ai - AtomicInteger whose value is returned.
          +
          Returns:
          +
          the current value
          +
          +
        • +
        + + + +
          +
        • +

          set

          +
          public static void set(java.util.concurrent.atomic.AtomicInteger ai,
          +                       int newValue)
          +
          Sets to the given value to the given AtomicInteger.
          +
          +
          Parameters:
          +
          ai - AtomicInteger whose value is set.
          +
          newValue - the new value
          +
          +
        • +
        + + + +
          +
        • +

          lazySet

          +
          public static void lazySet(java.util.concurrent.atomic.AtomicInteger ai,
          +                           int newValue)
          +
          Eventually sets to the given value to the given AtomicInteger.
          +
          +
          Parameters:
          +
          ai - AtomicInteger whose value is lazily set.
          +
          newValue - the new value
          +
          +
        • +
        + + + +
          +
        • +

          compareAndSet

          +
          public static boolean compareAndSet(java.util.concurrent.atomic.AtomicInteger ai,
          +                                    int expect,
          +                                    int update)
          +
          Atomically sets the value of given AtomitInteger to the given + updated value if the current value == the expected value.
          +
          +
          Parameters:
          +
          ai - AtomicInteger whose value is compared and set.
          +
          expect - the expected value
          +
          update - the new value
          +
          Returns:
          +
          true if successful. False return indicates that + the actual value was not equal to the expected value.
          +
          +
        • +
        + + + +
          +
        • +

          weakCompareAndSet

          +
          public static boolean weakCompareAndSet(java.util.concurrent.atomic.AtomicInteger ai,
          +                                        int expect,
          +                                        int update)
          +
          Atomically sets the value to the given updated value + if the current value == the expected value. + +

          May fail spuriously + and does not provide ordering guarantees, so is only rarely an + appropriate alternative to compareAndSet.

          +
          +
          Parameters:
          +
          ai - AtomicInteger whose value is weakly compared and set.
          +
          expect - the expected value
          +
          update - the new value
          +
          Returns:
          +
          true if successful.
          +
          +
        • +
        + + + +
          +
        • +

          getAndIncrement

          +
          public static int getAndIncrement(java.util.concurrent.atomic.AtomicInteger ai)
          +
          Atomically increments by one the current value of given AtomicInteger.
          +
          +
          Parameters:
          +
          ai - AtomicInteger that is incremented.
          +
          Returns:
          +
          the previous value
          +
          +
        • +
        + + + +
          +
        • +

          getAndDecrement

          +
          public static int getAndDecrement(java.util.concurrent.atomic.AtomicInteger ai)
          +
          Atomically decrements by one the current value of given AtomicInteger.
          +
          +
          Parameters:
          +
          ai - AtomicInteger that is decremented.
          +
          Returns:
          +
          the previous value
          +
          +
        • +
        + + + +
          +
        • +

          incrementAndGet

          +
          public static int incrementAndGet(java.util.concurrent.atomic.AtomicInteger ai)
          +
          Atomically increments by one the current value of given AtomicInteger.
          +
          +
          Parameters:
          +
          ai - AtomicInteger that is incremented.
          +
          Returns:
          +
          the updated value
          +
          +
        • +
        + + + +
          +
        • +

          decrementAndGet

          +
          public static int decrementAndGet(java.util.concurrent.atomic.AtomicInteger ai)
          +
          Atomically decrements by one the current value of given AtomicInteger.
          +
          +
          Parameters:
          +
          ai - AtomicInteger whose value is decremented.
          +
          Returns:
          +
          the updated value
          +
          +
        • +
        + + + +
          +
        • +

          getAndAdd

          +
          public static int getAndAdd(java.util.concurrent.atomic.AtomicInteger ai,
          +                            int delta)
          +
          Atomically adds the given value to the current value.
          +
          +
          Parameters:
          +
          ai - AtomicInteger whose value is added to.
          +
          delta - the value to add
          +
          Returns:
          +
          the previous value
          +
          +
        • +
        + + + +
          +
        • +

          addAndGet

          +
          public static int addAndGet(java.util.concurrent.atomic.AtomicInteger ai,
          +                            int delta)
          +
          Atomically adds the given value to the current value.
          +
          +
          Parameters:
          +
          ai - AtomicInteger whose value is added to.
          +
          delta - the value to add
          +
          Returns:
          +
          the updated value
          +
          +
        • +
        + + + +
          +
        • +

          getAndSet

          +
          public static int getAndSet(java.util.concurrent.atomic.AtomicInteger ai,
          +                            int newValue)
          +
          Atomically sets to the given value and returns the old value.
          +
          +
          Parameters:
          +
          ai - AtomicInteger whose value is set.
          +
          newValue - the new value
          +
          Returns:
          +
          the previous value
          +
          +
        • +
        + + + +
          +
        • +

          newAtomicLong

          +
          public static java.util.concurrent.atomic.AtomicLong newAtomicLong(long initialValue)
          +
          Creates a new AtomicLong with the given initial value.
          +
          +
          Parameters:
          +
          initialValue - the initial value
          +
          +
        • +
        + + + +
          +
        • +

          get

          +
          public static long get(java.util.concurrent.atomic.AtomicLong al)
          +
          Gets the current value the given AtomicLong.
          +
          +
          Parameters:
          +
          al - AtomicLong whose value is returned.
          +
          Returns:
          +
          the current value
          +
          +
        • +
        + + + +
          +
        • +

          set

          +
          public static void set(java.util.concurrent.atomic.AtomicLong al,
          +                       long newValue)
          +
          Sets to the given value.
          +
          +
          Parameters:
          +
          al - AtomicLong whose value is set.
          +
          newValue - the new value
          +
          +
        • +
        + + + +
          +
        • +

          lazySet

          +
          public static void lazySet(java.util.concurrent.atomic.AtomicLong al,
          +                           long newValue)
          +
          Eventually sets to the given value to the given AtomicLong.
          +
          +
          Parameters:
          +
          al - AtomicLong whose value is set.
          +
          newValue - the new value
          +
          +
        • +
        + + + +
          +
        • +

          compareAndSet

          +
          public static boolean compareAndSet(java.util.concurrent.atomic.AtomicLong al,
          +                                    long expect,
          +                                    long update)
          +
          Atomically sets the value to the given updated value + if the current value == the expected value.
          +
          +
          Parameters:
          +
          al - AtomicLong whose value is compared and set.
          +
          expect - the expected value
          +
          update - the new value
          +
          Returns:
          +
          true if successful. False return indicates that + the actual value was not equal to the expected value.
          +
          +
        • +
        + + + +
          +
        • +

          weakCompareAndSet

          +
          public static boolean weakCompareAndSet(java.util.concurrent.atomic.AtomicLong al,
          +                                        long expect,
          +                                        long update)
          +
          Atomically sets the value to the given updated value + if the current value == the expected value. + +

          May fail spuriously + and does not provide ordering guarantees, so is only rarely an + appropriate alternative to compareAndSet.

          +
          +
          Parameters:
          +
          al - AtomicLong whose value is compared and set.
          +
          expect - the expected value
          +
          update - the new value
          +
          Returns:
          +
          true if successful.
          +
          +
        • +
        + + + +
          +
        • +

          getAndIncrement

          +
          public static long getAndIncrement(java.util.concurrent.atomic.AtomicLong al)
          +
          Atomically increments by one the current value.
          +
          +
          Parameters:
          +
          al - AtomicLong whose value is incremented.
          +
          Returns:
          +
          the previous value
          +
          +
        • +
        + + + +
          +
        • +

          getAndDecrement

          +
          public static long getAndDecrement(java.util.concurrent.atomic.AtomicLong al)
          +
          Atomically decrements by one the current value.
          +
          +
          Parameters:
          +
          al - AtomicLong whose value is decremented.
          +
          Returns:
          +
          the previous value
          +
          +
        • +
        + + + +
          +
        • +

          incrementAndGet

          +
          public static long incrementAndGet(java.util.concurrent.atomic.AtomicLong al)
          +
          Atomically increments by one the current value.
          +
          +
          Parameters:
          +
          al - AtomicLong whose value is incremented.
          +
          Returns:
          +
          the updated value
          +
          +
        • +
        + + + +
          +
        • +

          decrementAndGet

          +
          public static long decrementAndGet(java.util.concurrent.atomic.AtomicLong al)
          +
          Atomically decrements by one the current value.
          +
          +
          Parameters:
          +
          al - AtomicLong whose value is decremented.
          +
          Returns:
          +
          the updated value
          +
          +
        • +
        + + + +
          +
        • +

          getAndAdd

          +
          public static long getAndAdd(java.util.concurrent.atomic.AtomicLong al,
          +                             long delta)
          +
          Atomically adds the given value to the current value.
          +
          +
          Parameters:
          +
          al - AtomicLong whose value is added to.
          +
          delta - the value to add
          +
          Returns:
          +
          the previous value
          +
          +
        • +
        + + + +
          +
        • +

          addAndGet

          +
          public static long addAndGet(java.util.concurrent.atomic.AtomicLong al,
          +                             long delta)
          +
          Atomically adds the given value to the current value.
          +
          +
          Parameters:
          +
          al - AtomicLong whose value is added to
          +
          delta - the value to add
          +
          Returns:
          +
          the updated value
          +
          +
        • +
        + + + +
          +
        • +

          getAndSet

          +
          public static long getAndSet(java.util.concurrent.atomic.AtomicLong al,
          +                             long newValue)
          +
          Atomically sets to the given value and returns the old value.
          +
          +
          Parameters:
          +
          al - AtomicLong that is set.
          +
          newValue - the new value
          +
          Returns:
          +
          the previous value
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Collections.html b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Collections.html new file mode 100644 index 00000000..d1951eaf --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Collections.html @@ -0,0 +1,651 @@ + + + + + +BTraceUtils.Collections (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class BTraceUtils.Collections

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.BTraceUtils.Collections
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing class:
      +
      BTraceUtils
      +
      +
      +
      +
      public static class BTraceUtils.Collections
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        Collections() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static <V> voidaddLast(java.util.Deque<V> queue, + V value) 
        static <K,V> voidclear(java.util.Map<K,V> map) 
        static <E> booleancontains(java.util.Collection<E> coll, + java.lang.Object obj) 
        static booleancontains(java.lang.Object[] array, + java.lang.Object value) 
        static <K,V> booleancontainsKey(java.util.Map<K,V> map, + K key) 
        static <K,V> booleancontainsValue(java.util.Map<K,V> map, + V value) 
        static <V> voidcopy(java.util.Collection<V> src, + java.util.Collection<V> dst) 
        static <K,V> voidcopy(java.util.Map<K,V> src, + java.util.Map<K,V> dst) 
        static <K,V> Vget(java.util.Map<K,V> map, + K key) 
        static <E> booleanisEmpty(java.util.Collection<E> coll) 
        static <K,V> booleanisEmpty(java.util.Map<K,V> map) 
        static <V> java.util.Deque<V>newDeque() 
        static <K,V> java.util.Map<K,V>newHashMap() 
        static <K,V> java.util.Map<K,V>newWeakMap() 
        static <V> Vpeek(java.util.Deque<V> queue) 
        static <V> VpeekFirst(java.util.Deque<V> queue) 
        static <V> VpeekLast(java.util.Deque<V> queue) 
        static <V> Vpoll(java.util.Deque<V> queue) 
        static <V> voidpush(java.util.Deque<V> queue, + V value) 
        static <K,V> Vput(java.util.Map<K,V> map, + K key, + V value) 
        static <K,V> voidputAll(java.util.Map<K,V> src, + java.util.Map<K,V> dst) 
        static <K,V> Vremove(java.util.Map<K,V> map, + K key) 
        static <V> VremoveFirst(java.util.Deque<V> queue) 
        static <V> VremoveLast(java.util.Deque<V> queue) 
        static <E> intsize(java.util.Collection<E> coll) 
        static <K,V> intsize(java.util.Map<K,V> map) 
        static <E> java.lang.Object[]toArray(java.util.Collection<E> collection) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Collections

          +
          public Collections()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          newHashMap

          +
          public static <K,V> java.util.Map<K,V> newHashMap()
          +
        • +
        + + + +
          +
        • +

          newWeakMap

          +
          public static <K,V> java.util.Map<K,V> newWeakMap()
          +
        • +
        + + + +
          +
        • +

          newDeque

          +
          public static <V> java.util.Deque<V> newDeque()
          +
        • +
        + + + +
          +
        • +

          putAll

          +
          public static <K,V> void putAll(java.util.Map<K,V> src,
          +                                java.util.Map<K,V> dst)
          +
        • +
        + + + +
          +
        • +

          copy

          +
          public static <K,V> void copy(java.util.Map<K,V> src,
          +                              java.util.Map<K,V> dst)
          +
        • +
        + + + +
          +
        • +

          copy

          +
          public static <V> void copy(java.util.Collection<V> src,
          +                            java.util.Collection<V> dst)
          +
        • +
        + + + + + +
          +
        • +

          get

          +
          public static <K,V> V get(java.util.Map<K,V> map,
          +                          K key)
          +
        • +
        + + + + + +
          +
        • +

          containsKey

          +
          public static <K,V> boolean containsKey(java.util.Map<K,V> map,
          +                                        K key)
          +
        • +
        + + + + + +
          +
        • +

          containsValue

          +
          public static <K,V> boolean containsValue(java.util.Map<K,V> map,
          +                                          V value)
          +
        • +
        + + + + + +
          +
        • +

          put

          +
          public static <K,V> V put(java.util.Map<K,V> map,
          +                          K key,
          +                          V value)
          +
        • +
        + + + + + +
          +
        • +

          remove

          +
          public static <K,V> V remove(java.util.Map<K,V> map,
          +                             K key)
          +
        • +
        + + + +
          +
        • +

          clear

          +
          public static <K,V> void clear(java.util.Map<K,V> map)
          +
        • +
        + + + +
          +
        • +

          size

          +
          public static <K,V> int size(java.util.Map<K,V> map)
          +
        • +
        + + + +
          +
        • +

          isEmpty

          +
          public static <K,V> boolean isEmpty(java.util.Map<K,V> map)
          +
        • +
        + + + +
          +
        • +

          size

          +
          public static <E> int size(java.util.Collection<E> coll)
          +
        • +
        + + + +
          +
        • +

          isEmpty

          +
          public static <E> boolean isEmpty(java.util.Collection<E> coll)
          +
        • +
        + + + +
          +
        • +

          contains

          +
          public static <E> boolean contains(java.util.Collection<E> coll,
          +                                   java.lang.Object obj)
          +
        • +
        + + + +
          +
        • +

          contains

          +
          public static boolean contains(java.lang.Object[] array,
          +                               java.lang.Object value)
          +
        • +
        + + + +
          +
        • +

          toArray

          +
          public static <E> java.lang.Object[] toArray(java.util.Collection<E> collection)
          +
        • +
        + + + + + +
          +
        • +

          push

          +
          public static <V> void push(java.util.Deque<V> queue,
          +                            V value)
          +
        • +
        + + + +
          +
        • +

          poll

          +
          public static <V> V poll(java.util.Deque<V> queue)
          +
        • +
        + + + +
          +
        • +

          peek

          +
          public static <V> V peek(java.util.Deque<V> queue)
          +
        • +
        + + + + + +
          +
        • +

          addLast

          +
          public static <V> void addLast(java.util.Deque<V> queue,
          +                               V value)
          +
        • +
        + + + +
          +
        • +

          peekFirst

          +
          public static <V> V peekFirst(java.util.Deque<V> queue)
          +
        • +
        + + + +
          +
        • +

          peekLast

          +
          public static <V> V peekLast(java.util.Deque<V> queue)
          +
        • +
        + + + +
          +
        • +

          removeLast

          +
          public static <V> V removeLast(java.util.Deque<V> queue)
          +
        • +
        + + + +
          +
        • +

          removeFirst

          +
          public static <V> V removeFirst(java.util.Deque<V> queue)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Counters.html b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Counters.html new file mode 100644 index 00000000..ff63bc40 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Counters.html @@ -0,0 +1,308 @@ + + + + + +BTraceUtils.Counters (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class BTraceUtils.Counters

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.BTraceUtils.Counters
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing class:
      +
      BTraceUtils
      +
      +
      +
      +
      public static class BTraceUtils.Counters
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        Counters() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static longperfInt(java.lang.String name) +
        accessing jvmstat (perf) int counter
        +
        static longperfLong(java.lang.String name) +
        accessing jvmstat (perf) long counter
        +
        static java.lang.StringperfString(java.lang.String name) +
        accessing jvmstat (perf) String counter
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Counters

          +
          public Counters()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          perfInt

          +
          public static long perfInt(java.lang.String name)
          +
          accessing jvmstat (perf) int counter
          +
        • +
        + + + +
          +
        • +

          perfLong

          +
          public static long perfLong(java.lang.String name)
          +
          accessing jvmstat (perf) long counter
          +
        • +
        + + + +
          +
        • +

          perfString

          +
          public static java.lang.String perfString(java.lang.String name)
          +
          accessing jvmstat (perf) String counter
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.D.html b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.D.html new file mode 100644 index 00000000..28325a19 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.D.html @@ -0,0 +1,338 @@ + + + + + +BTraceUtils.D (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class BTraceUtils.D

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.BTraceUtils.D
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing class:
      +
      BTraceUtils
      +
      +
      +
      +
      public static class BTraceUtils.D
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        D() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static intprobe(java.lang.String str1, + java.lang.String str2) +
        BTrace to DTrace communication chennal.
        +
        static intprobe(java.lang.String str1, + java.lang.String str2, + int i1) +
        BTrace to DTrace communication chennal.
        +
        static intprobe(java.lang.String str1, + java.lang.String str2, + int i1, + int i2) +
        BTrace to DTrace communication channel.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          D

          +
          public D()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          probe

          +
          public static int probe(java.lang.String str1,
          +                        java.lang.String str2)
          +
          BTrace to DTrace communication chennal. + Raise DTrace USDT probe from BTrace.
          +
          +
          See Also:
          +
          BTraceUtils.dtraceProbe(String,String,int,int)
          +
          +
        • +
        + + + +
          +
        • +

          probe

          +
          public static int probe(java.lang.String str1,
          +                        java.lang.String str2,
          +                        int i1)
          +
          BTrace to DTrace communication chennal. + Raise DTrace USDT probe from BTrace.
          +
          +
          See Also:
          +
          BTraceUtils.dtraceProbe(String,String,int,int)
          +
          +
        • +
        + + + +
          +
        • +

          probe

          +
          public static int probe(java.lang.String str1,
          +                        java.lang.String str2,
          +                        int i1,
          +                        int i2)
          +
          BTrace to DTrace communication channel. + Raise DTrace USDT probe from BTrace.
          +
          +
          Parameters:
          +
          str1 - first String param to DTrace probe
          +
          str2 - second String param to DTrace probe
          +
          i1 - first int param to DTrace probe
          +
          i2 - second int param to DTrace probe
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Export.html b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Export.html new file mode 100644 index 00000000..4c40fde9 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Export.html @@ -0,0 +1,355 @@ + + + + + +BTraceUtils.Export (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class BTraceUtils.Export

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.BTraceUtils.Export
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing class:
      +
      BTraceUtils
      +
      +
      +
      +
      public static class BTraceUtils.Export
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        Export() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static voidserialize(java.io.Serializable obj, + java.lang.String fileName) +
        Serialize a given object into the given file.
        +
        static java.lang.StringtoXML(java.lang.Object obj) +
        Creates an XML document to persist the tree of the all + transitively reachable objects from given "root" object.
        +
        static voidwriteDOT(java.lang.Object obj, + java.lang.String fileName) +
        Writes a .dot document to persist the tree of the all the + transitively reachable objects from the given "root" object.
        +
        static voidwriteXML(java.lang.Object obj, + java.lang.String fileName) +
        Writes an XML document to persist the tree of the all the + transitively reachable objects from the given "root" object.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Export

          +
          public Export()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          serialize

          +
          public static void serialize(java.io.Serializable obj,
          +                             java.lang.String fileName)
          +
          Serialize a given object into the given file. + Under the current dir of traced app, ./btrace<pid>/<btrace-class>/ + directory is created. Under that directory, a file of given + fileName is created.
          +
          +
          Parameters:
          +
          obj - object that has to be serialized.
          +
          fileName - name of the file to which the object is serialized.
          +
          +
        • +
        + + + +
          +
        • +

          toXML

          +
          public static java.lang.String toXML(java.lang.Object obj)
          +
          Creates an XML document to persist the tree of the all + transitively reachable objects from given "root" object.
          +
        • +
        + + + +
          +
        • +

          writeXML

          +
          public static void writeXML(java.lang.Object obj,
          +                            java.lang.String fileName)
          +
          Writes an XML document to persist the tree of the all the + transitively reachable objects from the given "root" object. + Under the current dir of traced app, ./btrace<pid>/<btrace-class>/ + directory is created. Under that directory, a file of the given + fileName is created.
          +
        • +
        + + + +
          +
        • +

          writeDOT

          +
          public static void writeDOT(java.lang.Object obj,
          +                            java.lang.String fileName)
          +
          Writes a .dot document to persist the tree of the all the + transitively reachable objects from the given "root" object. + .dot documents can be viewed by Graphviz application (www.graphviz.org) + Under the current dir of traced app, ./btrace<pid>/<btrace-class>/ + directory is created. Under that directory, a file of the given + fileName is created.
          +
          +
          Since:
          +
          1.1
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Numbers.html b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Numbers.html new file mode 100644 index 00000000..dc16689f --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Numbers.html @@ -0,0 +1,1062 @@ + + + + + +BTraceUtils.Numbers (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class BTraceUtils.Numbers

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.BTraceUtils.Numbers
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing class:
      +
      BTraceUtils
      +
      +
      +
      +
      public static class BTraceUtils.Numbers
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        Numbers() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static java.lang.Booleanbox(boolean b) +
        Returns a Boolean instance representing the specified + boolean value.
        +
        static java.lang.Bytebox(byte b) +
        Returns a Byte instance representing the specified + byte value.
        +
        static java.lang.Characterbox(char c) +
        Returns a Character instance representing the specified + char value.
        +
        static java.lang.Doublebox(double d) +
        Returns a Double instance representing the specified + double value.
        +
        static java.lang.Floatbox(float f) +
        Returns a Float instance representing the specified + float value.
        +
        static java.lang.Integerbox(int i) +
        Returns a Integer instance representing the specified + int value.
        +
        static java.lang.Longbox(long l) +
        Returns a Long instance representing the specified + long value.
        +
        static java.lang.Shortbox(short s) +
        Returns a Short instance representing the specified + short value.
        +
        static doubleexp(double a) +
        Returns Euler's number e raised to the power of a + double value.
        +
        static booleanisInfinite(double d) +
        Returns true if the specified number is infinitely + large in magnitude, false otherwise.
        +
        static booleanisInfinite(float f) +
        Returns true if the specified number is infinitely + large in magnitude, false otherwise.
        +
        static booleanisNaN(double d) +
        Returns true if the specified number is a + Not-a-Number (NaN) value, false otherwise.
        +
        static booleanisNaN(float f) +
        Returns true if the specified number is a + Not-a-Number (NaN) value, false otherwise.
        +
        static doublelog(double a) +
        Returns the natural logarithm (base e) of a double + value.
        +
        static doublelog10(double a) +
        Returns the base 10 logarithm of a double value.
        +
        static booleanparseBoolean(java.lang.String s) +
        Parses the string argument as a boolean.
        +
        static byteparseByte(java.lang.String s) +
        Parses the string argument as a signed decimal + byte.
        +
        static doubleparseDouble(java.lang.String s) +
        Returns a new double initialized to the value + represented by the specified String, as performed + by the valueOf methcod of class + Double.
        +
        static floatparseFloat(java.lang.String s) +
        Returns a new float initialized to the value + represented by the specified String, as performed + by the valueOf method of class Float.
        +
        static intparseInt(java.lang.String s) +
        Parses the string argument as a signed decimal integer.
        +
        static longparseLong(java.lang.String s) +
        Parses the string argument as a signed decimal + long.
        +
        static shortparseShort(java.lang.String s) +
        Parses the string argument as a signed decimal + short.
        +
        static doublerandom() +
        Returns a double value with a positive sign, greater + than or equal to 0.0 and less than 1.0.
        +
        static booleanunbox(java.lang.Boolean b) +
        Returns the value of the given Boolean object as a boolean + primitive.
        +
        static byteunbox(java.lang.Byte b) +
        Returns the value of the specified Byte as a byte.
        +
        static charunbox(java.lang.Character ch) +
        Returns the value of the given Character object as a char + primitive.
        +
        static doubleunbox(java.lang.Double d) +
        Returns the double value represented by the specified Double.
        +
        static floatunbox(java.lang.Float f) +
        Returns the float value represented by the specified Float.
        +
        static intunbox(java.lang.Integer i) +
        Returns the value of represented by Integer.
        +
        static longunbox(java.lang.Long l) +
        Returns the long value represented by the specified Long.
        +
        static shortunbox(java.lang.Short s) +
        Returns the short value represented by Short.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Numbers

          +
          public Numbers()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          random

          +
          public static double random()
          +
          Returns a double value with a positive sign, greater + than or equal to 0.0 and less than 1.0. + Returned values are chosen pseudorandomly with (approximately) + uniform distribution from that range.
          +
        • +
        + + + +
          +
        • +

          log

          +
          public static double log(double a)
          +
          Returns the natural logarithm (base e) of a double + value. Special cases: +
          • If the argument is NaN or less than zero, then the result + is NaN. +
          • If the argument is positive infinity, then the result is + positive infinity. +
          • If the argument is positive zero or negative zero, then the + result is negative infinity.
          + +

          The computed result must be within 1 ulp of the exact result. + Results must be semi-monotonic.

          +
          +
          Parameters:
          +
          a - a value
          +
          Returns:
          +
          the value ln a, the natural logarithm of + a.
          +
          +
        • +
        + + + +
          +
        • +

          log10

          +
          public static double log10(double a)
          +
          Returns the base 10 logarithm of a double value. + Special cases: + +
          • If the argument is NaN or less than zero, then the result + is NaN. +
          • If the argument is positive infinity, then the result is + positive infinity. +
          • If the argument is positive zero or negative zero, then the + result is negative infinity. +
          • If the argument is equal to 10n for + integer n, then the result is n. +
          + +

          The computed result must be within 1 ulp of the exact result. + Results must be semi-monotonic.

          +
          +
          Parameters:
          +
          a - a value
          +
          Returns:
          +
          the base 10 logarithm of a.
          +
          +
        • +
        + + + +
          +
        • +

          exp

          +
          public static double exp(double a)
          +
          Returns Euler's number e raised to the power of a + double value. Special cases: +
          • If the argument is NaN, the result is NaN. +
          • If the argument is positive infinity, then the result is + positive infinity. +
          • If the argument is negative infinity, then the result is + positive zero.
          + +

          The computed result must be within 1 ulp of the exact result. + Results must be semi-monotonic.

          +
          +
          Parameters:
          +
          a - the exponent to raise e to.
          +
          Returns:
          +
          the value ea, + where e is the base of the natural logarithms.
          +
          +
        • +
        + + + +
          +
        • +

          isNaN

          +
          public static boolean isNaN(double d)
          +
          Returns true if the specified number is a + Not-a-Number (NaN) value, false otherwise.
          +
          +
          Parameters:
          +
          d - the value to be tested.
          +
          Returns:
          +
          true if the value of the argument is NaN; + false otherwise.
          +
          +
        • +
        + + + +
          +
        • +

          isNaN

          +
          public static boolean isNaN(float f)
          +
          Returns true if the specified number is a + Not-a-Number (NaN) value, false otherwise.
          +
          +
          Parameters:
          +
          f - the value to be tested.
          +
          Returns:
          +
          true if the value of the argument is NaN; + false otherwise.
          +
          +
        • +
        + + + +
          +
        • +

          isInfinite

          +
          public static boolean isInfinite(double d)
          +
          Returns true if the specified number is infinitely + large in magnitude, false otherwise.
          +
          +
          Parameters:
          +
          d - the value to be tested.
          +
          Returns:
          +
          true if the value of the argument is positive + infinity or negative infinity; false otherwise.
          +
          +
        • +
        + + + +
          +
        • +

          isInfinite

          +
          public static boolean isInfinite(float f)
          +
          Returns true if the specified number is infinitely + large in magnitude, false otherwise.
          +
          +
          Parameters:
          +
          f - the value to be tested.
          +
          Returns:
          +
          true if the value of the argument is positive + infinity or negative infinity; false otherwise.
          +
          +
        • +
        + + + +
          +
        • +

          parseBoolean

          +
          public static boolean parseBoolean(java.lang.String s)
          +
          Parses the string argument as a boolean. The boolean + returned represents the value true if the string argument + is not null and is equal, ignoring case, to the string + "true".

          + Example: Boolean.parseBoolean("True") returns true.
          + Example: Boolean.parseBoolean("yes") returns false.

          +
          +
          Parameters:
          +
          s - the String containing the boolean + representation to be parsed
          +
          Returns:
          +
          the boolean represented by the string argument
          +
          +
        • +
        + + + +
          +
        • +

          parseByte

          +
          public static byte parseByte(java.lang.String s)
          +
          Parses the string argument as a signed decimal + byte. The characters in the string must all be + decimal digits, except that the first character may be an ASCII + minus sign '-' ('\u002D') to + indicate a negative value. The resulting byte value is + returned.
          +
          +
          Parameters:
          +
          s - a String containing the + byte representation to be parsed
          +
          Returns:
          +
          the byte value represented by the + argument in decimal
          +
          +
        • +
        + + + +
          +
        • +

          parseShort

          +
          public static short parseShort(java.lang.String s)
          +
          Parses the string argument as a signed decimal + short. The characters in the string must all be + decimal digits, except that the first character may be an ASCII + minus sign '-' ('\u002D') to + indicate a negative value. The resulting short value is + returned.
          +
          +
          Parameters:
          +
          s - a String containing the short + representation to be parsed
          +
          Returns:
          +
          the short value represented by the + argument in decimal.
          +
          +
        • +
        + + + +
          +
        • +

          parseInt

          +
          public static int parseInt(java.lang.String s)
          +
          Parses the string argument as a signed decimal integer. The + characters in the string must all be decimal digits, except that + the first character may be an ASCII minus sign '-' + ('\u002D') to indicate a negative value. The resulting + integer value is returned.
          +
          +
          Parameters:
          +
          s - a String containing the int + representation to be parsed
          +
          Returns:
          +
          the integer value represented by the argument in decimal.
          +
          +
        • +
        + + + +
          +
        • +

          parseLong

          +
          public static long parseLong(java.lang.String s)
          +
          Parses the string argument as a signed decimal + long. The characters in the string must all be + decimal digits, except that the first character may be an ASCII + minus sign '-' (\u002D') to + indicate a negative value. The resulting long + value is returned. +

          + Note that neither the character L + ('\u004C') nor l + ('\u006C') is permitted to appear at the end + of the string as a type indicator, as would be permitted in + Java programming language source code.

          +
          +
          Parameters:
          +
          s - a String containing the long + representation to be parsed
          +
          Returns:
          +
          the long represented by the argument in + decimal.
          +
          +
        • +
        + + + +
          +
        • +

          parseFloat

          +
          public static float parseFloat(java.lang.String s)
          +
          Returns a new float initialized to the value + represented by the specified String, as performed + by the valueOf method of class Float.
          +
          +
          Parameters:
          +
          s - the string to be parsed.
          +
          Returns:
          +
          the float value represented by the string + argument.
          +
          +
        • +
        + + + +
          +
        • +

          parseDouble

          +
          public static double parseDouble(java.lang.String s)
          +
          Returns a new double initialized to the value + represented by the specified String, as performed + by the valueOf methcod of class + Double.
          +
          +
          Parameters:
          +
          s - the string to be parsed.
          +
          Returns:
          +
          the double value represented by the string + argument.
          +
          +
        • +
        + + + +
          +
        • +

          box

          +
          public static java.lang.Boolean box(boolean b)
          +
          Returns a Boolean instance representing the specified + boolean value. If the specified boolean value + is true, this method returns Boolean.TRUE; + if it is false, this method returns Boolean.FALSE.
          +
          +
          Parameters:
          +
          b - a boolean value.
          +
          Returns:
          +
          a Boolean instance representing b.
          +
          +
        • +
        + + + +
          +
        • +

          box

          +
          public static java.lang.Character box(char c)
          +
          Returns a Character instance representing the specified + char value.
          +
          +
          Parameters:
          +
          c - a char value.
          +
          Returns:
          +
          a Character instance representing c.
          +
          +
        • +
        + + + +
          +
        • +

          box

          +
          public static java.lang.Byte box(byte b)
          +
          Returns a Byte instance representing the specified + byte value.
          +
          +
          Parameters:
          +
          b - a byte value.
          +
          Returns:
          +
          a Byte instance representing b.
          +
          +
        • +
        + + + +
          +
        • +

          box

          +
          public static java.lang.Short box(short s)
          +
          Returns a Short instance representing the specified + short value.
          +
          +
          Parameters:
          +
          s - a short value.
          +
          Returns:
          +
          a Short instance representing s.
          +
          +
        • +
        + + + +
          +
        • +

          box

          +
          public static java.lang.Integer box(int i)
          +
          Returns a Integer instance representing the specified + int value.
          +
          +
          Parameters:
          +
          i - an int value.
          +
          Returns:
          +
          a Integer instance representing i.
          +
          +
        • +
        + + + +
          +
        • +

          box

          +
          public static java.lang.Long box(long l)
          +
          Returns a Long instance representing the specified + long value.
          +
          +
          Parameters:
          +
          l - a long value.
          +
          Returns:
          +
          a Long instance representing l.
          +
          +
        • +
        + + + +
          +
        • +

          box

          +
          public static java.lang.Float box(float f)
          +
          Returns a Float instance representing the specified + float value.
          +
          +
          Parameters:
          +
          f - a float value.
          +
          Returns:
          +
          a Float instance representing f.
          +
          +
        • +
        + + + +
          +
        • +

          box

          +
          public static java.lang.Double box(double d)
          +
          Returns a Double instance representing the specified + double value.
          +
          +
          Parameters:
          +
          d - a double value.
          +
          Returns:
          +
          a Double instance representing d.
          +
          +
        • +
        + + + +
          +
        • +

          unbox

          +
          public static boolean unbox(java.lang.Boolean b)
          +
          Returns the value of the given Boolean object as a boolean + primitive.
          +
          +
          Parameters:
          +
          b - the Boolean object whose value is returned.
          +
          Returns:
          +
          the primitive boolean value of the object.
          +
          +
        • +
        + + + +
          +
        • +

          unbox

          +
          public static char unbox(java.lang.Character ch)
          +
          Returns the value of the given Character object as a char + primitive.
          +
          +
          Parameters:
          +
          ch - the Character object whose value is returned.
          +
          Returns:
          +
          the primitive char value of the object.
          +
          +
        • +
        + + + +
          +
        • +

          unbox

          +
          public static byte unbox(java.lang.Byte b)
          +
          Returns the value of the specified Byte as a byte.
          +
          +
          Parameters:
          +
          b - Byte that is unboxed
          +
          Returns:
          +
          the byte value represented by the Byte.
          +
          +
        • +
        + + + +
          +
        • +

          unbox

          +
          public static short unbox(java.lang.Short s)
          +
          Returns the short value represented by Short.
          +
          +
          Parameters:
          +
          s - Short that is unboxed.
          +
          Returns:
          +
          the short value represented by the Short.
          +
          +
        • +
        + + + +
          +
        • +

          unbox

          +
          public static int unbox(java.lang.Integer i)
          +
          Returns the value of represented by Integer.
          +
          +
          Parameters:
          +
          i - Integer that is unboxed.
          +
          Returns:
          +
          the int value represented by the Integer.
          +
          +
        • +
        + + + +
          +
        • +

          unbox

          +
          public static long unbox(java.lang.Long l)
          +
          Returns the long value represented by the specified Long.
          +
          +
          Parameters:
          +
          l - Long to be unboxed.
          +
          Returns:
          +
          the long value represented by the Long.
          +
          +
        • +
        + + + +
          +
        • +

          unbox

          +
          public static float unbox(java.lang.Float f)
          +
          Returns the float value represented by the specified Float.
          +
          +
          Parameters:
          +
          f - Float to be unboxed.
          +
          Returns:
          +
          the float value represented by the Float.
          +
          +
        • +
        + + + +
          +
        • +

          unbox

          +
          public static double unbox(java.lang.Double d)
          +
          Returns the double value represented by the specified Double.
          +
          +
          Parameters:
          +
          d - Double to be unboxed.
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Profiling.html b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Profiling.html new file mode 100644 index 00000000..46e387dd --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Profiling.html @@ -0,0 +1,443 @@ + + + + + +BTraceUtils.Profiling (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class BTraceUtils.Profiling

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.BTraceUtils.Profiling
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing class:
      +
      BTraceUtils
      +
      +
      +
      +
      public static class BTraceUtils.Profiling
      +extends java.lang.Object
      +
      Profiling support. It is a highly specialized aggregation (therefore not + included in the generic aggregations support) which is able to calculate + clean self time spent in hierarchically called methods (or bigger parts + of code)
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Profiling

          +
          public Profiling()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          newProfiler

          +
          public static Profiler newProfiler()
          +
          Creates a new Profiler instance
          +
          +
          Returns:
          +
          A new Profiler instance
          +
          +
        • +
        + + + +
          +
        • +

          newProfiler

          +
          public static Profiler newProfiler(int expectedBlockCnt)
          +
          Creates a new Profiler instance with the specified + expected count of the distinct methods to be recorded.
          +
          +
          Parameters:
          +
          expectedBlockCnt - The expected count of the distinct blocks + to be recorded.
          +
          Returns:
          +
          Returns a new Profiler instance
          +
          +
        • +
        + + + +
          +
        • +

          recordEntry

          +
          public static void recordEntry(Profiler profiler,
          +                               java.lang.String blockName)
          +
          Records the entry to a particular code block
          +
          +
          Parameters:
          +
          profiler - The Profiler instance to use
          +
          blockName - The block identifier
          +
          +
        • +
        + + + +
          +
        • +

          recordExit

          +
          public static void recordExit(Profiler profiler,
          +                              java.lang.String blockName,
          +                              long duration)
          +
          Records the exit out of a particular code block
          +
          +
          Parameters:
          +
          profiler - The Profiler instance to use
          +
          blockName - The block identifier
          +
          duration - The time spent in the mentioned block
          +
          +
        • +
        + + + +
          +
        • +

          snapshot

          +
          public static Profiler.Snapshot snapshot(Profiler profiler)
          +
          Creates a new snapshot of the profiling metrics collected sofar
          +
          +
          Parameters:
          +
          profiler - The Profiler instance to use
          +
          Returns:
          +
          Returns an immutable snapshot of the profiling metrics in + the form of a map where the key is the block name and + the value is a map of metrics names and the appropriate + values
          + The supported metrics names are: "selfTime", "wallTime" and + "invocations"
          +
          +
        • +
        + + + + + + + +
          +
        • +

          reset

          +
          public static void reset(Profiler profiler)
          +
        • +
        + + + +
          +
        • +

          printSnapshot

          +
          public static void printSnapshot(java.lang.String name,
          +                                 Profiler profiler)
          +
        • +
        + + + +
          +
        • +

          printSnapshot

          +
          public static void printSnapshot(java.lang.String name,
          +                                 Profiler profiler,
          +                                 java.lang.String format)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.References.html b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.References.html new file mode 100644 index 00000000..6007b21e --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.References.html @@ -0,0 +1,329 @@ + + + + + +BTraceUtils.References (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class BTraceUtils.References

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.BTraceUtils.References
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing class:
      +
      BTraceUtils
      +
      +
      +
      +
      public static class BTraceUtils.References
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        References() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static java.lang.Objectderef(java.lang.ref.Reference ref) +
        Returns the given reference object's referent.
        +
        static java.lang.ref.SoftReferencesoftRef(java.lang.Object obj) +
        Creates and returns a soft reference to the given object.
        +
        static java.lang.ref.WeakReferenceweakRef(java.lang.Object obj) +
        Creates and returns a weak reference to the given object.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          References

          +
          public References()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          weakRef

          +
          public static java.lang.ref.WeakReference weakRef(java.lang.Object obj)
          +
          Creates and returns a weak reference to the given object.
          +
          +
          Parameters:
          +
          obj - object for which a weak reference is created.
          +
          Returns:
          +
          a weak reference to the given object.
          +
          +
        • +
        + + + +
          +
        • +

          softRef

          +
          public static java.lang.ref.SoftReference softRef(java.lang.Object obj)
          +
          Creates and returns a soft reference to the given object.
          +
          +
          Parameters:
          +
          obj - object for which a soft reference is created.
          +
          Returns:
          +
          a soft reference to the given object.
          +
          +
        • +
        + + + +
          +
        • +

          deref

          +
          public static java.lang.Object deref(java.lang.ref.Reference ref)
          +
          Returns the given reference object's referent. If the reference object has + been cleared, either by the program or by the garbage collector, then + this method returns null.
          +
          +
          Parameters:
          +
          ref - reference object whose referent is returned.
          +
          Returns:
          +
          The object to which the reference refers, or + null if the reference object has been cleared.
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Reflective.html b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Reflective.html new file mode 100644 index 00000000..7669c4fb --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Reflective.html @@ -0,0 +1,1788 @@ + + + + + +BTraceUtils.Reflective (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class BTraceUtils.Reflective

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.BTraceUtils.Reflective
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing class:
      +
      BTraceUtils
      +
      +
      +
      +
      public static class BTraceUtils.Reflective
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        Reflective() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static intaccessFlags(java.lang.Class clazz) +
        Returns the access flags of the given Class.
        +
        static intaccessFlags(java.lang.reflect.Field field) +
        Returns the access flags of the given Field.
        +
        static java.lang.ClassclassForName(java.lang.String name) +
        Returns Class object for given class name.
        +
        static java.lang.ClassclassForName(java.lang.String name, + java.lang.ClassLoader cl) +
        Returns the Class for the given class name + using the given class loader.
        +
        static java.lang.ClassclassOf(java.lang.Object obj) +
        Returns the runtime class of the given Object.
        +
        static java.lang.ClassLoadercontextClassLoader() +
        Returns the current context class loader
        +
        static java.lang.ClassdeclaringClass(java.lang.reflect.Field field) +
        Returns the Class object representing the class or interface + that declares the field represented by the given Field object.
        +
        static java.lang.reflect.Fieldfield(java.lang.Class clazz, + java.lang.String name) +
        Returns a Field object that reflects the specified declared + field of the class or interface represented by the given Class + object.
        +
        static java.lang.reflect.Fieldfield(java.lang.Class clazz, + java.lang.String name, + boolean throwException) +
        Returns a Field object that reflects the specified declared + field of the class or interface represented by the given Class + object.
        +
        static java.lang.reflect.Fieldfield(java.lang.String clazz, + java.lang.String name) +
        Returns a Field object that reflects the specified declared + field of the class or interface represented by the given Class + object.
        +
        static java.lang.reflect.Fieldfield(java.lang.String clazz, + java.lang.String name, + boolean throwException) +
        Returns a Field object that reflects the specified declared + field of the class or interface represented by the given Class + object.
        +
        static java.lang.Objectget(java.lang.reflect.Field field) +
        Gets the value of a static reference field.
        +
        static java.lang.Objectget(java.lang.reflect.Field field, + java.lang.Object obj) +
        Gets the value of an instance reference field.
        +
        static java.lang.Objectget(java.lang.String name, + java.lang.Object instance) +
        Gets the value of an instance reference field.
        +
        static booleangetBoolean(java.lang.reflect.Field field) +
        Gets the value of a static boolean field.
        +
        static booleangetBoolean(java.lang.reflect.Field field, + java.lang.Object obj) +
        Gets the value of an instance boolean field.
        +
        static booleangetBoolean(java.lang.String name, + java.lang.Object instance) +
        Gets the value of an instance boolean field.
        +
        static booleangetBooleanStatic(java.lang.String name, + java.lang.Class clazz) +
        Gets the value of a static boolean field.
        +
        static bytegetByte(java.lang.reflect.Field field) +
        Gets the value of a static byte field.
        +
        static bytegetByte(java.lang.reflect.Field field, + java.lang.Object obj) +
        Gets the value of an instance byte field.
        +
        static bytegetByte(java.lang.String name, + java.lang.Object instance) +
        Gets the value of an instance byte field.
        +
        static bytegetByteStatic(java.lang.String name, + java.lang.Class clazz) +
        Gets the value of a static byte field.
        +
        static chargetChar(java.lang.reflect.Field field) +
        Gets the value of a static char field.
        +
        static chargetChar(java.lang.reflect.Field field, + java.lang.Object obj) +
        Gets the value of an instance char field.
        +
        static chargetChar(java.lang.String name, + java.lang.Object instance) +
        Gets the value of an instance char field.
        +
        static chargetCharStatic(java.lang.String name, + java.lang.Class clazz) +
        Gets the value of a static char field.
        +
        static java.lang.ClassgetComponentType(java.lang.Class clazz) +
        returns component type of an array Class.
        +
        static doublegetDouble(java.lang.reflect.Field field) +
        Gets the value of a static double field.
        +
        static doublegetDouble(java.lang.reflect.Field field, + java.lang.Object obj) +
        Gets the value of an instance double field.
        +
        static doublegetDouble(java.lang.String name, + java.lang.Class clazz) +
        Gets the value of a static double field.
        +
        static doublegetDouble(java.lang.String name, + java.lang.Object instance) +
        Gets the value of an instance double field.
        +
        static floatgetFloat(java.lang.reflect.Field field) +
        Gets the value of a static float field.
        +
        static floatgetFloat(java.lang.reflect.Field field, + java.lang.Object obj) +
        Gets the value of an instance float field.
        +
        static floatgetFloat(java.lang.String name, + java.lang.Object instance) +
        Gets the value of an instance float field.
        +
        static floatgetFloatStatic(java.lang.String name, + java.lang.Class clazz) +
        Gets the value of a static float field.
        +
        static intgetInt(java.lang.reflect.Field field) +
        Gets the value of a static int field.
        +
        static intgetInt(java.lang.reflect.Field field, + java.lang.Object obj) +
        Gets the value of an instance int field.
        +
        static intgetInt(java.lang.String name, + java.lang.Object instance) +
        Gets the value of an instance int field.
        +
        static intgetIntStatic(java.lang.String name, + java.lang.Class clazz) +
        Gets the value of a sttaic int field.
        +
        static longgetLong(java.lang.reflect.Field field) +
        Gets the value of a static long field.
        +
        static longgetLong(java.lang.reflect.Field field, + java.lang.Object obj) +
        Gets the value of an instance long field.
        +
        static longgetLong(java.lang.String name, + java.lang.Object instance) +
        Gets the value of an instance long field.
        +
        static longgetLongStatic(java.lang.String name, + java.lang.Class clazz) +
        Gets the value of a static long field.
        +
        static shortgetShort(java.lang.reflect.Field field) +
        Gets the value of a static short field.
        +
        static shortgetShort(java.lang.reflect.Field field, + java.lang.Object obj) +
        Gets the value of an instance short field.
        +
        static shortgetShort(java.lang.String name, + java.lang.Object instance) +
        Gets the value of an instance short field.
        +
        static shortgetShortStatic(java.lang.String name, + java.lang.Class clazz) +
        Gets the value of a static short field.
        +
        static java.lang.ObjectgetStatic(java.lang.String name, + java.lang.Class clazz) +
        Gets the value of a static reference field.
        +
        static java.lang.ClassgetSuperclass(java.lang.Class clazz) +
        Returns the Class representing the superclass of the entity + (class, interface, primitive type or void) represented by the given + Class.
        +
        static booleanisArray(java.lang.Class clazz) +
        Determines if the given Class object represents an array class.
        +
        static booleanisAssignableFrom(java.lang.Class<?> a, + java.lang.Class<?> b) +
        Determines if the class or interface represented by the first + Class object is either the same as, or is a superclass or + superinterface of, the class or interface represented by the second + Class parameter.
        +
        static booleanisInstance(java.lang.Class clazz, + java.lang.Object obj) +
        Determines if the specified Object is assignment-compatible + with the object represented by the specified Class.
        +
        static booleanisInterface(java.lang.Class clazz) +
        Determines if the specified Class object represents an + interface type.
        +
        static booleanisPrimitive(java.lang.Class clazz) +
        Returns whether the given Class represent primitive type or not.
        +
        static java.lang.Stringname(java.lang.Class clazz) +
        Returns the name of the given Class object.
        +
        static java.lang.Stringname(java.lang.reflect.Field field) +
        Returns the name of the Field object.
        +
        static voidprintFields(java.lang.Object obj) +
        Print all instance fields of an object as name-value + pairs.
        +
        static voidprintFields(java.lang.Object obj, + boolean classNamePrefix) +
        Print all instance fields of an object as name-value + pairs.
        +
        static voidprintStaticFields(java.lang.Class clazz) +
        Print all static fields of the class as name-value + pairs.
        +
        static voidprintStaticFields(java.lang.Class clazz, + boolean classNamePrefix) +
        Print all static fields of the class as name-value + pairs.
        +
        static java.lang.Classtype(java.lang.reflect.Field field) +
        Returns the type of the Field object.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Reflective

          +
          public Reflective()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          classOf

          +
          public static java.lang.Class classOf(java.lang.Object obj)
          +
          Returns the runtime class of the given Object.
          +
          +
          Parameters:
          +
          obj - the Object whose Class is returned
          +
          Returns:
          +
          the Class object of given object
          +
          +
        • +
        + + + +
          +
        • +

          declaringClass

          +
          public static java.lang.Class declaringClass(java.lang.reflect.Field field)
          +
          Returns the Class object representing the class or interface + that declares the field represented by the given Field object.
          +
          +
          Parameters:
          +
          field - whose declaring Class is returned
          +
          +
        • +
        + + + +
          +
        • +

          name

          +
          public static java.lang.String name(java.lang.Class clazz)
          +
          Returns the name of the given Class object.
          +
        • +
        + + + +
          +
        • +

          name

          +
          public static java.lang.String name(java.lang.reflect.Field field)
          +
          Returns the name of the Field object.
          +
          +
          Parameters:
          +
          field - Field for which name is returned
          +
          Returns:
          +
          name of the given field
          +
          +
        • +
        + + + +
          +
        • +

          type

          +
          public static java.lang.Class type(java.lang.reflect.Field field)
          +
          Returns the type of the Field object.
          +
          +
          Parameters:
          +
          field - Field for which type is returned
          +
          Returns:
          +
          type of the given field
          +
          +
        • +
        + + + +
          +
        • +

          accessFlags

          +
          public static int accessFlags(java.lang.Class clazz)
          +
          Returns the access flags of the given Class.
          +
        • +
        + + + +
          +
        • +

          accessFlags

          +
          public static int accessFlags(java.lang.reflect.Field field)
          +
          Returns the access flags of the given Field.
          +
        • +
        + + + +
          +
        • +

          contextClassLoader

          +
          public static java.lang.ClassLoader contextClassLoader()
          +
          Returns the current context class loader
          +
        • +
        + + + +
          +
        • +

          classForName

          +
          public static java.lang.Class classForName(java.lang.String name)
          +
          Returns Class object for given class name.
          +
        • +
        + + + +
          +
        • +

          classForName

          +
          public static java.lang.Class classForName(java.lang.String name,
          +                                           java.lang.ClassLoader cl)
          +
          Returns the Class for the given class name + using the given class loader.
          +
        • +
        + + + +
          +
        • +

          isAssignableFrom

          +
          public static boolean isAssignableFrom(java.lang.Class<?> a,
          +                                       java.lang.Class<?> b)
          +
          Determines if the class or interface represented by the first + Class object is either the same as, or is a superclass or + superinterface of, the class or interface represented by the second + Class parameter. It returns true if so; + otherwise it returns false.
          +
        • +
        + + + +
          +
        • +

          isInstance

          +
          public static boolean isInstance(java.lang.Class clazz,
          +                                 java.lang.Object obj)
          +
          Determines if the specified Object is assignment-compatible + with the object represented by the specified Class. This method is + the dynamic equivalent of the Java language instanceof + operator. The method returns true if the specified + Object argument is non-null and can be cast to the + reference type represented by this Class object without + raising a ClassCastException. It returns false + otherwise.
          +
          +
          Parameters:
          +
          clazz - the class that is checked.
          +
          obj - the object to check.
          +
          Returns:
          +
          true if obj is an instance of the given class.
          +
          +
        • +
        + + + +
          +
        • +

          getSuperclass

          +
          public static java.lang.Class getSuperclass(java.lang.Class clazz)
          +
          Returns the Class representing the superclass of the entity + (class, interface, primitive type or void) represented by the given + Class. If the given Class represents either the + Object class, an interface, a primitive type, or void, then + null is returned. If the given object represents an array class then the + Class object representing the Object class is + returned.
          +
          +
          Parameters:
          +
          clazz - the Class whose super class is returned.
          +
          Returns:
          +
          the superclass of the class represented by the given object.
          +
          +
        • +
        + + + +
          +
        • +

          isInterface

          +
          public static boolean isInterface(java.lang.Class clazz)
          +
          Determines if the specified Class object represents an + interface type.
          +
          +
          Parameters:
          +
          clazz - the Class object to check.
          +
          Returns:
          +
          true if the Class represents an interface; + false otherwise.
          +
          +
        • +
        + + + +
          +
        • +

          isArray

          +
          public static boolean isArray(java.lang.Class clazz)
          +
          Determines if the given Class object represents an array class.
          +
          +
          Parameters:
          +
          clazz - Class object to check.
          +
          Returns:
          +
          true if the given object represents an array class; + false otherwise.
          +
          +
        • +
        + + + +
          +
        • +

          isPrimitive

          +
          public static boolean isPrimitive(java.lang.Class clazz)
          +
          Returns whether the given Class represent primitive type or not.
          +
        • +
        + + + +
          +
        • +

          getComponentType

          +
          public static java.lang.Class getComponentType(java.lang.Class clazz)
          +
          returns component type of an array Class.
          +
        • +
        + + + +
          +
        • +

          field

          +
          public static java.lang.reflect.Field field(java.lang.Class clazz,
          +                                            java.lang.String name,
          +                                            boolean throwException)
          +
          Returns a Field object that reflects the specified declared + field of the class or interface represented by the given Class + object. The name parameter is a String that + specifies the simple name of the desired field. Returns null on not finding + field if throwException parameter is false. Else throws a RuntimeException + when field is not found.
          +
          +
          Parameters:
          +
          clazz - Class whose field is returned
          +
          name - the name of the field
          +
          throwException - whether to throw exception on failing to find field or not
          +
          Returns:
          +
          the Field object for the specified field in this + class
          +
          +
        • +
        + + + +
          +
        • +

          field

          +
          public static java.lang.reflect.Field field(java.lang.Class clazz,
          +                                            java.lang.String name)
          +
          Returns a Field object that reflects the specified declared + field of the class or interface represented by the given Class + object. The name parameter is a String that + specifies the simple name of the desired field. Throws a RuntimeException + when field is not found.
          +
          +
          Parameters:
          +
          clazz - Class whose field is returned
          +
          name - the name of the field
          +
          Returns:
          +
          the Field object for the specified field in this + class
          +
          +
        • +
        + + + +
          +
        • +

          field

          +
          public static java.lang.reflect.Field field(java.lang.String clazz,
          +                                            java.lang.String name,
          +                                            boolean throwException)
          +
          Returns a Field object that reflects the specified declared + field of the class or interface represented by the given Class + object. The name parameter is a String that + specifies the simple name of the desired field. Returns null on not finding + field if throwException parameter is false. Else throws a RuntimeException + when field is not found.
          +
          +
          Parameters:
          +
          clazz - Class whose field is returned
          +
          name - the name of the field
          +
          throwException - whether to throw exception on failing to find field or not
          +
          Returns:
          +
          the Field object for the specified field in this + class
          +
          +
        • +
        + + + +
          +
        • +

          field

          +
          public static java.lang.reflect.Field field(java.lang.String clazz,
          +                                            java.lang.String name)
          +
          Returns a Field object that reflects the specified declared + field of the class or interface represented by the given Class + object. The name parameter is a String that + specifies the simple name of the desired field. Throws a RuntimeException + when field is not found.
          +
          +
          Parameters:
          +
          clazz - Class whose field is returned
          +
          name - the name of the field
          +
          Returns:
          +
          the Field object for the specified field in this + class
          +
          +
        • +
        + + + +
          +
        • +

          getByte

          +
          public static byte getByte(java.lang.reflect.Field field)
          +
          Gets the value of a static byte field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          Returns:
          +
          the value of the byte field
          +
          +
        • +
        + + + +
          +
        • +

          getByte

          +
          public static byte getByte(java.lang.reflect.Field field,
          +                           java.lang.Object obj)
          +
          Gets the value of an instance byte field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          obj - the object to extract the byte value + from
          +
          Returns:
          +
          the value of the byte field
          +
          +
        • +
        + + + +
          +
        • +

          getByte

          +
          public static byte getByte(java.lang.String name,
          +                           java.lang.Object instance)
          +
          Gets the value of an instance byte field.
          +
          +
          Parameters:
          +
          name - name of the field whose value is returned.
          +
          instance - the object to extract the byte value + from
          +
          Returns:
          +
          the value of the byte field
          +
          Since:
          +
          1.3.5
          +
          +
        • +
        + + + +
          +
        • +

          getByteStatic

          +
          public static byte getByteStatic(java.lang.String name,
          +                                 java.lang.Class clazz)
          +
          Gets the value of a static byte field.
          +
          +
          Parameters:
          +
          name - name of the field whose value is returned.
          +
          clazz - the class to extract the byte value + from
          +
          Returns:
          +
          the value of the byte field
          +
          Since:
          +
          1.3.5
          +
          +
        • +
        + + + +
          +
        • +

          getShort

          +
          public static short getShort(java.lang.reflect.Field field)
          +
          Gets the value of a static short field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          Returns:
          +
          the value of the short field
          +
          +
        • +
        + + + +
          +
        • +

          getShort

          +
          public static short getShort(java.lang.reflect.Field field,
          +                             java.lang.Object obj)
          +
          Gets the value of an instance short field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          obj - the object to extract the short value + from
          +
          Returns:
          +
          the value of the short field
          +
          +
        • +
        + + + +
          +
        • +

          getShort

          +
          public static short getShort(java.lang.String name,
          +                             java.lang.Object instance)
          +
          Gets the value of an instance short field.
          +
          +
          Parameters:
          +
          name - name of the field whose value is returned.
          +
          instance - the object to extract the short value + from
          +
          Returns:
          +
          the value of the short field
          +
          Since:
          +
          1.3.5
          +
          +
        • +
        + + + +
          +
        • +

          getShortStatic

          +
          public static short getShortStatic(java.lang.String name,
          +                                   java.lang.Class clazz)
          +
          Gets the value of a static short field.
          +
          +
          Parameters:
          +
          name - name of the field whose value is returned.
          +
          clazz - the class to extract the short value + from
          +
          Returns:
          +
          the value of the short field
          +
          Since:
          +
          1.3.5
          +
          +
        • +
        + + + +
          +
        • +

          getInt

          +
          public static int getInt(java.lang.reflect.Field field)
          +
          Gets the value of a static int field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          Returns:
          +
          the value of the int field
          +
          +
        • +
        + + + +
          +
        • +

          getInt

          +
          public static int getInt(java.lang.reflect.Field field,
          +                         java.lang.Object obj)
          +
          Gets the value of an instance int field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          obj - the object to extract the int value + from
          +
          Returns:
          +
          the value of the int field
          +
          +
        • +
        + + + +
          +
        • +

          getInt

          +
          public static int getInt(java.lang.String name,
          +                         java.lang.Object instance)
          +
          Gets the value of an instance int field.
          +
          +
          Parameters:
          +
          name - name of the field whose value is returned.
          +
          instance - the object to extract the int value + from
          +
          Returns:
          +
          the value of the int field
          +
          Since:
          +
          1.3.5
          +
          +
        • +
        + + + +
          +
        • +

          getIntStatic

          +
          public static int getIntStatic(java.lang.String name,
          +                               java.lang.Class clazz)
          +
          Gets the value of a sttaic int field.
          +
          +
          Parameters:
          +
          name - name of the field whose value is returned.
          +
          clazz - the class to extract the int value + from
          +
          Returns:
          +
          the value of the int field
          +
          Since:
          +
          1.3.5
          +
          +
        • +
        + + + +
          +
        • +

          getLong

          +
          public static long getLong(java.lang.reflect.Field field)
          +
          Gets the value of a static long field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          Returns:
          +
          the value of the long field
          +
          +
        • +
        + + + +
          +
        • +

          getLong

          +
          public static long getLong(java.lang.reflect.Field field,
          +                           java.lang.Object obj)
          +
          Gets the value of an instance long field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          obj - the object to extract the long value + from
          +
          Returns:
          +
          the value of the long field
          +
          +
        • +
        + + + +
          +
        • +

          getLong

          +
          public static long getLong(java.lang.String name,
          +                           java.lang.Object instance)
          +
          Gets the value of an instance long field.
          +
          +
          Parameters:
          +
          name - name of the field whose value is returned.
          +
          instance - the object to extract the long value + from
          +
          Returns:
          +
          the value of the long field
          +
          Since:
          +
          1.3.5
          +
          +
        • +
        + + + +
          +
        • +

          getLongStatic

          +
          public static long getLongStatic(java.lang.String name,
          +                                 java.lang.Class clazz)
          +
          Gets the value of a static long field.
          +
          +
          Parameters:
          +
          name - name of the field whose value is returned.
          +
          clazz - the class to extract the long value + from
          +
          Returns:
          +
          the value of the long field
          +
          Since:
          +
          1.3.5
          +
          +
        • +
        + + + +
          +
        • +

          getFloat

          +
          public static float getFloat(java.lang.reflect.Field field)
          +
          Gets the value of a static float field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          Returns:
          +
          the value of the float field
          +
          +
        • +
        + + + +
          +
        • +

          getFloat

          +
          public static float getFloat(java.lang.reflect.Field field,
          +                             java.lang.Object obj)
          +
          Gets the value of an instance float field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          obj - the object to extract the float value + from
          +
          Returns:
          +
          the value of the float field
          +
          +
        • +
        + + + +
          +
        • +

          getFloat

          +
          public static float getFloat(java.lang.String name,
          +                             java.lang.Object instance)
          +
          Gets the value of an instance float field.
          +
          +
          Parameters:
          +
          name - name of the field whose value is returned.
          +
          instance - the object to extract the float value + from
          +
          Returns:
          +
          the value of the float field
          +
          Since:
          +
          1.3.5
          +
          +
        • +
        + + + +
          +
        • +

          getFloatStatic

          +
          public static float getFloatStatic(java.lang.String name,
          +                                   java.lang.Class clazz)
          +
          Gets the value of a static float field.
          +
          +
          Parameters:
          +
          name - name of the field whose value is returned.
          +
          clazz - the class to extract the float value + from
          +
          Returns:
          +
          the value of the float field
          +
          Since:
          +
          1.3.5
          +
          +
        • +
        + + + +
          +
        • +

          getDouble

          +
          public static double getDouble(java.lang.reflect.Field field)
          +
          Gets the value of a static double field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          Returns:
          +
          the value of the double field
          +
          +
        • +
        + + + +
          +
        • +

          getDouble

          +
          public static double getDouble(java.lang.reflect.Field field,
          +                               java.lang.Object obj)
          +
          Gets the value of an instance double field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          obj - the object to extract the double value + from
          +
          Returns:
          +
          the value of the double field
          +
          +
        • +
        + + + +
          +
        • +

          getDouble

          +
          public static double getDouble(java.lang.String name,
          +                               java.lang.Object instance)
          +
          Gets the value of an instance double field.
          +
          +
          Parameters:
          +
          name - name of the field whose value is returned.
          +
          instance - the object to extract the double value + from
          +
          Returns:
          +
          the value of the double field
          +
          Since:
          +
          1.3.5
          +
          +
        • +
        + + + +
          +
        • +

          getDouble

          +
          public static double getDouble(java.lang.String name,
          +                               java.lang.Class clazz)
          +
          Gets the value of a static double field.
          +
          +
          Parameters:
          +
          name - name of the field whose value is returned.
          +
          clazz - the class to extract the double value + from
          +
          Returns:
          +
          the value of the double field
          +
          Since:
          +
          1.3.5
          +
          +
        • +
        + + + +
          +
        • +

          getBoolean

          +
          public static boolean getBoolean(java.lang.reflect.Field field)
          +
          Gets the value of a static boolean field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          Returns:
          +
          the value of the boolean field
          +
          +
        • +
        + + + +
          +
        • +

          getBoolean

          +
          public static boolean getBoolean(java.lang.reflect.Field field,
          +                                 java.lang.Object obj)
          +
          Gets the value of an instance boolean field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          obj - the object to extract the boolean value + from
          +
          Returns:
          +
          the value of the boolean field
          +
          +
        • +
        + + + +
          +
        • +

          getBoolean

          +
          public static boolean getBoolean(java.lang.String name,
          +                                 java.lang.Object instance)
          +
          Gets the value of an instance boolean field.
          +
          +
          Parameters:
          +
          name - name of the field whose value is returned.
          +
          instance - the object to extract the boolean value + from
          +
          Returns:
          +
          the value of the boolean field
          +
          Since:
          +
          1.3.5
          +
          +
        • +
        + + + +
          +
        • +

          getBooleanStatic

          +
          public static boolean getBooleanStatic(java.lang.String name,
          +                                       java.lang.Class clazz)
          +
          Gets the value of a static boolean field.
          +
          +
          Parameters:
          +
          name - name of the field whose value is returned.
          +
          clazz - the class to extract the boolean value + from
          +
          Returns:
          +
          the value of the boolean field
          +
          Since:
          +
          1.3.5
          +
          +
        • +
        + + + +
          +
        • +

          getChar

          +
          public static char getChar(java.lang.reflect.Field field)
          +
          Gets the value of a static char field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          Returns:
          +
          the value of the char field
          +
          +
        • +
        + + + +
          +
        • +

          getChar

          +
          public static char getChar(java.lang.reflect.Field field,
          +                           java.lang.Object obj)
          +
          Gets the value of an instance char field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          obj - the object to extract the char value + from
          +
          Returns:
          +
          the value of the char field
          +
          +
        • +
        + + + +
          +
        • +

          getChar

          +
          public static char getChar(java.lang.String name,
          +                           java.lang.Object instance)
          +
          Gets the value of an instance char field.
          +
          +
          Parameters:
          +
          name - name of the field whose value is returned.
          +
          instance - the object to extract the char value + from
          +
          Returns:
          +
          the value of the char field
          +
          Since:
          +
          1.3.5
          +
          +
        • +
        + + + +
          +
        • +

          getCharStatic

          +
          public static char getCharStatic(java.lang.String name,
          +                                 java.lang.Class clazz)
          +
          Gets the value of a static char field.
          +
          +
          Parameters:
          +
          name - name of the field whose value is returned.
          +
          clazz - the class to extract the char value + from
          +
          Returns:
          +
          the value of the char field
          +
          Since:
          +
          1.3.5
          +
          +
        • +
        + + + +
          +
        • +

          get

          +
          public static java.lang.Object get(java.lang.reflect.Field field)
          +
          Gets the value of a static reference field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          Returns:
          +
          the value of the reference field
          +
          +
        • +
        + + + +
          +
        • +

          get

          +
          public static java.lang.Object get(java.lang.reflect.Field field,
          +                                   java.lang.Object obj)
          +
          Gets the value of an instance reference field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          obj - the object to extract the reference value + from
          +
          Returns:
          +
          the value of the reference field
          +
          +
        • +
        + + + +
          +
        • +

          get

          +
          public static java.lang.Object get(java.lang.String name,
          +                                   java.lang.Object instance)
          +
          Gets the value of an instance reference field.
          +
          +
          Parameters:
          +
          name - name of the field whose value is returned.
          +
          instance - the object to extract the reference value + from
          +
          Returns:
          +
          the value of the reference field
          +
          Since:
          +
          1.3.5
          +
          +
        • +
        + + + +
          +
        • +

          getStatic

          +
          public static java.lang.Object getStatic(java.lang.String name,
          +                                         java.lang.Class clazz)
          +
          Gets the value of a static reference field.
          +
          +
          Parameters:
          +
          name - name of the field whose value is returned.
          +
          clazz - the class to extract the reference value + from
          +
          Returns:
          +
          the value of the reference field
          +
          Since:
          +
          1.3.5
          +
          +
        • +
        + + + +
          +
        • +

          printFields

          +
          public static void printFields(java.lang.Object obj)
          +
          Print all instance fields of an object as name-value + pairs. Includes the inherited fields as well.
          +
          +
          Parameters:
          +
          obj - Object whose fields are printed.
          +
          +
        • +
        + + + +
          +
        • +

          printFields

          +
          public static void printFields(java.lang.Object obj,
          +                               boolean classNamePrefix)
          +
          Print all instance fields of an object as name-value + pairs. Includes the inherited fields as well. Optionally, + prints name of the declaring class before each field - so that + if same named field in super class chain may be disambiguated.
          +
          +
          Parameters:
          +
          obj - Object whose fields are printed.
          +
          classNamePrefix - flag to tell whether to prefix field names + names by class name or not.
          +
          +
        • +
        + + + +
          +
        • +

          printStaticFields

          +
          public static void printStaticFields(java.lang.Class clazz)
          +
          Print all static fields of the class as name-value + pairs. Includes the inherited fields as well.
          +
          +
          Parameters:
          +
          clazz - Class whose static fields are printed.
          +
          +
        • +
        + + + +
          +
        • +

          printStaticFields

          +
          public static void printStaticFields(java.lang.Class clazz,
          +                                     boolean classNamePrefix)
          +
          Print all static fields of the class as name-value + pairs. Includes the inherited fields as well. Optionally, + prints name of the declaring class before each field - so that + if same named field in super class chain may be disambigated.
          +
          +
          Parameters:
          +
          clazz - Class whose static fields are printed.
          +
          classNamePrefix - flag to tell whether to prefix field names + names by class name or not.
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Speculation.html b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Speculation.html new file mode 100644 index 00000000..280b3fa6 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Speculation.html @@ -0,0 +1,340 @@ + + + + + +BTraceUtils.Speculation (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class BTraceUtils.Speculation

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.BTraceUtils.Speculation
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing class:
      +
      BTraceUtils
      +
      +
      +
      +
      public static class BTraceUtils.Speculation
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        Speculation() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static voidcommit(int id) +
        Commits the speculative buffer associated with id.
        +
        static voiddiscard(int id) +
        Discards the speculative buffer associated with id.
        +
        static voidspeculate(int id) +
        Sets current speculative buffer id.
        +
        static intspeculation() +
        Returns an identifier for a new speculative buffer.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Speculation

          +
          public Speculation()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          speculation

          +
          public static int speculation()
          +
          Returns an identifier for a new speculative buffer.
          +
          +
          Returns:
          +
          new speculative buffer id
          +
          +
        • +
        + + + +
          +
        • +

          speculate

          +
          public static void speculate(int id)
          +
          Sets current speculative buffer id.
          +
          +
          Parameters:
          +
          id - the speculative buffer id
          +
          +
        • +
        + + + +
          +
        • +

          commit

          +
          public static void commit(int id)
          +
          Commits the speculative buffer associated with id.
          +
          +
          Parameters:
          +
          id - the speculative buffer id
          +
          +
        • +
        + + + +
          +
        • +

          discard

          +
          public static void discard(int id)
          +
          Discards the speculative buffer associated with id.
          +
          +
          Parameters:
          +
          id - the speculative buffer id
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Strings.html b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Strings.html new file mode 100644 index 00000000..aa660c00 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Strings.html @@ -0,0 +1,1183 @@ + + + + + +BTraceUtils.Strings (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class BTraceUtils.Strings

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.BTraceUtils.Strings
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing class:
      +
      BTraceUtils
      +
      +
      +
      +
      public static class BTraceUtils.Strings
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        Strings() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static java.lang.Appendableappend(java.lang.Appendable buffer, + java.lang.String strToAppend) +
        Appends a string to an appendable buffer created by newStringBuilder()
        +
        static intcompareTo(java.lang.String str1, + java.lang.String str2) +
        Compares two strings lexicographically.
        +
        static intcompareToIgnoreCase(java.lang.String str1, + java.lang.String str2) +
        Compares two strings lexicographically, ignoring case + differences.
        +
        static java.lang.Stringconcat(java.lang.String str1, + java.lang.String str2) +
        Concatenates the specified strings together.
        +
        static booleanendsWith(java.lang.String s, + java.lang.String end) 
        static intindexOf(java.lang.String str1, + java.lang.String str2) 
        static intlastIndexOf(java.lang.String str1, + java.lang.String str2) 
        static intlength(java.lang.Appendable buffer) +
        Checks the length of an appendable buffer created by newStringBuilder()
        +
        static intlength(java.lang.String str) +
        Returns the length of the given string.
        +
        static booleanmatches(java.util.regex.Pattern regex, + java.lang.String input) +
        Matches the given (precompiled) regular expression and attempts + to match the given input against it.
        +
        static booleanmatches(java.lang.String regex, + java.lang.String input) +
        Compiles the given regular expression and attempts to match the given + input against it.
        +
        static java.lang.AppendablenewStringBuilder() +
        Safely creates a new instance of an appendable string buffer
        + The buffer will not be thread safe.
        +
        static java.lang.AppendablenewStringBuilder(boolean threadSafe) +
        Safely creates a new instance of an appendable string buffer
        +
        static java.util.regex.Patternpattern(java.lang.String regex) +
        This is synonym for "regexp".
        +
        static java.util.regex.Patternpattern(java.lang.String regex, + int flags) +
        This is synonym for "regexp".
        +
        static java.util.regex.Patternregexp(java.lang.String regex) +
        Compiles the given regular expression into a pattern.
        +
        static java.util.regex.Patternregexp(java.lang.String regex, + int flags) +
        Compiles the given regular expression into a pattern with the given + flags.
        +
        static booleanstartsWith(java.lang.String s, + java.lang.String start) 
        static java.lang.Stringstr(boolean b) +
        Returns a String object representing the specified + boolean.
        +
        static java.lang.Stringstr(char c) +
        Returns a String object representing the + specified char.
        +
        static java.lang.Stringstr(double d) +
        Returns a string representation of the double + argument.
        +
        static java.lang.Stringstr(float f) +
        Returns a string representation of the float + argument.
        +
        static java.lang.Stringstr(int i) +
        Returns a String object representing the + specified integer.
        +
        static java.lang.Stringstr(long l) +
        Returns a String object representing the specified + long.
        +
        static java.lang.Stringstr(java.lang.Object obj) +
        Returns a string representation of the object.
        +
        static java.lang.Stringstrcat(java.lang.String str1, + java.lang.String str2) +
        This is synonym to "concat".
        +
        static intstrcmp(java.lang.String str1, + java.lang.String str2) +
        This is synonym to "compareTo" method.
        +
        static intstricmp(java.lang.String str1, + java.lang.String str2) +
        This is synonym to "compareToIgnoreCase".
        +
        static intstrlen(java.lang.String str) +
        This is synonym for "length".
        +
        static intstrstr(java.lang.String str1, + java.lang.String str2) +
        Find String within String
        +
        static java.lang.Stringsubstr(java.lang.String str, + int start) 
        static java.lang.Stringsubstr(java.lang.String str, + int start, + int end) +
        Substring
        +
        static java.lang.StringtoHexString(int i) +
        Returns a string representation of the integer argument as an + unsigned integer in base 16.
        +
        static java.lang.StringtoHexString(long l) +
        Returns a string representation of the long + argument as an unsigned integer in base 16.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Strings

          +
          public Strings()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          startsWith

          +
          public static boolean startsWith(java.lang.String s,
          +                                 java.lang.String start)
          +
        • +
        + + + +
          +
        • +

          endsWith

          +
          public static boolean endsWith(java.lang.String s,
          +                               java.lang.String end)
          +
        • +
        + + + +
          +
        • +

          strcat

          +
          public static java.lang.String strcat(java.lang.String str1,
          +                                      java.lang.String str2)
          +
          This is synonym to "concat".
          +
          +
          See Also:
          +
          concat(String, String)
          +
          +
        • +
        + + + +
          +
        • +

          concat

          +
          public static java.lang.String concat(java.lang.String str1,
          +                                      java.lang.String str2)
          +
          Concatenates the specified strings together.
          +
        • +
        + + + +
          +
        • +

          compareTo

          +
          public static int compareTo(java.lang.String str1,
          +                            java.lang.String str2)
          +
          Compares two strings lexicographically. + The comparison is based on the Unicode value of each character in + the strings. The character sequence represented by the first + String object is compared lexicographically to the + character sequence represented by the second string. The result is + a negative integer if the first String object + lexicographically precedes the second string. The result is a + positive integer if the first String object lexicographically + follows the second string. The result is zero if the strings + are equal; compareTo returns 0 exactly when + the String.equals(Object) method would return true.
          +
        • +
        + + + + + + + +
          +
        • +

          compareToIgnoreCase

          +
          public static int compareToIgnoreCase(java.lang.String str1,
          +                                      java.lang.String str2)
          +
          Compares two strings lexicographically, ignoring case + differences. This method returns an integer whose sign is that of + calling compareTo with normalized versions of the strings + where case differences have been eliminated by calling + Character.toLowerCase(Character.toUpperCase(character)) on + each character.
          +
        • +
        + + + + + + + +
          +
        • +

          strstr

          +
          public static int strstr(java.lang.String str1,
          +                         java.lang.String str2)
          +
          Find String within String
          +
        • +
        + + + +
          +
        • +

          indexOf

          +
          public static int indexOf(java.lang.String str1,
          +                          java.lang.String str2)
          +
        • +
        + + + +
          +
        • +

          lastIndexOf

          +
          public static int lastIndexOf(java.lang.String str1,
          +                              java.lang.String str2)
          +
        • +
        + + + +
          +
        • +

          substr

          +
          public static java.lang.String substr(java.lang.String str,
          +                                      int start,
          +                                      int end)
          +
          Substring
          +
        • +
        + + + +
          +
        • +

          substr

          +
          public static java.lang.String substr(java.lang.String str,
          +                                      int start)
          +
        • +
        + + + +
          +
        • +

          length

          +
          public static int length(java.lang.String str)
          +
          Returns the length of the given string. + The length is equal to the number of Unicode + code units in the string.
          +
          +
          Parameters:
          +
          str - String whose length is calculated.
          +
          Returns:
          +
          the length of the sequence of characters represented by this + object.
          +
          +
        • +
        + + + +
          +
        • +

          strlen

          +
          public static int strlen(java.lang.String str)
          +
          This is synonym for "length".
          +
          +
          See Also:
          +
          length(String)
          +
          +
        • +
        + + + +
          +
        • +

          regexp

          +
          public static java.util.regex.Pattern regexp(java.lang.String regex)
          +
          Compiles the given regular expression into a pattern.
          +
          +
          Parameters:
          +
          regex - The expression to be compiled
          +
          Throws:
          +
          java.util.regex.PatternSyntaxException - If the expression's syntax is invalid
          +
          +
        • +
        + + + +
          +
        • +

          pattern

          +
          public static java.util.regex.Pattern pattern(java.lang.String regex)
          +
          This is synonym for "regexp".
          +
          +
          See Also:
          +
          regexp(String)
          +
          +
        • +
        + + + +
          +
        • +

          regexp

          +
          public static java.util.regex.Pattern regexp(java.lang.String regex,
          +                                             int flags)
          +
          Compiles the given regular expression into a pattern with the given + flags.
          +
          +
          Parameters:
          +
          regex - The expression to be compiled
          +
          flags - Match flags, a bit mask that may include + Pattern.CASE_INSENSITIVE, Pattern.MULTILINE, Pattern.DOTALL, + Pattern.UNICODE_CASE, Pattern.CANON_EQ, Pattern.UNIX_LINES, + Pattern.LITERAL and Pattern.COMMENTS
          +
          Throws:
          +
          java.lang.IllegalArgumentException - If bit values other than those corresponding to the defined + match flags are set in flags
          +
          java.util.regex.PatternSyntaxException - If the expression's syntax is invalid
          +
          +
        • +
        + + + +
          +
        • +

          pattern

          +
          public static java.util.regex.Pattern pattern(java.lang.String regex,
          +                                              int flags)
          +
          This is synonym for "regexp".
          +
          +
          See Also:
          +
          regexp(String, int)
          +
          +
        • +
        + + + +
          +
        • +

          matches

          +
          public static boolean matches(java.util.regex.Pattern regex,
          +                              java.lang.String input)
          +
          Matches the given (precompiled) regular expression and attempts + to match the given input against it.
          +
        • +
        + + + +
          +
        • +

          matches

          +
          public static boolean matches(java.lang.String regex,
          +                              java.lang.String input)
          +
          Compiles the given regular expression and attempts to match the given + input against it. + +

          An invocation of this convenience method of the form + +

          + Pattern.matches(regex, input);
          + + behaves in exactly the same way as the expression + +
          + Pattern.compile(regex).matcher(input).matches()
          + +

          + If a pattern is to be used multiple times, compiling it once and reusing + it will be more efficient than invoking this method each time.

          +
          +
          Parameters:
          +
          regex - The expression to be compiled
          +
          input - The character sequence to be matched
          +
          Throws:
          +
          java.util.regex.PatternSyntaxException - If the expression's syntax is invalid
          +
          +
        • +
        + + + +
          +
        • +

          str

          +
          public static java.lang.String str(boolean b)
          +
          Returns a String object representing the specified + boolean. If the specified boolean is true, then + the string "true" will be returned, otherwise the + string "false" will be returned.
          +
          +
          Parameters:
          +
          b - the boolean to be converted
          +
          Returns:
          +
          the string representation of the specified boolean
          +
          +
        • +
        + + + +
          +
        • +

          str

          +
          public static java.lang.String str(char c)
          +
          Returns a String object representing the + specified char. The result is a string of length + 1 consisting solely of the specified char.
          +
          +
          Parameters:
          +
          c - the char to be converted
          +
          Returns:
          +
          the string representation of the specified char
          +
          +
        • +
        + + + +
          +
        • +

          str

          +
          public static java.lang.String str(int i)
          +
          Returns a String object representing the + specified integer. The argument is converted to signed decimal + representation and returned as a string.
          +
          +
          Parameters:
          +
          i - an integer to be converted.
          +
          Returns:
          +
          a string representation of the argument in base 10.
          +
          +
        • +
        + + + +
          +
        • +

          toHexString

          +
          public static java.lang.String toHexString(int i)
          +
          Returns a string representation of the integer argument as an + unsigned integer in base 16. +

          + The unsigned integer value is the argument plus 232 + if the argument is negative; otherwise, it is equal to the + argument. This value is converted to a string of ASCII digits + in hexadecimal (base 16) with no extra leading + 0s. If the unsigned magnitude is zero, it is + represented by a single zero character '0' + ('\u0030'); otherwise, the first character of + the representation of the unsigned magnitude will not be the + zero character. The following characters are used as + hexadecimal digits: +

          + 0123456789abcdef
          + 
          + These are the characters '\u0030' through + '\u0039' and '\u0061' through + '\u0066'.
          +
          +
          Parameters:
          +
          i - an integer to be converted to a string.
          +
          Returns:
          +
          the string representation of the unsigned integer value + represented by the argument in hexadecimal (base 16).
          +
          +
        • +
        + + + +
          +
        • +

          str

          +
          public static java.lang.String str(long l)
          +
          Returns a String object representing the specified + long. The argument is converted to signed decimal + representation and returned as a string.
          +
          +
          Parameters:
          +
          l - a long to be converted.
          +
          Returns:
          +
          a string representation of the argument in base 10.
          +
          +
        • +
        + + + +
          +
        • +

          str

          +
          public static java.lang.String str(java.lang.Object obj)
          +
          Returns a string representation of the object. In general, the + toString method returns a string that + "textually represents" this object. The result should + be a concise but informative representation that is easy for a + person to read. For bootstrap classes, returns the result of + calling Object.toString() override. For non-bootstrap classes, + default toString() value [className@hashCode] is returned.
          +
          +
          Parameters:
          +
          obj - the object whose string representation is returned
          +
          Returns:
          +
          a string representation of the given object.
          +
          +
        • +
        + + + +
          +
        • +

          toHexString

          +
          public static java.lang.String toHexString(long l)
          +
          Returns a string representation of the long + argument as an unsigned integer in base 16. +

          + The unsigned long value is the argument plus + 264 if the argument is negative; otherwise, it is + equal to the argument. This value is converted to a string of + ASCII digits in hexadecimal (base 16) with no extra + leading 0s. If the unsigned magnitude is zero, it + is represented by a single zero character '0' + ('\u0030'); otherwise, the first character of + the representation of the unsigned magnitude will not be the + zero character. The following characters are used as + hexadecimal digits: +

          + 0123456789abcdef
          + 
          + These are the characters '\u0030' through + '\u0039' and '\u0061' through + '\u0066'.
          +
          +
          Parameters:
          +
          l - a long to be converted to a string.
          +
          Returns:
          +
          the string representation of the unsigned long + value represented by the argument in hexadecimal + (base 16).
          +
          +
        • +
        + + + +
          +
        • +

          str

          +
          public static java.lang.String str(float f)
          +
          Returns a string representation of the float + argument. All characters mentioned below are ASCII characters. +
            +
          • If the argument is NaN, the result is the string + "NaN". +
          • Otherwise, the result is a string that represents the sign and + magnitude (absolute value) of the argument. If the sign is + negative, the first character of the result is + '-' ('\u002D'); if the sign is + positive, no sign character appears in the result. As for + the magnitude m: +
              +
            • If m is infinity, it is represented by the characters + "Infinity"; thus, positive infinity produces + the result "Infinity" and negative infinity + produces the result "-Infinity". +
            • If m is zero, it is represented by the characters + "0.0"; thus, negative zero produces the result + "-0.0" and positive zero produces the result + "0.0". +
            • If m is greater than or equal to 10-3 but + less than 107, then it is represented as the + integer part of m, in decimal form with no leading + zeroes, followed by '.' + ('\u002E'), followed by one or more + decimal digits representing the fractional part of + m. +
            • If m is less than 10-3 or greater than or + equal to 107, then it is represented in + so-called "computerized scientific notation." Let n + be the unique integer such that 10n <= + m < 10n+1; then let a + be the mathematically exact quotient of m and + 10n so that 1 <= a < 10. + The magnitude is then represented as the integer part of + a, as a single decimal digit, followed by + '.' ('\u002E'), followed by + decimal digits representing the fractional part of + a, followed by the letter 'E' + ('\u0045'), followed by a representation + of n as a decimal integer, as produced by the + method Integer.toString(int). +
            +
          + How many digits must be printed for the fractional part of + m or a? There must be at least one digit + to represent the fractional part, and beyond that as many, but + only as many, more digits as are needed to uniquely distinguish + the argument value from adjacent values of type + float. That is, suppose that x is the + exact mathematical value represented by the decimal + representation produced by this method for a finite nonzero + argument f. Then f must be the float + value nearest to x; or, if two float values are + equally close to x, then f must be one of + them and the least significant bit of the significand of + f must be 0. +

          +
          +
          Parameters:
          +
          f - the float to be converted.
          +
          Returns:
          +
          a string representation of the argument.
          +
          +
        • +
        + + + +
          +
        • +

          str

          +
          public static java.lang.String str(double d)
          +
          Returns a string representation of the double + argument. All characters mentioned below are ASCII characters. +
            +
          • If the argument is NaN, the result is the string + "NaN". +
          • Otherwise, the result is a string that represents the sign and + magnitude (absolute value) of the argument. If the sign is negative, + the first character of the result is '-' + ('\u002D'); if the sign is positive, no sign character + appears in the result. As for the magnitude m: +
              +
            • If m is infinity, it is represented by the characters + "Infinity"; thus, positive infinity produces the result + "Infinity" and negative infinity produces the result + "-Infinity". + +
            • If m is zero, it is represented by the characters + "0.0"; thus, negative zero produces the result + "-0.0" and positive zero produces the result + "0.0". + +
            • If m is greater than or equal to 10-3 but less + than 107, then it is represented as the integer part of + m, in decimal form with no leading zeroes, followed by + '.' ('\u002E'), followed by one or + more decimal digits representing the fractional part of m. + +
            • If m is less than 10-3 or greater than or + equal to 107, then it is represented in so-called + "computerized scientific notation." Let n be the unique + integer such that 10n <= m < + 10n+1; then let a be the + mathematically exact quotient of m and + 10n so that 1 <= a < 10. The + magnitude is then represented as the integer part of a, + as a single decimal digit, followed by '.' + ('\u002E'), followed by decimal digits + representing the fractional part of a, followed by the + letter 'E' ('\u0045'), followed + by a representation of n as a decimal integer, as + produced by the method Integer.toString(int). +
            +
          + How many digits must be printed for the fractional part of + m or a? There must be at least one digit to represent + the fractional part, and beyond that as many, but only as many, more + digits as are needed to uniquely distinguish the argument value from + adjacent values of type double. That is, suppose that + x is the exact mathematical value represented by the decimal + representation produced by this method for a finite nonzero argument + d. Then d must be the double value nearest + to x; or if two double values are equally close + to x, then d must be one of them and the least + significant bit of the significand of d must be 0. +

          +
          +
          Parameters:
          +
          d - the double to be converted.
          +
          Returns:
          +
          a string representation of the argument.
          +
          +
        • +
        + + + +
          +
        • +

          newStringBuilder

          +
          public static java.lang.Appendable newStringBuilder(boolean threadSafe)
          +
          Safely creates a new instance of an appendable string buffer
          +
          +
          Parameters:
          +
          threadSafe - Specifies whether the buffer should be thread safe
          +
          Returns:
          +
          Returns either StringBuilder or StringBuffer + instance depending on whether the instance is required to be + thread safe or not, respectively.
          +
          Since:
          +
          1.2
          +
          +
        • +
        + + + +
          +
        • +

          newStringBuilder

          +
          public static java.lang.Appendable newStringBuilder()
          +
          Safely creates a new instance of an appendable string buffer
          + The buffer will not be thread safe.
          +
          +
          Returns:
          +
          Returns a new instance of StringBuilder class
          +
          Since:
          +
          1.2
          +
          +
        • +
        + + + +
          +
        • +

          append

          +
          public static java.lang.Appendable append(java.lang.Appendable buffer,
          +                                          java.lang.String strToAppend)
          +
          Appends a string to an appendable buffer created by newStringBuilder()
          +
          +
          Parameters:
          +
          buffer - The appendable buffer to append to
          +
          strToAppend - The string to append
          +
          Returns:
          +
          Returns the same appendable buffer instance
          +
          Since:
          +
          1.2
          +
          +
        • +
        + + + +
          +
        • +

          length

          +
          public static int length(java.lang.Appendable buffer)
          +
          Checks the length of an appendable buffer created by newStringBuilder()
          +
          +
          Parameters:
          +
          buffer - The appendable buffer instance
          +
          Returns:
          +
          Returns the length of the text contained by the buffer
          +
          Since:
          +
          1.2
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Sys.Env.html b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Sys.Env.html new file mode 100644 index 00000000..33ce414b --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Sys.Env.html @@ -0,0 +1,414 @@ + + + + + +BTraceUtils.Sys.Env (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class BTraceUtils.Sys.Env

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.BTraceUtils.Sys.Env
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing class:
      +
      BTraceUtils.Sys
      +
      +
      +
      +
      public static class BTraceUtils.Sys.Env
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        Env() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static longavailableProcessors() +
        Returns the number of processors available to the Java virtual machine.
        +
        static java.util.Map<java.lang.String,java.lang.String>getenv() +
        Returns an unmodifiable string map view of the current system environment.
        +
        static java.lang.Stringgetenv(java.lang.String name) +
        Gets the value of the specified environment variable.
        +
        static voidprintEnv() +
        Prints all system environment values.
        +
        static voidprintProperties() +
        Prints all Sys properties.
        +
        static java.util.Propertiesproperties() +
        Returns all Sys properties.
        +
        static java.lang.Stringproperty(java.lang.String key) +
        Gets the system property indicated by the specified key.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Env

          +
          public Env()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          property

          +
          public static java.lang.String property(java.lang.String key)
          +
          Gets the system property indicated by the specified key.
          +
          +
          Parameters:
          +
          key - the name of the system property.
          +
          Returns:
          +
          the string value of the system property, + or null if there is no property with that key.
          +
          Throws:
          +
          java.lang.NullPointerException - if key is + null.
          +
          java.lang.IllegalArgumentException - if key is empty.
          +
          +
        • +
        + + + +
          +
        • +

          properties

          +
          public static java.util.Properties properties()
          +
          Returns all Sys properties.
          +
          +
          Returns:
          +
          the system properties
          +
          +
        • +
        + + + +
          +
        • +

          printProperties

          +
          public static void printProperties()
          +
          Prints all Sys properties.
          +
        • +
        + + + +
          +
        • +

          getenv

          +
          public static java.lang.String getenv(java.lang.String name)
          +
          Gets the value of the specified environment variable. An + environment variable is a system-dependent external named + value.
          +
          +
          Parameters:
          +
          name - the name of the environment variable
          +
          Returns:
          +
          the string value of the variable, or null + if the variable is not defined in the system environment
          +
          Throws:
          +
          java.lang.NullPointerException - if name is null
          +
          +
        • +
        + + + +
          +
        • +

          getenv

          +
          public static java.util.Map<java.lang.String,java.lang.String> getenv()
          +
          Returns an unmodifiable string map view of the current system environment. + The environment is a system-dependent mapping from names to + values which is passed from parent to child processes.
          +
          +
          Returns:
          +
          the environment as a map of variable names to values
          +
          +
        • +
        + + + +
          +
        • +

          printEnv

          +
          public static void printEnv()
          +
          Prints all system environment values.
          +
        • +
        + + + +
          +
        • +

          availableProcessors

          +
          public static long availableProcessors()
          +
          Returns the number of processors available to the Java virtual machine. +

          + This value may change during a particular invocation of the virtual + machine. Applications that are sensitive to the number of available + processors should therefore occasionally poll this property and adjust + their resource usage appropriately.

          +
          +
          Returns:
          +
          the maximum number of processors available to the virtual + machine; never smaller than one
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Sys.Memory.html b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Sys.Memory.html new file mode 100644 index 00000000..df7bbe8b --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Sys.Memory.html @@ -0,0 +1,608 @@ + + + + + +BTraceUtils.Sys.Memory (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class BTraceUtils.Sys.Memory

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.BTraceUtils.Sys.Memory
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing class:
      +
      BTraceUtils.Sys
      +
      +
      +
      +
      public static class BTraceUtils.Sys.Memory
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        Memory() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static longcommitted(java.lang.management.MemoryUsage mu) +
        Returns the amount of memory in bytes that is committed for the Java + virtual machine to use.
        +
        static voiddumpHeap(java.lang.String fileName) +
        Dump the snapshot of the Java heap to a file in hprof + binary format.
        +
        static voiddumpHeap(java.lang.String fileName, + boolean live) +
        Dump the snapshot of the Java heap to a file in hprof + binary format.
        +
        static longfinalizationCount() +
        Returns the approximate number of objects for + which finalization is pending.
        +
        static longfreeMemory() +
        Returns the amount of free memory in the Java Virtual Machine.
        +
        static voidgc() +
        Runs the garbage collector.
        +
        static java.lang.StringgetMemoryPoolUsage(java.lang.String poolFormat) +
        Returns an overview of available memory pools
        + It is possible to provide a text format the overview will use
        +
        static longgetTotalGcTime() +
        Returns the total amount of time spent in GarbageCollection up to this point + since the application was started.
        +
        static java.lang.management.MemoryUsageheapUsage() +
        Returns heap memory usage
        +
        static longinit(java.lang.management.MemoryUsage mu) +
        Returns the amount of memory in bytes that the Java virtual + machine initially requests from the operating system for + memory management.
        +
        static longmax(java.lang.management.MemoryUsage mu) +
        Returns the maximum amount of memory in bytes that can be used + for memory management.
        +
        static longmaxMemory() +
        Returns the maximum amount of memory that the Java virtual machine will + attempt to use.
        +
        static java.lang.management.MemoryUsagenonHeapUsage() +
        Returns non-heap memory usage
        +
        static voidrunFinalization() +
        Runs the finalization methods of any objects pending finalization.
        +
        static longtotalMemory() +
        Returns the total amount of memory in the Java virtual machine.
        +
        static longused(java.lang.management.MemoryUsage mu) +
        Returns the amount of used memory in bytes.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Memory

          +
          public Memory()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          freeMemory

          +
          public static long freeMemory()
          +
          Returns the amount of free memory in the Java Virtual Machine. + Calling the + gc method may result in increasing the value returned + by freeMemory.
          +
          +
          Returns:
          +
          an approximation to the total amount of memory currently + available for future allocated objects, measured in bytes.
          +
          +
        • +
        + + + +
          +
        • +

          totalMemory

          +
          public static long totalMemory()
          +
          Returns the total amount of memory in the Java virtual machine. + The value returned by this method may vary over time, depending on + the host environment. +

          + Note that the amount of memory required to hold an object of any + given type may be implementation-dependent.

          +
          +
          Returns:
          +
          the total amount of memory currently available for current + and future objects, measured in bytes.
          +
          +
        • +
        + + + +
          +
        • +

          maxMemory

          +
          public static long maxMemory()
          +
          Returns the maximum amount of memory that the Java virtual machine will + attempt to use. If there is no inherent limit then the value Long.MAX_VALUE will be returned.
          +
          +
          Returns:
          +
          the maximum amount of memory that the virtual machine will + attempt to use, measured in bytes
          +
          +
        • +
        + + + +
          +
        • +

          heapUsage

          +
          public static java.lang.management.MemoryUsage heapUsage()
          +
          Returns heap memory usage
          +
        • +
        + + + +
          +
        • +

          nonHeapUsage

          +
          public static java.lang.management.MemoryUsage nonHeapUsage()
          +
          Returns non-heap memory usage
          +
        • +
        + + + +
          +
        • +

          init

          +
          public static long init(java.lang.management.MemoryUsage mu)
          +
          Returns the amount of memory in bytes that the Java virtual + machine initially requests from the operating system for + memory management.
          +
        • +
        + + + +
          +
        • +

          committed

          +
          public static long committed(java.lang.management.MemoryUsage mu)
          +
          Returns the amount of memory in bytes that is committed for the Java + virtual machine to use. This amount of memory is guaranteed for the + Java virtual machine to use.
          +
        • +
        + + + +
          +
        • +

          max

          +
          public static long max(java.lang.management.MemoryUsage mu)
          +
          Returns the maximum amount of memory in bytes that can be used + for memory management. This method returns -1 if the maximum memory + size is undefined.
          +
        • +
        + + + +
          +
        • +

          used

          +
          public static long used(java.lang.management.MemoryUsage mu)
          +
          Returns the amount of used memory in bytes.
          +
        • +
        + + + +
          +
        • +

          finalizationCount

          +
          public static long finalizationCount()
          +
          Returns the approximate number of objects for + which finalization is pending.
          +
        • +
        + + + +
          +
        • +

          dumpHeap

          +
          public static void dumpHeap(java.lang.String fileName)
          +
          Dump the snapshot of the Java heap to a file in hprof + binary format. Only the live objects are dumped. + Under the current dir of traced app, ./btrace<pid>/<btrace-class>/ + directory is created. Under that directory, a file of given + fileName is created.
          +
          +
          Parameters:
          +
          fileName - name of the file to which heap is dumped
          +
          +
        • +
        + + + +
          +
        • +

          dumpHeap

          +
          public static void dumpHeap(java.lang.String fileName,
          +                            boolean live)
          +
          Dump the snapshot of the Java heap to a file in hprof + binary format. + Under the current dir of traced app, ./btrace<pid>/<btrace-class>/ + directory is created. Under that directory, a file of given + fileName is created.
          +
          +
          Parameters:
          +
          fileName - name of the file to which heap is dumped
          +
          live - flag that tells whether only live objects are + to be dumped or all objects are to be dumped.
          +
          +
        • +
        + + + +
          +
        • +

          gc

          +
          public static void gc()
          +
          Runs the garbage collector. +

          + Calling the gc method suggests that the Java Virtual + Machine expend effort toward recycling unused objects in order to + make the memory they currently occupy available for quick reuse. + When control returns from the method call, the Java Virtual + Machine has made a best effort to reclaim space from all discarded + objects. This method calls Sys.gc() to perform GC.

          +
        • +
        + + + +
          +
        • +

          getTotalGcTime

          +
          public static long getTotalGcTime()
          +
          Returns the total amount of time spent in GarbageCollection up to this point + since the application was started.
          +
          +
          Returns:
          +
          Returns the amount of overall time spent in GC
          +
          +
        • +
        + + + +
          +
        • +

          getMemoryPoolUsage

          +
          public static java.lang.String getMemoryPoolUsage(java.lang.String poolFormat)
          +
          Returns an overview of available memory pools
          + It is possible to provide a text format the overview will use
          +
          +
          Parameters:
          +
          poolFormat - The text format string to format the overview.
          + Exactly 5 arguments are passed to the format function.
          + The format defaults to ";%1$s;%2$d;%3$d;%4$d;%5$d;Memory]"
          +
          Returns:
          +
          Returns the formatted value of memory pools overview
          +
          Since:
          +
          1.2
          +
          +
        • +
        + + + +
          +
        • +

          runFinalization

          +
          public static void runFinalization()
          +
          Runs the finalization methods of any objects pending finalization. +

          + Calling this method suggests that the Java Virtual Machine expend + effort toward running the finalize methods of objects + that have been found to be discarded but whose finalize + methods have not yet been run. When control returns from the + method call, the Java Virtual Machine has made a best effort to + complete all outstanding finalizations. This method calls + Sys.runFinalization() to run finalization.

          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Sys.VM.html b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Sys.VM.html new file mode 100644 index 00000000..743c735f --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Sys.VM.html @@ -0,0 +1,653 @@ + + + + + +BTraceUtils.Sys.VM (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class BTraceUtils.Sys.VM

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.BTraceUtils.Sys.VM
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing class:
      +
      BTraceUtils.Sys
      +
      +
      +
      +
      public static class BTraceUtils.Sys.VM
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        VM() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static java.lang.StringbootClassPath() +
        Returns the boot class path that is used by the bootstrap class loader + to search for class files.
        +
        static java.lang.StringclassPath() +
        Returns the Java class path that is used by the system class loader + to search for class files.
        +
        static longcurrentThreadCpuTime() +
        Returns the total CPU time for the current thread in nanoseconds.
        +
        static longcurrentThreadUserTime() +
        Returns the CPU time that the current thread has executed + in user mode in nanoseconds.
        +
        static longdaemonThreadCount() +
        Returns the current number of live daemon threads.
        +
        static booleanisBootClassPathSupported() +
        Tests if the Java virtual machine supports the boot class path + mechanism used by the bootstrap class loader to search for class + files.
        +
        static java.lang.StringlibraryPath() +
        Returns the Java library path.
        +
        static longpeakThreadCount() +
        Returns the peak live thread count since the Java virtual machine + started or peak was reset.
        +
        static voidprintVmArguments() +
        Prints VM input arguments list.
        +
        static longprocessCPUTime() +
        Returns the CPU time used by the process on which the Java virtual machine is running in nanoseconds.
        +
        static doublesystemLoadAverage() +
        Returns the system load average for the last minute
        +
        static longthreadCount() +
        Returns the current number of live threads including both + daemon and non-daemon threads.
        +
        static longtotalStartedThreadCount() +
        Returns the total number of threads created and also started + since the Java virtual machine started.
        +
        static java.util.List<java.lang.String>vmArguments() +
        Returns the input arguments passed to the Java virtual machine + which does not include the arguments to the main method.
        +
        static longvmStartTime() +
        Returns the start time of the Java virtual machine in milliseconds.
        +
        static longvmUptime() +
        Returns the uptime of the Java virtual machine in milliseconds.
        +
        static java.lang.StringvmVersion() +
        Returns the Java virtual machine implementation version.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          VM

          +
          public VM()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          vmArguments

          +
          public static java.util.List<java.lang.String> vmArguments()
          +
          Returns the input arguments passed to the Java virtual machine + which does not include the arguments to the main method. + This method returns an empty list if there is no input argument + to the Java virtual machine. +

          + Some Java virtual machine implementations may take input arguments + from multiple different sources: for examples, arguments passed from + the application that launches the Java virtual machine such as + the 'java' command, environment variables, configuration files, etc. +

          + Typically, not all command-line options to the 'java' command + are passed to the Java virtual machine. + Thus, the returned input arguments may not + include all command-line options.

          +
          +
          Returns:
          +
          a list of String objects; each element + is an argument passed to the Java virtual machine.
          +
          +
        • +
        + + + +
          +
        • +

          printVmArguments

          +
          public static void printVmArguments()
          +
          Prints VM input arguments list.
          +
          +
          See Also:
          +
          vmArguments()
          +
          +
        • +
        + + + +
          +
        • +

          vmVersion

          +
          public static java.lang.String vmVersion()
          +
          Returns the Java virtual machine implementation version. + This method is equivalent to Sys.getProperty("java.vm.version")}.
          +
          +
          Returns:
          +
          the Java virtual machine implementation version.
          +
          +
        • +
        + + + +
          +
        • +

          isBootClassPathSupported

          +
          public static boolean isBootClassPathSupported()
          +
          Tests if the Java virtual machine supports the boot class path + mechanism used by the bootstrap class loader to search for class + files.
          +
          +
          Returns:
          +
          true if the Java virtual machine supports the + class path mechanism; false otherwise.
          +
          +
        • +
        + + + +
          +
        • +

          bootClassPath

          +
          public static java.lang.String bootClassPath()
          +
          Returns the boot class path that is used by the bootstrap class loader + to search for class files. + +

          Multiple paths in the boot class path are separated by the + path separator character of the platform on which the Java + virtual machine is running. + +

          A Java virtual machine implementation may not support + the boot class path mechanism for the bootstrap class loader + to search for class files. + The isBootClassPathSupported() method can be used + to determine if the Java virtual machine supports this method.

          +
          +
          Returns:
          +
          the boot class path.
          +
          Throws:
          +
          java.lang.UnsupportedOperationException - if the Java virtual machine does not support this operation.
          +
          +
        • +
        + + + +
          +
        • +

          classPath

          +
          public static java.lang.String classPath()
          +
          Returns the Java class path that is used by the system class loader + to search for class files. + This method is equivalent to Sys.getProperty("java.class.path").
          +
          +
          Returns:
          +
          the Java class path.
          +
          +
        • +
        + + + +
          +
        • +

          libraryPath

          +
          public static java.lang.String libraryPath()
          +
          Returns the Java library path. + This method is equivalent to Sys.getProperty("java.library.path"). + +

          Multiple paths in the Java library path are separated by the + path separator character of the platform of the Java virtual machine + being monitored.

          +
          +
          Returns:
          +
          the Java library path.
          +
          +
        • +
        + + + +
          +
        • +

          threadCount

          +
          public static long threadCount()
          +
          Returns the current number of live threads including both + daemon and non-daemon threads.
          +
          +
          Returns:
          +
          the current number of live threads.
          +
          +
        • +
        + + + +
          +
        • +

          peakThreadCount

          +
          public static long peakThreadCount()
          +
          Returns the peak live thread count since the Java virtual machine + started or peak was reset.
          +
          +
          Returns:
          +
          the peak live thread count.
          +
          +
        • +
        + + + +
          +
        • +

          totalStartedThreadCount

          +
          public static long totalStartedThreadCount()
          +
          Returns the total number of threads created and also started + since the Java virtual machine started.
          +
          +
          Returns:
          +
          the total number of threads started.
          +
          +
        • +
        + + + +
          +
        • +

          daemonThreadCount

          +
          public static long daemonThreadCount()
          +
          Returns the current number of live daemon threads.
          +
          +
          Returns:
          +
          the current number of live daemon threads.
          +
          +
        • +
        + + + +
          +
        • +

          systemLoadAverage

          +
          public static double systemLoadAverage()
          +
          Returns the system load average for the last minute
          +
          +
          Returns:
          +
          the system load average for the last minute
          +
          +
        • +
        + + + +
          +
        • +

          processCPUTime

          +
          public static long processCPUTime()
          +
          Returns the CPU time used by the process on which the Java virtual machine is running in nanoseconds.
          +
          +
          Returns:
          +
          the CPU time used by the process on which the JVM is running in nanoseconds. Returns -1 if + this operation is not supported on this platform
          +
          +
        • +
        + + + +
          +
        • +

          vmStartTime

          +
          public static long vmStartTime()
          +
          Returns the start time of the Java virtual machine in milliseconds. + This method returns the approximate time when the Java virtual + machine started.
          +
          +
          Returns:
          +
          start time of the Java virtual machine in milliseconds.
          +
          +
        • +
        + + + +
          +
        • +

          vmUptime

          +
          public static long vmUptime()
          +
          Returns the uptime of the Java virtual machine in milliseconds.
          +
          +
          Returns:
          +
          uptime of the Java virtual machine in milliseconds.
          +
          +
        • +
        + + + +
          +
        • +

          currentThreadCpuTime

          +
          public static long currentThreadCpuTime()
          +
          Returns the total CPU time for the current thread in nanoseconds. + The returned value is of nanoseconds precision but + not necessarily nanoseconds accuracy. + If the implementation distinguishes between user mode time and system + mode time, the returned CPU time is the amount of time that + the current thread has executed in user mode or system mode.
          +
        • +
        + + + +
          +
        • +

          currentThreadUserTime

          +
          public static long currentThreadUserTime()
          +
          Returns the CPU time that the current thread has executed + in user mode in nanoseconds. + The returned value is of nanoseconds precision but + not necessarily nanoseconds accuracy.
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Sys.html b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Sys.html new file mode 100644 index 00000000..786ff9d1 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Sys.html @@ -0,0 +1,413 @@ + + + + + +BTraceUtils.Sys (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class BTraceUtils.Sys

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.BTraceUtils.Sys
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing class:
      +
      BTraceUtils
      +
      +
      +
      +
      public static class BTraceUtils.Sys
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + + + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        Sys() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static java.lang.String$(int n) +
        Returns n'th command line argument.
        +
        static java.lang.String$(java.lang.String key) +
        Returns a command line argument value for the given key.
        +
        static int$length() +
        Returns the number of command line arguments.
        +
        static voidexit() +
        This is same as exit(int) except that the exit code + is zero.
        +
        static voidexit(int exitCode) +
        Exits the BTrace session -- note that the particular client's tracing + session exits and not the observed/traced program! After exit call, + the trace action method terminates immediately and no other probe action + method (of that client) will be called after that.
        +
        static intgetpid() +
        Returns the process id of the currently BTrace'd process.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Sys

          +
          public Sys()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          $

          +
          public static java.lang.String $(int n)
          +
          Returns n'th command line argument. null if not available.
          +
          +
          Parameters:
          +
          n - command line argument index
          +
          Returns:
          +
          n'th command line argument or null if out-of-range
          +
          +
        • +
        + + + +
          +
        • +

          $

          +
          public static java.lang.String $(java.lang.String key)
          +
          Returns a command line argument value for the given key. null if not available.
          + In order to provide a key-value pair on the command line it must have the following syntax - + <key>=<value>
          +
          +
          Parameters:
          +
          key - the argument key
          +
          Returns:
          +
          the corresponding value or null
          +
          +
        • +
        + + + +
          +
        • +

          getpid

          +
          public static int getpid()
          +
          Returns the process id of the currently BTrace'd process.
          +
        • +
        + + + +
          +
        • +

          $length

          +
          public static int $length()
          +
          Returns the number of command line arguments.
          +
        • +
        + + + +
          +
        • +

          exit

          +
          public static void exit(int exitCode)
          +
          Exits the BTrace session -- note that the particular client's tracing + session exits and not the observed/traced program! After exit call, + the trace action method terminates immediately and no other probe action + method (of that client) will be called after that.
          +
          +
          Parameters:
          +
          exitCode - exit value sent to the client
          +
          +
        • +
        + + + +
          +
        • +

          exit

          +
          public static void exit()
          +
          This is same as exit(int) except that the exit code + is zero.
          +
          +
          See Also:
          +
          exit(int)
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Threads.html b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Threads.html new file mode 100644 index 00000000..93aa2d94 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Threads.html @@ -0,0 +1,688 @@ + + + + + +BTraceUtils.Threads (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class BTraceUtils.Threads

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.BTraceUtils.Threads
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing class:
      +
      BTraceUtils
      +
      +
      +
      +
      public static class BTraceUtils.Threads
      +extends java.lang.Object
      +
      Namespaced methods
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        Threads() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static java.lang.ThreadcurrentThread() +
        Returns a reference to the currently executing thread object.
        +
        static voiddeadlocks() +
        Prints the Java level deadlocks detected (if any).
        +
        static voiddeadlocks(boolean stackTrace) +
        Prints deadlocks detected (if any).
        +
        static booleanholdsLock(java.lang.Object obj) +
        Returns true if and only if the current thread holds the + monitor lock on the specified object.
        +
        static booleanisInteruppted() +
        Tests whether this thread has been interrupted.
        +
        static voidjstack() +
        Prints the java stack trace of the current thread.
        +
        static voidjstack(int numFrames) +
        Prints the java stack trace of the current thread.
        +
        static voidjstack(java.lang.Throwable exception) +
        Prints the stack trace of the given exception object.
        +
        static voidjstack(java.lang.Throwable exception, + int numFrames) +
        Prints the stack trace of the given exception object.
        +
        static voidjstackAll() +
        Prints Java stack traces of all the Java threads.
        +
        static voidjstackAll(int numFrames) +
        Prints Java stack traces of all the Java threads.
        +
        static java.lang.StringjstackAllStr() +
        Returns the stack traces of all Java threads as a String.
        +
        static java.lang.StringjstackAllStr(int numFrames) +
        Returns atmost given number of frames in stack traces + of all threads as a String.
        +
        static java.lang.StringjstackStr() +
        Returns the stack trace of current thread as a String.
        +
        static java.lang.StringjstackStr(int numFrames) +
        Returns the stack trace of the current thread as a String + but includes atmost the given number of frames.
        +
        static java.lang.StringjstackStr(java.lang.Throwable exception) +
        Returns the stack trace of given exception object as a String.
        +
        static java.lang.StringjstackStr(java.lang.Throwable exception, + int numFrames) +
        Returns stack trace of given exception object as a String.
        +
        static java.lang.Stringname(java.lang.Thread thread) +
        Returns the name of the given thread.
        +
        static longthreadId(java.lang.Thread thread) +
        Returns the identifier of the given Thread.
        +
        static java.lang.Thread.StatethreadState(java.lang.Thread thread) +
        Returns the state of the given thread.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Threads

          +
          public Threads()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          isInteruppted

          +
          public static boolean isInteruppted()
          +
          Tests whether this thread has been interrupted. The interrupted + status of the thread is unaffected by this method. + +

          A thread interruption ignored because a thread was not alive + at the time of the interrupt will be reflected by this method + returning false.

          +
          +
          Returns:
          +
          true if this thread has been interrupted; + false otherwise.
          +
          +
        • +
        + + + +
          +
        • +

          jstack

          +
          public static void jstack()
          +
          Prints the java stack trace of the current thread.
          +
        • +
        + + + +
          +
        • +

          jstack

          +
          public static void jstack(int numFrames)
          +
          Prints the java stack trace of the current thread. But, + atmost given number of frames.
          +
          +
          Parameters:
          +
          numFrames - number of frames to be printed. When this is + negative all frames are printed.
          +
          +
        • +
        + + + +
          +
        • +

          jstackAll

          +
          public static void jstackAll()
          +
          Prints Java stack traces of all the Java threads.
          +
        • +
        + + + +
          +
        • +

          jstackAll

          +
          public static void jstackAll(int numFrames)
          +
          Prints Java stack traces of all the Java threads. But, + atmost given number of frames.
          +
          +
          Parameters:
          +
          numFrames - number of frames to be printed. When this is + negative all frames are printed.
          +
          +
        • +
        + + + +
          +
        • +

          jstackStr

          +
          public static java.lang.String jstackStr()
          +
          Returns the stack trace of current thread as a String.
          +
          +
          Returns:
          +
          the stack trace as a String.
          +
          +
        • +
        + + + +
          +
        • +

          jstackStr

          +
          public static java.lang.String jstackStr(int numFrames)
          +
          Returns the stack trace of the current thread as a String + but includes atmost the given number of frames.
          +
          +
          Parameters:
          +
          numFrames - number of frames to be included. When this is + negative all frames are included.
          +
          Returns:
          +
          the stack trace as a String.
          +
          +
        • +
        + + + +
          +
        • +

          jstackAllStr

          +
          public static java.lang.String jstackAllStr()
          +
          Returns the stack traces of all Java threads as a String.
          +
          +
          Returns:
          +
          the stack traces as a String.
          +
          +
        • +
        + + + +
          +
        • +

          jstackAllStr

          +
          public static java.lang.String jstackAllStr(int numFrames)
          +
          Returns atmost given number of frames in stack traces + of all threads as a String.
          +
          +
          Parameters:
          +
          numFrames - number of frames to be included. When this is + negative all frames are included.
          +
          Returns:
          +
          the stack traces as a String.
          +
          +
        • +
        + + + +
          +
        • +

          jstack

          +
          public static void jstack(java.lang.Throwable exception)
          +
          Prints the stack trace of the given exception object.
          +
          +
          Parameters:
          +
          exception - throwable for which stack trace is printed.
          +
          +
        • +
        + + + +
          +
        • +

          jstack

          +
          public static void jstack(java.lang.Throwable exception,
          +                          int numFrames)
          +
          Prints the stack trace of the given exception object. But, + prints atmost given number of frames.
          +
          +
          Parameters:
          +
          exception - throwable for which stack trace is printed.
          +
          numFrames - maximum number of frames to be printed.
          +
          +
        • +
        + + + +
          +
        • +

          jstackStr

          +
          public static java.lang.String jstackStr(java.lang.Throwable exception)
          +
          Returns the stack trace of given exception object as a String.
          +
          +
          Parameters:
          +
          exception - the throwable for which stack trace is returned.
          +
          +
        • +
        + + + +
          +
        • +

          jstackStr

          +
          public static java.lang.String jstackStr(java.lang.Throwable exception,
          +                                         int numFrames)
          +
          Returns stack trace of given exception object as a String.
          +
          +
          Parameters:
          +
          exception - throwable for which stack trace is returned.
          +
          numFrames - maximum number of frames to be returned.
          +
          +
        • +
        + + + +
          +
        • +

          currentThread

          +
          public static java.lang.Thread currentThread()
          +
          Returns a reference to the currently executing thread object.
          +
          +
          Returns:
          +
          the currently executing thread.
          +
          +
        • +
        + + + +
          +
        • +

          threadId

          +
          public static long threadId(java.lang.Thread thread)
          +
          Returns the identifier of the given Thread. The thread ID is a positive + long number generated when the given thread was created. + The thread ID is unique and remains unchanged during its lifetime. + When a thread is terminated, the thread ID may be reused.
          +
        • +
        + + + +
          +
        • +

          threadState

          +
          public static java.lang.Thread.State threadState(java.lang.Thread thread)
          +
          Returns the state of the given thread. + This method is designed for use in monitoring of the system state, + not for synchronization control.
          +
        • +
        + + + +
          +
        • +

          holdsLock

          +
          public static boolean holdsLock(java.lang.Object obj)
          +
          Returns true if and only if the current thread holds the + monitor lock on the specified object. + +

          This method is designed to allow a program to assert that + the current thread already holds a specified lock: +

          +     assert Thread.holdsLock(obj);
          + 
          +
          +
          Parameters:
          +
          obj - the object on which to test lock ownership
          +
          Returns:
          +
          true if the current thread holds the monitor lock on + the specified object.
          +
          Throws:
          +
          java.lang.NullPointerException - if obj is null
          +
          +
        • +
        + + + +
          +
        • +

          deadlocks

          +
          public static void deadlocks()
          +
          Prints the Java level deadlocks detected (if any).
          +
        • +
        + + + +
          +
        • +

          deadlocks

          +
          public static void deadlocks(boolean stackTrace)
          +
          Prints deadlocks detected (if any). Optionally prints + stack trace of the deadlocked threads.
          +
          +
          Parameters:
          +
          stackTrace - boolean flag to specify whether to + print stack traces of deadlocked threads or not.
          +
          +
        • +
        + + + +
          +
        • +

          name

          +
          public static java.lang.String name(java.lang.Thread thread)
          +
          Returns the name of the given thread.
          +
          +
          Parameters:
          +
          thread - thread whose name is returned
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Time.html b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Time.html new file mode 100644 index 00000000..42e2fa10 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.Time.html @@ -0,0 +1,365 @@ + + + + + +BTraceUtils.Time (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class BTraceUtils.Time

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.BTraceUtils.Time
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing class:
      +
      BTraceUtils
      +
      +
      +
      +
      public static class BTraceUtils.Time
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        Time() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static longmillis() +
        Returns the current time in milliseconds.
        +
        static longnanos() +
        Returns the current value of the most precise available system + timer, in nanoseconds.
        +
        static java.lang.Stringtimestamp() +
        Generates a string timestamp (current date&time) in the default system format
        +
        static java.lang.Stringtimestamp(java.lang.String format) +
        Generates a string timestamp (current date&time)
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Time

          +
          public Time()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          millis

          +
          public static long millis()
          +
          Returns the current time in milliseconds. Note that + while the unit of time of the return value is a millisecond, + the granularity of the value depends on the underlying + operating system and may be larger. For example, many + operating systems measure time in units of tens of + milliseconds.
          +
          +
          Returns:
          +
          the difference, measured in milliseconds, between + the current time and midnight, January 1, 1970 UTC.
          +
          +
        • +
        + + + +
          +
        • +

          nanos

          +
          public static long nanos()
          +
          Returns the current value of the most precise available system + timer, in nanoseconds. + +

          This method can only be used to measure elapsed time and is + not related to any other notion of system or wall-clock time. + The value returned represents nanoseconds since some fixed but + arbitrary time (perhaps in the future, so values may be + negative). This method provides nanosecond precision, but not + necessarily nanosecond accuracy. No guarantees are made about + how frequently values change. Differences in successive calls + that span greater than approximately 292 years (263 + nanoseconds) will not accurately compute elapsed time due to + numerical overflow.

          +
          +
          Returns:
          +
          The current value of the system timer, in nanoseconds.
          +
          +
        • +
        + + + +
          +
        • +

          timestamp

          +
          public static java.lang.String timestamp(java.lang.String format)
          +

          Generates a string timestamp (current date&time)

          +
          +
          Parameters:
          +
          format - The format to be used - see SimpleDateFormat
          +
          Returns:
          +
          Returns a string representing current date&time
          +
          Since:
          +
          1.1
          +
          +
        • +
        + + + +
          +
        • +

          timestamp

          +
          public static java.lang.String timestamp()
          +

          Generates a string timestamp (current date&time) in the default system format

          +
          +
          Returns:
          +
          Returns a string representing current date&time
          +
          Since:
          +
          1.1
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.html b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.html new file mode 100644 index 00000000..a26f47fb --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/BTraceUtils.html @@ -0,0 +1,6954 @@ + + + + + +BTraceUtils (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class BTraceUtils

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.BTraceUtils
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public class BTraceUtils
      +extends java.lang.Object
      +
      This class is an all-in-one wrapper for BTrace DSL methods
      +
    • +
    +
    +
    +
      +
    • + + + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods Deprecated Methods 
        Modifier and TypeMethod and Description
        static java.lang.String$(int n) +
        Returns n'th command line argument.
        +
        static java.lang.String$(java.lang.String key) +
        Returns a command line argument value for the given key.
        +
        static int$length() +
        Returns the number of command line arguments.
        +
        static intaccessFlags(java.lang.Class clazz) +
        Returns the access flags of the given Class.
        +
        static intaccessFlags(java.lang.reflect.Field field) +
        Returns the access flags of the given Field.
        +
        static intaddAndGet(java.util.concurrent.atomic.AtomicInteger ai, + int delta) +
        Atomically adds the given value to the current value.
        +
        static longaddAndGet(java.util.concurrent.atomic.AtomicLong al, + long delta) +
        Atomically adds the given value to the current value.
        +
        static <V> voidaddLast(java.util.Deque<V> queue, + V value) 
        static voidaddToAggregation(Aggregation aggregation, + AggregationKey key, + long value) +
        Adds a value to the aggregation with a grouping key.
        +
        static voidaddToAggregation(Aggregation aggregation, + long value) +
        Adds a value to the aggregation with no grouping key.
        +
        static longavailableProcessors() +
        Returns the number of processors available to the Java virtual machine.
        +
        static java.lang.StringbootClassPath() +
        Returns the boot class path that is used by the bootstrap class loader + to search for class files.
        +
        static java.lang.Booleanbox(boolean b) +
        Returns a Boolean instance representing the specified + boolean value.
        +
        static java.lang.Bytebox(byte b) +
        Returns a Byte instance representing the specified + byte value.
        +
        static java.lang.Characterbox(char c) +
        Returns a Character instance representing the specified + char value.
        +
        static java.lang.Doublebox(double d) +
        Returns a Double instance representing the specified + double value.
        +
        static java.lang.Floatbox(float f) +
        Returns a Float instance representing the specified + float value.
        +
        static java.lang.Integerbox(int i) +
        Returns a Integer instance representing the specified + int value.
        +
        static java.lang.Longbox(long l) +
        Returns a Long instance representing the specified + long value.
        +
        static java.lang.Shortbox(short s) +
        Returns a Short instance representing the specified + short value.
        +
        static java.lang.ClassclassForName(java.lang.String name) +
        Returns Class object for given class name.
        +
        static java.lang.ClassclassForName(java.lang.String name, + java.lang.ClassLoader cl) +
        Returns the Class for the given class name + using the given class loader.
        +
        static java.lang.ClassclassOf(java.lang.Object obj) +
        Returns the runtime class of the given Object.
        +
        static java.lang.StringclassPath() +
        Returns the Java class path that is used by the system class loader + to search for class files.
        +
        static <K,V> voidclear(java.util.Map<K,V> map) 
        static voidclearAggregation(Aggregation aggregation) +
        Resets values within the aggregation to the default.
        +
        static voidcommit(int id) +
        Commits the speculative buffer associated with id.
        +
        static longcommitted(java.lang.management.MemoryUsage mu) +
        Returns the amount of memory in bytes that is committed for the Java + virtual machine to use.
        +
        static booleancompare(java.lang.Object obj1, + java.lang.Object obj2) +
        Indicates whether two given objects are "equal to" one another.
        +
        static booleancompareAndSet(java.util.concurrent.atomic.AtomicInteger ai, + int expect, + int update) +
        Atomically sets the value of given AtomitInteger to the given + updated value if the current value == the expected value.
        +
        static booleancompareAndSet(java.util.concurrent.atomic.AtomicLong al, + long expect, + long update) +
        Atomically sets the value to the given updated value + if the current value == the expected value.
        +
        static intcompareTo(java.lang.String str1, + java.lang.String str2) +
        Compares two strings lexicographically.
        +
        static intcompareToIgnoreCase(java.lang.String str1, + java.lang.String str2) +
        Compares two strings lexicographically, ignoring case + differences.
        +
        static java.lang.Stringconcat(java.lang.String str1, + java.lang.String str2) +
        Concatenates the specified strings together.
        +
        static <E> booleancontains(java.util.Collection<E> coll, + java.lang.Object obj) 
        static booleancontains(java.lang.Object[] array, + java.lang.Object value) 
        static <K,V> booleancontainsKey(java.util.Map<K,V> map, + K key) 
        static <K,V> booleancontainsValue(java.util.Map<K,V> map, + V value) 
        static java.lang.ClassLoadercontextClassLoader() +
        Returns the current context class loader
        +
        static java.lang.ThreadcurrentThread() +
        Returns a reference to the currently executing thread object.
        +
        static longcurrentThreadCpuTime() +
        Returns the total CPU time for the current thread in nanoseconds.
        +
        static longcurrentThreadUserTime() +
        Returns the CPU time that the current thread has executed + in user mode in nanoseconds.
        +
        static longdaemonThreadCount() +
        Returns the current number of live daemon threads.
        +
        static voiddeadlocks() +
        Prints the Java level deadlocks detected (if any).
        +
        static voiddeadlocks(boolean stackTrace) +
        Prints deadlocks detected (if any).
        +
        static java.lang.ClassdeclaringClass(java.lang.reflect.Field field) +
        Returns the Class object representing the class or interface + that declares the field represented by the given Field object.
        +
        static intdecrementAndGet(java.util.concurrent.atomic.AtomicInteger ai) +
        Atomically decrements by one the current value of given AtomicInteger.
        +
        static longdecrementAndGet(java.util.concurrent.atomic.AtomicLong al) +
        Atomically decrements by one the current value.
        +
        static java.lang.Objectderef(java.lang.ref.Reference ref) +
        Returns the given reference object's referent.
        +
        static voiddiscard(int id) +
        Discards the speculative buffer associated with id.
        +
        static intdtraceProbe(java.lang.String str1, + java.lang.String str2) +
        BTrace to DTrace communication chennal.
        +
        static intdtraceProbe(java.lang.String str1, + java.lang.String str2, + int i1) +
        BTrace to DTrace communication chennal.
        +
        static intdtraceProbe(java.lang.String str1, + java.lang.String str2, + int i1, + int i2) +
        BTrace to DTrace communication channel.
        +
        static voiddumpHeap(java.lang.String fileName) +
        Dump the snapshot of the Java heap to a file in hprof + binary format.
        +
        static voiddumpHeap(java.lang.String fileName, + boolean live) +
        Dump the snapshot of the Java heap to a file in hprof + binary format.
        +
        static booleanendsWith(java.lang.String s, + java.lang.String end) 
        static voidexit() +
        This is same as exit(int) except that the exit code + is zero.
        +
        static voidexit(int exitCode) +
        Exits the BTrace session -- note that the particular client's tracing + session exits and not the observed/traced program! After exit call, + the trace action method terminates immediately and no other probe action + method (of that client) will be called after that.
        +
        static doubleexp(double a) +
        Returns Euler's number e raised to the power of a + double value.
        +
        static java.lang.reflect.Fieldfield(java.lang.Class clazz, + java.lang.String name) +
        Returns a Field object that reflects the specified declared + field of the class or interface represented by the given Class + object.
        +
        static java.lang.reflect.Fieldfield(java.lang.Class clazz, + java.lang.String name, + boolean throwException) +
        Returns a Field object that reflects the specified declared + field of the class or interface represented by the given Class + object.
        +
        static java.lang.reflect.Fieldfield(java.lang.String clazz, + java.lang.String name) +
        Returns a Field object that reflects the specified declared + field of the class or interface represented by the given Class + object.
        +
        static java.lang.reflect.Fieldfield(java.lang.String clazz, + java.lang.String name, + boolean throwException) +
        Returns a Field object that reflects the specified declared + field of the class or interface represented by the given Class + object.
        +
        static longfinalizationCount() +
        Returns the approximate number of objects for + which finalization is pending.
        +
        static longfreeMemory() +
        Returns the amount of free memory in the Java Virtual Machine.
        +
        static voidgc() +
        Runs the garbage collector.
        +
        static intget(java.util.concurrent.atomic.AtomicInteger ai) +
        Gets the current value of the given AtomicInteger.
        +
        static longget(java.util.concurrent.atomic.AtomicLong al) +
        Gets the current value the given AtomicLong.
        +
        static java.lang.Objectget(java.lang.reflect.Field field) +
        Gets the value of a static reference field.
        +
        static java.lang.Objectget(java.lang.reflect.Field field, + java.lang.Object obj) +
        Gets the value of an instance reference field.
        +
        static <K,V> Vget(java.util.Map<K,V> map, + K key) 
        static intgetAndAdd(java.util.concurrent.atomic.AtomicInteger ai, + int delta) +
        Atomically adds the given value to the current value.
        +
        static longgetAndAdd(java.util.concurrent.atomic.AtomicLong al, + long delta) +
        Atomically adds the given value to the current value.
        +
        static intgetAndDecrement(java.util.concurrent.atomic.AtomicInteger ai) +
        Atomically decrements by one the current value of given AtomicInteger.
        +
        static longgetAndDecrement(java.util.concurrent.atomic.AtomicLong al) +
        Atomically decrements by one the current value.
        +
        static intgetAndIncrement(java.util.concurrent.atomic.AtomicInteger ai) +
        Atomically increments by one the current value of given AtomicInteger.
        +
        static longgetAndIncrement(java.util.concurrent.atomic.AtomicLong al) +
        Atomically increments by one the current value.
        +
        static intgetAndSet(java.util.concurrent.atomic.AtomicInteger ai, + int newValue) +
        Atomically sets to the given value and returns the old value.
        +
        static longgetAndSet(java.util.concurrent.atomic.AtomicLong al, + long newValue) +
        Atomically sets to the given value and returns the old value.
        +
        static booleangetBoolean(java.lang.reflect.Field field) +
        Gets the value of a static boolean field.
        +
        static booleangetBoolean(java.lang.reflect.Field field, + java.lang.Object obj) +
        Gets the value of an instance boolean field.
        +
        static bytegetByte(java.lang.reflect.Field field) +
        Gets the value of a static byte field.
        +
        static bytegetByte(java.lang.reflect.Field field, + java.lang.Object obj) +
        Gets the value of an instance byte field.
        +
        static chargetChar(java.lang.reflect.Field field) +
        Gets the value of a static char field.
        +
        static chargetChar(java.lang.reflect.Field field, + java.lang.Object obj) +
        Gets the value of an instance char field.
        +
        static java.lang.ClassgetComponentType(java.lang.Class clazz) +
        returns component type of an array Class.
        +
        static doublegetDouble(java.lang.reflect.Field field) +
        Gets the value of a static double field.
        +
        static doublegetDouble(java.lang.reflect.Field field, + java.lang.Object obj) +
        Gets the value of an instance double field.
        +
        static java.util.Map<java.lang.String,java.lang.String>getenv() +
        Returns an unmodifiable string map view of the current system environment.
        +
        static java.lang.Stringgetenv(java.lang.String name) +
        Gets the value of the specified environment variable.
        +
        static floatgetFloat(java.lang.reflect.Field field) +
        Gets the value of a static float field.
        +
        static floatgetFloat(java.lang.reflect.Field field, + java.lang.Object obj) +
        Gets the value of an instance float field.
        +
        static intgetInstrumentationLevel() +
        Returns the current instrumentation level.
        +
        static intgetInt(java.lang.reflect.Field field) +
        Gets the value of a static int field.
        +
        static intgetInt(java.lang.reflect.Field field, + java.lang.Object obj) +
        Gets the value of an instance int field.
        +
        static longgetLong(java.lang.reflect.Field field) +
        Gets the value of a static long field.
        +
        static longgetLong(java.lang.reflect.Field field, + java.lang.Object obj) +
        Gets the value of an instance long field.
        +
        static intgetpid() +
        Returns the process id of the currently BTrace'd process.
        +
        static shortgetShort(java.lang.reflect.Field field) +
        Gets the value of a static short field.
        +
        static shortgetShort(java.lang.reflect.Field field, + java.lang.Object obj) +
        Gets the value of an instance short field.
        +
        static java.lang.ClassgetSuperclass(java.lang.Class clazz) +
        Returns the Class representing the superclass of the entity + (class, interface, primitive type or void) represented by the given + Class.
        +
        static longgetTotalGcTime() +
        Returns the total amount of time spent in GarbageCollection up to this point + since the application was started.
        +
        static inthash(java.lang.Object obj) +
        Returns a hash code value for the object.
        +
        static java.lang.management.MemoryUsageheapUsage() +
        Returns heap memory usage
        +
        static booleanholdsLock(java.lang.Object obj) +
        Returns true if and only if the current thread holds the + monitor lock on the specified object.
        +
        static intidentityHashCode(java.lang.Object obj) +
        Returns the same hash code for the given object as + would be returned by the default method hashCode(), + whether or not the given object's class overrides + hashCode().
        +
        static java.lang.StringidentityStr(java.lang.Object obj) +
        Returns identity string of the form class-name@identity-hash
        +
        static intincrementAndGet(java.util.concurrent.atomic.AtomicInteger ai) +
        Atomically increments by one the current value of given AtomicInteger.
        +
        static longincrementAndGet(java.util.concurrent.atomic.AtomicLong al) +
        Atomically increments by one the current value.
        +
        static intindexOf(java.lang.String str1, + java.lang.String str2) 
        static longinit(java.lang.management.MemoryUsage mu) +
        Returns the amount of memory in bytes that the Java virtual + machine initially requests from the operating system for + memory management.
        +
        static booleaninstanceOf(java.lang.Object obj, + java.lang.String className) +
        Checks whether the provided object is an instance of the named class.
        +
        static booleanisArray(java.lang.Class clazz) +
        Determines if the given Class object represents an array class.
        +
        static booleanisAssignableFrom(java.lang.Class<?> a, + java.lang.Class<?> b) +
        Determines if the class or interface represented by the first + Class object is either the same as, or is a superclass or + superinterface of, the class or interface represented by the second + Class parameter.
        +
        static booleanisBootClassPathSupported() +
        Tests if the Java virtual machine supports the boot class path + mechanism used by the bootstrap class loader to search for class + files.
        +
        static <E> booleanisEmpty(java.util.Collection<E> coll) 
        static <K,V> booleanisEmpty(java.util.Map<K,V> map) 
        static booleanisInfinite(double d) +
        Returns true if the specified number is infinitely + large in magnitude, false otherwise.
        +
        static booleanisInfinite(float f) +
        Returns true if the specified number is infinitely + large in magnitude, false otherwise.
        +
        static booleanisInstance(java.lang.Class clazz, + java.lang.Object obj) +
        Determines if the specified Object is assignment-compatible + with the object represented by the specified Class.
        +
        static booleanisInterface(java.lang.Class clazz) +
        Determines if the specified Class object represents an + interface type.
        +
        static booleanisInteruppted() +
        Tests whether this thread has been interrupted.
        +
        static booleanisNaN(double d) +
        Returns true if the specified number is a + Not-a-Number (NaN) value, false otherwise.
        +
        static booleanisNaN(float f) +
        Returns true if the specified number is a + Not-a-Number (NaN) value, false otherwise.
        +
        static booleanisPrimitive(java.lang.Class clazz) +
        Returns whether the given Class represent primitive type or not.
        +
        static voidjstack() +
        Prints the java stack trace of the current thread.
        +
        static voidjstack(int numFrames) +
        Prints the java stack trace of the current thread.
        +
        static voidjstack(java.lang.Throwable exception) +
        Prints the stack trace of the given exception object.
        +
        static voidjstack(java.lang.Throwable exception, + int numFrames) +
        Prints the stack trace of the given exception object.
        +
        static voidjstackAll() +
        Prints Java stack traces of all the Java threads.
        +
        static voidjstackAll(int numFrames) +
        Prints Java stack traces of all the Java threads.
        +
        static java.lang.StringjstackAllStr() +
        Returns the stack traces of all Java threads as a String.
        +
        static java.lang.StringjstackAllStr(int numFrames) +
        Returns atmost given number of frames in stack traces + of all threads as a String.
        +
        static java.lang.StringjstackStr() +
        Returns the stack trace of current thread as a String.
        +
        static java.lang.StringjstackStr(int numFrames) +
        Returns the stack trace of the current thread as a String + but includes atmost the given number of frames.
        +
        static java.lang.StringjstackStr(java.lang.Throwable exception) +
        Returns the stack trace of given exception object as a String.
        +
        static java.lang.StringjstackStr(java.lang.Throwable exception, + int numFrames) +
        Returns stack trace of given exception object as a String.
        +
        static intlastIndexOf(java.lang.String str1, + java.lang.String str2) 
        static voidlazySet(java.util.concurrent.atomic.AtomicInteger ai, + int newValue) +
        Eventually sets to the given value to the given AtomicInteger.
        +
        static voidlazySet(java.util.concurrent.atomic.AtomicLong al, + long newValue) +
        Eventually sets to the given value to the given AtomicLong.
        +
        static intlength(java.lang.String str) +
        Returns the length of the given string.
        +
        static java.lang.StringlibraryPath() +
        Returns the Java library path.
        +
        static java.lang.ClassLoaderloader(java.lang.Class clazz) +
        Returns the class loader for the given class.
        +
        static doublelog(double a) +
        Returns the natural logarithm (base e) of a double + value.
        +
        static doublelog10(double a) +
        Returns the base 10 logarithm of a double value.
        +
        static booleanmatches(java.util.regex.Pattern regex, + java.lang.String input) +
        Matches the given (precompiled) regular expression and attempts + to match the given input against it.
        +
        static booleanmatches(java.lang.String regex, + java.lang.String input) +
        Compiles the given regular expression and attempts to match the given + input against it.
        +
        static longmax(java.lang.management.MemoryUsage mu) +
        Returns the maximum amount of memory in bytes that can be used + for memory management.
        +
        static longmaxMemory() +
        Returns the maximum amount of memory that the Java virtual machine will + attempt to use.
        +
        static java.lang.Stringname(java.lang.Class clazz) +
        Returns the name of the given Class object.
        +
        static java.lang.Stringname(java.lang.reflect.Field field) +
        Returns the name of the Field object.
        +
        static java.lang.Stringname(java.lang.Thread thread) +
        Returns the name of the given thread.
        +
        static AggregationnewAggregation(AggregationFunction type) +
        Creates a new aggregation based on the given aggregation function type.
        +
        static AggregationKeynewAggregationKey(java.lang.Object element1) +
        Creates a grouping aggregation key with the provided value.
        +
        static AggregationKeynewAggregationKey(java.lang.Object element1, + java.lang.Object element2) +
        Creates a composite grouping aggregation key with the provided values.
        +
        static AggregationKeynewAggregationKey(java.lang.Object element1, + java.lang.Object element2, + java.lang.Object element3) +
        Creates a composite grouping aggregation key with the provided values.
        +
        static AggregationKeynewAggregationKey(java.lang.Object element1, + java.lang.Object element2, + java.lang.Object element3, + java.lang.Object element4) +
        Creates a composite grouping aggregation key with the provided values.
        +
        static java.util.concurrent.atomic.AtomicIntegernewAtomicInteger(int initialValue) +
        Creates a new AtomicInteger with the given initial value.
        +
        static java.util.concurrent.atomic.AtomicLongnewAtomicLong(long initialValue) +
        Creates a new AtomicLong with the given initial value.
        +
        static <V> java.util.Deque<V>newDeque() 
        static <K,V> java.util.Map<K,V>newHashMap() +
        Operating on maps
        +
        static <K,V> java.util.Map<K,V>newWeakMap() 
        static java.lang.management.MemoryUsagenonHeapUsage() +
        Returns non-heap memory usage
        +
        static java.lang.ClassLoaderparentLoader(java.lang.ClassLoader loader) +
        Returns the parent class loader of the given loader.
        +
        static booleanparseBoolean(java.lang.String s) +
        Parses the string argument as a boolean.
        +
        static byteparseByte(java.lang.String s) +
        Parses the string argument as a signed decimal + byte.
        +
        static doubleparseDouble(java.lang.String s) +
        Returns a new double initialized to the value + represented by the specified String, as performed + by the valueOf methcod of class + Double.
        +
        static floatparseFloat(java.lang.String s) +
        Returns a new float initialized to the value + represented by the specified String, as performed + by the valueOf method of class Float.
        +
        static intparseInt(java.lang.String s) +
        Parses the string argument as a signed decimal integer.
        +
        static longparseLong(java.lang.String s) +
        Parses the string argument as a signed decimal + long.
        +
        static shortparseShort(java.lang.String s) +
        Parses the string argument as a signed decimal + short.
        +
        static java.util.regex.Patternpattern(java.lang.String regex) +
        This is synonym for "regexp".
        +
        static java.util.regex.Patternpattern(java.lang.String regex, + int flags) +
        This is synonym for "regexp".
        +
        static longpeakThreadCount() +
        Returns the peak live thread count since the Java virtual machine + started or peak was reset.
        +
        static <V> Vpeek(java.util.Deque<V> queue) 
        static <V> VpeekFirst(java.util.Deque<V> queue) 
        static <V> VpeekLast(java.util.Deque<V> queue) 
        static longperfInt(java.lang.String name) +
        accessing jvmstat (perf) int counter
        +
        static longperfLong(java.lang.String name) +
        accessing jvmstat (perf) long counter
        +
        static java.lang.StringperfString(java.lang.String name) +
        accessing jvmstat (perf) String counter
        +
        static <V> Vpoll(java.util.Deque<V> queue) 
        static voidprint(boolean b) +
        Prints a boolean value.
        +
        static voidprint(char c) +
        Prints a character.
        +
        static voidprint(double d) +
        Prints a double-precision floating-point number.
        +
        static voidprint(float f) +
        Prints a floating-point number.
        +
        static voidprint(int i) +
        Prints an integer.
        +
        static voidprint(long l) +
        Prints a long integer.
        +
        static voidprint(java.lang.Object obj) 
        static voidprintAggregation(java.lang.String name, + Aggregation aggregation) +
        Prints the aggregation.
        +
        static voidprintAggregation(java.lang.String name, + Aggregation aggregation, + java.lang.String format) +
        Prints aggregation using the provided format
        +
        static voidprintArray(boolean[] array) +
        Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
        +
        static voidprintArray(byte[] array) +
        Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
        +
        static voidprintArray(char[] array) +
        Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
        +
        static voidprintArray(double[] array) +
        Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
        +
        static voidprintArray(float[] array) +
        Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
        +
        static voidprintArray(int[] array) +
        Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
        +
        static voidprintArray(long[] array) +
        Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
        +
        static voidprintArray(java.lang.Object[] array) +
        Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
        +
        static voidprintArray(short[] array) +
        Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
        +
        static voidprintEnv() +
        Prints all system environment values.
        +
        static voidprintFields(java.lang.Object obj) +
        Print all instance fields of an object as name-value + pairs.
        +
        static voidprintFields(java.lang.Object obj, + boolean classNamePrefix) +
        Print all instance fields of an object as name-value + pairs.
        +
        static voidprintln() +
        Terminates the current line by writing the line separator string.
        +
        static voidprintln(boolean b) +
        Prints a boolean and then terminate the line.
        +
        static voidprintln(char c) +
        Prints a character and then terminate the line.
        +
        static voidprintln(double d) +
        Prints a double and then terminate the line.
        +
        static voidprintln(float f) +
        Prints a float and then terminate the line.
        +
        static voidprintln(int i) +
        Prints an integer and then terminate the line.
        +
        static voidprintln(long l) +
        Prints a long and then terminate the line.
        +
        static voidprintln(java.lang.Object obj) +
        Prints the given object and then prints a newline
        +
        static voidprintMap(java.util.Map map) +
        Prints the given Map.
        +
        static voidprintNumber(java.lang.String name, + java.lang.Number value) +
        Prints a number.
        +
        static voidprintNumberMap(java.lang.String name, + java.util.Map<java.lang.String,? extends java.lang.Number> data) +
        Prints the given Map.
        +
        static voidprintProperties() +
        Prints all Sys properties.
        +
        static voidprintStaticFields(java.lang.Class clazz) +
        Print all static fields of the class as name-value + pairs.
        +
        static voidprintStaticFields(java.lang.Class clazz, + boolean classNamePrefix) +
        Print all static fields of the class as name-value + pairs.
        +
        static voidprintStringMap(java.lang.String name, + java.util.Map<java.lang.String,java.lang.String> data) +
        Prints the given Map.
        +
        static voidprintVmArguments() +
        Prints VM input arguments list.
        +
        static java.lang.ClassprobeClass() +
        Deprecated.  +
        Since 1.1. Use ProbeClassName and Self annotations instead
        +
        +
        static intprobeLine() +
        Returns the currently probed source line number (if available).
        +
        static java.lang.StringprobeMethod() +
        Deprecated.  +
        Since 1.1. Use ProbeMethodName annotation instead
        +
        +
        static java.util.Propertiesproperties() +
        Returns all Sys properties.
        +
        static java.lang.Stringproperty(java.lang.String key) +
        Gets the system property indicated by the specified key.
        +
        static <V> voidpush(java.util.Deque<V> queue, + V value) 
        static <K,V> Vput(java.util.Map<K,V> map, + K key, + V value) 
        static doublerandom() +
        Returns a double value with a positive sign, greater + than or equal to 0.0 and less than 1.0.
        +
        static java.util.regex.Patternregexp(java.lang.String regex) +
        Compiles the given regular expression into a pattern.
        +
        static java.util.regex.Patternregexp(java.lang.String regex, + int flags) +
        Compiles the given regular expression into a pattern with the given + flags.
        +
        static <K,V> Vremove(java.util.Map<K,V> map, + K key) 
        static <V> VremoveFirst(java.util.Deque<V> queue) 
        static <V> VremoveLast(java.util.Deque<V> queue) 
        static voidrunFinalization() +
        Runs the finalization methods of any objects pending finalization.
        +
        static voidserialize(java.io.Serializable obj, + java.lang.String fileName) +
        Serialize a given object into the given file.
        +
        static voidset(java.util.concurrent.atomic.AtomicInteger ai, + int newValue) +
        Sets to the given value to the given AtomicInteger.
        +
        static voidset(java.util.concurrent.atomic.AtomicLong al, + long newValue) +
        Sets to the given value.
        +
        static voidsetInstrumentationLevel(int level) +
        Sets the current instrumentation level.
        +
        static <E> intsize(java.util.Collection<E> coll) 
        static <K,V> intsize(java.util.Map<K,V> map) 
        static longsizeof(java.lang.Object objectToSize) +
        Returns an implementation-specific approximation of the amount of storage consumed by + the specified object.
        +
        static java.lang.ref.SoftReferencesoftRef(java.lang.Object obj) +
        Creates and returns a soft reference to the given object.
        +
        static voidspeculate(int id) +
        Sets current speculative buffer id.
        +
        static intspeculation() +
        Returns an identifier for a new speculative buffer.
        +
        static booleanstartsWith(java.lang.String s, + java.lang.String start) 
        static java.lang.Stringstr(boolean b) +
        Returns a String object representing the specified + boolean.
        +
        static java.lang.Stringstr(char c) +
        Returns a String object representing the + specified char.
        +
        static java.lang.Stringstr(double d) +
        Returns a string representation of the double + argument.
        +
        static java.lang.Stringstr(float f) +
        Returns a string representation of the float + argument.
        +
        static java.lang.Stringstr(int i) +
        Returns a String object representing the + specified integer.
        +
        static java.lang.Stringstr(long l) +
        Returns a String object representing the specified + long.
        +
        static java.lang.Stringstr(java.lang.Object obj) +
        Returns a string representation of the object.
        +
        static java.lang.Stringstrcat(java.lang.String str1, + java.lang.String str2) +
        This is synonym to "concat".
        +
        static intstrcmp(java.lang.String str1, + java.lang.String str2) +
        This is synonym to "compareTo" method.
        +
        static intstricmp(java.lang.String str1, + java.lang.String str2) +
        This is synonym to "compareToIgnoreCase".
        +
        static intstrlen(java.lang.String str) +
        This is synonym for "length".
        +
        static intstrstr(java.lang.String str1, + java.lang.String str2) +
        Find String within String
        +
        static java.lang.Stringsubstr(java.lang.String str, + int start) 
        static java.lang.Stringsubstr(java.lang.String str, + int start, + int end) +
        Substring
        +
        static longthreadCount() +
        Returns the current number of live threads including both + daemon and non-daemon threads.
        +
        static longthreadId(java.lang.Thread thread) +
        Returns the identifier of the given Thread.
        +
        static java.lang.Thread.StatethreadState(java.lang.Thread thread) +
        Returns the state of the given thread.
        +
        static longtimeMillis() +
        Returns the current time in milliseconds.
        +
        static longtimeNanos() +
        Returns the current value of the most precise available system + timer, in nanoseconds.
        +
        static java.lang.Stringtimestamp() +
        Generates a string getTimestamp (current date&time) in the default system format
        +
        static java.lang.Stringtimestamp(java.lang.String format) +
        Generates a string getTimestamp (current date&time)
        +
        static java.lang.StringtoHexString(int i) +
        Returns a string representation of the integer argument as an + unsigned integer in base 16.
        +
        static java.lang.StringtoHexString(long l) +
        Returns a string representation of the long + argument as an unsigned integer in base 16.
        +
        static longtotalMemory() +
        Returns the total amount of memory in the Java virtual machine.
        +
        static longtotalStartedThreadCount() +
        Returns the total number of threads created and also started + since the Java virtual machine started.
        +
        static java.lang.StringtoXML(java.lang.Object obj) +
        Creates an XML document to persist the tree of the all + transitively reachable objects from given "root" object.
        +
        static voidtruncateAggregation(Aggregation aggregation, + int count) +
        Removes all aggregated values from the aggregation except for the largest or smallest + abs(count) elements.
        +
        static java.lang.Classtype(java.lang.reflect.Field field) +
        Returns the type of the Field object.
        +
        static booleanunbox(java.lang.Boolean b) +
        Returns the value of the given Boolean object as a boolean + primitive.
        +
        static byteunbox(java.lang.Byte b) +
        Returns the value of the specified Byte as a byte.
        +
        static charunbox(java.lang.Character ch) +
        Returns the value of the given Character object as a char + primitive.
        +
        static doubleunbox(java.lang.Double d) +
        Returns the double value represented by the specified Double.
        +
        static floatunbox(java.lang.Float f) +
        Returns the float value represented by the specified Float.
        +
        static intunbox(java.lang.Integer i) +
        Returns the value of represented by Integer.
        +
        static longunbox(java.lang.Long l) +
        Returns the long value represented by the specified Long.
        +
        static shortunbox(java.lang.Short s) +
        Returns the short value represented by Short.
        +
        static longused(java.lang.management.MemoryUsage mu) +
        Returns the amount of used memory in bytes.
        +
        static java.util.List<java.lang.String>vmArguments() +
        Returns the input arguments passed to the Java virtual machine + which does not include the arguments to the main method.
        +
        static longvmStartTime() +
        Returns the start time of the Java virtual machine in milliseconds.
        +
        static longvmUptime() +
        Returns the uptime of the Java virtual machine in milliseconds.
        +
        static java.lang.StringvmVersion() +
        Returns the Java virtual machine implementation version.
        +
        static booleanweakCompareAndSet(java.util.concurrent.atomic.AtomicInteger ai, + int expect, + int update) +
        Atomically sets the value to the given updated value + if the current value == the expected value.
        +
        static booleanweakCompareAndSet(java.util.concurrent.atomic.AtomicLong al, + long expect, + long update) +
        Atomically sets the value to the given updated value + if the current value == the expected value.
        +
        static java.lang.ref.WeakReferenceweakRef(java.lang.Object obj) +
        Creates and returns a weak reference to the given object.
        +
        static voidwriteDOT(java.lang.Object obj, + java.lang.String fileName) +
        Writes a .dot document to persist the tree of the all the + transitively reachable objects from the given "root" object.
        +
        static voidwriteXML(java.lang.Object obj, + java.lang.String fileName) +
        Writes an XML document to persist the tree of the all the + transitively reachable objects from the given "root" object.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          isInteruppted

          +
          public static boolean isInteruppted()
          +
          Tests whether this thread has been interrupted. The interrupted + status of the thread is unaffected by this method. + +

          A thread interruption ignored because a thread was not alive + at the time of the interrupt will be reflected by this method + returning false.

          +
          +
          Returns:
          +
          true if this thread has been interrupted; + false otherwise.
          +
          +
        • +
        + + + +
          +
        • +

          jstack

          +
          public static void jstack()
          +
          Prints the java stack trace of the current thread.
          +
        • +
        + + + +
          +
        • +

          jstack

          +
          public static void jstack(int numFrames)
          +
          Prints the java stack trace of the current thread. But, + atmost given number of frames.
          +
          +
          Parameters:
          +
          numFrames - number of frames to be printed. When this is + negative all frames are printed.
          +
          +
        • +
        + + + +
          +
        • +

          jstackAll

          +
          public static void jstackAll()
          +
          Prints Java stack traces of all the Java threads.
          +
        • +
        + + + +
          +
        • +

          jstackAll

          +
          public static void jstackAll(int numFrames)
          +
          Prints Java stack traces of all the Java threads. But, + atmost given number of frames.
          +
          +
          Parameters:
          +
          numFrames - number of frames to be printed. When this is + negative all frames are printed.
          +
          +
        • +
        + + + +
          +
        • +

          jstackStr

          +
          public static java.lang.String jstackStr()
          +
          Returns the stack trace of current thread as a String.
          +
          +
          Returns:
          +
          the stack trace as a String.
          +
          +
        • +
        + + + +
          +
        • +

          jstackStr

          +
          public static java.lang.String jstackStr(int numFrames)
          +
          Returns the stack trace of the current thread as a String + but includes atmost the given number of frames.
          +
          +
          Parameters:
          +
          numFrames - number of frames to be included. When this is + negative all frames are included.
          +
          Returns:
          +
          the stack trace as a String.
          +
          +
        • +
        + + + +
          +
        • +

          jstackAllStr

          +
          public static java.lang.String jstackAllStr()
          +
          Returns the stack traces of all Java threads as a String.
          +
          +
          Returns:
          +
          the stack traces as a String.
          +
          +
        • +
        + + + +
          +
        • +

          jstackAllStr

          +
          public static java.lang.String jstackAllStr(int numFrames)
          +
          Returns atmost given number of frames in stack traces + of all threads as a String.
          +
          +
          Parameters:
          +
          numFrames - number of frames to be included. When this is + negative all frames are included.
          +
          Returns:
          +
          the stack traces as a String.
          +
          +
        • +
        + + + +
          +
        • +

          jstack

          +
          public static void jstack(java.lang.Throwable exception)
          +
          Prints the stack trace of the given exception object.
          +
          +
          Parameters:
          +
          exception - throwable for which stack trace is printed.
          +
          +
        • +
        + + + +
          +
        • +

          jstack

          +
          public static void jstack(java.lang.Throwable exception,
          +                          int numFrames)
          +
          Prints the stack trace of the given exception object. But, + prints atmost given number of frames.
          +
          +
          Parameters:
          +
          exception - throwable for which stack trace is printed.
          +
          numFrames - maximum number of frames to be printed.
          +
          +
        • +
        + + + +
          +
        • +

          jstackStr

          +
          public static java.lang.String jstackStr(java.lang.Throwable exception)
          +
          Returns the stack trace of given exception object as a String.
          +
          +
          Parameters:
          +
          exception - the throwable for which stack trace is returned.
          +
          +
        • +
        + + + +
          +
        • +

          jstackStr

          +
          public static java.lang.String jstackStr(java.lang.Throwable exception,
          +                                         int numFrames)
          +
          Returns stack trace of given exception object as a String.
          +
          +
          Parameters:
          +
          exception - throwable for which stack trace is returned.
          +
          numFrames - maximum number of frames to be returned.
          +
          +
        • +
        + + + +
          +
        • +

          currentThread

          +
          public static java.lang.Thread currentThread()
          +
          Returns a reference to the currently executing thread object.
          +
          +
          Returns:
          +
          the currently executing thread.
          +
          +
        • +
        + + + +
          +
        • +

          threadId

          +
          public static long threadId(java.lang.Thread thread)
          +
          Returns the identifier of the given Thread. The thread ID is a positive + long number generated when the given thread was created. + The thread ID is unique and remains unchanged during its lifetime. + When a thread is terminated, the thread ID may be reused.
          +
        • +
        + + + +
          +
        • +

          threadState

          +
          public static java.lang.Thread.State threadState(java.lang.Thread thread)
          +
          Returns the state of the given thread. + This method is designed for use in monitoring of the system state, + not for synchronization control.
          +
        • +
        + + + +
          +
        • +

          holdsLock

          +
          public static boolean holdsLock(java.lang.Object obj)
          +
          Returns true if and only if the current thread holds the + monitor lock on the specified object. + +

          This method is designed to allow a program to assert that + the current thread already holds a specified lock: +

          +     assert Thread.holdsLock(obj);
          + 
          +
          +
          Parameters:
          +
          obj - the object on which to test lock ownership
          +
          Returns:
          +
          true if the current thread holds the monitor lock on + the specified object.
          +
          Throws:
          +
          java.lang.NullPointerException - if obj is null
          +
          +
        • +
        + + + +
          +
        • +

          deadlocks

          +
          public static void deadlocks()
          +
          Prints the Java level deadlocks detected (if any).
          +
        • +
        + + + +
          +
        • +

          deadlocks

          +
          public static void deadlocks(boolean stackTrace)
          +
          Prints deadlocks detected (if any). Optionally prints + stack trace of the deadlocked threads.
          +
          +
          Parameters:
          +
          stackTrace - boolean flag to specify whether to + print stack traces of deadlocked threads or not.
          +
          +
        • +
        + + + +
          +
        • +

          name

          +
          public static java.lang.String name(java.lang.Thread thread)
          +
          Returns the name of the given thread.
          +
          +
          Parameters:
          +
          thread - thread whose name is returned
          +
          +
        • +
        + + + +
          +
        • +

          loader

          +
          public static java.lang.ClassLoader loader(java.lang.Class clazz)
          +
          Returns the class loader for the given class. Some implementations may use + null to represent the bootstrap class loader. This method will return + null in such implementations if this class was loaded by the bootstrap + class loader.
          +
          +
          Parameters:
          +
          clazz - the Class for which the class loader is returned
          +
          +
        • +
        + + + +
          +
        • +

          parentLoader

          +
          public static java.lang.ClassLoader parentLoader(java.lang.ClassLoader loader)
          +
          Returns the parent class loader of the given loader. Some implementations may + use null to represent the bootstrap class loader. This method + will return null in such implementations if this class loader's + parent is the bootstrap class loader.
          +
          +
          Parameters:
          +
          loader - the loader for which the parent loader is returned
          +
          Returns:
          +
          The parent ClassLoader
          +
          +
        • +
        + + + +
          +
        • +

          str

          +
          public static java.lang.String str(java.lang.Object obj)
          +
          Returns a string representation of the object. In general, the + toString method returns a string that + "textually represents" this object. The result should + be a concise but informative representation that is easy for a + person to read. For bootstrap classes, returns the result of + calling Object.toString() override. For non-bootstrap classes, + default toString() value [className@hashCode] is returned.
          +
          +
          Parameters:
          +
          obj - the object whose string representation is returned
          +
          Returns:
          +
          a string representation of the given object.
          +
          +
        • +
        + + + +
          +
        • +

          identityStr

          +
          public static java.lang.String identityStr(java.lang.Object obj)
          +
          Returns identity string of the form class-name@identity-hash
          +
          +
          Parameters:
          +
          obj - object for which identity string is returned
          +
          Returns:
          +
          identity string
          +
          +
        • +
        + + + +
          +
        • +

          hash

          +
          public static int hash(java.lang.Object obj)
          +
          Returns a hash code value for the object. This method is supported + for the benefit of hashtables such as those provided by + java.util.Hashtable. For bootstrap classes, returns the + result of calling Object.hashCode() override. For non-bootstrap classes, + the identity hash code is returned.
          +
          +
          Parameters:
          +
          obj - the Object whose hash code is returned.
          +
          Returns:
          +
          a hash code value for the given object.
          +
          +
        • +
        + + + +
          +
        • +

          identityHashCode

          +
          public static int identityHashCode(java.lang.Object obj)
          +
          Returns the same hash code for the given object as + would be returned by the default method hashCode(), + whether or not the given object's class overrides + hashCode(). The hash code for the null reference is zero.
          +
          +
          Parameters:
          +
          obj - object for which the hashCode is to be calculated
          +
          Returns:
          +
          the hashCode
          +
          +
        • +
        + + + +
          +
        • +

          compare

          +
          public static boolean compare(java.lang.Object obj1,
          +                              java.lang.Object obj2)
          +
          Indicates whether two given objects are "equal to" one another. + For bootstrap classes, returns the result of calling Object.equals() + override. For non-bootstrap classes, the reference identity comparison + is done.
          +
          +
          Parameters:
          +
          obj1 - first object to compare equality
          +
          obj2 - second object to compare equality
          +
          Returns:
          +
          true if the given objects are equal; + false otherwise.
          +
          +
        • +
        + + + +
          +
        • +

          classOf

          +
          public static java.lang.Class classOf(java.lang.Object obj)
          +
          Returns the runtime class of the given Object.
          +
          +
          Parameters:
          +
          obj - the Object whose Class is returned
          +
          Returns:
          +
          the Class object of given object
          +
          +
        • +
        + + + +
          +
        • +

          instanceOf

          +
          public static boolean instanceOf(java.lang.Object obj,
          +                                 java.lang.String className)
          +
          Checks whether the provided object is an instance of the named class. + Note: this method can be rather CPU intensive, use with caution
          +
          +
          Parameters:
          +
          obj - the object to check
          +
          className - the class name; as a special case void can be provided + to check whether the instance is a void value wrapper - AnyType.VOID
          +
          Returns:
          +
          true if the object can be assigned to an instance of 'className' type
          +
          Since:
          +
          1.3.5
          +
          +
        • +
        + + + +
          +
        • +

          declaringClass

          +
          public static java.lang.Class declaringClass(java.lang.reflect.Field field)
          +
          Returns the Class object representing the class or interface + that declares the field represented by the given Field object.
          +
          +
          Parameters:
          +
          field - whose declaring Class is returned
          +
          +
        • +
        + + + +
          +
        • +

          name

          +
          public static java.lang.String name(java.lang.Class clazz)
          +
          Returns the name of the given Class object.
          +
        • +
        + + + +
          +
        • +

          name

          +
          public static java.lang.String name(java.lang.reflect.Field field)
          +
          Returns the name of the Field object.
          +
          +
          Parameters:
          +
          field - Field for which name is returned
          +
          Returns:
          +
          name of the given field
          +
          +
        • +
        + + + +
          +
        • +

          type

          +
          public static java.lang.Class type(java.lang.reflect.Field field)
          +
          Returns the type of the Field object.
          +
          +
          Parameters:
          +
          field - Field for which type is returned
          +
          Returns:
          +
          type of the given field
          +
          +
        • +
        + + + +
          +
        • +

          accessFlags

          +
          public static int accessFlags(java.lang.Class clazz)
          +
          Returns the access flags of the given Class.
          +
        • +
        + + + +
          +
        • +

          accessFlags

          +
          public static int accessFlags(java.lang.reflect.Field field)
          +
          Returns the access flags of the given Field.
          +
        • +
        + + + +
          +
        • +

          contextClassLoader

          +
          public static java.lang.ClassLoader contextClassLoader()
          +
          Returns the current context class loader
          +
        • +
        + + + +
          +
        • +

          classForName

          +
          public static java.lang.Class classForName(java.lang.String name)
          +
          Returns Class object for given class name.
          +
        • +
        + + + +
          +
        • +

          classForName

          +
          public static java.lang.Class classForName(java.lang.String name,
          +                                           java.lang.ClassLoader cl)
          +
          Returns the Class for the given class name + using the given class loader.
          +
        • +
        + + + +
          +
        • +

          isAssignableFrom

          +
          public static boolean isAssignableFrom(java.lang.Class<?> a,
          +                                       java.lang.Class<?> b)
          +
          Determines if the class or interface represented by the first + Class object is either the same as, or is a superclass or + superinterface of, the class or interface represented by the second + Class parameter. It returns true if so; + otherwise it returns false.
          +
        • +
        + + + +
          +
        • +

          isInstance

          +
          public static boolean isInstance(java.lang.Class clazz,
          +                                 java.lang.Object obj)
          +
          Determines if the specified Object is assignment-compatible + with the object represented by the specified Class. This method is + the dynamic equivalent of the Java language instanceof + operator. The method returns true if the specified + Object argument is non-null and can be cast to the + reference type represented by this Class object without + raising a ClassCastException. It returns false + otherwise.
          +
          +
          Parameters:
          +
          clazz - the class that is checked.
          +
          obj - the object to check.
          +
          Returns:
          +
          true if obj is an instance of the given class.
          +
          +
        • +
        + + + +
          +
        • +

          getSuperclass

          +
          public static java.lang.Class getSuperclass(java.lang.Class clazz)
          +
          Returns the Class representing the superclass of the entity + (class, interface, primitive type or void) represented by the given + Class. If the given Class represents either the + Object class, an interface, a primitive type, or void, then + null is returned. If the given object represents an array class then the + Class object representing the Object class is + returned.
          +
          +
          Parameters:
          +
          clazz - the Class whose super class is returned.
          +
          Returns:
          +
          the superclass of the class represented by the given object.
          +
          +
        • +
        + + + +
          +
        • +

          isInterface

          +
          public static boolean isInterface(java.lang.Class clazz)
          +
          Determines if the specified Class object represents an + interface type.
          +
          +
          Parameters:
          +
          clazz - the Class object to check.
          +
          Returns:
          +
          true if the Class represents an interface; + false otherwise.
          +
          +
        • +
        + + + +
          +
        • +

          isArray

          +
          public static boolean isArray(java.lang.Class clazz)
          +
          Determines if the given Class object represents an array class.
          +
          +
          Parameters:
          +
          clazz - Class object to check.
          +
          Returns:
          +
          true if the given object represents an array class; + false otherwise.
          +
          +
        • +
        + + + +
          +
        • +

          isPrimitive

          +
          public static boolean isPrimitive(java.lang.Class clazz)
          +
          Returns whether the given Class represent primitive type or not.
          +
        • +
        + + + +
          +
        • +

          getComponentType

          +
          public static java.lang.Class getComponentType(java.lang.Class clazz)
          +
          returns component type of an array Class.
          +
        • +
        + + + +
          +
        • +

          field

          +
          public static java.lang.reflect.Field field(java.lang.Class clazz,
          +                                            java.lang.String name,
          +                                            boolean throwException)
          +
          Returns a Field object that reflects the specified declared + field of the class or interface represented by the given Class + object. The name parameter is a String that + specifies the simple name of the desired field. Returns null on not finding + field if throwException parameter is false. Else throws a RuntimeException + when field is not found.
          +
          +
          Parameters:
          +
          clazz - Class whose field is returned
          +
          name - the name of the field
          +
          throwException - whether to throw exception on failing to find field or not
          +
          Returns:
          +
          the Field object for the specified field in this + class
          +
          +
        • +
        + + + +
          +
        • +

          field

          +
          public static java.lang.reflect.Field field(java.lang.Class clazz,
          +                                            java.lang.String name)
          +
          Returns a Field object that reflects the specified declared + field of the class or interface represented by the given Class + object. The name parameter is a String that + specifies the simple name of the desired field. Throws a RuntimeException + when field is not found.
          +
          +
          Parameters:
          +
          clazz - Class whose field is returned
          +
          name - the name of the field
          +
          Returns:
          +
          the Field object for the specified field in this + class
          +
          +
        • +
        + + + +
          +
        • +

          field

          +
          public static java.lang.reflect.Field field(java.lang.String clazz,
          +                                            java.lang.String name,
          +                                            boolean throwException)
          +
          Returns a Field object that reflects the specified declared + field of the class or interface represented by the given Class + object. The name parameter is a String that + specifies the simple name of the desired field. Returns null on not finding + field if throwException parameter is false. Else throws a RuntimeException + when field is not found.
          +
          +
          Parameters:
          +
          clazz - Class whose field is returned
          +
          name - the name of the field
          +
          throwException - whether to throw exception on failing to find field or not
          +
          Returns:
          +
          the Field object for the specified field in this + class
          +
          +
        • +
        + + + +
          +
        • +

          field

          +
          public static java.lang.reflect.Field field(java.lang.String clazz,
          +                                            java.lang.String name)
          +
          Returns a Field object that reflects the specified declared + field of the class or interface represented by the given Class + object. The name parameter is a String that + specifies the simple name of the desired field. Throws a RuntimeException + when field is not found.
          +
          +
          Parameters:
          +
          clazz - Class whose field is returned
          +
          name - the name of the field
          +
          Returns:
          +
          the Field object for the specified field in this + class
          +
          +
        • +
        + + + +
          +
        • +

          getByte

          +
          public static byte getByte(java.lang.reflect.Field field)
          +
          Gets the value of a static byte field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          Returns:
          +
          the value of the byte field
          +
          +
        • +
        + + + +
          +
        • +

          getByte

          +
          public static byte getByte(java.lang.reflect.Field field,
          +                           java.lang.Object obj)
          +
          Gets the value of an instance byte field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          obj - the object to extract the byte value + from
          +
          Returns:
          +
          the value of the byte field
          +
          +
        • +
        + + + +
          +
        • +

          getShort

          +
          public static short getShort(java.lang.reflect.Field field)
          +
          Gets the value of a static short field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          Returns:
          +
          the value of the short field
          +
          +
        • +
        + + + +
          +
        • +

          getShort

          +
          public static short getShort(java.lang.reflect.Field field,
          +                             java.lang.Object obj)
          +
          Gets the value of an instance short field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          obj - the object to extract the short value + from
          +
          Returns:
          +
          the value of the short field
          +
          +
        • +
        + + + +
          +
        • +

          getInt

          +
          public static int getInt(java.lang.reflect.Field field)
          +
          Gets the value of a static int field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          Returns:
          +
          the value of the int field
          +
          +
        • +
        + + + +
          +
        • +

          getInt

          +
          public static int getInt(java.lang.reflect.Field field,
          +                         java.lang.Object obj)
          +
          Gets the value of an instance int field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          obj - the object to extract the int value + from
          +
          Returns:
          +
          the value of the int field
          +
          +
        • +
        + + + +
          +
        • +

          getLong

          +
          public static long getLong(java.lang.reflect.Field field)
          +
          Gets the value of a static long field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          Returns:
          +
          the value of the long field
          +
          +
        • +
        + + + +
          +
        • +

          getLong

          +
          public static long getLong(java.lang.reflect.Field field,
          +                           java.lang.Object obj)
          +
          Gets the value of an instance long field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          obj - the object to extract the long value + from
          +
          Returns:
          +
          the value of the long field
          +
          +
        • +
        + + + +
          +
        • +

          getFloat

          +
          public static float getFloat(java.lang.reflect.Field field)
          +
          Gets the value of a static float field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          Returns:
          +
          the value of the float field
          +
          +
        • +
        + + + +
          +
        • +

          getFloat

          +
          public static float getFloat(java.lang.reflect.Field field,
          +                             java.lang.Object obj)
          +
          Gets the value of an instance float field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          obj - the object to extract the float value + from
          +
          Returns:
          +
          the value of the float field
          +
          +
        • +
        + + + +
          +
        • +

          getDouble

          +
          public static double getDouble(java.lang.reflect.Field field)
          +
          Gets the value of a static double field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          Returns:
          +
          the value of the double field
          +
          +
        • +
        + + + +
          +
        • +

          getDouble

          +
          public static double getDouble(java.lang.reflect.Field field,
          +                               java.lang.Object obj)
          +
          Gets the value of an instance double field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          obj - the object to extract the double value + from
          +
          Returns:
          +
          the value of the double field
          +
          +
        • +
        + + + +
          +
        • +

          getBoolean

          +
          public static boolean getBoolean(java.lang.reflect.Field field)
          +
          Gets the value of a static boolean field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          Returns:
          +
          the value of the boolean field
          +
          +
        • +
        + + + +
          +
        • +

          getBoolean

          +
          public static boolean getBoolean(java.lang.reflect.Field field,
          +                                 java.lang.Object obj)
          +
          Gets the value of an instance boolean field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          obj - the object to extract the boolean value + from
          +
          Returns:
          +
          the value of the boolean field
          +
          +
        • +
        + + + +
          +
        • +

          getChar

          +
          public static char getChar(java.lang.reflect.Field field)
          +
          Gets the value of a static char field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          Returns:
          +
          the value of the char field
          +
          +
        • +
        + + + +
          +
        • +

          getChar

          +
          public static char getChar(java.lang.reflect.Field field,
          +                           java.lang.Object obj)
          +
          Gets the value of an instance char field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          obj - the object to extract the char value + from
          +
          Returns:
          +
          the value of the char field
          +
          +
        • +
        + + + +
          +
        • +

          get

          +
          public static java.lang.Object get(java.lang.reflect.Field field)
          +
          Gets the value of a static reference field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          Returns:
          +
          the value of the reference field
          +
          +
        • +
        + + + +
          +
        • +

          get

          +
          public static java.lang.Object get(java.lang.reflect.Field field,
          +                                   java.lang.Object obj)
          +
          Gets the value of an instance reference field.
          +
          +
          Parameters:
          +
          field - Field object whose value is returned.
          +
          obj - the object to extract the reference value + from
          +
          Returns:
          +
          the value of the reference field
          +
          +
        • +
        + + + +
          +
        • +

          weakRef

          +
          public static java.lang.ref.WeakReference weakRef(java.lang.Object obj)
          +
          Creates and returns a weak reference to the given object.
          +
          +
          Parameters:
          +
          obj - object for which a weak reference is created.
          +
          Returns:
          +
          a weak reference to the given object.
          +
          +
        • +
        + + + +
          +
        • +

          softRef

          +
          public static java.lang.ref.SoftReference softRef(java.lang.Object obj)
          +
          Creates and returns a soft reference to the given object.
          +
          +
          Parameters:
          +
          obj - object for which a soft reference is created.
          +
          Returns:
          +
          a soft reference to the given object.
          +
          +
        • +
        + + + +
          +
        • +

          deref

          +
          public static java.lang.Object deref(java.lang.ref.Reference ref)
          +
          Returns the given reference object's referent. If the reference object has + been cleared, either by the program or by the garbage collector, then + this method returns null.
          +
          +
          Parameters:
          +
          ref - reference object whose referent is returned.
          +
          Returns:
          +
          The object to which the reference refers, or + null if the reference object has been cleared.
          +
          +
        • +
        + + + +
          +
        • +

          probeClass

          +
          @Deprecated
          +public static java.lang.Class probeClass()
          +
          Deprecated. Since 1.1. Use ProbeClassName and Self annotations instead
          +
          Returns the Class object of the currently + probed (or traced) class.
          +
        • +
        + + + +
          +
        • +

          probeMethod

          +
          @Deprecated
          +public static java.lang.String probeMethod()
          +
          Deprecated. Since 1.1. Use ProbeMethodName annotation instead
          +
          Returns the currently probed method's name.
          +
        • +
        + + + +
          +
        • +

          probeLine

          +
          public static int probeLine()
          +
          Returns the currently probed source line number (if available).
          +
        • +
        + + + +
          +
        • +

          printMap

          +
          public static void printMap(java.util.Map map)
          +
          Prints the given Map.
          +
          +
          Parameters:
          +
          map - Map that is printed.
          +
          +
        • +
        + + + +
          +
        • +

          printStringMap

          +
          public static void printStringMap(java.lang.String name,
          +                                  java.util.Map<java.lang.String,java.lang.String> data)
          +
          Prints the given Map.
          +
          +
          Parameters:
          +
          name - - the name of the map
          +
          data - - the map data
          +
          +
        • +
        + + + +
          +
        • +

          printNumberMap

          +
          public static void printNumberMap(java.lang.String name,
          +                                  java.util.Map<java.lang.String,? extends java.lang.Number> data)
          +
          Prints the given Map.
          +
          +
          Parameters:
          +
          name - - the name of the map
          +
          data - - the map data
          +
          +
        • +
        + + + +
          +
        • +

          printNumber

          +
          public static void printNumber(java.lang.String name,
          +                               java.lang.Number value)
          +
          Prints a number.
          +
          +
          Parameters:
          +
          name - - name of the number data
          +
          value - - value of the numerical data
          +
          +
        • +
        + + + +
          +
        • +

          printArray

          +
          public static void printArray(java.lang.Object[] array)
          +
          Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
          +
        • +
        + + + +
          +
        • +

          printArray

          +
          public static void printArray(int[] array)
          +
          Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
          +
          +
          Since:
          +
          1.3.11
          +
          +
        • +
        + + + +
          +
        • +

          printArray

          +
          public static void printArray(long[] array)
          +
          Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
          +
          +
          Since:
          +
          1.3.11
          +
          +
        • +
        + + + +
          +
        • +

          printArray

          +
          public static void printArray(float[] array)
          +
          Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
          +
          +
          Since:
          +
          1.3.11
          +
          +
        • +
        + + + +
          +
        • +

          printArray

          +
          public static void printArray(double[] array)
          +
          Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
          +
          +
          Since:
          +
          1.3.11
          +
          +
        • +
        + + + +
          +
        • +

          printArray

          +
          public static void printArray(boolean[] array)
          +
          Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
          +
          +
          Since:
          +
          1.3.11
          +
          +
        • +
        + + + +
          +
        • +

          printArray

          +
          public static void printArray(char[] array)
          +
          Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
          +
          +
          Since:
          +
          1.3.11
          +
          +
        • +
        + + + +
          +
        • +

          printArray

          +
          public static void printArray(byte[] array)
          +
          Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
          +
          +
          Since:
          +
          1.3.11
          +
          +
        • +
        + + + +
          +
        • +

          printArray

          +
          public static void printArray(short[] array)
          +
          Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
          +
          +
          Since:
          +
          1.3.11
          +
          +
        • +
        + + + +
          +
        • +

          printFields

          +
          public static void printFields(java.lang.Object obj)
          +
          Print all instance fields of an object as name-value + pairs. Includes the inherited fields as well.
          +
          +
          Parameters:
          +
          obj - Object whose fields are printed.
          +
          +
        • +
        + + + +
          +
        • +

          printFields

          +
          public static void printFields(java.lang.Object obj,
          +                               boolean classNamePrefix)
          +
          Print all instance fields of an object as name-value + pairs. Includes the inherited fields as well. Optionally, + prints name of the declaring class before each field - so that + if same named field in super class chain may be disambiguated.
          +
          +
          Parameters:
          +
          obj - Object whose fields are printed.
          +
          classNamePrefix - flag to tell whether to prefix field names + names by class name or not.
          +
          +
        • +
        + + + +
          +
        • +

          printStaticFields

          +
          public static void printStaticFields(java.lang.Class clazz)
          +
          Print all static fields of the class as name-value + pairs. Includes the inherited fields as well.
          +
          +
          Parameters:
          +
          clazz - Class whose static fields are printed.
          +
          +
        • +
        + + + +
          +
        • +

          printStaticFields

          +
          public static void printStaticFields(java.lang.Class clazz,
          +                                     boolean classNamePrefix)
          +
          Print all static fields of the class as name-value + pairs. Includes the inherited fields as well. Optionally, + prints name of the declaring class before each field - so that + if same named field in super class chain may be disambiguated.
          +
          +
          Parameters:
          +
          clazz - Class whose static fields are printed.
          +
          classNamePrefix - flag to tell whether to prefix field names + names by class name or not.
          +
          +
        • +
        + + + +
          +
        • +

          print

          +
          public static void print(java.lang.Object obj)
          +
        • +
        + + + +
          +
        • +

          print

          +
          public static void print(boolean b)
          +
          Prints a boolean value. The string produced by String.valueOf(boolean) is sent to BTrace client + for "printing".
          +
          +
          Parameters:
          +
          b - The boolean to be printed
          +
          +
        • +
        + + + +
          +
        • +

          print

          +
          public static void print(char c)
          +
          Prints a character. The string produced by Character.valueOf(char) is sent to BTrace client + for "printing".
          +
          +
          Parameters:
          +
          c - The char to be printed
          +
          +
        • +
        + + + +
          +
        • +

          print

          +
          public static void print(int i)
          +
          Prints an integer. The string produced by String.valueOf(int) is sent to BTrace client for "printing".
          +
          +
          Parameters:
          +
          i - The int to be printed
          +
          See Also:
          +
          Integer.toString(int)
          +
          +
        • +
        + + + +
          +
        • +

          print

          +
          public static void print(long l)
          +
          Prints a long integer. The string produced by String.valueOf(long) is sent to BTrace client for "printing".
          +
          +
          Parameters:
          +
          l - The long to be printed
          +
          See Also:
          +
          Long.toString(long)
          +
          +
        • +
        + + + +
          +
        • +

          print

          +
          public static void print(float f)
          +
          Prints a floating-point number. The string produced by String.valueOf(float) is sent to BTrace client for "printing".
          +
          +
          Parameters:
          +
          f - The float to be printed
          +
          See Also:
          +
          Float.toString(float)
          +
          +
        • +
        + + + +
          +
        • +

          print

          +
          public static void print(double d)
          +
          Prints a double-precision floating-point number. The string produced by + String.valueOf(double) is sent to BTrace client + for "printing".
          +
          +
          Parameters:
          +
          d - The double to be printed
          +
          See Also:
          +
          Double.toString(double)
          +
          +
        • +
        + + + +
          +
        • +

          println

          +
          public static void println(java.lang.Object obj)
          +
          Prints the given object and then prints a newline
          +
        • +
        + + + +
          +
        • +

          println

          +
          public static void println(boolean b)
          +
          Prints a boolean and then terminate the line. This method behaves as + though it invokes print(boolean) and then + println().
          +
          +
          Parameters:
          +
          b - The boolean to be printed
          +
          +
        • +
        + + + +
          +
        • +

          println

          +
          public static void println(char c)
          +
          Prints a character and then terminate the line. This method behaves as + though it invokes print(char) and then + println().
          +
          +
          Parameters:
          +
          c - The char to be printed.
          +
          +
        • +
        + + + +
          +
        • +

          println

          +
          public static void println(int i)
          +
          Prints an integer and then terminate the line. This method behaves as + though it invokes print(int) and then + println().
          +
          +
          Parameters:
          +
          i - The int to be printed.
          +
          +
        • +
        + + + +
          +
        • +

          println

          +
          public static void println(long l)
          +
          Prints a long and then terminate the line. This method behaves as + though it invokes print(long) and then + println().
          +
          +
          Parameters:
          +
          l - a The long to be printed.
          +
          +
        • +
        + + + +
          +
        • +

          println

          +
          public static void println(float f)
          +
          Prints a float and then terminate the line. This method behaves as + though it invokes print(float) and then + println().
          +
          +
          Parameters:
          +
          f - The float to be printed.
          +
          +
        • +
        + + + +
          +
        • +

          println

          +
          public static void println(double d)
          +
          Prints a double and then terminate the line. This method behaves as + though it invokes print(double) and then + println().
          +
          +
          Parameters:
          +
          d - The double to be printed.
          +
          +
        • +
        + + + +
          +
        • +

          println

          +
          public static void println()
          +
          Terminates the current line by writing the line separator string. The + line separator string is defined by the system property + line.separator, and is not necessarily a single newline + character ('\n').
          +
        • +
        + + + +
          +
        • +

          vmStartTime

          +
          public static long vmStartTime()
          +
          Returns the start time of the Java virtual machine in milliseconds. + This method returns the approximate time when the Java virtual + machine started.
          +
          +
          Returns:
          +
          start time of the Java virtual machine in milliseconds.
          +
          +
        • +
        + + + +
          +
        • +

          vmUptime

          +
          public static long vmUptime()
          +
          Returns the uptime of the Java virtual machine in milliseconds.
          +
          +
          Returns:
          +
          uptime of the Java virtual machine in milliseconds.
          +
          +
        • +
        + + + +
          +
        • +

          timeMillis

          +
          public static long timeMillis()
          +
          Returns the current time in milliseconds. Note that + while the unit of time of the return value is a millisecond, + the granularity of the value depends on the underlying + operating system and may be larger. For example, many + operating systems measure time in units of tens of + milliseconds.
          +
          +
          Returns:
          +
          the difference, measured in milliseconds, between + the current time and midnight, January 1, 1970 UTC.
          +
          +
        • +
        + + + +
          +
        • +

          timeNanos

          +
          public static long timeNanos()
          +
          Returns the current value of the most precise available system + timer, in nanoseconds. + +

          This method can only be used to measure elapsed time and is + not related to any other notion of system or wall-clock time. + The value returned represents nanoseconds since some fixed but + arbitrary time (perhaps in the future, so values may be + negative). This method provides nanosecond precision, but not + necessarily nanosecond accuracy. No guarantees are made about + how frequently values change. Differences in successive calls + that span greater than approximately 292 years (263 + nanoseconds) will not accurately compute elapsed time due to + numerical overflow.

          +
          +
          Returns:
          +
          The current value of the system timer, in nanoseconds.
          +
          +
        • +
        + + + +
          +
        • +

          timestamp

          +
          public static java.lang.String timestamp(java.lang.String format)
          +

          Generates a string getTimestamp (current date&time)

          +
          +
          Parameters:
          +
          format - The format to be used - see SimpleDateFormat
          +
          Returns:
          +
          Returns a string representing current date&time
          +
          Since:
          +
          1.1
          +
          +
        • +
        + + + +
          +
        • +

          timestamp

          +
          public static java.lang.String timestamp()
          +

          Generates a string getTimestamp (current date&time) in the default system format

          +
          +
          Returns:
          +
          Returns a string representing current date&time
          +
          Since:
          +
          1.1
          +
          +
        • +
        + + + +
          +
        • +

          startsWith

          +
          public static boolean startsWith(java.lang.String s,
          +                                 java.lang.String start)
          +
        • +
        + + + +
          +
        • +

          endsWith

          +
          public static boolean endsWith(java.lang.String s,
          +                               java.lang.String end)
          +
        • +
        + + + +
          +
        • +

          strcat

          +
          public static java.lang.String strcat(java.lang.String str1,
          +                                      java.lang.String str2)
          +
          This is synonym to "concat".
          +
          +
          See Also:
          +
          concat(String, String)
          +
          +
        • +
        + + + +
          +
        • +

          concat

          +
          public static java.lang.String concat(java.lang.String str1,
          +                                      java.lang.String str2)
          +
          Concatenates the specified strings together.
          +
        • +
        + + + +
          +
        • +

          compareTo

          +
          public static int compareTo(java.lang.String str1,
          +                            java.lang.String str2)
          +
          Compares two strings lexicographically. + The comparison is based on the Unicode value of each character in + the strings. The character sequence represented by the first + String object is compared lexicographically to the + character sequence represented by the second string. The result is + a negative integer if the first String object + lexicographically precedes the second string. The result is a + positive integer if the first String object lexicographically + follows the second string. The result is zero if the strings + are equal; compareTo returns 0 exactly when + the String.equals(Object) method would return true.
          +
        • +
        + + + + + + + +
          +
        • +

          compareToIgnoreCase

          +
          public static int compareToIgnoreCase(java.lang.String str1,
          +                                      java.lang.String str2)
          +
          Compares two strings lexicographically, ignoring case + differences. This method returns an integer whose sign is that of + calling compareTo with normalized versions of the strings + where case differences have been eliminated by calling + Character.toLowerCase(Character.toUpperCase(character)) on + each character.
          +
        • +
        + + + + + + + +
          +
        • +

          strstr

          +
          public static int strstr(java.lang.String str1,
          +                         java.lang.String str2)
          +
          Find String within String
          +
        • +
        + + + +
          +
        • +

          indexOf

          +
          public static int indexOf(java.lang.String str1,
          +                          java.lang.String str2)
          +
        • +
        + + + +
          +
        • +

          lastIndexOf

          +
          public static int lastIndexOf(java.lang.String str1,
          +                              java.lang.String str2)
          +
        • +
        + + + +
          +
        • +

          substr

          +
          public static java.lang.String substr(java.lang.String str,
          +                                      int start,
          +                                      int end)
          +
          Substring
          +
        • +
        + + + +
          +
        • +

          substr

          +
          public static java.lang.String substr(java.lang.String str,
          +                                      int start)
          +
        • +
        + + + +
          +
        • +

          length

          +
          public static int length(java.lang.String str)
          +
          Returns the length of the given string. + The length is equal to the number of Unicode + code units in the string.
          +
          +
          Parameters:
          +
          str - String whose length is calculated.
          +
          Returns:
          +
          the length of the sequence of characters represented by this + object.
          +
          +
        • +
        + + + +
          +
        • +

          strlen

          +
          public static int strlen(java.lang.String str)
          +
          This is synonym for "length".
          +
          +
          See Also:
          +
          length(String)
          +
          +
        • +
        + + + +
          +
        • +

          regexp

          +
          public static java.util.regex.Pattern regexp(java.lang.String regex)
          +
          Compiles the given regular expression into a pattern.
          +
          +
          Parameters:
          +
          regex - The expression to be compiled
          +
          Throws:
          +
          java.util.regex.PatternSyntaxException - If the expression's syntax is invalid
          +
          +
        • +
        + + + +
          +
        • +

          pattern

          +
          public static java.util.regex.Pattern pattern(java.lang.String regex)
          +
          This is synonym for "regexp".
          +
          +
          See Also:
          +
          regexp(String)
          +
          +
        • +
        + + + +
          +
        • +

          regexp

          +
          public static java.util.regex.Pattern regexp(java.lang.String regex,
          +                                             int flags)
          +
          Compiles the given regular expression into a pattern with the given + flags.
          +
          +
          Parameters:
          +
          regex - The expression to be compiled
          +
          flags - Match flags, a bit mask that may include + Pattern.CASE_INSENSITIVE, Pattern.MULTILINE, Pattern.DOTALL, + Pattern.UNICODE_CASE, Pattern.CANON_EQ, Pattern.UNIX_LINES, + Pattern.LITERAL and Pattern.COMMENTS
          +
          Throws:
          +
          java.lang.IllegalArgumentException - If bit values other than those corresponding to the defined + match flags are set in flags
          +
          java.util.regex.PatternSyntaxException - If the expression's syntax is invalid
          +
          +
        • +
        + + + +
          +
        • +

          pattern

          +
          public static java.util.regex.Pattern pattern(java.lang.String regex,
          +                                              int flags)
          +
          This is synonym for "regexp".
          +
          +
          See Also:
          +
          regexp(String, int)
          +
          +
        • +
        + + + +
          +
        • +

          matches

          +
          public static boolean matches(java.util.regex.Pattern regex,
          +                              java.lang.String input)
          +
          Matches the given (precompiled) regular expression and attempts + to match the given input against it.
          +
        • +
        + + + +
          +
        • +

          matches

          +
          public static boolean matches(java.lang.String regex,
          +                              java.lang.String input)
          +
          Compiles the given regular expression and attempts to match the given + input against it. + +

          An invocation of this convenience method of the form + +

          + Pattern.matches(regex, input);
          + + behaves in exactly the same way as the expression + +
          + Pattern.compile(regex).matcher(input).matches()
          + +

          + If a pattern is to be used multiple times, compiling it once and reusing + it will be more efficient than invoking this method each time.

          +
          +
          Parameters:
          +
          regex - The expression to be compiled
          +
          input - The character sequence to be matched
          +
          Throws:
          +
          java.util.regex.PatternSyntaxException - If the expression's syntax is invalid
          +
          +
        • +
        + + + +
          +
        • +

          random

          +
          public static double random()
          +
          Returns a double value with a positive sign, greater + than or equal to 0.0 and less than 1.0. + Returned values are chosen pseudorandomly with (approximately) + uniform distribution from that range.
          +
        • +
        + + + +
          +
        • +

          log

          +
          public static double log(double a)
          +
          Returns the natural logarithm (base e) of a double + value. Special cases: +
          • If the argument is NaN or less than zero, then the result + is NaN. +
          • If the argument is positive infinity, then the result is + positive infinity. +
          • If the argument is positive zero or negative zero, then the + result is negative infinity.
          + +

          The computed result must be within 1 ulp of the exact result. + Results must be semi-monotonic.

          +
          +
          Parameters:
          +
          a - a value
          +
          Returns:
          +
          the value ln a, the natural logarithm of + a.
          +
          +
        • +
        + + + +
          +
        • +

          log10

          +
          public static double log10(double a)
          +
          Returns the base 10 logarithm of a double value. + Special cases: + +
          • If the argument is NaN or less than zero, then the result + is NaN. +
          • If the argument is positive infinity, then the result is + positive infinity. +
          • If the argument is positive zero or negative zero, then the + result is negative infinity. +
          • If the argument is equal to 10n for + integer n, then the result is n. +
          + +

          The computed result must be within 1 ulp of the exact result. + Results must be semi-monotonic.

          +
          +
          Parameters:
          +
          a - a value
          +
          Returns:
          +
          the base 10 logarithm of a.
          +
          +
        • +
        + + + +
          +
        • +

          exp

          +
          public static double exp(double a)
          +
          Returns Euler's number e raised to the power of a + double value. Special cases: +
          • If the argument is NaN, the result is NaN. +
          • If the argument is positive infinity, then the result is + positive infinity. +
          • If the argument is negative infinity, then the result is + positive zero.
          + +

          The computed result must be within 1 ulp of the exact result. + Results must be semi-monotonic.

          +
          +
          Parameters:
          +
          a - the exponent to raise e to.
          +
          Returns:
          +
          the value ea, + where e is the base of the natural logarithms.
          +
          +
        • +
        + + + +
          +
        • +

          isNaN

          +
          public static boolean isNaN(double d)
          +
          Returns true if the specified number is a + Not-a-Number (NaN) value, false otherwise.
          +
          +
          Parameters:
          +
          d - the value to be tested.
          +
          Returns:
          +
          true if the value of the argument is NaN; + false otherwise.
          +
          +
        • +
        + + + +
          +
        • +

          isNaN

          +
          public static boolean isNaN(float f)
          +
          Returns true if the specified number is a + Not-a-Number (NaN) value, false otherwise.
          +
          +
          Parameters:
          +
          f - the value to be tested.
          +
          Returns:
          +
          true if the value of the argument is NaN; + false otherwise.
          +
          +
        • +
        + + + +
          +
        • +

          isInfinite

          +
          public static boolean isInfinite(double d)
          +
          Returns true if the specified number is infinitely + large in magnitude, false otherwise.
          +
          +
          Parameters:
          +
          d - the value to be tested.
          +
          Returns:
          +
          true if the value of the argument is positive + infinity or negative infinity; false otherwise.
          +
          +
        • +
        + + + +
          +
        • +

          isInfinite

          +
          public static boolean isInfinite(float f)
          +
          Returns true if the specified number is infinitely + large in magnitude, false otherwise.
          +
          +
          Parameters:
          +
          f - the value to be tested.
          +
          Returns:
          +
          true if the value of the argument is positive + infinity or negative infinity; false otherwise.
          +
          +
        • +
        + + + +
          +
        • +

          parseBoolean

          +
          public static boolean parseBoolean(java.lang.String s)
          +
          Parses the string argument as a boolean. The boolean + returned represents the value true if the string argument + is not null and is equal, ignoring case, to the string + "true".

          + Example: Boolean.parseBoolean("True") returns true.
          + Example: Boolean.parseBoolean("yes") returns false.

          +
          +
          Parameters:
          +
          s - the String containing the boolean + representation to be parsed
          +
          Returns:
          +
          the boolean represented by the string argument
          +
          +
        • +
        + + + +
          +
        • +

          parseByte

          +
          public static byte parseByte(java.lang.String s)
          +
          Parses the string argument as a signed decimal + byte. The characters in the string must all be + decimal digits, except that the first character may be an ASCII + minus sign '-' ('\u002D') to + indicate a negative value. The resulting byte value is + returned.
          +
          +
          Parameters:
          +
          s - a String containing the + byte representation to be parsed
          +
          Returns:
          +
          the byte value represented by the + argument in decimal
          +
          +
        • +
        + + + +
          +
        • +

          parseShort

          +
          public static short parseShort(java.lang.String s)
          +
          Parses the string argument as a signed decimal + short. The characters in the string must all be + decimal digits, except that the first character may be an ASCII + minus sign '-' ('\u002D') to + indicate a negative value. The resulting short value is + returned.
          +
          +
          Parameters:
          +
          s - a String containing the short + representation to be parsed
          +
          Returns:
          +
          the short value represented by the + argument in decimal.
          +
          +
        • +
        + + + +
          +
        • +

          parseInt

          +
          public static int parseInt(java.lang.String s)
          +
          Parses the string argument as a signed decimal integer. The + characters in the string must all be decimal digits, except that + the first character may be an ASCII minus sign '-' + ('\u002D') to indicate a negative value. The resulting + integer value is returned.
          +
          +
          Parameters:
          +
          s - a String containing the int + representation to be parsed
          +
          Returns:
          +
          the integer value represented by the argument in decimal.
          +
          +
        • +
        + + + +
          +
        • +

          parseLong

          +
          public static long parseLong(java.lang.String s)
          +
          Parses the string argument as a signed decimal + long. The characters in the string must all be + decimal digits, except that the first character may be an ASCII + minus sign '-' (\u002D') to + indicate a negative value. The resulting long + value is returned. +

          + Note that neither the character L + ('\u004C') nor l + ('\u006C') is permitted to appear at the end + of the string as a type indicator, as would be permitted in + Java programming language source code.

          +
          +
          Parameters:
          +
          s - a String containing the long + representation to be parsed
          +
          Returns:
          +
          the long represented by the argument in + decimal.
          +
          +
        • +
        + + + +
          +
        • +

          parseFloat

          +
          public static float parseFloat(java.lang.String s)
          +
          Returns a new float initialized to the value + represented by the specified String, as performed + by the valueOf method of class Float.
          +
          +
          Parameters:
          +
          s - the string to be parsed.
          +
          Returns:
          +
          the float value represented by the string + argument.
          +
          +
        • +
        + + + +
          +
        • +

          parseDouble

          +
          public static double parseDouble(java.lang.String s)
          +
          Returns a new double initialized to the value + represented by the specified String, as performed + by the valueOf methcod of class + Double.
          +
          +
          Parameters:
          +
          s - the string to be parsed.
          +
          Returns:
          +
          the double value represented by the string + argument.
          +
          +
        • +
        + + + +
          +
        • +

          box

          +
          public static java.lang.Boolean box(boolean b)
          +
          Returns a Boolean instance representing the specified + boolean value. If the specified boolean value + is true, this method returns Boolean.TRUE; + if it is false, this method returns Boolean.FALSE.
          +
          +
          Parameters:
          +
          b - a boolean value.
          +
          Returns:
          +
          a Boolean instance representing b.
          +
          +
        • +
        + + + +
          +
        • +

          box

          +
          public static java.lang.Character box(char c)
          +
          Returns a Character instance representing the specified + char value.
          +
          +
          Parameters:
          +
          c - a char value.
          +
          Returns:
          +
          a Character instance representing c.
          +
          +
        • +
        + + + +
          +
        • +

          box

          +
          public static java.lang.Byte box(byte b)
          +
          Returns a Byte instance representing the specified + byte value.
          +
          +
          Parameters:
          +
          b - a byte value.
          +
          Returns:
          +
          a Byte instance representing b.
          +
          +
        • +
        + + + +
          +
        • +

          box

          +
          public static java.lang.Short box(short s)
          +
          Returns a Short instance representing the specified + short value.
          +
          +
          Parameters:
          +
          s - a short value.
          +
          Returns:
          +
          a Short instance representing s.
          +
          +
        • +
        + + + +
          +
        • +

          box

          +
          public static java.lang.Integer box(int i)
          +
          Returns a Integer instance representing the specified + int value.
          +
          +
          Parameters:
          +
          i - an int value.
          +
          Returns:
          +
          a Integer instance representing i.
          +
          +
        • +
        + + + +
          +
        • +

          box

          +
          public static java.lang.Long box(long l)
          +
          Returns a Long instance representing the specified + long value.
          +
          +
          Parameters:
          +
          l - a long value.
          +
          Returns:
          +
          a Long instance representing l.
          +
          +
        • +
        + + + +
          +
        • +

          box

          +
          public static java.lang.Float box(float f)
          +
          Returns a Float instance representing the specified + float value.
          +
          +
          Parameters:
          +
          f - a float value.
          +
          Returns:
          +
          a Float instance representing f.
          +
          +
        • +
        + + + +
          +
        • +

          box

          +
          public static java.lang.Double box(double d)
          +
          Returns a Double instance representing the specified + double value.
          +
          +
          Parameters:
          +
          d - a double value.
          +
          Returns:
          +
          a Double instance representing d.
          +
          +
        • +
        + + + +
          +
        • +

          unbox

          +
          public static boolean unbox(java.lang.Boolean b)
          +
          Returns the value of the given Boolean object as a boolean + primitive.
          +
          +
          Parameters:
          +
          b - the Boolean object whose value is returned.
          +
          Returns:
          +
          the primitive boolean value of the object.
          +
          +
        • +
        + + + +
          +
        • +

          unbox

          +
          public static char unbox(java.lang.Character ch)
          +
          Returns the value of the given Character object as a char + primitive.
          +
          +
          Parameters:
          +
          ch - the Character object whose value is returned.
          +
          Returns:
          +
          the primitive char value of the object.
          +
          +
        • +
        + + + +
          +
        • +

          unbox

          +
          public static byte unbox(java.lang.Byte b)
          +
          Returns the value of the specified Byte as a byte.
          +
          +
          Parameters:
          +
          b - Byte that is unboxed
          +
          Returns:
          +
          the byte value represented by the Byte.
          +
          +
        • +
        + + + +
          +
        • +

          unbox

          +
          public static short unbox(java.lang.Short s)
          +
          Returns the short value represented by Short.
          +
          +
          Parameters:
          +
          s - Short that is unboxed.
          +
          Returns:
          +
          the short value represented by the Short.
          +
          +
        • +
        + + + +
          +
        • +

          unbox

          +
          public static int unbox(java.lang.Integer i)
          +
          Returns the value of represented by Integer.
          +
          +
          Parameters:
          +
          i - Integer that is unboxed.
          +
          Returns:
          +
          the int value represented by the Integer.
          +
          +
        • +
        + + + +
          +
        • +

          unbox

          +
          public static long unbox(java.lang.Long l)
          +
          Returns the long value represented by the specified Long.
          +
          +
          Parameters:
          +
          l - Long to be unboxed.
          +
          Returns:
          +
          the long value represented by the Long.
          +
          +
        • +
        + + + +
          +
        • +

          unbox

          +
          public static float unbox(java.lang.Float f)
          +
          Returns the float value represented by the specified Float.
          +
          +
          Parameters:
          +
          f - Float to be unboxed.
          +
          Returns:
          +
          the float value represented by the Float.
          +
          +
        • +
        + + + +
          +
        • +

          unbox

          +
          public static double unbox(java.lang.Double d)
          +
          Returns the double value represented by the specified Double.
          +
          +
          Parameters:
          +
          d - Double to be unboxed.
          +
          +
        • +
        + + + +
          +
        • +

          str

          +
          public static java.lang.String str(boolean b)
          +
          Returns a String object representing the specified + boolean. If the specified boolean is true, then + the string "true" will be returned, otherwise the + string "false" will be returned.
          +
          +
          Parameters:
          +
          b - the boolean to be converted
          +
          Returns:
          +
          the string representation of the specified boolean
          +
          +
        • +
        + + + +
          +
        • +

          str

          +
          public static java.lang.String str(char c)
          +
          Returns a String object representing the + specified char. The result is a string of length + 1 consisting solely of the specified char.
          +
          +
          Parameters:
          +
          c - the char to be converted
          +
          Returns:
          +
          the string representation of the specified char
          +
          +
        • +
        + + + +
          +
        • +

          str

          +
          public static java.lang.String str(int i)
          +
          Returns a String object representing the + specified integer. The argument is converted to signed decimal + representation and returned as a string.
          +
          +
          Parameters:
          +
          i - an integer to be converted.
          +
          Returns:
          +
          a string representation of the argument in base 10.
          +
          +
        • +
        + + + +
          +
        • +

          toHexString

          +
          public static java.lang.String toHexString(int i)
          +
          Returns a string representation of the integer argument as an + unsigned integer in base 16. +

          + The unsigned integer value is the argument plus 232 + if the argument is negative; otherwise, it is equal to the + argument. This value is converted to a string of ASCII digits + in hexadecimal (base 16) with no extra leading + 0s. If the unsigned magnitude is zero, it is + represented by a single zero character '0' + ('\u0030'); otherwise, the first character of + the representation of the unsigned magnitude will not be the + zero character. The following characters are used as + hexadecimal digits: +

          + 0123456789abcdef
          + 
          + These are the characters '\u0030' through + '\u0039' and '\u0061' through + '\u0066'.
          +
          +
          Parameters:
          +
          i - an integer to be converted to a string.
          +
          Returns:
          +
          the string representation of the unsigned integer value + represented by the argument in hexadecimal (base 16).
          +
          +
        • +
        + + + +
          +
        • +

          str

          +
          public static java.lang.String str(long l)
          +
          Returns a String object representing the specified + long. The argument is converted to signed decimal + representation and returned as a string.
          +
          +
          Parameters:
          +
          l - a long to be converted.
          +
          Returns:
          +
          a string representation of the argument in base 10.
          +
          +
        • +
        + + + +
          +
        • +

          toHexString

          +
          public static java.lang.String toHexString(long l)
          +
          Returns a string representation of the long + argument as an unsigned integer in base 16. +

          + The unsigned long value is the argument plus + 264 if the argument is negative; otherwise, it is + equal to the argument. This value is converted to a string of + ASCII digits in hexadecimal (base 16) with no extra + leading 0s. If the unsigned magnitude is zero, it + is represented by a single zero character '0' + ('\u0030'); otherwise, the first character of + the representation of the unsigned magnitude will not be the + zero character. The following characters are used as + hexadecimal digits: +

          + 0123456789abcdef
          + 
          + These are the characters '\u0030' through + '\u0039' and '\u0061' through + '\u0066'.
          +
          +
          Parameters:
          +
          l - a long to be converted to a string.
          +
          Returns:
          +
          the string representation of the unsigned long + value represented by the argument in hexadecimal + (base 16).
          +
          +
        • +
        + + + +
          +
        • +

          str

          +
          public static java.lang.String str(float f)
          +
          Returns a string representation of the float + argument. All characters mentioned below are ASCII characters. +
            +
          • If the argument is NaN, the result is the string + "NaN". +
          • Otherwise, the result is a string that represents the sign and + magnitude (absolute value) of the argument. If the sign is + negative, the first character of the result is + '-' ('\u002D'); if the sign is + positive, no sign character appears in the result. As for + the magnitude m: +
              +
            • If m is infinity, it is represented by the characters + "Infinity"; thus, positive infinity produces + the result "Infinity" and negative infinity + produces the result "-Infinity". +
            • If m is zero, it is represented by the characters + "0.0"; thus, negative zero produces the result + "-0.0" and positive zero produces the result + "0.0". +
            • If m is greater than or equal to 10-3 but + less than 107, then it is represented as the + integer part of m, in decimal form with no leading + zeroes, followed by '.' + ('\u002E'), followed by one or more + decimal digits representing the fractional part of + m. +
            • If m is less than 10-3 or greater than or + equal to 107, then it is represented in + so-called "computerized scientific notation." Let n + be the unique integer such that 10n <= + m < 10n+1; then let a + be the mathematically exact quotient of m and + 10n so that 1 <= a < 10. + The magnitude is then represented as the integer part of + a, as a single decimal digit, followed by + '.' ('\u002E'), followed by + decimal digits representing the fractional part of + a, followed by the letter 'E' + ('\u0045'), followed by a representation + of n as a decimal integer, as produced by the + method Integer.toString(int). +
            +
          + How many digits must be printed for the fractional part of + m or a? There must be at least one digit + to represent the fractional part, and beyond that as many, but + only as many, more digits as are needed to uniquely distinguish + the argument value from adjacent values of type + float. That is, suppose that x is the + exact mathematical value represented by the decimal + representation produced by this method for a finite nonzero + argument f. Then f must be the float + value nearest to x; or, if two float values are + equally close to x, then f must be one of + them and the least significant bit of the significand of + f must be 0. +

          +
          +
          Parameters:
          +
          f - the float to be converted.
          +
          Returns:
          +
          a string representation of the argument.
          +
          +
        • +
        + + + +
          +
        • +

          str

          +
          public static java.lang.String str(double d)
          +
          Returns a string representation of the double + argument. All characters mentioned below are ASCII characters. +
            +
          • If the argument is NaN, the result is the string + "NaN". +
          • Otherwise, the result is a string that represents the sign and + magnitude (absolute value) of the argument. If the sign is negative, + the first character of the result is '-' + ('\u002D'); if the sign is positive, no sign character + appears in the result. As for the magnitude m: +
              +
            • If m is infinity, it is represented by the characters + "Infinity"; thus, positive infinity produces the result + "Infinity" and negative infinity produces the result + "-Infinity". + +
            • If m is zero, it is represented by the characters + "0.0"; thus, negative zero produces the result + "-0.0" and positive zero produces the result + "0.0". + +
            • If m is greater than or equal to 10-3 but less + than 107, then it is represented as the integer part of + m, in decimal form with no leading zeroes, followed by + '.' ('\u002E'), followed by one or + more decimal digits representing the fractional part of m. + +
            • If m is less than 10-3 or greater than or + equal to 107, then it is represented in so-called + "computerized scientific notation." Let n be the unique + integer such that 10n <= m < + 10n+1; then let a be the + mathematically exact quotient of m and + 10n so that 1 <= a < 10. The + magnitude is then represented as the integer part of a, + as a single decimal digit, followed by '.' + ('\u002E'), followed by decimal digits + representing the fractional part of a, followed by the + letter 'E' ('\u0045'), followed + by a representation of n as a decimal integer, as + produced by the method Integer.toString(int). +
            +
          + How many digits must be printed for the fractional part of + m or a? There must be at least one digit to represent + the fractional part, and beyond that as many, but only as many, more + digits as are needed to uniquely distinguish the argument value from + adjacent values of type double. That is, suppose that + x is the exact mathematical value represented by the decimal + representation produced by this method for a finite nonzero argument + d. Then d must be the double value nearest + to x; or if two double values are equally close + to x, then d must be one of them and the least + significant bit of the significand of d must be 0. +

          +
          +
          Parameters:
          +
          d - the double to be converted.
          +
          Returns:
          +
          a string representation of the argument.
          +
          +
        • +
        + + + +
          +
        • +

          exit

          +
          public static void exit(int exitCode)
          +
          Exits the BTrace session -- note that the particular client's tracing + session exits and not the observed/traced program! After exit call, + the trace action method terminates immediately and no other probe action + method (of that client) will be called after that.
          +
          +
          Parameters:
          +
          exitCode - exit value sent to the client
          +
          +
        • +
        + + + +
          +
        • +

          exit

          +
          public static void exit()
          +
          This is same as exit(int) except that the exit code + is zero.
          +
          +
          See Also:
          +
          exit(int)
          +
          +
        • +
        + + + +
          +
        • +

          perfInt

          +
          public static long perfInt(java.lang.String name)
          +
          accessing jvmstat (perf) int counter
          +
        • +
        + + + +
          +
        • +

          perfLong

          +
          public static long perfLong(java.lang.String name)
          +
          accessing jvmstat (perf) long counter
          +
        • +
        + + + +
          +
        • +

          perfString

          +
          public static java.lang.String perfString(java.lang.String name)
          +
          accessing jvmstat (perf) String counter
          +
        • +
        + + + +
          +
        • +

          newHashMap

          +
          public static <K,V> java.util.Map<K,V> newHashMap()
          +
          Operating on maps
          +
        • +
        + + + +
          +
        • +

          newWeakMap

          +
          public static <K,V> java.util.Map<K,V> newWeakMap()
          +
        • +
        + + + +
          +
        • +

          newDeque

          +
          public static <V> java.util.Deque<V> newDeque()
          +
        • +
        + + + + + +
          +
        • +

          get

          +
          public static <K,V> V get(java.util.Map<K,V> map,
          +                          K key)
          +
        • +
        + + + + + +
          +
        • +

          containsKey

          +
          public static <K,V> boolean containsKey(java.util.Map<K,V> map,
          +                                        K key)
          +
        • +
        + + + + + +
          +
        • +

          containsValue

          +
          public static <K,V> boolean containsValue(java.util.Map<K,V> map,
          +                                          V value)
          +
        • +
        + + + + + +
          +
        • +

          put

          +
          public static <K,V> V put(java.util.Map<K,V> map,
          +                          K key,
          +                          V value)
          +
        • +
        + + + + + +
          +
        • +

          remove

          +
          public static <K,V> V remove(java.util.Map<K,V> map,
          +                             K key)
          +
        • +
        + + + +
          +
        • +

          clear

          +
          public static <K,V> void clear(java.util.Map<K,V> map)
          +
        • +
        + + + +
          +
        • +

          size

          +
          public static <K,V> int size(java.util.Map<K,V> map)
          +
        • +
        + + + +
          +
        • +

          isEmpty

          +
          public static <K,V> boolean isEmpty(java.util.Map<K,V> map)
          +
        • +
        + + + +
          +
        • +

          size

          +
          public static <E> int size(java.util.Collection<E> coll)
          +
        • +
        + + + +
          +
        • +

          isEmpty

          +
          public static <E> boolean isEmpty(java.util.Collection<E> coll)
          +
        • +
        + + + +
          +
        • +

          contains

          +
          public static <E> boolean contains(java.util.Collection<E> coll,
          +                                   java.lang.Object obj)
          +
        • +
        + + + +
          +
        • +

          contains

          +
          public static boolean contains(java.lang.Object[] array,
          +                               java.lang.Object value)
          +
        • +
        + + + + + +
          +
        • +

          push

          +
          public static <V> void push(java.util.Deque<V> queue,
          +                            V value)
          +
        • +
        + + + +
          +
        • +

          poll

          +
          public static <V> V poll(java.util.Deque<V> queue)
          +
        • +
        + + + +
          +
        • +

          peek

          +
          public static <V> V peek(java.util.Deque<V> queue)
          +
        • +
        + + + + + +
          +
        • +

          addLast

          +
          public static <V> void addLast(java.util.Deque<V> queue,
          +                               V value)
          +
        • +
        + + + +
          +
        • +

          peekFirst

          +
          public static <V> V peekFirst(java.util.Deque<V> queue)
          +
        • +
        + + + +
          +
        • +

          peekLast

          +
          public static <V> V peekLast(java.util.Deque<V> queue)
          +
        • +
        + + + +
          +
        • +

          removeLast

          +
          public static <V> V removeLast(java.util.Deque<V> queue)
          +
        • +
        + + + +
          +
        • +

          removeFirst

          +
          public static <V> V removeFirst(java.util.Deque<V> queue)
          +
        • +
        + + + +
          +
        • +

          setInstrumentationLevel

          +
          public static void setInstrumentationLevel(int level)
          +
          Sets the current instrumentation level. +

          + Instrumentation level is used in evaluating OnMethod.enableAt() + expressions to enable/disable the probe handler.

          +
          +
          Parameters:
          +
          level - an arbitrary non negative integer number
          +
          Since:
          +
          1.3.4
          +
          +
        • +
        + + + +
          +
        • +

          getInstrumentationLevel

          +
          public static int getInstrumentationLevel()
          +
          Returns the current instrumentation level. +

          + Instrumentation level is used in evaluating OnMethod.enableAt() + expressions to enable/disable the probe handler.

          +
          +
          Returns:
          +
          the instrumentation level (non negative integer)
          +
          Since:
          +
          1.3.4
          +
          +
        • +
        + + + +
          +
        • +

          $

          +
          public static java.lang.String $(int n)
          +
          Returns n'th command line argument. null if not available.
          +
          +
          Parameters:
          +
          n - command line argument index
          +
          Returns:
          +
          n'th command line argument
          +
          +
        • +
        + + + +
          +
        • +

          $

          +
          public static java.lang.String $(java.lang.String key)
          +
          Returns a command line argument value for the given key. null if not available.
          + In order to provide a key-value pair on the command line it must have the following syntax - + <key>=<value>
          +
          +
          Parameters:
          +
          key - the argument key
          +
          Returns:
          +
          the corresponding value or null
          +
          +
        • +
        + + + +
          +
        • +

          getpid

          +
          public static int getpid()
          +
          Returns the process id of the currently BTrace'd process.
          +
        • +
        + + + +
          +
        • +

          $length

          +
          public static int $length()
          +
          Returns the number of command line arguments.
          +
        • +
        + + + +
          +
        • +

          newAtomicInteger

          +
          public static java.util.concurrent.atomic.AtomicInteger newAtomicInteger(int initialValue)
          +
          Creates a new AtomicInteger with the given initial value.
          +
          +
          Parameters:
          +
          initialValue - the initial value
          +
          +
        • +
        + + + +
          +
        • +

          get

          +
          public static int get(java.util.concurrent.atomic.AtomicInteger ai)
          +
          Gets the current value of the given AtomicInteger.
          +
          +
          Parameters:
          +
          ai - AtomicInteger whose value is returned.
          +
          Returns:
          +
          the current value
          +
          +
        • +
        + + + +
          +
        • +

          set

          +
          public static void set(java.util.concurrent.atomic.AtomicInteger ai,
          +                       int newValue)
          +
          Sets to the given value to the given AtomicInteger.
          +
          +
          Parameters:
          +
          ai - AtomicInteger whose value is set.
          +
          newValue - the new value
          +
          +
        • +
        + + + +
          +
        • +

          lazySet

          +
          public static void lazySet(java.util.concurrent.atomic.AtomicInteger ai,
          +                           int newValue)
          +
          Eventually sets to the given value to the given AtomicInteger.
          +
          +
          Parameters:
          +
          ai - AtomicInteger whose value is lazily set.
          +
          newValue - the new value
          +
          +
        • +
        + + + +
          +
        • +

          compareAndSet

          +
          public static boolean compareAndSet(java.util.concurrent.atomic.AtomicInteger ai,
          +                                    int expect,
          +                                    int update)
          +
          Atomically sets the value of given AtomitInteger to the given + updated value if the current value == the expected value.
          +
          +
          Parameters:
          +
          ai - AtomicInteger whose value is compared and set.
          +
          expect - the expected value
          +
          update - the new value
          +
          Returns:
          +
          true if successful. False return indicates that + the actual value was not equal to the expected value.
          +
          +
        • +
        + + + +
          +
        • +

          weakCompareAndSet

          +
          public static boolean weakCompareAndSet(java.util.concurrent.atomic.AtomicInteger ai,
          +                                        int expect,
          +                                        int update)
          +
          Atomically sets the value to the given updated value + if the current value == the expected value. + +

          May fail spuriously + and does not provide ordering guarantees, so is only rarely an + appropriate alternative to compareAndSet.

          +
          +
          Parameters:
          +
          ai - AtomicInteger whose value is weakly compared and set.
          +
          expect - the expected value
          +
          update - the new value
          +
          Returns:
          +
          true if successful.
          +
          +
        • +
        + + + +
          +
        • +

          getAndIncrement

          +
          public static int getAndIncrement(java.util.concurrent.atomic.AtomicInteger ai)
          +
          Atomically increments by one the current value of given AtomicInteger.
          +
          +
          Parameters:
          +
          ai - AtomicInteger that is incremented.
          +
          Returns:
          +
          the previous value
          +
          +
        • +
        + + + +
          +
        • +

          getAndDecrement

          +
          public static int getAndDecrement(java.util.concurrent.atomic.AtomicInteger ai)
          +
          Atomically decrements by one the current value of given AtomicInteger.
          +
          +
          Parameters:
          +
          ai - AtomicInteger that is decremented.
          +
          Returns:
          +
          the previous value
          +
          +
        • +
        + + + +
          +
        • +

          incrementAndGet

          +
          public static int incrementAndGet(java.util.concurrent.atomic.AtomicInteger ai)
          +
          Atomically increments by one the current value of given AtomicInteger.
          +
          +
          Parameters:
          +
          ai - AtomicInteger that is incremented.
          +
          Returns:
          +
          the updated value
          +
          +
        • +
        + + + +
          +
        • +

          decrementAndGet

          +
          public static int decrementAndGet(java.util.concurrent.atomic.AtomicInteger ai)
          +
          Atomically decrements by one the current value of given AtomicInteger.
          +
          +
          Parameters:
          +
          ai - AtomicInteger whose value is decremented.
          +
          Returns:
          +
          the updated value
          +
          +
        • +
        + + + +
          +
        • +

          getAndAdd

          +
          public static int getAndAdd(java.util.concurrent.atomic.AtomicInteger ai,
          +                            int delta)
          +
          Atomically adds the given value to the current value.
          +
          +
          Parameters:
          +
          ai - AtomicInteger whose value is added to.
          +
          delta - the value to add
          +
          Returns:
          +
          the previous value
          +
          +
        • +
        + + + +
          +
        • +

          addAndGet

          +
          public static int addAndGet(java.util.concurrent.atomic.AtomicInteger ai,
          +                            int delta)
          +
          Atomically adds the given value to the current value.
          +
          +
          Parameters:
          +
          ai - AtomicInteger whose value is added to.
          +
          delta - the value to add
          +
          Returns:
          +
          the updated value
          +
          +
        • +
        + + + +
          +
        • +

          getAndSet

          +
          public static int getAndSet(java.util.concurrent.atomic.AtomicInteger ai,
          +                            int newValue)
          +
          Atomically sets to the given value and returns the old value.
          +
          +
          Parameters:
          +
          ai - AtomicInteger whose value is set.
          +
          newValue - the new value
          +
          Returns:
          +
          the previous value
          +
          +
        • +
        + + + +
          +
        • +

          newAtomicLong

          +
          public static java.util.concurrent.atomic.AtomicLong newAtomicLong(long initialValue)
          +
          Creates a new AtomicLong with the given initial value.
          +
          +
          Parameters:
          +
          initialValue - the initial value
          +
          +
        • +
        + + + +
          +
        • +

          get

          +
          public static long get(java.util.concurrent.atomic.AtomicLong al)
          +
          Gets the current value the given AtomicLong.
          +
          +
          Parameters:
          +
          al - AtomicLong whose value is returned.
          +
          Returns:
          +
          the current value
          +
          +
        • +
        + + + +
          +
        • +

          set

          +
          public static void set(java.util.concurrent.atomic.AtomicLong al,
          +                       long newValue)
          +
          Sets to the given value.
          +
          +
          Parameters:
          +
          al - AtomicLong whose value is set.
          +
          newValue - the new value
          +
          +
        • +
        + + + +
          +
        • +

          lazySet

          +
          public static void lazySet(java.util.concurrent.atomic.AtomicLong al,
          +                           long newValue)
          +
          Eventually sets to the given value to the given AtomicLong.
          +
          +
          Parameters:
          +
          al - AtomicLong whose value is set.
          +
          newValue - the new value
          +
          +
        • +
        + + + +
          +
        • +

          compareAndSet

          +
          public static boolean compareAndSet(java.util.concurrent.atomic.AtomicLong al,
          +                                    long expect,
          +                                    long update)
          +
          Atomically sets the value to the given updated value + if the current value == the expected value.
          +
          +
          Parameters:
          +
          al - AtomicLong whose value is compared and set.
          +
          expect - the expected value
          +
          update - the new value
          +
          Returns:
          +
          true if successful. False return indicates that + the actual value was not equal to the expected value.
          +
          +
        • +
        + + + +
          +
        • +

          weakCompareAndSet

          +
          public static boolean weakCompareAndSet(java.util.concurrent.atomic.AtomicLong al,
          +                                        long expect,
          +                                        long update)
          +
          Atomically sets the value to the given updated value + if the current value == the expected value. + +

          May fail spuriously + and does not provide ordering guarantees, so is only rarely an + appropriate alternative to compareAndSet.

          +
          +
          Parameters:
          +
          al - AtomicLong whose value is compared and set.
          +
          expect - the expected value
          +
          update - the new value
          +
          Returns:
          +
          true if successful.
          +
          +
        • +
        + + + +
          +
        • +

          getAndIncrement

          +
          public static long getAndIncrement(java.util.concurrent.atomic.AtomicLong al)
          +
          Atomically increments by one the current value.
          +
          +
          Parameters:
          +
          al - AtomicLong whose value is incremented.
          +
          Returns:
          +
          the previous value
          +
          +
        • +
        + + + +
          +
        • +

          getAndDecrement

          +
          public static long getAndDecrement(java.util.concurrent.atomic.AtomicLong al)
          +
          Atomically decrements by one the current value.
          +
          +
          Parameters:
          +
          al - AtomicLong whose value is decremented.
          +
          Returns:
          +
          the previous value
          +
          +
        • +
        + + + +
          +
        • +

          incrementAndGet

          +
          public static long incrementAndGet(java.util.concurrent.atomic.AtomicLong al)
          +
          Atomically increments by one the current value.
          +
          +
          Parameters:
          +
          al - AtomicLong whose value is incremented.
          +
          Returns:
          +
          the updated value
          +
          +
        • +
        + + + +
          +
        • +

          decrementAndGet

          +
          public static long decrementAndGet(java.util.concurrent.atomic.AtomicLong al)
          +
          Atomically decrements by one the current value.
          +
          +
          Parameters:
          +
          al - AtomicLong whose value is decremented.
          +
          Returns:
          +
          the updated value
          +
          +
        • +
        + + + +
          +
        • +

          getAndAdd

          +
          public static long getAndAdd(java.util.concurrent.atomic.AtomicLong al,
          +                             long delta)
          +
          Atomically adds the given value to the current value.
          +
          +
          Parameters:
          +
          al - AtomicLong whose value is added to.
          +
          delta - the value to add
          +
          Returns:
          +
          the previous value
          +
          +
        • +
        + + + +
          +
        • +

          addAndGet

          +
          public static long addAndGet(java.util.concurrent.atomic.AtomicLong al,
          +                             long delta)
          +
          Atomically adds the given value to the current value.
          +
          +
          Parameters:
          +
          al - AtomicLong whose value is added to
          +
          delta - the value to add
          +
          Returns:
          +
          the updated value
          +
          +
        • +
        + + + +
          +
        • +

          getAndSet

          +
          public static long getAndSet(java.util.concurrent.atomic.AtomicLong al,
          +                             long newValue)
          +
          Atomically sets to the given value and returns the old value.
          +
          +
          Parameters:
          +
          al - AtomicLong that is set.
          +
          newValue - the new value
          +
          Returns:
          +
          the previous value
          +
          +
        • +
        + + + +
          +
        • +

          dtraceProbe

          +
          public static int dtraceProbe(java.lang.String str1,
          +                              java.lang.String str2)
          +
          BTrace to DTrace communication chennal. + Raise DTrace USDT probe from BTrace.
          +
          +
          See Also:
          +
          dtraceProbe(String,String,int,int)
          +
          +
        • +
        + + + +
          +
        • +

          dtraceProbe

          +
          public static int dtraceProbe(java.lang.String str1,
          +                              java.lang.String str2,
          +                              int i1)
          +
          BTrace to DTrace communication chennal. + Raise DTrace USDT probe from BTrace.
          +
          +
          See Also:
          +
          dtraceProbe(String,String,int,int)
          +
          +
        • +
        + + + +
          +
        • +

          dtraceProbe

          +
          public static int dtraceProbe(java.lang.String str1,
          +                              java.lang.String str2,
          +                              int i1,
          +                              int i2)
          +
          BTrace to DTrace communication channel. + Raise DTrace USDT probe from BTrace.
          +
          +
          Parameters:
          +
          str1 - first String param to DTrace probe
          +
          str2 - second String param to DTrace probe
          +
          i1 - first int param to DTrace probe
          +
          i2 - second int param to DTrace probe
          +
          +
        • +
        + + + +
          +
        • +

          property

          +
          public static java.lang.String property(java.lang.String key)
          +
          Gets the system property indicated by the specified key.
          +
          +
          Parameters:
          +
          key - the name of the system property.
          +
          Returns:
          +
          the string value of the system property, + or null if there is no property with that key.
          +
          Throws:
          +
          java.lang.NullPointerException - if key is + null.
          +
          java.lang.IllegalArgumentException - if key is empty.
          +
          +
        • +
        + + + +
          +
        • +

          properties

          +
          public static java.util.Properties properties()
          +
          Returns all Sys properties.
          +
          +
          Returns:
          +
          the system properties
          +
          +
        • +
        + + + +
          +
        • +

          printProperties

          +
          public static void printProperties()
          +
          Prints all Sys properties.
          +
        • +
        + + + +
          +
        • +

          getenv

          +
          public static java.lang.String getenv(java.lang.String name)
          +
          Gets the value of the specified environment variable. An + environment variable is a system-dependent external named + value.
          +
          +
          Parameters:
          +
          name - the name of the environment variable
          +
          Returns:
          +
          the string value of the variable, or null + if the variable is not defined in the system environment
          +
          Throws:
          +
          java.lang.NullPointerException - if name is null
          +
          +
        • +
        + + + +
          +
        • +

          getenv

          +
          public static java.util.Map<java.lang.String,java.lang.String> getenv()
          +
          Returns an unmodifiable string map view of the current system environment. + The environment is a system-dependent mapping from names to + values which is passed from parent to child processes.
          +
          +
          Returns:
          +
          the environment as a map of variable names to values
          +
          +
        • +
        + + + +
          +
        • +

          printEnv

          +
          public static void printEnv()
          +
          Prints all system environment values.
          +
        • +
        + + + +
          +
        • +

          availableProcessors

          +
          public static long availableProcessors()
          +
          Returns the number of processors available to the Java virtual machine. +

          + This value may change during a particular invocation of the virtual + machine. Applications that are sensitive to the number of available + processors should therefore occasionally poll this property and adjust + their resource usage appropriately.

          +
          +
          Returns:
          +
          the maximum number of processors available to the virtual + machine; never smaller than one
          +
          +
        • +
        + + + +
          +
        • +

          freeMemory

          +
          public static long freeMemory()
          +
          Returns the amount of free memory in the Java Virtual Machine. + Calling the + gc method may result in increasing the value returned + by freeMemory.
          +
          +
          Returns:
          +
          an approximation to the total amount of memory currently + available for future allocated objects, measured in bytes.
          +
          +
        • +
        + + + +
          +
        • +

          totalMemory

          +
          public static long totalMemory()
          +
          Returns the total amount of memory in the Java virtual machine. + The value returned by this method may vary over time, depending on + the host environment. +

          + Note that the amount of memory required to hold an object of any + given type may be implementation-dependent.

          +
          +
          Returns:
          +
          the total amount of memory currently available for current + and future objects, measured in bytes.
          +
          +
        • +
        + + + +
          +
        • +

          maxMemory

          +
          public static long maxMemory()
          +
          Returns the maximum amount of memory that the Java virtual machine will + attempt to use. If there is no inherent limit then the value Long.MAX_VALUE will be returned.
          +
          +
          Returns:
          +
          the maximum amount of memory that the virtual machine will + attempt to use, measured in bytes
          +
          +
        • +
        + + + +
          +
        • +

          heapUsage

          +
          public static java.lang.management.MemoryUsage heapUsage()
          +
          Returns heap memory usage
          +
        • +
        + + + +
          +
        • +

          nonHeapUsage

          +
          public static java.lang.management.MemoryUsage nonHeapUsage()
          +
          Returns non-heap memory usage
          +
        • +
        + + + +
          +
        • +

          init

          +
          public static long init(java.lang.management.MemoryUsage mu)
          +
          Returns the amount of memory in bytes that the Java virtual + machine initially requests from the operating system for + memory management.
          +
        • +
        + + + +
          +
        • +

          committed

          +
          public static long committed(java.lang.management.MemoryUsage mu)
          +
          Returns the amount of memory in bytes that is committed for the Java + virtual machine to use. This amount of memory is guaranteed for the + Java virtual machine to use.
          +
        • +
        + + + +
          +
        • +

          max

          +
          public static long max(java.lang.management.MemoryUsage mu)
          +
          Returns the maximum amount of memory in bytes that can be used + for memory management. This method returns -1 if the maximum memory + size is undefined.
          +
        • +
        + + + +
          +
        • +

          used

          +
          public static long used(java.lang.management.MemoryUsage mu)
          +
          Returns the amount of used memory in bytes.
          +
        • +
        + + + +
          +
        • +

          finalizationCount

          +
          public static long finalizationCount()
          +
          Returns the approximate number of objects for + which finalization is pending.
          +
        • +
        + + + +
          +
        • +

          vmArguments

          +
          public static java.util.List<java.lang.String> vmArguments()
          +
          Returns the input arguments passed to the Java virtual machine + which does not include the arguments to the main method. + This method returns an empty list if there is no input argument + to the Java virtual machine. +

          + Some Java virtual machine implementations may take input arguments + from multiple different sources: for examples, arguments passed from + the application that launches the Java virtual machine such as + the 'java' command, environment variables, configuration files, etc. +

          + Typically, not all command-line options to the 'java' command + are passed to the Java virtual machine. + Thus, the returned input arguments may not + include all command-line options.

          +
          +
          Returns:
          +
          a list of String objects; each element + is an argument passed to the Java virtual machine.
          +
          +
        • +
        + + + +
          +
        • +

          printVmArguments

          +
          public static void printVmArguments()
          +
          Prints VM input arguments list.
          +
          +
          See Also:
          +
          vmArguments()
          +
          +
        • +
        + + + +
          +
        • +

          vmVersion

          +
          public static java.lang.String vmVersion()
          +
          Returns the Java virtual machine implementation version. + This method is equivalent to Sys.getProperty("java.vm.version").
          +
          +
          Returns:
          +
          the Java virtual machine implementation version.
          +
          +
        • +
        + + + +
          +
        • +

          isBootClassPathSupported

          +
          public static boolean isBootClassPathSupported()
          +
          Tests if the Java virtual machine supports the boot class path + mechanism used by the bootstrap class loader to search for class + files.
          +
          +
          Returns:
          +
          true if the Java virtual machine supports the + class path mechanism; false otherwise.
          +
          +
        • +
        + + + +
          +
        • +

          bootClassPath

          +
          public static java.lang.String bootClassPath()
          +
          Returns the boot class path that is used by the bootstrap class loader + to search for class files. + +

          Multiple paths in the boot class path are separated by the + path separator character of the platform on which the Java + virtual machine is running. + +

          A Java virtual machine implementation may not support + the boot class path mechanism for the bootstrap class loader + to search for class files. + The isBootClassPathSupported() method can be used + to determine if the Java virtual machine supports this method.

          +
          +
          Returns:
          +
          the boot class path.
          +
          Throws:
          +
          java.lang.UnsupportedOperationException - if the Java virtual machine does not support this operation.
          +
          +
        • +
        + + + +
          +
        • +

          classPath

          +
          public static java.lang.String classPath()
          +
          Returns the Java class path that is used by the system class loader + to search for class files. + This method is equivalent to Sys.getProperty("java.class.path").
          +
          +
          Returns:
          +
          the Java class path.
          +
          +
        • +
        + + + +
          +
        • +

          libraryPath

          +
          public static java.lang.String libraryPath()
          +
          Returns the Java library path. + This method is equivalent to Sys.getProperty("java.library.path"). + +

          Multiple paths in the Java library path are separated by the + path separator character of the platform of the Java virtual machine + being monitored.

          +
          +
          Returns:
          +
          the Java library path.
          +
          +
        • +
        + + + +
          +
        • +

          threadCount

          +
          public static long threadCount()
          +
          Returns the current number of live threads including both + daemon and non-daemon threads.
          +
          +
          Returns:
          +
          the current number of live threads.
          +
          +
        • +
        + + + +
          +
        • +

          peakThreadCount

          +
          public static long peakThreadCount()
          +
          Returns the peak live thread count since the Java virtual machine + started or peak was reset.
          +
          +
          Returns:
          +
          the peak live thread count.
          +
          +
        • +
        + + + +
          +
        • +

          totalStartedThreadCount

          +
          public static long totalStartedThreadCount()
          +
          Returns the total number of threads created and also started + since the Java virtual machine started.
          +
          +
          Returns:
          +
          the total number of threads started.
          +
          +
        • +
        + + + +
          +
        • +

          daemonThreadCount

          +
          public static long daemonThreadCount()
          +
          Returns the current number of live daemon threads.
          +
          +
          Returns:
          +
          the current number of live daemon threads.
          +
          +
        • +
        + + + +
          +
        • +

          currentThreadCpuTime

          +
          public static long currentThreadCpuTime()
          +
          Returns the total CPU time for the current thread in nanoseconds. + The returned value is of nanoseconds precision but + not necessarily nanoseconds accuracy. + If the implementation distinguishes between user mode time and system + mode time, the returned CPU time is the amount of time that + the current thread has executed in user mode or system mode.
          +
        • +
        + + + +
          +
        • +

          currentThreadUserTime

          +
          public static long currentThreadUserTime()
          +
          Returns the CPU time that the current thread has executed + in user mode in nanoseconds. + The returned value is of nanoseconds precision but + not necessarily nanoseconds accuracy.
          +
        • +
        + + + +
          +
        • +

          getTotalGcTime

          +
          public static long getTotalGcTime()
          +
          Returns the total amount of time spent in GarbageCollection up to this point + since the application was started.
          +
          +
          Returns:
          +
          Returns the amount of overall time spent in GC
          +
          +
        • +
        + + + +
          +
        • +

          sizeof

          +
          public static long sizeof(java.lang.Object objectToSize)
          +
          Returns an implementation-specific approximation of the amount of storage consumed by + the specified object. The result may include some or all of the object's overhead, + and thus is useful for comparison within an implementation but not between implementations. + + The estimate may change during a single invocation of the JVM.
          +
          +
          Parameters:
          +
          objectToSize - the object to size
          +
          Returns:
          +
          an implementation-specific approximation of the amount of storage consumed by the specified object
          +
          Throws:
          +
          java.lang.NullPointerException - if the supplied Object is null.
          +
          +
        • +
        + + + +
          +
        • +

          dumpHeap

          +
          public static void dumpHeap(java.lang.String fileName)
          +
          Dump the snapshot of the Java heap to a file in hprof + binary format. Only the live objects are dumped. + Under the current dir of traced app, ./btrace<pid>/<btrace-class>/ + directory is created. Under that directory, a file of given + fileName is created.
          +
          +
          Parameters:
          +
          fileName - name of the file to which heap is dumped
          +
          +
        • +
        + + + +
          +
        • +

          dumpHeap

          +
          public static void dumpHeap(java.lang.String fileName,
          +                            boolean live)
          +
          Dump the snapshot of the Java heap to a file in hprof + binary format. + Under the current dir of traced app, ./btrace<pid>/<btrace-class>/ + directory is created. Under that directory, a file of given + fileName is created.
          +
          +
          Parameters:
          +
          fileName - name of the file to which heap is dumped
          +
          live - flag that tells whether only live objects are + to be dumped or all objects are to be dumped.
          +
          +
        • +
        + + + +
          +
        • +

          gc

          +
          public static void gc()
          +
          Runs the garbage collector. +

          + Calling the gc method suggests that the Java Virtual + Machine expend effort toward recycling unused objects in order to + make the memory they currently occupy available for quick reuse. + When control returns from the method call, the Java Virtual + Machine has made a best effort to reclaim space from all discarded + objects. This method calls Sys.gc() to perform GC.

          +
        • +
        + + + +
          +
        • +

          runFinalization

          +
          public static void runFinalization()
          +
          Runs the finalization methods of any objects pending finalization. +

          + Calling this method suggests that the Java Virtual Machine expend + effort toward running the finalize methods of objects + that have been found to be discarded but whose finalize + methods have not yet been run. When control returns from the + method call, the Java Virtual Machine has made a best effort to + complete all outstanding finalizations. This method calls + Sys.runFinalization() to run finalization.

          +
        • +
        + + + +
          +
        • +

          serialize

          +
          public static void serialize(java.io.Serializable obj,
          +                             java.lang.String fileName)
          +
          Serialize a given object into the given file. + Under the current dir of traced app, ./btrace<pid>/<btrace-class>/ + directory is created. Under that directory, a file of given + fileName is created.
          +
          +
          Parameters:
          +
          obj - object that has to be serialized.
          +
          fileName - name of the file to which the object is serialized.
          +
          +
        • +
        + + + +
          +
        • +

          toXML

          +
          public static java.lang.String toXML(java.lang.Object obj)
          +
          Creates an XML document to persist the tree of the all + transitively reachable objects from given "root" object.
          +
        • +
        + + + +
          +
        • +

          writeXML

          +
          public static void writeXML(java.lang.Object obj,
          +                            java.lang.String fileName)
          +
          Writes an XML document to persist the tree of the all the + transitively reachable objects from the given "root" object. + Under the current dir of traced app, ./btrace<pid>/<btrace-class>/ + directory is created. Under that directory, a file of the given + fileName is created.
          +
        • +
        + + + +
          +
        • +

          writeDOT

          +
          public static void writeDOT(java.lang.Object obj,
          +                            java.lang.String fileName)
          +
          Writes a .dot document to persist the tree of the all the + transitively reachable objects from the given "root" object. + .dot documents can be viewed by Graphviz application (www.graphviz.org) + Under the current dir of traced app, ./btrace<pid>/<btrace-class>/ + directory is created. Under that directory, a file of the given + fileName is created.
          +
          +
          Since:
          +
          1.1
          +
          +
        • +
        + + + +
          +
        • +

          speculation

          +
          public static int speculation()
          +
          Returns an identifier for a new speculative buffer.
          +
          +
          Returns:
          +
          new speculative buffer id
          +
          +
        • +
        + + + +
          +
        • +

          speculate

          +
          public static void speculate(int id)
          +
          Sets current speculative buffer id.
          +
          +
          Parameters:
          +
          id - the speculative buffer id
          +
          +
        • +
        + + + +
          +
        • +

          commit

          +
          public static void commit(int id)
          +
          Commits the speculative buffer associated with id.
          +
          +
          Parameters:
          +
          id - the speculative buffer id
          +
          +
        • +
        + + + +
          +
        • +

          discard

          +
          public static void discard(int id)
          +
          Discards the speculative buffer associated with id.
          +
          +
          Parameters:
          +
          id - the speculative buffer id
          +
          +
        • +
        + + + +
          +
        • +

          newAggregation

          +
          public static Aggregation newAggregation(AggregationFunction type)
          +
          Creates a new aggregation based on the given aggregation function type.
          +
          +
          Parameters:
          +
          type - the aggregating function to be performed on the data being added to the aggregation.
          +
          +
        • +
        + + + +
          +
        • +

          newAggregationKey

          +
          public static AggregationKey newAggregationKey(java.lang.Object element1)
          +
          Creates a grouping aggregation key with the provided value. The value must be a String or Number type.
          +
          +
          Parameters:
          +
          element1 - the value of the aggregation key
          +
          +
        • +
        + + + +
          +
        • +

          newAggregationKey

          +
          public static AggregationKey newAggregationKey(java.lang.Object element1,
          +                                               java.lang.Object element2)
          +
          Creates a composite grouping aggregation key with the provided values. The values must be String or Number types.
          +
          +
          Parameters:
          +
          element1 - the first element of the composite aggregation key
          +
          element2 - the second element of the composite aggregation key
          +
          +
        • +
        + + + +
          +
        • +

          newAggregationKey

          +
          public static AggregationKey newAggregationKey(java.lang.Object element1,
          +                                               java.lang.Object element2,
          +                                               java.lang.Object element3)
          +
          Creates a composite grouping aggregation key with the provided values. The values must be String or Number types.
          +
          +
          Parameters:
          +
          element1 - the first element of the composite aggregation key
          +
          element2 - the second element of the composite aggregation key
          +
          element3 - the third element of the composite aggregation key
          +
          +
        • +
        + + + +
          +
        • +

          newAggregationKey

          +
          public static AggregationKey newAggregationKey(java.lang.Object element1,
          +                                               java.lang.Object element2,
          +                                               java.lang.Object element3,
          +                                               java.lang.Object element4)
          +
          Creates a composite grouping aggregation key with the provided values. The values must be String or Number types.
          +
          +
          Parameters:
          +
          element1 - the first element of the composite aggregation key
          +
          element2 - the second element of the composite aggregation key
          +
          element3 - the third element of the composite aggregation key
          +
          element4 - the fourth element of the composite aggregation key
          +
          +
        • +
        + + + +
          +
        • +

          addToAggregation

          +
          public static void addToAggregation(Aggregation aggregation,
          +                                    long value)
          +
          Adds a value to the aggregation with no grouping key. This method should be used when the aggregation + is to calculate only a single aggregated value.
          +
          +
          Parameters:
          +
          aggregation - the aggregation to which the value should be added
          +
          +
        • +
        + + + +
          +
        • +

          addToAggregation

          +
          public static void addToAggregation(Aggregation aggregation,
          +                                    AggregationKey key,
          +                                    long value)
          +
          Adds a value to the aggregation with a grouping key. This method should be used when the aggregation + should effectively perform a "group by" on the key value. The aggregation will calculate a separate + aggregated value for each unique aggregation key.
          +
          +
          Parameters:
          +
          aggregation - the aggregation to which the value should be added
          +
          key - the grouping aggregation key
          +
          +
        • +
        + + + +
          +
        • +

          clearAggregation

          +
          public static void clearAggregation(Aggregation aggregation)
          +
          Resets values within the aggregation to the default. This will affect all values within the aggregation + when multiple aggregation keys have been used.
          +
          +
          Parameters:
          +
          aggregation - the aggregation to be cleared
          +
          +
        • +
        + + + +
          +
        • +

          truncateAggregation

          +
          public static void truncateAggregation(Aggregation aggregation,
          +                                       int count)
          +
          Removes all aggregated values from the aggregation except for the largest or smallest + abs(count) elements. + +

          If count is positive, the largest aggregated values in the aggregation will be + preserved. If count is negative the smallest values will be preserved. If count + is zero then all elements will be removed. + +

          Behavior is intended to be similar to the dtrace trunc() function.

          +
          +
          Parameters:
          +
          aggregation - the aggregation to be truncated
          +
          count - the number of elements to preserve. If negative, the smallest abs(count) elements are preserved.
          +
          +
        • +
        + + + +
          +
        • +

          printAggregation

          +
          public static void printAggregation(java.lang.String name,
          +                                    Aggregation aggregation)
          +
          Prints the aggregation.
          +
        • +
        + + + +
          +
        • +

          printAggregation

          +
          public static void printAggregation(java.lang.String name,
          +                                    Aggregation aggregation,
          +                                    java.lang.String format)
          +
          Prints aggregation using the provided format
          +
          +
          Parameters:
          +
          name - The name of the aggregation to be used in the textual output
          +
          aggregation - The aggregation to print
          +
          format - The format to use. It mimics String.format(java.lang.String, java.lang.Object[]) behaviour + with the addition of the ability to address the key title as a 0-indexed item
          +
          Since:
          +
          1.1
          +
          See Also:
          +
          String.format(java.lang.String, java.lang.Object[])
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/CommandListener.html b/misc/btrace/javadoc/com/sun/btrace/CommandListener.html new file mode 100644 index 00000000..fa352f6e --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/CommandListener.html @@ -0,0 +1,226 @@ + + + + + +CommandListener (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Interface CommandListener

    +
    +
    +
    +
      +
    • +
      +
      +
      public interface CommandListener
      +
      Callback interface called to notify wire + protocol commands.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          onCommand

          +
          void onCommand(Command cmd)
          +        throws java.io.IOException
          +
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/DOTWriter.html b/misc/btrace/javadoc/com/sun/btrace/DOTWriter.html new file mode 100644 index 00000000..1524d6d7 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/DOTWriter.html @@ -0,0 +1,774 @@ + + + + + +DOTWriter (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class DOTWriter

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.DOTWriter
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public class DOTWriter
      +extends java.lang.Object
      +
      Library for constructing a dot file format file containing the state of select + objects in the current running application. + + Introduction + ============ + + Sometimes when debugging an complex problem, a picture is worth more than a + thousand words. Looking at an object set graphically can simplify understanding + of some of the problems. + + DOTWriter is designed to analyze a set of Java objects and generate a + dot format file. The file can be passed to any number of tools for further + analysis. The multi-platform tools are described at http://graphviz.org/. The + most commonly used are the 'dot' command and the 'Graphviz' application. + + The 'dot' command can be used to convert a dot format file into any number of + visual format files; jpg, png, pdf et cetera. + + Ex. + dot -Tpdf -osample.pdf sample.dot + + There are also other tools to convert dot format files to other representations + such gxl (using dot2gxl.) + + Using DOTWriter is straight forward. Simply construct an DOTWriter instance, + add objects to observe, then close the instance. + + Ex. + + import com.sun.btrace.DOTWriter; + + var dot = new DOTWriter("sample.dot"); + dot.addNodes(a, b, c); + dot.close(); + + There is also a quick and dirty form to do the same. Note: to get dependency + edges you need to build the class file with -XDannobindees + + Ex. + DOTWriter.graph("sample.dot", a, b, c); + + The other calls on the public interface allows more detailed control of the + graph. Details below. + + You also have the ability to control dot format properties. + + Ex. + DOTWriter.graph("sample.dot", "fillcolor=lightblue", a, "fillcolor=lightpink", b, c); + + Will display 'a' in blue and 'b'/'c' in pink. Properties are specified in + "k=v, ..., k=v" form. + + + Public Interface + ================ + + Graphing + -------- + + public DOTWriter(String fileName); + + The constructor creates a file stream for the dot output. The filename string + is the name of the file, and should have the .dot extension. + + + public void close(); + + This method writes the graph to the file stream and closes out the graph. Any + further operations will be ignored. + + + public static void graph(String fileName, Object... objects); + + All-in-one graph objects. Specify which objects you want graphed. If an object + argument is a String then it is used as the default properties for all object + arguments following. + + + public void addNodes(Object... objects); + + Add a set of objects to the graph. If an object argument is a string then the + string is used as a property string for the remaining object arguments. + + + public void addNode(String propertyString, Object object); + + Add an individual object to the graph. The property string defines the dot + Properties for the string. If the object is of primitive data type or null then + it will be ignored. + + + public void addEdge(Object head, Object tail); + public void addEdge(Object head, Object tail, String propertyString); + public void addEdge(Object head, int headFieldId, Object tail, int tailFieldId); + public void addEdge(Object head, int headFieldId, Object tail, int tailFieldId, String propertyString); + + Add Edges to the node. Field ids indicate which slot to start/end from, -1 + indicates the whole object. + + + + Control Display + ---------------- + + public void objectLimit(int objectLimit); + + The maximum number of objects to display in detail in the graph (default=256.) + More objects may be displayed but they will be truncated. Having a lower limit + speeds up the processing of the graph. + + + public void fieldLimit(int fieldLimit); + + The maximum number of fields to display for an object (default=64.) Having a + lower limit speeds up the processing of the graph. + + + public void arrayLimit(int arrayLimit); + + The maximum number of slots to display for an array (default=32.) Having a + lower limit speeds up the processing of the graph. + + + public void stringLimit(int stringLimit); + + The maximum length of a string to display (default=32.) Having a + lower limit speeds up the processing of the graph. + + + public void expandCollections(boolean expandCollections); + + Controls the display of collections. By default, collections are displayed + as simple arrays. expandCollections == true, displays collections as + individual java objects. + + public void displayStatics(boolean displayStatics) + + Controls whether static fields are displayed. By default displayStatics == false. + + + public void displayLinks(boolean displayLinks); + + Controls whether data links are displayed. By default displayLinks == true. + You may want to set displayLinks = false, if all you want to look at is + dependencies. + + Filtering + --------- + + public void includeObjects(Object... objects); + + Only objects specified are included in the graph. + + + public void excludeObjects(Object... objects) + + Objects specified are excluded from the graph. This may truncated data links + as well. + + + public void includeClasses(Class... clazzes); + + Only objects that are instances of the specified classes are included in the + graph. + + public void excludeClasses(Class... clazzes); + + Classes to be excluded from the graph.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Summary

        + + + + + + + + + + +
        Fields 
        Modifier and TypeField and Description
        static java.lang.StringDOTWRITER_PREFIX 
        +
      • +
      + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        DOTWriter(java.lang.String fileName) 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        voidaddEdge(java.lang.Object head, + int headFieldId, + java.lang.Object tail, + int tailFieldId) 
        voidaddEdge(java.lang.Object head, + int headFieldId, + java.lang.Object tail, + int tailFieldId, + java.lang.String propertyString) 
        voidaddEdge(java.lang.Object head, + java.lang.Object tail) 
        voidaddEdge(java.lang.Object head, + java.lang.Object tail, + java.lang.String propertyString) 
        voidaddNode(java.lang.String propertyString, + java.lang.Object object) 
        voidaddNodes(java.lang.Object... objects) 
        voidarrayLimit(int arrayLimit) 
        voidclose() 
        voidcustomize(java.util.Properties props) 
        voiddisplayLinks(boolean displayLinks) 
        voiddisplayStatics(boolean displayStatics) 
        voidexcludeClasses(java.lang.Class... clazzes) 
        voidexcludeClassNames(java.util.regex.Pattern pattern) 
        voidexcludeObjects(java.lang.Object... objects) 
        voidexpandCollections(boolean expandCollections) 
        voidfieldLimit(int fieldLimit) 
        static voidgraph(java.lang.String fileName, + java.lang.Object... objects) 
        voidincludeClasses(java.lang.Class... clazzes) 
        voidincludeClassNames(java.util.regex.Pattern pattern) 
        voidincludeObjects(java.lang.Object... objects) 
        voidobjectLimit(int objectLimit) 
        voidstringLimit(int stringLimit) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Detail

        + + + +
          +
        • +

          DOTWRITER_PREFIX

          +
          public static final java.lang.String DOTWRITER_PREFIX
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          DOTWriter

          +
          public DOTWriter(java.lang.String fileName)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          customize

          +
          public void customize(java.util.Properties props)
          +
        • +
        + + + +
          +
        • +

          graph

          +
          public static void graph(java.lang.String fileName,
          +                         java.lang.Object... objects)
          +
        • +
        + + + +
          +
        • +

          addNodes

          +
          public void addNodes(java.lang.Object... objects)
          +
        • +
        + + + +
          +
        • +

          addNode

          +
          public void addNode(java.lang.String propertyString,
          +                    java.lang.Object object)
          +
        • +
        + + + +
          +
        • +

          objectLimit

          +
          public void objectLimit(int objectLimit)
          +
        • +
        + + + +
          +
        • +

          fieldLimit

          +
          public void fieldLimit(int fieldLimit)
          +
        • +
        + + + +
          +
        • +

          arrayLimit

          +
          public void arrayLimit(int arrayLimit)
          +
        • +
        + + + +
          +
        • +

          stringLimit

          +
          public void stringLimit(int stringLimit)
          +
        • +
        + + + +
          +
        • +

          expandCollections

          +
          public void expandCollections(boolean expandCollections)
          +
        • +
        + + + +
          +
        • +

          displayStatics

          +
          public void displayStatics(boolean displayStatics)
          +
        • +
        + + + +
          +
        • +

          displayLinks

          +
          public void displayLinks(boolean displayLinks)
          +
        • +
        + + + +
          +
        • +

          includeObjects

          +
          public void includeObjects(java.lang.Object... objects)
          +
        • +
        + + + +
          +
        • +

          excludeObjects

          +
          public void excludeObjects(java.lang.Object... objects)
          +
        • +
        + + + +
          +
        • +

          includeClasses

          +
          public void includeClasses(java.lang.Class... clazzes)
          +
        • +
        + + + +
          +
        • +

          includeClassNames

          +
          public void includeClassNames(java.util.regex.Pattern pattern)
          +
        • +
        + + + +
          +
        • +

          excludeClasses

          +
          public void excludeClasses(java.lang.Class... clazzes)
          +
        • +
        + + + +
          +
        • +

          excludeClassNames

          +
          public void excludeClassNames(java.util.regex.Pattern pattern)
          +
        • +
        + + + +
          +
        • +

          addEdge

          +
          public void addEdge(java.lang.Object head,
          +                    java.lang.Object tail)
          +
        • +
        + + + +
          +
        • +

          addEdge

          +
          public void addEdge(java.lang.Object head,
          +                    java.lang.Object tail,
          +                    java.lang.String propertyString)
          +
        • +
        + + + +
          +
        • +

          addEdge

          +
          public void addEdge(java.lang.Object head,
          +                    int headFieldId,
          +                    java.lang.Object tail,
          +                    int tailFieldId)
          +
        • +
        + + + +
          +
        • +

          addEdge

          +
          public void addEdge(java.lang.Object head,
          +                    int headFieldId,
          +                    java.lang.Object tail,
          +                    int tailFieldId,
          +                    java.lang.String propertyString)
          +
        • +
        + + + +
          +
        • +

          close

          +
          public void close()
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/DebugSupport.html b/misc/btrace/javadoc/com/sun/btrace/DebugSupport.html new file mode 100644 index 00000000..e813ae00 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/DebugSupport.html @@ -0,0 +1,363 @@ + + + + + +DebugSupport (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class DebugSupport

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.DebugSupport
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class DebugSupport
      +extends java.lang.Object
      +
      Centralized support for logging various debug information.
      +
    • +
    +
    +
    +
      +
    • + + + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        voiddebug(java.lang.String msg) 
        voiddebug(java.lang.Throwable th) 
        voiddumpClass(java.lang.String className, + byte[] code) 
        static voidinfo(java.lang.String msg) 
        booleanisDebug() 
        booleanisDumpClasses() 
        static voidwarning(java.lang.String msg) 
        static voidwarning(java.lang.Throwable th) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + + + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          isDebug

          +
          public boolean isDebug()
          +
        • +
        + + + +
          +
        • +

          isDumpClasses

          +
          public boolean isDumpClasses()
          +
        • +
        + + + +
          +
        • +

          dumpClass

          +
          public void dumpClass(java.lang.String className,
          +                      byte[] code)
          +
        • +
        + + + +
          +
        • +

          info

          +
          public static void info(java.lang.String msg)
          +
        • +
        + + + +
          +
        • +

          debug

          +
          public void debug(java.lang.String msg)
          +
        • +
        + + + +
          +
        • +

          debug

          +
          public void debug(java.lang.Throwable th)
          +
        • +
        + + + +
          +
        • +

          warning

          +
          public static void warning(java.lang.String msg)
          +
        • +
        + + + +
          +
        • +

          warning

          +
          public static void warning(java.lang.Throwable th)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/PerfReader.html b/misc/btrace/javadoc/com/sun/btrace/PerfReader.html new file mode 100644 index 00000000..37bd282d --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/PerfReader.html @@ -0,0 +1,248 @@ + + + + + +PerfReader (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Interface PerfReader

    +
    +
    +
    +
      +
    • +
      +
      +
      public interface PerfReader
      +
      This interface hides jvmstat classes from the + caller. The implementor of this interface should + read perf counters and return the value.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          perfInt

          +
          int perfInt(java.lang.String name)
          +
        • +
        + + + +
          +
        • +

          perfLong

          +
          long perfLong(java.lang.String name)
          +
        • +
        + + + +
          +
        • +

          perfString

          +
          java.lang.String perfString(java.lang.String name)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/Profiler.MBeanValueProvider.html b/misc/btrace/javadoc/com/sun/btrace/Profiler.MBeanValueProvider.html new file mode 100644 index 00000000..d2618789 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/Profiler.MBeanValueProvider.html @@ -0,0 +1,229 @@ + + + + + +Profiler.MBeanValueProvider (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Interface Profiler.MBeanValueProvider

    +
    +
    +
    +
      +
    • +
      +
      All Known Implementing Classes:
      +
      MethodInvocationProfiler
      +
      +
      +
      Enclosing class:
      +
      Profiler
      +
      +
      +
      +
      public static interface Profiler.MBeanValueProvider
      +
      Helper interface to make accessing a Profiler as an MBean + type safe.
      +
    • +
    +
    +
    + +
    +
    + +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/Profiler.Record.html b/misc/btrace/javadoc/com/sun/btrace/Profiler.Record.html new file mode 100644 index 00000000..961b4138 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/Profiler.Record.html @@ -0,0 +1,495 @@ + + + + + +Profiler.Record (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class Profiler.Record

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.Profiler.Record
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing class:
      +
      Profiler
      +
      +
      +
      +
      public static final class Profiler.Record
      +extends java.lang.Object
      +
      Record represents an atomic unit in the application execution call tree
      +
      +
      Since:
      +
      1.2
      +
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Field Detail

        + + + +
          +
        • +

          COMPARATOR

          +
          public static final java.util.Comparator<Profiler.Record> COMPARATOR
          +
        • +
        + + + +
          +
        • +

          blockName

          +
          public final java.lang.String blockName
          +
        • +
        + + + +
          +
        • +

          wallTime

          +
          public long wallTime
          +
        • +
        + + + +
          +
        • +

          wallTimeMax

          +
          public long wallTimeMax
          +
        • +
        + + + +
          +
        • +

          wallTimeMin

          +
          public long wallTimeMin
          +
        • +
        + + + +
          +
        • +

          selfTime

          +
          public long selfTime
          +
        • +
        + + + +
          +
        • +

          selfTimeMax

          +
          public long selfTimeMax
          +
        • +
        + + + +
          +
        • +

          selfTimeMin

          +
          public long selfTimeMin
          +
        • +
        + + + +
          +
        • +

          invocations

          +
          public long invocations
          +
        • +
        + + + +
          +
        • +

          onStack

          +
          public boolean onStack
          +
        • +
        + + + + +
      • +
      + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Record

          +
          public Record(java.lang.String blockName)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + + + + + +
          +
        • +

          equals

          +
          public boolean equals(java.lang.Object obj)
          +
          +
          Overrides:
          +
          equals in class java.lang.Object
          +
          +
        • +
        + + + +
          +
        • +

          hashCode

          +
          public int hashCode()
          +
          +
          Overrides:
          +
          hashCode in class java.lang.Object
          +
          +
        • +
        + + + +
          +
        • +

          toString

          +
          public java.lang.String toString()
          +
          +
          Overrides:
          +
          toString in class java.lang.Object
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/Profiler.Snapshot.html b/misc/btrace/javadoc/com/sun/btrace/Profiler.Snapshot.html new file mode 100644 index 00000000..9b16cd5a --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/Profiler.Snapshot.html @@ -0,0 +1,313 @@ + + + + + +Profiler.Snapshot (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class Profiler.Snapshot

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.Profiler.Snapshot
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing class:
      +
      Profiler
      +
      +
      +
      +
      public static final class Profiler.Snapshot
      +extends java.lang.Object
      +
      Snapshot is an immutable image of the current profiling data collected + by the Profiler +

      + It is created by calling Profiler.snapshot() method
      +
      +
      Since:
      +
      1.2
      +
      +
    • +
    +
    +
    +
      +
    • + + + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        Snapshot(Profiler.Record[] data, + long startTs, + long stopTs) 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Detail

        + + + +
          +
        • +

          timeStamp

          +
          public final long timeStamp
          +
        • +
        + + + +
          +
        • +

          timeInterval

          +
          public final long timeInterval
          +
        • +
        + + + + +
      • +
      + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Snapshot

          +
          public Snapshot(Profiler.Record[] data,
          +                long startTs,
          +                long stopTs)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/Profiler.html b/misc/btrace/javadoc/com/sun/btrace/Profiler.html new file mode 100644 index 00000000..34b4ffd4 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/Profiler.html @@ -0,0 +1,456 @@ + + + + + +Profiler (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class Profiler

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.Profiler
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Direct Known Subclasses:
      +
      MethodInvocationProfiler
      +
      +
      +
      +
      public abstract class Profiler
      +extends java.lang.Object
      +
      Profiler is a highly specialized aggregation-like data collector optimized + for high-speed collection of the application execution call tree data. +

      + It is exposable as MBean via Property annotation

      +
      +
      Since:
      +
      1.2
      +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Nested Class Summary

        + + + + + + + + + + + + + + + + + + +
        Nested Classes 
        Modifier and TypeClass and Description
        static interface Profiler.MBeanValueProvider +
        Helper interface to make accessing a Profiler as an MBean + type safe.
        +
        static class Profiler.Record +
        Record represents an atomic unit in the application execution call tree
        +
        static class Profiler.Snapshot +
        Snapshot is an immutable image of the current profiling data collected + by the Profiler +

        + It is created by calling snapshot() method
        +
        +
      • +
      + +
        +
      • + + +

        Field Summary

        + + + + + + + + + + +
        Fields 
        Modifier and TypeField and Description
        longSTART_TIME +
        This property exposes the time of creating this particular Profiler instance.
        +
        +
      • +
      + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        Profiler() +
        Creates a new Profiler instance
        +
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Abstract Methods Concrete Methods 
        Modifier and TypeMethod and Description
        abstract voidrecordEntry(java.lang.String blockName) +
        Records the event of entering an execution unit (eg.
        +
        abstract voidrecordExit(java.lang.String blockName, + long duration) +
        Records the event of exiting an execution unit (eg.
        +
        abstract voidreset() +
        Resets all the collected data
        +
        Profiler.Snapshotsnapshot() +
        Creates an immutable snapshot of the collected profiling data
        +
        abstract Profiler.Snapshotsnapshot(boolean reset) +
        Creates an immutable snapshot of the collected profiling data.
        + Makes it possible to reset the profiler after creating the snapshot, eventually
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Detail

        + + + +
          +
        • +

          START_TIME

          +
          public final long START_TIME
          +
          This property exposes the time of creating this particular Profiler instance. +
          + The unit is milliseconds.
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Profiler

          +
          public Profiler()
          +
          Creates a new Profiler instance
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          recordEntry

          +
          public abstract void recordEntry(java.lang.String blockName)
          +
          Records the event of entering an execution unit (eg. method)
          + Must be paired with a call to recordExit(java.lang.String, long) + with the same blockName, eventually
          +
          +
          Parameters:
          +
          blockName - The execution unit identifier (eg. method FQN)
          +
          +
        • +
        + + + +
          +
        • +

          recordExit

          +
          public abstract void recordExit(java.lang.String blockName,
          +                                long duration)
          +
          Records the event of exiting an execution unit (eg. method)
          + Must be preceded by a call to recordEntry(java.lang.String) + with the same blockName
          +
          +
          Parameters:
          +
          blockName - The execution unit identifier (eg. method FQN)
          +
          duration - Invocation duration in nanoseconds
          +
          +
        • +
        + + + +
          +
        • +

          snapshot

          +
          public final Profiler.Snapshot snapshot()
          +
          Creates an immutable snapshot of the collected profiling data
          +
          +
          Returns:
          +
          Returns the immutable Profiler.Snapshot instance
          +
          +
        • +
        + + + +
          +
        • +

          snapshot

          +
          public abstract Profiler.Snapshot snapshot(boolean reset)
          +
          Creates an immutable snapshot of the collected profiling data.
          + Makes it possible to reset the profiler after creating the snapshot, eventually
          +
          +
          Parameters:
          +
          reset - Signals the profiler to perform reset right after getting the snapshot (in an atomic transaction)
          +
          Returns:
          +
          Returns the immutable Profiler.Snapshot instance
          +
          +
        • +
        + + + +
          +
        • +

          reset

          +
          public abstract void reset()
          +
          Resets all the collected data
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/SharedSettings.html b/misc/btrace/javadoc/com/sun/btrace/SharedSettings.html new file mode 100644 index 00000000..36fafc1b --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/SharedSettings.html @@ -0,0 +1,877 @@ + + + + + +SharedSettings (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class SharedSettings

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.SharedSettings
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class SharedSettings
      +extends java.lang.Object
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Field Detail

        + + + + + + + +
          +
        • +

          DUMP_DIR_KEY

          +
          public static final java.lang.String DUMP_DIR_KEY
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          UNSAFE_KEY

          +
          @Deprecated
          +public static final java.lang.String UNSAFE_KEY
          +
          Deprecated. 
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          TRUSTED_KEY

          +
          public static final java.lang.String TRUSTED_KEY
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          TRACK_RETRANSFORMS_KEY

          +
          public static final java.lang.String TRACK_RETRANSFORMS_KEY
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          PROBE_DESC_PATH_KEY

          +
          public static final java.lang.String PROBE_DESC_PATH_KEY
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          STATSD_HOST_KEY

          +
          public static final java.lang.String STATSD_HOST_KEY
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          STATSD_PORT_KEY

          +
          public static final java.lang.String STATSD_PORT_KEY
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          FILEROLL_INTERVAL_KEY

          +
          public static final java.lang.String FILEROLL_INTERVAL_KEY
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          FILEROLL_MAXROLLS_KEY

          +
          public static final java.lang.String FILEROLL_MAXROLLS_KEY
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          OUTPUT_FILE_KEY

          +
          public static final java.lang.String OUTPUT_FILE_KEY
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + + +
      • +
      + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          SharedSettings

          +
          public SharedSettings()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          from

          +
          public void from(java.util.Map<java.lang.String,java.lang.Object> params)
          +
        • +
        + + + + + + + +
          +
        • +

          isDebug

          +
          public boolean isDebug()
          +
        • +
        + + + +
          +
        • +

          isDumpClasses

          +
          public boolean isDumpClasses()
          +
        • +
        + + + +
          +
        • +

          isUnsafe

          +
          @Deprecated
          +public boolean isUnsafe()
          +
          Deprecated. 
          +
        • +
        + + + +
          +
        • +

          isTrusted

          +
          public boolean isTrusted()
          +
        • +
        + + + +
          +
        • +

          getDumpDir

          +
          public java.lang.String getDumpDir()
          +
        • +
        + + + +
          +
        • +

          isTrackRetransforms

          +
          public boolean isTrackRetransforms()
          +
        • +
        + + + +
          +
        • +

          getProbeDescPath

          +
          public java.lang.String getProbeDescPath()
          +
        • +
        + + + +
          +
        • +

          setDebug

          +
          public void setDebug(boolean value)
          +
        • +
        + + + +
          +
        • +

          setTrusted

          +
          public void setTrusted(boolean value)
          +
        • +
        + + + +
          +
        • +

          setDumpDir

          +
          public void setDumpDir(java.lang.String value)
          +
        • +
        + + + +
          +
        • +

          setTrackRetransforms

          +
          public void setTrackRetransforms(boolean value)
          +
        • +
        + + + +
          +
        • +

          setProbeDescPath

          +
          public void setProbeDescPath(java.lang.String probeDescPath)
          +
        • +
        + + + +
          +
        • +

          getStatsdHost

          +
          public java.lang.String getStatsdHost()
          +
        • +
        + + + +
          +
        • +

          setStatsdHost

          +
          public void setStatsdHost(java.lang.String statsdHost)
          +
        • +
        + + + +
          +
        • +

          getStatsdPort

          +
          public int getStatsdPort()
          +
        • +
        + + + +
          +
        • +

          setStatsdPort

          +
          public void setStatsdPort(int statsdPort)
          +
        • +
        + + + +
          +
        • +

          getFileRollMilliseconds

          +
          public int getFileRollMilliseconds()
          +
        • +
        + + + +
          +
        • +

          setFileRollMilliseconds

          +
          public void setFileRollMilliseconds(int fileRollMilliseconds)
          +
        • +
        + + + +
          +
        • +

          getFileRollMaxRolls

          +
          public int getFileRollMaxRolls()
          +
        • +
        + + + +
          +
        • +

          setFileRollMaxRolls

          +
          public void setFileRollMaxRolls(int fileRollMaxRolls)
          +
        • +
        + + + +
          +
        • +

          setRetransformStartup

          +
          public void setRetransformStartup(boolean val)
          +
        • +
        + + + +
          +
        • +

          isRetransformStartup

          +
          public boolean isRetransformStartup()
          +
        • +
        + + + +
          +
        • +

          getOutputFile

          +
          public java.lang.String getOutputFile()
          +
        • +
        + + + +
          +
        • +

          setOutputFile

          +
          public void setOutputFile(java.lang.String outputFile)
          +
        • +
        + + + +
          +
        • +

          setOutputDir

          +
          public void setOutputDir(java.lang.String p)
          +
        • +
        + + + +
          +
        • +

          getOutputDir

          +
          public java.lang.String getOutputDir()
          +
        • +
        + + + +
          +
        • +

          getClientName

          +
          public java.lang.String getClientName()
          +
        • +
        + + + +
          +
        • +

          setClientName

          +
          public void setClientName(java.lang.String clientName)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/VerifierException.html b/misc/btrace/javadoc/com/sun/btrace/VerifierException.html new file mode 100644 index 00000000..cfffe4b6 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/VerifierException.html @@ -0,0 +1,279 @@ + + + + + +VerifierException (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace
    +

    Class VerifierException

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • java.lang.Throwable
      • +
      • +
          +
        • java.lang.Exception
        • +
        • +
            +
          • java.lang.RuntimeException
          • +
          • +
              +
            • com.sun.btrace.VerifierException
            • +
            +
          • +
          +
        • +
        +
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.io.Serializable
      +
      +
      +
      +
      public class VerifierException
      +extends java.lang.RuntimeException
      +
      Instance of this exception type is thrown by BTrace + Verifier when an input .class is not a valid BTrace program.
      +
      +
      See Also:
      +
      Serialized Form
      +
      +
    • +
    +
    +
    +
      +
    • + + + +
        +
      • + + +

        Method Summary

        +
          +
        • + + +

          Methods inherited from class java.lang.Throwable

          +addSuppressed, fillInStackTrace, getCause, getLocalizedMessage, getMessage, getStackTrace, getSuppressed, initCause, printStackTrace, printStackTrace, printStackTrace, setStackTrace, toString
        • +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          VerifierException

          +
          public VerifierException(java.lang.String msg)
          +
        • +
        + + + +
          +
        • +

          VerifierException

          +
          public VerifierException(java.lang.Throwable cause)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/agent/Main.html b/misc/btrace/javadoc/com/sun/btrace/agent/Main.html new file mode 100644 index 00000000..1804e2c6 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/agent/Main.html @@ -0,0 +1,327 @@ + + + + + +Main (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.agent
    +

    Class Main

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.agent.Main
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class Main
      +extends java.lang.Object
      +
      This is the main class for BTrace java.lang.instrument agent.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Summary

        + + + + + + + + + + +
        Fields 
        Modifier and TypeField and Description
        static intBTRACE_DEFAULT_PORT 
        +
      • +
      + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        Main() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static voidagentmain(java.lang.String args, + java.lang.instrument.Instrumentation inst) 
        static voidpremain(java.lang.String args, + java.lang.instrument.Instrumentation inst) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + + + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Main

          +
          public Main()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          premain

          +
          public static void premain(java.lang.String args,
          +                           java.lang.instrument.Instrumentation inst)
          +
        • +
        + + + +
          +
        • +

          agentmain

          +
          public static void agentmain(java.lang.String args,
          +                             java.lang.instrument.Instrumentation inst)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/agent/package-frame.html b/misc/btrace/javadoc/com/sun/btrace/agent/package-frame.html new file mode 100644 index 00000000..24dc39de --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/agent/package-frame.html @@ -0,0 +1,20 @@ + + + + + +com.sun.btrace.agent (btrace 1.3.11 API) + + + + + +

    com.sun.btrace.agent

    +
    +

    Classes

    + +
    + + diff --git a/misc/btrace/javadoc/com/sun/btrace/agent/package-summary.html b/misc/btrace/javadoc/com/sun/btrace/agent/package-summary.html new file mode 100644 index 00000000..a36dfb0b --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/agent/package-summary.html @@ -0,0 +1,142 @@ + + + + + +com.sun.btrace.agent (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Package com.sun.btrace.agent

    +
    +
    +
      +
    • + + + + + + + + + + + + +
      Class Summary 
      ClassDescription
      Main +
      This is the main class for BTrace java.lang.instrument agent.
      +
      +
    • +
    +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/agent/package-tree.html b/misc/btrace/javadoc/com/sun/btrace/agent/package-tree.html new file mode 100644 index 00000000..e01c5a2b --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/agent/package-tree.html @@ -0,0 +1,135 @@ + + + + + +com.sun.btrace.agent Class Hierarchy (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Hierarchy For Package com.sun.btrace.agent

    +Package Hierarchies: + +
    +
    +

    Class Hierarchy

    +
      +
    • java.lang.Object +
        +
      • com.sun.btrace.agent.Main
      • +
      +
    • +
    +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/aggregation/Aggregation.html b/misc/btrace/javadoc/com/sun/btrace/aggregation/Aggregation.html new file mode 100644 index 00000000..799af180 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/aggregation/Aggregation.html @@ -0,0 +1,437 @@ + + + + + +Aggregation (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.aggregation
    +

    Class Aggregation

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.aggregation.Aggregation
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.lang.Cloneable
      +
      +
      +
      +
      public class Aggregation
      +extends java.lang.Object
      +implements java.lang.Cloneable
      +
      BTrace stores the results of aggregating functions in an Aggregation. The aggregated values may be grouped using a + composite AggregationKey. +

      +
    • +
    +
    +
    +
      +
    • + + + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        voidadd(AggregationKey key, + long data) +
        Adds an item of data to the aggregation with the specified grouping key.
        +
        voidadd(long data) +
        Adds an item of data to the aggregation with an empty key.
        +
        voidclear() +
        Resets all values in the aggregation to their default.
        +
        protected java.lang.Objectclone() 
        java.util.List<java.lang.Object[]>getData() +
        Returns details of the aggregation in a tabular format which can be serialized across the wire and formatted for + display.
        +
        java.util.List<AggregationKey>getKeyData() +
        Returns a list of the AggregationKeys that belong to this aggregation.
        +
        java.lang.LonggetValueForKey(AggregationKey key) +
        Returns a value for the given key if the key has a value associated with it.
        +
        voidtruncate(int count) +
        Reduces the size of the aggregation to the absolute value of count.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Aggregation

          +
          public Aggregation(AggregationFunction type)
          +
          Creates an aggregation.
          +
          +
          Parameters:
          +
          type - the type of aggregation function to use
          +
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          add

          +
          public void add(long data)
          +
          Adds an item of data to the aggregation with an empty key. This method is recommended if the aggregation will + contain only a single value.
          +
          +
          Parameters:
          +
          data - the value to be added
          +
          +
        • +
        + + + +
          +
        • +

          add

          +
          public void add(AggregationKey key,
          +                long data)
          +
          Adds an item of data to the aggregation with the specified grouping key.
          +
          +
          Parameters:
          +
          key - the aggregation key
          +
          data - the value to be added
          +
          +
        • +
        + + + +
          +
        • +

          clear

          +
          public void clear()
          +
          Resets all values in the aggregation to their default.
          +
        • +
        + + + +
          +
        • +

          truncate

          +
          public void truncate(int count)
          +
          Reduces the size of the aggregation to the absolute value of count. If count is greater than + zero, the largest aggregated values are preserved. If it is less than zero, the smallest aggregated values are + preserved. Passing a value of zero clears the aggregation completely.
          +
          +
          Parameters:
          +
          count - the absolute number indicates the number of aggregated values to preserve.
          +
          +
        • +
        + + + +
          +
        • +

          getData

          +
          public java.util.List<java.lang.Object[]> getData()
          +
          Returns details of the aggregation in a tabular format which can be serialized across the wire and formatted for + display. The data is represented as a List of rows. The last element in each row represents the aggregated value, + the elements before this in the row contain the elements of the aggregating key.
          +
          +
          Returns:
          +
          details of the aggregation in a tabular format.
          +
          +
        • +
        + + + +
          +
        • +

          getKeyData

          +
          public java.util.List<AggregationKey> getKeyData()
          +
          Returns a list of the AggregationKeys that belong to this aggregation.
          +
          +
          Returns:
          +
          a list of aggregationsKeys belonging to this aggregation.
          +
          +
        • +
        + + + +
          +
        • +

          getValueForKey

          +
          public java.lang.Long getValueForKey(AggregationKey key)
          +
          Returns a value for the given key if the key has a value associated with it. Returns zero if the key is not + valid for this Aggregation.
          +
          +
          Returns:
          +
          the value for the given key, or zero.
          +
          +
        • +
        + + + +
          +
        • +

          clone

          +
          protected java.lang.Object clone()
          +                          throws java.lang.CloneNotSupportedException
          +
          +
          Overrides:
          +
          clone in class java.lang.Object
          +
          Throws:
          +
          java.lang.CloneNotSupportedException
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/aggregation/AggregationFunction.html b/misc/btrace/javadoc/com/sun/btrace/aggregation/AggregationFunction.html new file mode 100644 index 00000000..5d499f57 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/aggregation/AggregationFunction.html @@ -0,0 +1,402 @@ + + + + + +AggregationFunction (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.aggregation
    +

    Enum AggregationFunction

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • java.lang.Enum<AggregationFunction>
      • +
      • +
          +
        • com.sun.btrace.aggregation.AggregationFunction
        • +
        +
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.io.Serializable, java.lang.Comparable<AggregationFunction>
      +
      +
      +
      +
      public enum AggregationFunction
      +extends java.lang.Enum<AggregationFunction>
      +
      The type of aggregation functions. +

      +
    • +
    +
    +
    + +
    +
    +
      +
    • + + + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          values

          +
          public static AggregationFunction[] values()
          +
          Returns an array containing the constants of this enum type, in +the order they are declared. This method may be used to iterate +over the constants as follows: +
          +for (AggregationFunction c : AggregationFunction.values())
          +    System.out.println(c);
          +
          +
          +
          Returns:
          +
          an array containing the constants of this enum type, in the order they are declared
          +
          +
        • +
        + + + +
          +
        • +

          valueOf

          +
          public static AggregationFunction valueOf(java.lang.String name)
          +
          Returns the enum constant of this type with the specified name. +The string must match exactly an identifier used to declare an +enum constant in this type. (Extraneous whitespace characters are +not permitted.)
          +
          +
          Parameters:
          +
          name - the name of the enum constant to be returned.
          +
          Returns:
          +
          the enum constant with the specified name
          +
          Throws:
          +
          java.lang.IllegalArgumentException - if this enum type has no constant with the specified name
          +
          java.lang.NullPointerException - if the argument is null
          +
          +
        • +
        + + + + +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/aggregation/AggregationKey.html b/misc/btrace/javadoc/com/sun/btrace/aggregation/AggregationKey.html new file mode 100644 index 00000000..34a42ca8 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/aggregation/AggregationKey.html @@ -0,0 +1,306 @@ + + + + + +AggregationKey (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.aggregation
    +

    Class AggregationKey

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.aggregation.AggregationKey
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class AggregationKey
      +extends java.lang.Object
      +
      A key identifying an element of data in an aggregation. This represents a tuple of object values contained in an + Object[] array. Elements in the tuple may be null or of type String or Number. +

      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        AggregationKey(java.lang.Object[] elements) 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        booleanequals(java.lang.Object obj) 
        java.lang.Object[]getElements() 
        inthashCode() 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, finalize, getClass, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          AggregationKey

          +
          public AggregationKey(java.lang.Object[] elements)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getElements

          +
          public java.lang.Object[] getElements()
          +
        • +
        + + + +
          +
        • +

          hashCode

          +
          public int hashCode()
          +
          +
          Overrides:
          +
          hashCode in class java.lang.Object
          +
          +
        • +
        + + + +
          +
        • +

          equals

          +
          public boolean equals(java.lang.Object obj)
          +
          +
          Overrides:
          +
          equals in class java.lang.Object
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/aggregation/AggregationValue.html b/misc/btrace/javadoc/com/sun/btrace/aggregation/AggregationValue.html new file mode 100644 index 00000000..2e9bcf6e --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/aggregation/AggregationValue.html @@ -0,0 +1,283 @@ + + + + + +AggregationValue (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.aggregation
    +

    Interface AggregationValue

    +
    +
    +
    +
      +
    • +
      +
      +
      public interface AggregationValue
      +
      An element of aggregated data stored in an Aggregation. + + Concrete implementations of this interface will implement different aggregating functions. +

      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Abstract Methods 
        Modifier and TypeMethod and Description
        voidadd(long data) +
        Adds a data item to the aggregated value.
        +
        voidclear() +
        Removes all data items previously added.
        +
        java.lang.ObjectgetData() 
        longgetValue() 
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          add

          +
          void add(long data)
          +
          Adds a data item to the aggregated value.
          +
          +
          Parameters:
          +
          data - the data value
          +
          +
        • +
        + + + +
          +
        • +

          clear

          +
          void clear()
          +
          Removes all data items previously added.
          +
        • +
        + + + +
          +
        • +

          getValue

          +
          long getValue()
          +
          +
          Returns:
          +
          the aggregated value of all data items added since the aggregation was created or last cleared. The + aggregation function is determined by the concrete implementation of the interface.
          +
          +
        • +
        + + + +
          +
        • +

          getData

          +
          java.lang.Object getData()
          +
          +
          Returns:
          +
          an object representation of the aggregated value. For most implementations this may be equivalent to + Integer.valueOf( getValue() ). More complex aggregations such may return objects + representing histograms, etc.
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/aggregation/HistogramData.html b/misc/btrace/javadoc/com/sun/btrace/aggregation/HistogramData.html new file mode 100644 index 00000000..580d65ae --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/aggregation/HistogramData.html @@ -0,0 +1,308 @@ + + + + + +HistogramData (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.aggregation
    +

    Class HistogramData

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.aggregation.HistogramData
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.io.Serializable
      +
      +
      +
      +
      public class HistogramData
      +extends java.lang.Object
      +implements java.io.Serializable
      +
      A wire data structure describing histogram data. +

      +
      +
      See Also:
      +
      Serialized Form
      +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        HistogramData(long[] values, + long[] counts) 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        long[]getCounts() 
        long[]getValues() 
        voidprint(java.io.PrintWriter p) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          HistogramData

          +
          public HistogramData(long[] values,
          +                     long[] counts)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getValues

          +
          public long[] getValues()
          +
        • +
        + + + +
          +
        • +

          getCounts

          +
          public long[] getCounts()
          +
        • +
        + + + +
          +
        • +

          print

          +
          public void print(java.io.PrintWriter p)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/aggregation/package-frame.html b/misc/btrace/javadoc/com/sun/btrace/aggregation/package-frame.html new file mode 100644 index 00000000..1c36ebc0 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/aggregation/package-frame.html @@ -0,0 +1,30 @@ + + + + + +com.sun.btrace.aggregation (btrace 1.3.11 API) + + + + + +

    com.sun.btrace.aggregation

    +
    +

    Interfaces

    + +

    Classes

    + +

    Enums

    + +
    + + diff --git a/misc/btrace/javadoc/com/sun/btrace/aggregation/package-summary.html b/misc/btrace/javadoc/com/sun/btrace/aggregation/package-summary.html new file mode 100644 index 00000000..676392d2 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/aggregation/package-summary.html @@ -0,0 +1,188 @@ + + + + + +com.sun.btrace.aggregation (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Package com.sun.btrace.aggregation

    +
    +
    +
      +
    • + + + + + + + + + + + + +
      Interface Summary 
      InterfaceDescription
      AggregationValue +
      An element of aggregated data stored in an Aggregation.
      +
      +
    • +
    • + + + + + + + + + + + + + + + + + + + + +
      Class Summary 
      ClassDescription
      Aggregation +
      BTrace stores the results of aggregating functions in an Aggregation.
      +
      AggregationKey +
      A key identifying an element of data in an aggregation.
      +
      HistogramData +
      A wire data structure describing histogram data.
      +
      +
    • +
    • + + + + + + + + + + + + +
      Enum Summary 
      EnumDescription
      AggregationFunction +
      The type of aggregation functions.
      +
      +
    • +
    +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/aggregation/package-tree.html b/misc/btrace/javadoc/com/sun/btrace/aggregation/package-tree.html new file mode 100644 index 00000000..a7d0acc0 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/aggregation/package-tree.html @@ -0,0 +1,153 @@ + + + + + +com.sun.btrace.aggregation Class Hierarchy (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Hierarchy For Package com.sun.btrace.aggregation

    +Package Hierarchies: + +
    +
    +

    Class Hierarchy

    +
      +
    • java.lang.Object +
        +
      • com.sun.btrace.aggregation.Aggregation (implements java.lang.Cloneable)
      • +
      • com.sun.btrace.aggregation.AggregationKey
      • +
      • com.sun.btrace.aggregation.HistogramData (implements java.io.Serializable)
      • +
      +
    • +
    +

    Interface Hierarchy

    + +

    Enum Hierarchy

    +
      +
    • java.lang.Object +
        +
      • java.lang.Enum<E> (implements java.lang.Comparable<T>, java.io.Serializable) + +
      • +
      +
    • +
    +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/BTrace.html b/misc/btrace/javadoc/com/sun/btrace/annotations/BTrace.html new file mode 100644 index 00000000..93a2472c --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/BTrace.html @@ -0,0 +1,281 @@ + + + + + +BTrace (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Annotation Type BTrace

    +
    +
    +
    +
      +
    • +
      +
      +
      @Retention(value=RUNTIME)
      + @Target(value=TYPE)
      +public @interface BTrace
      +
      Top-level annotation that identifies a BTrace + class.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Optional Element Summary

        + + + + + + + + + + + + + + + + + + + + + + +
        Optional Elements 
        Modifier and TypeOptional Element and Description
        java.lang.Stringdescription 
        java.lang.Stringname 
        booleantrusted 
        booleanunsafe +
        Deprecated. 
        +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Element Detail

        + + + +
          +
        • +

          name

          +
          public abstract java.lang.String name
          +
          +
          Default:
          +
          ""
          +
          +
        • +
        +
      • +
      +
        +
      • + + +
          +
        • +

          description

          +
          public abstract java.lang.String description
          +
          +
          Default:
          +
          ""
          +
          +
        • +
        +
      • +
      +
        +
      • + + +
          +
        • +

          unsafe

          +
          @Deprecated
          +public abstract boolean unsafe
          +
          Deprecated. 
          +
          +
          Default:
          +
          false
          +
          +
        • +
        +
      • +
      +
        +
      • + + +
          +
        • +

          trusted

          +
          public abstract boolean trusted
          +
          +
          Default:
          +
          false
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/DTrace.html b/misc/btrace/javadoc/com/sun/btrace/annotations/DTrace.html new file mode 100644 index 00000000..adc73ef4 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/DTrace.html @@ -0,0 +1,216 @@ + + + + + +DTrace (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Annotation Type DTrace

    +
    +
    +
    +
      +
    • +
      +
      +
      @Retention(value=RUNTIME)
      + @Target(value=TYPE)
      +public @interface DTrace
      +
      Annotation for BTrace program to associate a D-script with it. + D-script is specified as (inline) String value.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Required Element Summary

        + + + + + + + + + + +
        Required Elements 
        Modifier and TypeRequired Element and Description
        java.lang.Stringvalue +
        "one-liner" D-script String
        +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Element Detail

        + + + +
          +
        • +

          value

          +
          public abstract java.lang.String value
          +
          "one-liner" D-script String
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/DTraceRef.html b/misc/btrace/javadoc/com/sun/btrace/annotations/DTraceRef.html new file mode 100644 index 00000000..96784579 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/DTraceRef.html @@ -0,0 +1,216 @@ + + + + + +DTraceRef (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Annotation Type DTraceRef

    +
    +
    +
    +
      +
    • +
      +
      +
      @Retention(value=RUNTIME)
      + @Target(value=TYPE)
      +public @interface DTraceRef
      +
      Annotation for BTrace program to associate a D-script with it. + D-script is referred by a relative or absolute file path.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Required Element Summary

        + + + + + + + + + + +
        Required Elements 
        Modifier and TypeRequired Element and Description
        java.lang.Stringvalue +
        Locates D-script by a relative or absolute file path.
        +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Element Detail

        + + + +
          +
        • +

          value

          +
          public abstract java.lang.String value
          +
          Locates D-script by a relative or absolute file path.
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/Duration.html b/misc/btrace/javadoc/com/sun/btrace/annotations/Duration.html new file mode 100644 index 00000000..a0231763 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/Duration.html @@ -0,0 +1,172 @@ + + + + + +Duration (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Annotation Type Duration

    +
    +
    +
    +
      +
    • +
      +
      +
      @Target(value=PARAMETER)
      + @Retention(value=RUNTIME)
      +public @interface Duration
      +
      It is used to mark a probe method argument as the receiver of the duration value
      + Applicable only for OnMethod annotation with Location value + of Kind.RETURN or Kind.ERROR +

      + The duration is reported in nanoseconds, using resolution available by OS

      +
      +
      Since:
      +
      1.1
      +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/Export.html b/misc/btrace/javadoc/com/sun/btrace/annotations/Export.html new file mode 100644 index 00000000..30eca3a8 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/Export.html @@ -0,0 +1,165 @@ + + + + + +Export (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Annotation Type Export

    +
    +
    +
    +
      +
    • +
      +
      +
      @Retention(value=RUNTIME)
      + @Target(value=FIELD)
      +public @interface Export
      +
      BTrace fields with this annotation are exposed to + out-of-process tools using mechanisms such as jvmstat.
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/Injected.html b/misc/btrace/javadoc/com/sun/btrace/annotations/Injected.html new file mode 100644 index 00000000..1ad27672 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/Injected.html @@ -0,0 +1,249 @@ + + + + + +Injected (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Annotation Type Injected

    +
    +
    +
    +
      +
    • +
      +
      +
      @Target(value=FIELD)
      + @Retention(value=CLASS)
      +public @interface Injected
      +
      Annotates a field as an injected service.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Optional Element Summary

        + + + + + + + + + + + + + + +
        Optional Elements 
        Modifier and TypeOptional Element and Description
        java.lang.StringfactoryMethod +
        The factory method to be used.
        +
        ServiceTypevalue +
        The injected service type
        +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Element Detail

        + + + +
          +
        • +

          value

          +
          public abstract ServiceType value
          +
          The injected service type
          +
          +
          Default:
          +
          com.sun.btrace.annotations.ServiceType.SIMPLE
          +
          +
        • +
        +
      • +
      +
        +
      • + + +
          +
        • +

          factoryMethod

          +
          public abstract java.lang.String factoryMethod
          +
          The factory method to be used. +

          + It must be a static method declared by the service class + and returning the service class instance

          +
          +
          Returns:
          +
          The name of the static method to be used as the factory method or an empty string
          +
          +
          +
          Default:
          +
          ""
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/Kind.html b/misc/btrace/javadoc/com/sun/btrace/annotations/Kind.html new file mode 100644 index 00000000..e29296a5 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/Kind.html @@ -0,0 +1,825 @@ + + + + + +Kind (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Enum Kind

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • java.lang.Enum<Kind>
      • +
      • +
          +
        • com.sun.btrace.annotations.Kind
        • +
        +
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.io.Serializable, java.lang.Comparable<Kind>
      +
      +
      +
      +
      public enum Kind
      +extends java.lang.Enum<Kind>
      +
      This enum is specified in the Location + annotation to specify probe point kind. + This enum identifies various "points" of + interest within a Java method's bytecode.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Enum Constant Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        Enum Constants 
        Enum Constant and Description
        ARRAY_GET +
        Array element load
        +
        ARRAY_SET +
        Array element store
        +
        CALL +
        Method call
        +
        CATCH +
        Exception catch
        +
        CHECKCAST +
        Checkcast
        +
        ENTRY +
        Method entry
        +
        ERROR +
        "return" because of no-catch
        +
        FIELD_GET +
        Getting a field value
        +
        FIELD_SET +
        Setting a field value
        +
        INSTANCEOF +
        instanceof check
        +
        LINE +
        Source line number
        +
        NEW +
        New object created
        +
        NEWARRAY +
        New array created
        +
        RETURN +
        Return from method
        +
        SYNC_ENTRY +
        Entry into a synchronized block
        +
        SYNC_EXIT +
        Exit from a synchronized block
        +
        THROW +
        Throwing an exception
        +
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static KindvalueOf(java.lang.String name) +
        Returns the enum constant of this type with the specified name.
        +
        static Kind[]values() +
        Returns an array containing the constants of this enum type, in +the order they are declared.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Enum

          +clone, compareTo, equals, finalize, getDeclaringClass, hashCode, name, ordinal, toString, valueOf
        • +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +getClass, notify, notifyAll, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Enum Constant Detail

        + + + +
          +
        • +

          ARRAY_GET

          +
          public static final Kind ARRAY_GET
          +

          Array element load

          + +

          Unannotated probe handler parameters:

          +
            +
          1. type[] - the array instance
          2. +
          3. int - array index
          4. +
          +

          Allowed probe handler parameter annotations:

          +
            +
          • ProbeClassName - the name of the enclosing class
          • +
          • ProbeMethodName - the name of the enclosing method
          • +
          • Self - the instance enclosing the declaring method or null + if that method is static
          • +
          • Return - the return value of the method call (only for Where.AFTER)
          • +
          +
        • +
        + + + +
          +
        • +

          ARRAY_SET

          +
          public static final Kind ARRAY_SET
          +

          Array element store

          + +

          Unannotated probe handler parameters:

          +
            +
          1. type[] - the array instance
          2. +
          3. int - array index
          4. +
          5. Object - new value
          6. +
          +

          Allowed probe handler parameter annotations:

          +
            +
          • ProbeClassName - the name of the enclosing class
          • +
          • ProbeMethodName - the name of the enclosing method
          • +
          • Self - the instance enclosing the declaring method or null + if that method is static
          • +
          +
        • +
        + + + +
          +
        • +

          CALL

          +
          public static final Kind CALL
          +

          Method call

          +

          + The order and number of unannotated parameters (if provided) must + fully match the called method signature. Instead of specific parameter + types one can use AnyType to match any type. +

          + If the only unannotated parameter is of type AnyType[] + it will contain the called method parameters in the order defined by + its signature. + +

          Allowed probe handler parameter annotations:

          +
          +
        • +
        + + + +
          +
        • +

          CATCH

          +
          public static final Kind CATCH
          +

          Exception catch

          + +

          + The order and number of unannotated parameters (if provided) must + fully match the probed method signature. Instead of specific parameter + types one can use AnyType to match any type. +

          + If the only unannotated parameter is of type AnyType[] + it will contain the probed method parameters in the order defined by + its signature. +

          Allowed probe handler parameter annotations:

          +
            +
          • ProbeClassName - the name of the enclosing class
          • +
          • ProbeMethodName - the name of the enclosing method
          • +
          • Self - the instance enclosing the declaring method or null + if that method is static
          • +
          • TargetInstance - the caught Throwable (@since 1.3.11)
          • +
          +
        • +
        + + + +
          +
        • +

          CHECKCAST

          +
          public static final Kind CHECKCAST
          +

          Checkcast

          + +

          Unannotated probe handler parameters:

          +
            +
          1. String - type to cast to
          2. +
          +

          Allowed probe handler parameter annotations:

          +
          +
        • +
        + + + +
          +
        • +

          ENTRY

          +
          public static final Kind ENTRY
          +

          Method entry

          +

          + The order and number of unannotated parameters (if provided) must + fully match the probed method signature. Instead of specific parameter + types one can use AnyType to match any type. +

          + If the only unannotated parameter is of type AnyType[] + it will contain the probed method parameters in the order defined by + its signature. + +

          Allowed probe handler parameter annotations:

          +
            +
          • ProbeClassName - the name of the enclosing class
          • +
          • ProbeMethodName - the name of the enclosing method
          • +
          • Self - the instance enclosing the declaring method or null + if that method is static
          • +
          +
        • +
        + + + +
          +
        • +

          ERROR

          +
          public static final Kind ERROR
          +

          "return" because of no-catch

          + +

          + The order and number of unannotated parameters (if provided) must + fully match the probed method signature. Instead of specific parameter + types one can use AnyType to match any type. +

          + If the only unannotated parameter is of type AnyType[] + it will contain the probed method parameters in the order defined by + its signature. +

          Allowed probe handler parameter annotations:

          +
          +
        • +
        + + + +
          +
        • +

          FIELD_GET

          +
          public static final Kind FIELD_GET
          +

          Getting a field value

          + +

          Allowed probe handler parameter annotations:

          +
          +
        • +
        + + + +
          +
        • +

          FIELD_SET

          +
          public static final Kind FIELD_SET
          +

          Setting a field value

          + +

          Unannotated probe handler parameters:

          +
            +
          1. Object - new field value
          2. +
          +

          Allowed probe handler parameter annotations:

          +
            +
          • ProbeClassName - the name of the enclosing class
          • +
          • ProbeMethodName - the name of the enclosing method
          • +
          • Self - the instance enclosing the declaring method or null + if that field is static
          • +
          • TargetInstance - the field owner instance or null + if the field is static
          • +
          • TargetMethodOrField - the name of the method which is called
          • +
          +
        • +
        + + + +
          +
        • +

          INSTANCEOF

          +
          public static final Kind INSTANCEOF
          +

          instanceof check

          + +

          Unannotated probe handler parameters:

          +
            +
          1. String - type to check against
          2. +
          +

          Allowed probe handler parameter annotations:

          +
          +
        • +
        + + + +
          +
        • +

          LINE

          +
          public static final Kind LINE
          +

          Source line number

          + +

          Unannotated probe handler parameters:

          +
            +
          1. int - line number
          2. +
          +

          Allowed probe handler parameter annotations:

          +
            +
          • ProbeClassName - the name of the enclosing class
          • +
          • ProbeMethodName - the name of the enclosing method
          • +
          • Self - the instance enclosing the declaring method or null + if that method is static
          • +
          +
        • +
        + + + +
          +
        • +

          NEW

          +
          public static final Kind NEW
          +

          New object created

          + +

          Unannotated probe handler parameters:

          +
            +
          1. String - object type name
          2. +
          +

          Allowed probe handler parameter annotations:

          +
            +
          • ProbeClassName - the name of the enclosing class
          • +
          • ProbeMethodName - the name of the enclosing method
          • +
          • Self - the instance enclosing the declaring method or null + if that method is static
          • +
          • Return - the return value of the method call (only for Where.AFTER)
          • +
          +
        • +
        + + + +
          +
        • +

          NEWARRAY

          +
          public static final Kind NEWARRAY
          +

          New array created

          + +

          Unannotated probe handler parameters:

          +
            +
          1. String - array type name
          2. +
          3. int - number of dimensions
          4. +
          +

          Allowed probe handler parameter annotations:

          +
            +
          • ProbeClassName - the name of the enclosing class
          • +
          • ProbeMethodName - the name of the enclosing method
          • +
          • Self - the instance enclosing the declaring method or null + if that method is static
          • +
          • Return - the return value of the method call (only for Where.AFTER)
          • +
          +
        • +
        + + + +
          +
        • +

          RETURN

          +
          public static final Kind RETURN
          +

          Return from method

          +

          + The order and number of unannotated probe handler parameters (if provided) + must fully match the probed method signature. Instead of specific parameter + types one can use AnyType to match any type. +

          + If the only unannotated parameter is of type AnyType[] + it will contain the probed method parameters in the order defined by + its signature. + +

          Allowed probe handler parameter annotations:

          +
          +
        • +
        + + + +
          +
        • +

          SYNC_ENTRY

          +
          public static final Kind SYNC_ENTRY
          +

          Entry into a synchronized block

          + +

          Unannotated probe handler parameters:

          +
            +
          1. Object - lock object
          2. +
          +

          Allowed probe handler parameter annotations:

          +
            +
          • ProbeClassName - the name of the enclosing class
          • +
          • ProbeMethodName - the name of the enclosing method
          • +
          • Self - the instance enclosing the declaring method or null + if that method is static
          • +
          +
        • +
        + + + +
          +
        • +

          SYNC_EXIT

          +
          public static final Kind SYNC_EXIT
          +

          Exit from a synchronized block

          + +

          Unannotated probe handler parameters:

          +
            +
          1. Object - lock object
          2. +
          +

          Allowed probe handler parameter annotations:

          +
            +
          • ProbeClassName - the name of the enclosing class
          • +
          • ProbeMethodName - the name of the enclosing method
          • +
          • Self - the instance enclosing the declaring method or null + if that method is static
          • +
          +
        • +
        + + + +
          +
        • +

          THROW

          +
          public static final Kind THROW
          +

          Throwing an exception

          + +

          + The order and number of unannotated parameters (if provided) must + fully match the probed method signature. Instead of specific parameter + types one can use AnyType to match any type. +

          + If the only unannotated parameter is of type AnyType[] + it will contain the probed method parameters in the order defined by + its signature. +

          Allowed probe handler parameter annotations:

          +
            +
          • ProbeClassName - the name of the enclosing class
          • +
          • ProbeMethodName - the name of the enclosing method
          • +
          • Self - the instance enclosing the declaring method or null + if that method is static
          • +
          • TargetInstance - the thrown exception (@since 1.3.11)
          • +
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          values

          +
          public static Kind[] values()
          +
          Returns an array containing the constants of this enum type, in +the order they are declared. This method may be used to iterate +over the constants as follows: +
          +for (Kind c : Kind.values())
          +    System.out.println(c);
          +
          +
          +
          Returns:
          +
          an array containing the constants of this enum type, in the order they are declared
          +
          +
        • +
        + + + +
          +
        • +

          valueOf

          +
          public static Kind valueOf(java.lang.String name)
          +
          Returns the enum constant of this type with the specified name. +The string must match exactly an identifier used to declare an +enum constant in this type. (Extraneous whitespace characters are +not permitted.)
          +
          +
          Parameters:
          +
          name - the name of the enum constant to be returned.
          +
          Returns:
          +
          the enum constant with the specified name
          +
          Throws:
          +
          java.lang.IllegalArgumentException - if this enum type has no constant with the specified name
          +
          java.lang.NullPointerException - if the argument is null
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/Level.html b/misc/btrace/javadoc/com/sun/btrace/annotations/Level.html new file mode 100644 index 00000000..c475ba8e --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/Level.html @@ -0,0 +1,234 @@ + + + + + +Level (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Annotation Type Level

    +
    +
    +
    +
      +
    • +
      +
      +
      public @interface Level
      +
      Allows specifying a probe handler instrumentation level matching expression. +

      + See value() for the allowed expression syntax.

      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Optional Element Summary

        + + + + + + + + + + +
        Optional Elements 
        Modifier and TypeOptional Element and Description
        java.lang.Stringvalue +
        The level check expression.
        +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Element Detail

        + + + +
          +
        • +

          value

          +
          public abstract java.lang.String value
          +
          The level check expression. +

          Allowed syntax is one of the following +

            +
          • @Level("NUMBER") - the same as @Level(">=NUMBER") +
          • @Level("=NUMBER") - handler is enabled when instrumentation level + equals NUMBER
          • +
          • @Level(">NUMBER") - handler is enabled when instrumentation level + is greater than NUMBER
          • +
          • @Level(">=NUMBER") - handler is enabled when instrumentation level + is greater than or equal to NUMBER
          • +
          • @Level("<NUMBER") - handler is enabled when instrumentation level + is less than NUMBER
          • +
          • @Level("<=NUMBER") - handler is enabled when instrumentation level + is less than or equal to NUMBER
          • +
          +

          Where NUMBER is a non-negative integer number.

          +
          +
          Default:
          +
          ""
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/Location.html b/misc/btrace/javadoc/com/sun/btrace/annotations/Location.html new file mode 100644 index 00000000..0f8b856e --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/Location.html @@ -0,0 +1,430 @@ + + + + + +Location (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Annotation Type Location

    +
    +
    +
    +
      +
    • +
      +
      +
      @Retention(value=RUNTIME)
      + @Target(value=METHOD)
      +public @interface Location
      +
      This annotation specifies a particular "location" within a + traced/probed java method for BTrace probe specifications.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Optional Element Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        Optional Elements 
        Modifier and TypeOptional Element and Description
        java.lang.Stringclazz +
        Specifies the fully qualified class name for + certain kind of probe locations.
        +
        java.lang.Stringfield +
        Specifies the field name for Kind.FIELD_SET + and Kind.FIELD_GET probes.
        +
        intline +
        Specifies the line number for Kind.LINE probes.
        +
        java.lang.Stringmethod +
        Specifies the method name for + certain kind of probe locations.
        +
        java.lang.Stringtype +
        Specifies field or method type for + certain kind of probe locations.
        +
        Kindvalue +
        Kind of the location.
        +
        Wherewhere +
        Specifies where do want to probe with + respect to the location of interest.
        +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Element Detail

        + + + +
          +
        • +

          value

          +
          public abstract Kind value
          +
          Kind of the location.
          +
          +
          See Also:
          +
          Kind
          +
          +
          +
          Default:
          +
          com.sun.btrace.annotations.Kind.ENTRY
          +
          +
        • +
        +
      • +
      +
        +
      • + + +
          +
        • +

          where

          +
          public abstract Where where
          +
          Specifies where do want to probe with + respect to the location of interest.
          +
          +
          See Also:
          +
          Where
          +
          +
          +
          Default:
          +
          com.sun.btrace.annotations.Where.BEFORE
          +
          +
        • +
        +
      • +
      +
        +
      • + + +
          +
        • +

          clazz

          +
          public abstract java.lang.String clazz
          +
          Specifies the fully qualified class name for + certain kind of probe locations. + +

          +

          Since 1.3.11

          + The specification can contain references to user arguments. + These references are using Ant style substitution patterns. + If a reference is not resolvable the whole probe point will be effectively disabled. +
          +
          +  @OnMethod(clazz = "MyClass", method = "myMethod", location = @Location(clazz = "${package}.OtherClass"))
          + 
          +

          +
          +
          Default:
          +
          ""
          +
          +
        • +
        +
      • +
      +
        +
      • + + +
          +
        • +

          method

          +
          public abstract java.lang.String method
          +
          Specifies the method name for + certain kind of probe locations. + +

          +

          Since 1.3.11

          + The specification can contain references to user arguments. + These references are using Ant style substitution patterns. + If a reference is not resolvable the whole probe point will be effectively disabled. +
          +
          +  @OnMethod(clazz = "MyClass", method = "myMethod", location = @Location(clazz = "OtherClass", method = "${method}"))
          + 
          +

          +
          +
          Default:
          +
          ""
          +
          +
        • +
        +
      • +
      + +
        +
      • + + +
          +
        • +

          type

          +
          public abstract java.lang.String type
          +
          Specifies field or method type for + certain kind of probe locations. The type + is specified like in Java source - except + the method or field name and parameter names + are not included. + +

          +

          Since 1.3.11

          + The specification can contain references to user arguments. + These references are using Ant style substitution patterns. + If a reference is not resolvable the whole probe point will be effectively disabled. +
          +
          +  @OnMethod(clazz = "MyClass", method = "myMethod", location = @Location(clazz = "OtherClass", type = "${ret} ()"))
          + 
          +

          +
          +
          Default:
          +
          ""
          +
          +
        • +
        +
      • +
      +
        +
      • + + +
          +
        • +

          line

          +
          public abstract int line
          +
          Specifies the line number for Kind.LINE probes.
          +
          +
          See Also:
          +
          Kind.LINE
          +
          +
          +
          Default:
          +
          0
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/OnError.html b/misc/btrace/javadoc/com/sun/btrace/annotations/OnError.html new file mode 100644 index 00000000..8bbb44f9 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/OnError.html @@ -0,0 +1,165 @@ + + + + + +OnError (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Annotation Type OnError

    +
    +
    +
    +
      +
    • +
      +
      +
      @Retention(value=RUNTIME)
      + @Target(value=METHOD)
      +public @interface OnError
      +
      BTrace method annotated by this annotation is called when + any exception is thrown by any of the BTrace action methods.
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/OnEvent.html b/misc/btrace/javadoc/com/sun/btrace/annotations/OnEvent.html new file mode 100644 index 00000000..eafc6870 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/OnEvent.html @@ -0,0 +1,234 @@ + + + + + +OnEvent (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Annotation Type OnEvent

    +
    +
    +
    +
      +
    • +
      +
      +
      @Retention(value=RUNTIME)
      + @Target(value=METHOD)
      +public @interface OnEvent
      +
      BTrace methods annotated by this annotation are called when + BTrace client sends "event" command. Client may send an + event based on some form of user request to send (like + pressing Ctrl-C or a GUI menu). String value may used as + the name of the event.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Optional Element Summary

        + + + + + + + + + + +
        Optional Elements 
        Modifier and TypeOptional Element and Description
        java.lang.Stringvalue +
        The event name.
        +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Element Detail

        + + + +
          +
        • +

          value

          +
          public abstract java.lang.String value
          +
          The event name. + +

          +

          Since 1.3.11

          + The specification can contain references to user arguments. + These references are using Ant style substitution patterns. + If a reference is not resolvable the handler will be effectively disabled. +
          +
          +  @OnEvent(value = "${userEvent}")
          + 
          +

          +
          +
          Default:
          +
          ""
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/OnExit.html b/misc/btrace/javadoc/com/sun/btrace/annotations/OnExit.html new file mode 100644 index 00000000..b513b7b8 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/OnExit.html @@ -0,0 +1,166 @@ + + + + + +OnExit (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Annotation Type OnExit

    +
    +
    +
    +
      +
    • +
      +
      +
      @Retention(value=RUNTIME)
      + @Target(value=METHOD)
      +public @interface OnExit
      +
      BTrace method annotated by this annotation is called when + BTrace "exit(int)" built-in function is called by some + other BTrace action method.
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/OnLowMemory.html b/misc/btrace/javadoc/com/sun/btrace/annotations/OnLowMemory.html new file mode 100644 index 00000000..32126c3b --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/OnLowMemory.html @@ -0,0 +1,293 @@ + + + + + +OnLowMemory (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Annotation Type OnLowMemory

    +
    +
    +
    +
      +
    • +
      +
      +
      @Retention(value=RUNTIME)
      + @Target(value=METHOD)
      +public @interface OnLowMemory
      +
      BTrace methods annotated by this annotation are called when + the traced JVM's specified memory pool exceeds specified + threshold size.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Required Element Summary

        + + + + + + + + + + + + + + +
        Required Elements 
        Modifier and TypeRequired Element and Description
        java.lang.Stringpool +
        The memory pool name.
        +
        longthreshold +
        The threashold size to watch for.
        +
        +
      • +
      + +
        +
      • + + +

        Optional Element Summary

        + + + + + + + + + + +
        Optional Elements 
        Modifier and TypeOptional Element and Description
        java.lang.StringthresholdFrom +
        If specified the threshold will be taken from btrace arguments.
        +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Element Detail

        + + + +
          +
        • +

          pool

          +
          public abstract java.lang.String pool
          +
          The memory pool name. + +

          +

          Since 1.3.11

          + The specification can contain references to user arguments. + These references are using Ant style substitution patterns. + If a reference is not resolvable the handler will be effectively disabled. +
          +
          +  @OnLowMemory(pool = "${firstPool}")
          + 
          +

          +
        • +
        +
      • +
      +
        +
      • + + +
          +
        • +

          threshold

          +
          public abstract long threshold
          +
          The threashold size to watch for.
          +
        • +
        +
      • +
      + +
        +
      • + + +
          +
        • +

          thresholdFrom

          +
          public abstract java.lang.String thresholdFrom
          +
          If specified the threshold will be taken from btrace arguments. + The format is Ant-like property reference - eg. thresholdFrom = "${threshold}"
          +
          +
          Returns:
          +
          btrace argument name holding the threshold
          +
          Since:
          +
          1.3.11
          +
          +
          +
          Default:
          +
          ""
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/OnMethod.html b/misc/btrace/javadoc/com/sun/btrace/annotations/OnMethod.html new file mode 100644 index 00000000..269d5939 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/OnMethod.html @@ -0,0 +1,422 @@ + + + + + +OnMethod (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Annotation Type OnMethod

    +
    +
    +
    +
      +
    • +
      +
      +
      @Retention(value=RUNTIME)
      + @Target(value=METHOD)
      +public @interface OnMethod
      +
      This annotation specifies a BTrace probe point by specifying + a java class (or classes), a method (or methods in it) and + a specific location within it. A BTrace trace action method + annotated by this annotation is called when matching the traced + program reaches the specified location.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Required Element Summary

        + + + + + + + + + + +
        Required Elements 
        Modifier and TypeRequired Element and Description
        java.lang.Stringclazz +
        The probed (or traced) class name.
        +
        +
      • +
      + +
        +
      • + + +

        Optional Element Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + +
        Optional Elements 
        Modifier and TypeOptional Element and Description
        LevelenableAt +
        Activate this probe according to instrumentation level.
        +
        booleanexactTypeMatch +
        When set to true type checks will not involve assignability + checks based on class hierarchy and only exactly matching types will + be resolved as assignable.
        +
        Locationlocation +
        Identifies exact "location" or "point" of interest to + probe within the set of methods.
        +
        java.lang.Stringmethod +
        The probed (or traced) method name.
        +
        java.lang.Stringtype +
        This is method type declaration.
        +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Element Detail

        + + + +
          +
        • +

          clazz

          +
          public abstract java.lang.String clazz
          +
          The probed (or traced) class name. This is either + fully qualified name of the class or regular expression + within two forward slash characters [like /java\\.awt\\..+/] + or @annotation_of_the_class. i.e., specify a class indirectly + as a class annotated by specified annotation. +

          +

          Since 1.3.11

          + The specification can contain references to user arguments. + These references are using Ant style substitution patterns. + If a reference is not resolvable the whole probe point will be effectively disabled. +
          +
          +  @OnMethod(clazz = "${package}.MyClass")
          + 
          +

          +
        • +
        +
      • +
      + +
        +
      • + + +
          +
        • +

          method

          +
          public abstract java.lang.String method
          +
          The probed (or traced) method name. This is either + the name of the method or regular expression + within two forward slash characters [like /read.+/] + or @annotation_of_the_method. i.e., specify a method indirectly + as a method annotated by specified annotation. +

          +

          Since 1.3.11

          + The specification can contain references to user arguments. + These references are using Ant style substitution patterns. + If a reference is not resolvable the whole probe point will be effectively disabled. +
          +
          +  @OnMethod(clazz = "MyClass", method = "${method}")
          + 
          +

          +
          +
          Default:
          +
          ""
          +
          +
        • +
        +
      • +
      +
        +
      • + + +
          +
        • +

          exactTypeMatch

          +
          public abstract boolean exactTypeMatch
          +
          When set to true type checks will not involve assignability + checks based on class hierarchy and only exactly matching types will + be resolved as assignable.
          +
          +
          Returns:
          +
          true if exact type matching is requested; false otherwise (default)
          +
          +
          +
          Default:
          +
          false
          +
          +
        • +
        +
      • +
      +
        +
      • + + +
          +
        • +

          type

          +
          public abstract java.lang.String type
          +
          This is method type declaration. This is like Java method + declaration but not including method name, parameter + names and throws clause. +

          + Eg. public void myMethod(java.lang.String param) will become + void (java.lang.String) + +

          +

          Since 1.3.11

          + The specification can contain references to user arguments. + These references are using Ant style substitution patterns. + If a reference is not resolvable the whole probe point will be effectively disabled. +
          +
          +  @OnMethod(clazz = "MyClass", method = "method", type = "${retType} ()")
          + 
          +

          +
          +
          Default:
          +
          ""
          +
          +
        • +
        +
      • +
      +
        +
      • + + +
          +
        • +

          location

          +
          public abstract Location location
          +
          Identifies exact "location" or "point" of interest to + probe within the set of methods.
          +
          +
          Default:
          +
          @com.sun.btrace.annotations.Location
          +
          +
        • +
        +
      • +
      +
        +
      • + + +
          +
        • +

          enableAt

          +
          public abstract Level enableAt
          +
          Activate this probe according to instrumentation level. + +

          + It is possible to define enable/disable the handler according to the + current instrumentation level. Eg. @OnMethod(clazz="class", + method="method", enableAt=@Level(">1") +

          + The developer must make sure that all the handlers which are interconnected + in any way (eg. method entry/exit) will be enabled/disabled at a compatible + instrumentation level.

          +
          +
          Returns:
          +
          The instrumentation level (default @Level("0"))
          +
          Since:
          +
          1.3.4
          +
          See Also:
          +
          Level, +BTraceUtils.getInstrumentationLevel()
          +
          +
          +
          Default:
          +
          @com.sun.btrace.annotations.Level
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/OnProbe.html b/misc/btrace/javadoc/com/sun/btrace/annotations/OnProbe.html new file mode 100644 index 00000000..ea568fa6 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/OnProbe.html @@ -0,0 +1,243 @@ + + + + + +OnProbe (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Annotation Type OnProbe

    +
    +
    +
    +
      +
    • +
      +
      +
      @Retention(value=RUNTIME)
      + @Target(value=METHOD)
      +public @interface OnProbe
      +
      This annotation is used to specify a BTrace + probe point in an abstract fashion instead of + specifying the class and the method names. This + abstract namespace and (local) name are mapped to + one or more concrete probe points by the BTrace + agent at runtime.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Required Element Summary

        + + + + + + + + + + + + + + +
        Required Elements 
        Modifier and TypeRequired Element and Description
        java.lang.Stringname +
        Name within the namespace.
        +
        java.lang.Stringnamespace +
        Namespace for this abstract (a.k.a logical) + probe point.
        +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Element Detail

        + + + +
          +
        • +

          namespace

          +
          public abstract java.lang.String namespace
          +
          Namespace for this abstract (a.k.a logical) + probe point. Namespace follows java package name + conventions.
          +
        • +
        +
      • +
      +
        +
      • + + +
          +
        • +

          name

          +
          public abstract java.lang.String name
          +
          Name within the namespace. Identifies a probe + uniquely within the namespace.
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/OnTimer.html b/misc/btrace/javadoc/com/sun/btrace/annotations/OnTimer.html new file mode 100644 index 00000000..ef8385b0 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/OnTimer.html @@ -0,0 +1,256 @@ + + + + + +OnTimer (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Annotation Type OnTimer

    +
    +
    +
    +
      +
    • +
      +
      +
      @Retention(value=RUNTIME)
      + @Target(value=METHOD)
      +public @interface OnTimer
      +
      BTrace methods annotated by this annotation are called when + a timer reaches the specified period value. This can be used + to run periodic tracing actions.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Optional Element Summary

        + + + + + + + + + + + + + + +
        Optional Elements 
        Modifier and TypeOptional Element and Description
        java.lang.Stringfrom +
        If specified the timer period will be taken from btrace arguments.
        +
        longvalue +
        Time period of the timer in milliseconds.
        +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Element Detail

        + + + +
          +
        • +

          value

          +
          public abstract long value
          +
          Time period of the timer in milliseconds. + Defaults to 1 second
          +
          +
          Returns:
          +
          timer period
          +
          +
          +
          Default:
          +
          1000L
          +
          +
        • +
        +
      • +
      +
        +
      • + + +
          +
        • +

          from

          +
          public abstract java.lang.String from
          +
          If specified the timer period will be taken from btrace arguments. + The format is Ant-like property reference - eg. from = "${timer}"
          +
          +
          Returns:
          +
          btrace argument name holding timer period
          +
          Since:
          +
          1.3.11
          +
          +
          +
          Default:
          +
          ""
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/ProbeClassName.html b/misc/btrace/javadoc/com/sun/btrace/annotations/ProbeClassName.html new file mode 100644 index 00000000..f9ec5679 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/ProbeClassName.html @@ -0,0 +1,169 @@ + + + + + +ProbeClassName (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Annotation Type ProbeClassName

    +
    +
    +
    +
      +
    • +
      +
      +
      @Target(value=PARAMETER)
      + @Retention(value=RUNTIME)
      +public @interface ProbeClassName
      +
      It is used to mark a probe method argument as the receiver of the probe target class name
      + Applicable only for OnMethod annotation
      +
      +
      Since:
      +
      1.1
      +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/ProbeMethodName.html b/misc/btrace/javadoc/com/sun/btrace/annotations/ProbeMethodName.html new file mode 100644 index 00000000..63410f74 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/ProbeMethodName.html @@ -0,0 +1,224 @@ + + + + + +ProbeMethodName (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Annotation Type ProbeMethodName

    +
    +
    +
    +
      +
    • +
      +
      +
      @Target(value=PARAMETER)
      + @Retention(value=RUNTIME)
      +public @interface ProbeMethodName
      +
      It is used to mark a probe method argument as the receiver of the probe target class name
      + Applicable only for OnMethod annotation
      +
      +
      Since:
      +
      1.1
      +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Optional Element Summary

        + + + + + + + + + + +
        Optional Elements 
        Modifier and TypeOptional Element and Description
        booleanfqn +
        Flag indicating whether a fully qualified name (FQN) or a simple method name should be used
        +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Element Detail

        + + + +
          +
        • +

          fqn

          +
          public abstract boolean fqn
          +
          Flag indicating whether a fully qualified name (FQN) or a simple method name should be used
          +
          +
          Default:
          +
          false
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/Property.html b/misc/btrace/javadoc/com/sun/btrace/annotations/Property.html new file mode 100644 index 00000000..214374d6 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/Property.html @@ -0,0 +1,237 @@ + + + + + +Property (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Annotation Type Property

    +
    +
    +
    +
      +
    • +
      +
      +
      @Retention(value=RUNTIME)
      + @Target(value=FIELD)
      +public @interface Property
      +
      BTrace fields with this annotation are exposed as attributes of + the dynamic JMX bean that wraps the BTrace class.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Optional Element Summary

        + + + + + + + + + + + + + + +
        Optional Elements 
        Modifier and TypeOptional Element and Description
        java.lang.Stringdescription 
        java.lang.Stringname 
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Element Detail

        + + + +
          +
        • +

          name

          +
          public abstract java.lang.String name
          +
          +
          Default:
          +
          ""
          +
          +
        • +
        +
      • +
      +
        +
      • + + +
          +
        • +

          description

          +
          public abstract java.lang.String description
          +
          +
          Default:
          +
          ""
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/Return.html b/misc/btrace/javadoc/com/sun/btrace/annotations/Return.html new file mode 100644 index 00000000..59228877 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/Return.html @@ -0,0 +1,164 @@ + + + + + +Return (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Annotation Type Return

    +
    +
    +
    +
      +
    • +
      +
      +
      @Retention(value=RUNTIME)
      + @Target(value=PARAMETER)
      +public @interface Return
      +
      Marks a method parameter as the one that should contain the return value
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/Sampled.Sampler.html b/misc/btrace/javadoc/com/sun/btrace/annotations/Sampled.Sampler.html new file mode 100644 index 00000000..6495e614 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/Sampled.Sampler.html @@ -0,0 +1,370 @@ + + + + + +Sampled.Sampler (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Enum Sampled.Sampler

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • java.lang.Enum<Sampled.Sampler>
      • +
      • +
          +
        • com.sun.btrace.annotations.Sampled.Sampler
        • +
        +
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.io.Serializable, java.lang.Comparable<Sampled.Sampler>
      +
      +
      +
      Enclosing class:
      +
      Sampled
      +
      +
      +
      +
      public static enum Sampled.Sampler
      +extends java.lang.Enum<Sampled.Sampler>
      +
      Specifies the sampler kind +
        +
      • None - no sampling
      • +
      • Const - keeps the average number of events between samples
      • +
      • Adaptive - increases or decreases the average number of events between samples to lower overhead
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Enum Constant Summary

        + + + + + + + + + + + + + + +
        Enum Constants 
        Enum Constant and Description
        Adaptive +
        Increases or decreases the average number of events between samples to lower overhead
        +
        Const +
        Keeps the average number of events between samples
        +
        None +
        No Sampling
        +
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static Sampled.SamplervalueOf(java.lang.String name) +
        Returns the enum constant of this type with the specified name.
        +
        static Sampled.Sampler[]values() +
        Returns an array containing the constants of this enum type, in +the order they are declared.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Enum

          +clone, compareTo, equals, finalize, getDeclaringClass, hashCode, name, ordinal, toString, valueOf
        • +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +getClass, notify, notifyAll, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Enum Constant Detail

        + + + + + + + +
          +
        • +

          Const

          +
          public static final Sampled.Sampler Const
          +
          Keeps the average number of events between samples
          +
        • +
        + + + +
          +
        • +

          Adaptive

          +
          public static final Sampled.Sampler Adaptive
          +
          Increases or decreases the average number of events between samples to lower overhead
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          values

          +
          public static Sampled.Sampler[] values()
          +
          Returns an array containing the constants of this enum type, in +the order they are declared. This method may be used to iterate +over the constants as follows: +
          +for (Sampled.Sampler c : Sampled.Sampler.values())
          +    System.out.println(c);
          +
          +
          +
          Returns:
          +
          an array containing the constants of this enum type, in the order they are declared
          +
          +
        • +
        + + + +
          +
        • +

          valueOf

          +
          public static Sampled.Sampler valueOf(java.lang.String name)
          +
          Returns the enum constant of this type with the specified name. +The string must match exactly an identifier used to declare an +enum constant in this type. (Extraneous whitespace characters are +not permitted.)
          +
          +
          Parameters:
          +
          name - the name of the enum constant to be returned.
          +
          Returns:
          +
          the enum constant with the specified name
          +
          Throws:
          +
          java.lang.IllegalArgumentException - if this enum type has no constant with the specified name
          +
          java.lang.NullPointerException - if the argument is null
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/Sampled.html b/misc/btrace/javadoc/com/sun/btrace/annotations/Sampled.html new file mode 100644 index 00000000..26253b02 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/Sampled.html @@ -0,0 +1,295 @@ + + + + + +Sampled (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Annotation Type Sampled

    +
    +
    +
    +
      +
    • +
      +
      +
      @Target(value=METHOD)
      + @Retention(value=CLASS)
      +public @interface Sampled
      +
      Marks an OnMethod handler as a sampled one. + When a handler is sampled not all events will be traced - only a statistical + sample with the given mean. +

      + By default an adaptive sampling is used. BTrace will increase or decrease the + number of invocations between samples to keep the mean time window, thus + decreasing the overall overhead.

      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Summary

        + + + + + + + + + + +
        Fields 
        Modifier and TypeFields and Description
        static intMEAN_DEFAULT 
        +
      • +
      + +
        +
      • + + +

        Optional Element Summary

        + + + + + + + + + + + + + + +
        Optional Elements 
        Modifier and TypeOptional Element and Description
        Sampled.Samplerkind +
        The sampler kind
        +
        intmean +
        The sampler mean.
        +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Detail

        + + + +
          +
        • +

          MEAN_DEFAULT

          +
          public static final int MEAN_DEFAULT
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Element Detail

        + + + +
          +
        • +

          kind

          +
          public abstract Sampled.Sampler kind
          +
          The sampler kind
          +
          +
          Returns:
          +
          The sampler kind
          +
          +
          +
          Default:
          +
          com.sun.btrace.annotations.Sampled.Sampler.Const
          +
          +
        • +
        +
      • +
      +
        +
      • + + +
          +
        • +

          mean

          +
          public abstract int mean
          +
          The sampler mean. +

          + For Sampler.Const it is the average number of events between samples.
          + For Sampler.Adaptive it is the average time (in ns) between samples

          +
          +
          Returns:
          +
          The sampler mean
          +
          +
          +
          Default:
          +
          10
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/Self.html b/misc/btrace/javadoc/com/sun/btrace/annotations/Self.html new file mode 100644 index 00000000..e27e2038 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/Self.html @@ -0,0 +1,164 @@ + + + + + +Self (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Annotation Type Self

    +
    +
    +
    +
      +
    • +
      +
      +
      @Retention(value=RUNTIME)
      + @Target(value=PARAMETER)
      +public @interface Self
      +
      Marks a method parameter as the one that should contain *this* instance
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/ServiceType.html b/misc/btrace/javadoc/com/sun/btrace/annotations/ServiceType.html new file mode 100644 index 00000000..8f50a323 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/ServiceType.html @@ -0,0 +1,346 @@ + + + + + +ServiceType (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Enum ServiceType

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • java.lang.Enum<ServiceType>
      • +
      • +
          +
        • com.sun.btrace.annotations.ServiceType
        • +
        +
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.io.Serializable, java.lang.Comparable<ServiceType>
      +
      +
      +
      +
      public enum ServiceType
      +extends java.lang.Enum<ServiceType>
      +
      Service type enumeration
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Enum Constant Summary

        + + + + + + + + + + + +
        Enum Constants 
        Enum Constant and Description
        RUNTIME +
        A runtime-aware service; requires an instance per BTraceRuntime
        +
        SIMPLE +
        A simple service; possibly a globally shared singleton
        +
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static ServiceTypevalueOf(java.lang.String name) +
        Returns the enum constant of this type with the specified name.
        +
        static ServiceType[]values() +
        Returns an array containing the constants of this enum type, in +the order they are declared.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Enum

          +clone, compareTo, equals, finalize, getDeclaringClass, hashCode, name, ordinal, toString, valueOf
        • +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +getClass, notify, notifyAll, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Enum Constant Detail

        + + + +
          +
        • +

          SIMPLE

          +
          public static final ServiceType SIMPLE
          +
          A simple service; possibly a globally shared singleton
          +
        • +
        + + + +
          +
        • +

          RUNTIME

          +
          public static final ServiceType RUNTIME
          +
          A runtime-aware service; requires an instance per BTraceRuntime
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          values

          +
          public static ServiceType[] values()
          +
          Returns an array containing the constants of this enum type, in +the order they are declared. This method may be used to iterate +over the constants as follows: +
          +for (ServiceType c : ServiceType.values())
          +    System.out.println(c);
          +
          +
          +
          Returns:
          +
          an array containing the constants of this enum type, in the order they are declared
          +
          +
        • +
        + + + +
          +
        • +

          valueOf

          +
          public static ServiceType valueOf(java.lang.String name)
          +
          Returns the enum constant of this type with the specified name. +The string must match exactly an identifier used to declare an +enum constant in this type. (Extraneous whitespace characters are +not permitted.)
          +
          +
          Parameters:
          +
          name - the name of the enum constant to be returned.
          +
          Returns:
          +
          the enum constant with the specified name
          +
          Throws:
          +
          java.lang.IllegalArgumentException - if this enum type has no constant with the specified name
          +
          java.lang.NullPointerException - if the argument is null
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/TLS.html b/misc/btrace/javadoc/com/sun/btrace/annotations/TLS.html new file mode 100644 index 00000000..a313a4a0 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/TLS.html @@ -0,0 +1,171 @@ + + + + + +TLS (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Annotation Type TLS

    +
    +
    +
    +
      +
    • +
      +
      +
      @Retention(value=RUNTIME)
      + @Target(value=FIELD)
      +public @interface TLS
      +
      Annotation for thread-local BTrace fields. BTrace fields + annotated with this annotation are stored in thread local + storage. Field get/set are transparently converted to + thread local get and set respectively. + +

      Important!!!

      + It is not possible to access the data stored in the thread local storage + from any other handler than OnMethod
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/TargetInstance.html b/misc/btrace/javadoc/com/sun/btrace/annotations/TargetInstance.html new file mode 100644 index 00000000..31aacc76 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/TargetInstance.html @@ -0,0 +1,170 @@ + + + + + +TargetInstance (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Annotation Type TargetInstance

    +
    +
    +
    +
      +
    • +
      +
      +
      @Target(value=PARAMETER)
      + @Retention(value=RUNTIME)
      +public @interface TargetInstance
      +
      It is used to mark a probe method argument as the receiver of called instance + with Location value of Kind.CALL, Kind.FIELD_GET + or Kind.FIELD_SET.
      +
      +
      Since:
      +
      1.1
      +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/TargetMethodOrField.html b/misc/btrace/javadoc/com/sun/btrace/annotations/TargetMethodOrField.html new file mode 100644 index 00000000..21b8698c --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/TargetMethodOrField.html @@ -0,0 +1,224 @@ + + + + + +TargetMethodOrField (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Annotation Type TargetMethodOrField

    +
    +
    +
    +
      +
    • +
      +
      +
      @Target(value=PARAMETER)
      + @Retention(value=RUNTIME)
      +public @interface TargetMethodOrField
      +
      It is used to mark a probe method argument as the receiver of called method name + in Location = Kind.CALL
      +
      +
      Since:
      +
      1.1
      +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Optional Element Summary

        + + + + + + + + + + +
        Optional Elements 
        Modifier and TypeOptional Element and Description
        booleanfqn +
        Flag indicating whether a fully qualified name (FQN) or a simple method/field name should be used
        +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Element Detail

        + + + +
          +
        • +

          fqn

          +
          public abstract boolean fqn
          +
          Flag indicating whether a fully qualified name (FQN) or a simple method/field name should be used
          +
          +
          Default:
          +
          false
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/Where.html b/misc/btrace/javadoc/com/sun/btrace/annotations/Where.html new file mode 100644 index 00000000..4eb150a1 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/Where.html @@ -0,0 +1,348 @@ + + + + + +Where (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.annotations
    +

    Enum Where

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • java.lang.Enum<Where>
      • +
      • +
          +
        • com.sun.btrace.annotations.Where
        • +
        +
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.io.Serializable, java.lang.Comparable<Where>
      +
      +
      +
      +
      public enum Where
      +extends java.lang.Enum<Where>
      +
      This enum is specified in the Location + annotation to specify whether a probe point + is after or before specific point of interest.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Enum Constant Summary

        + + + + + + + + + + + +
        Enum Constants 
        Enum Constant and Description
        AFTER +
        after the location of interest
        +
        BEFORE +
        before the location of interest
        +
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static WherevalueOf(java.lang.String name) +
        Returns the enum constant of this type with the specified name.
        +
        static Where[]values() +
        Returns an array containing the constants of this enum type, in +the order they are declared.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Enum

          +clone, compareTo, equals, finalize, getDeclaringClass, hashCode, name, ordinal, toString, valueOf
        • +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +getClass, notify, notifyAll, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Enum Constant Detail

        + + + +
          +
        • +

          AFTER

          +
          public static final Where AFTER
          +
          after the location of interest
          +
        • +
        + + + +
          +
        • +

          BEFORE

          +
          public static final Where BEFORE
          +
          before the location of interest
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          values

          +
          public static Where[] values()
          +
          Returns an array containing the constants of this enum type, in +the order they are declared. This method may be used to iterate +over the constants as follows: +
          +for (Where c : Where.values())
          +    System.out.println(c);
          +
          +
          +
          Returns:
          +
          an array containing the constants of this enum type, in the order they are declared
          +
          +
        • +
        + + + +
          +
        • +

          valueOf

          +
          public static Where valueOf(java.lang.String name)
          +
          Returns the enum constant of this type with the specified name. +The string must match exactly an identifier used to declare an +enum constant in this type. (Extraneous whitespace characters are +not permitted.)
          +
          +
          Parameters:
          +
          name - the name of the enum constant to be returned.
          +
          Returns:
          +
          the enum constant with the specified name
          +
          Throws:
          +
          java.lang.IllegalArgumentException - if this enum type has no constant with the specified name
          +
          java.lang.NullPointerException - if the argument is null
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/package-frame.html b/misc/btrace/javadoc/com/sun/btrace/annotations/package-frame.html new file mode 100644 index 00000000..4f24dce3 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/package-frame.html @@ -0,0 +1,50 @@ + + + + + +com.sun.btrace.annotations (btrace 1.3.11 API) + + + + + +

    com.sun.btrace.annotations

    + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/package-summary.html b/misc/btrace/javadoc/com/sun/btrace/annotations/package-summary.html new file mode 100644 index 00000000..f97fea34 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/package-summary.html @@ -0,0 +1,345 @@ + + + + + +com.sun.btrace.annotations (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Package com.sun.btrace.annotations

    +
    +
    +
      +
    • + + + + + + + + + + + + + + + + + + + + + + + + +
      Enum Summary 
      EnumDescription
      Kind +
      This enum is specified in the Location + annotation to specify probe point kind.
      +
      Sampled.Sampler +
      Specifies the sampler kind + + None - no sampling + Const - keeps the average number of events between samples + Adaptive - increases or decreases the average number of events between samples to lower overhead +
      +
      ServiceType +
      Service type enumeration
      +
      Where +
      This enum is specified in the Location + annotation to specify whether a probe point + is after or before specific point of interest.
      +
      +
    • +
    • + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Annotation Types Summary 
      Annotation TypeDescription
      BTrace +
      Top-level annotation that identifies a BTrace + class.
      +
      DTrace +
      Annotation for BTrace program to associate a D-script with it.
      +
      DTraceRef +
      Annotation for BTrace program to associate a D-script with it.
      +
      Duration +
      It is used to mark a probe method argument as the receiver of the duration value
      + Applicable only for OnMethod annotation with Location value + of Kind.RETURN or Kind.ERROR
      +
      Export +
      BTrace fields with this annotation are exposed to + out-of-process tools using mechanisms such as jvmstat.
      +
      Injected +
      Annotates a field as an injected service.
      +
      Level +
      Allows specifying a probe handler instrumentation level matching expression.
      +
      Location +
      This annotation specifies a particular "location" within a + traced/probed java method for BTrace probe specifications.
      +
      OnError +
      BTrace method annotated by this annotation is called when + any exception is thrown by any of the BTrace action methods.
      +
      OnEvent +
      BTrace methods annotated by this annotation are called when + BTrace client sends "event" command.
      +
      OnExit +
      BTrace method annotated by this annotation is called when + BTrace "exit(int)" built-in function is called by some + other BTrace action method.
      +
      OnLowMemory +
      BTrace methods annotated by this annotation are called when + the traced JVM's specified memory pool exceeds specified + threshold size.
      +
      OnMethod +
      This annotation specifies a BTrace probe point by specifying + a java class (or classes), a method (or methods in it) and + a specific location within it.
      +
      OnProbe +
      This annotation is used to specify a BTrace + probe point in an abstract fashion instead of + specifying the class and the method names.
      +
      OnTimer +
      BTrace methods annotated by this annotation are called when + a timer reaches the specified period value.
      +
      ProbeClassName +
      It is used to mark a probe method argument as the receiver of the probe target class name
      + Applicable only for OnMethod annotation
      +
      ProbeMethodName +
      It is used to mark a probe method argument as the receiver of the probe target class name
      + Applicable only for OnMethod annotation
      +
      Property +
      BTrace fields with this annotation are exposed as attributes of + the dynamic JMX bean that wraps the BTrace class.
      +
      Return +
      Marks a method parameter as the one that should contain the return value
      +
      Sampled +
      Marks an OnMethod handler as a sampled one.
      +
      Self +
      Marks a method parameter as the one that should contain *this* instance
      +
      TargetInstance +
      It is used to mark a probe method argument as the receiver of called instance + with Location value of Kind.CALL, Kind.FIELD_GET + or Kind.FIELD_SET.
      +
      TargetMethodOrField +
      It is used to mark a probe method argument as the receiver of called method name + in Location = Kind.CALL
      +
      TLS +
      Annotation for thread-local BTrace fields.
      +
      +
    • +
    +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/annotations/package-tree.html b/misc/btrace/javadoc/com/sun/btrace/annotations/package-tree.html new file mode 100644 index 00000000..8b91bc80 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/annotations/package-tree.html @@ -0,0 +1,169 @@ + + + + + +com.sun.btrace.annotations Class Hierarchy (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Hierarchy For Package com.sun.btrace.annotations

    +Package Hierarchies: + +
    +
    +

    Annotation Type Hierarchy

    +
      +
    • com.sun.btrace.annotations.Duration (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.Injected (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.Self (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.OnError (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.Property (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.Sampled (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.OnExit (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.OnProbe (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.Location (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.ProbeClassName (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.BTrace (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.OnEvent (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.OnTimer (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.DTrace (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.TargetInstance (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.Level (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.OnLowMemory (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.TargetMethodOrField (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.Return (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.Export (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.ProbeMethodName (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.OnMethod (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.DTraceRef (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.TLS (implements java.lang.annotation.Annotation)
    • +
    +

    Enum Hierarchy

    +
      +
    • java.lang.Object +
        +
      • java.lang.Enum<E> (implements java.lang.Comparable<T>, java.io.Serializable) + +
      • +
      +
    • +
    +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/api/BTraceCompiler.html b/misc/btrace/javadoc/com/sun/btrace/api/BTraceCompiler.html new file mode 100644 index 00000000..923ee460 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/api/BTraceCompiler.html @@ -0,0 +1,331 @@ + + + + + +BTraceCompiler (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.api
    +

    Class BTraceCompiler

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.api.BTraceCompiler
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Direct Known Subclasses:
      +
      BaseBTraceCompiler
      +
      +
      +
      +
      public abstract class BTraceCompiler
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        BTraceCompiler() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Abstract Methods Concrete Methods 
        Modifier and TypeMethod and Description
        byte[]compile(java.lang.String source, + java.lang.String classPath) 
        abstract byte[]compile(java.lang.String source, + java.lang.String classPath, + java.io.Writer errorWriter) 
        abstract java.lang.StringgetAgentJarPath() 
        abstract java.lang.StringgetClientJarPath() 
        abstract java.lang.StringgetToolsJarPath() 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          BTraceCompiler

          +
          public BTraceCompiler()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          compile

          +
          public byte[] compile(java.lang.String source,
          +                      java.lang.String classPath)
          +
        • +
        + + + +
          +
        • +

          compile

          +
          public abstract byte[] compile(java.lang.String source,
          +                               java.lang.String classPath,
          +                               java.io.Writer errorWriter)
          +
        • +
        + + + +
          +
        • +

          getAgentJarPath

          +
          public abstract java.lang.String getAgentJarPath()
          +
        • +
        + + + +
          +
        • +

          getClientJarPath

          +
          public abstract java.lang.String getClientJarPath()
          +
        • +
        + + + +
          +
        • +

          getToolsJarPath

          +
          public abstract java.lang.String getToolsJarPath()
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/api/BTraceEngine.html b/misc/btrace/javadoc/com/sun/btrace/api/BTraceEngine.html new file mode 100644 index 00000000..b567e9af --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/api/BTraceEngine.html @@ -0,0 +1,302 @@ + + + + + +BTraceEngine (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.api
    +

    Class BTraceEngine

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.api.BTraceEngine
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Direct Known Subclasses:
      +
      BTraceEngineImpl
      +
      +
      +
      +
      public abstract class BTraceEngine
      +extends java.lang.Object
      +
      This class serves as a factory for BTraceTask instances +

      + Usually, when using BTrace on a process with given PID one would do +

      + BTraceTask task = BTraceEngine.sharedInstance().createTask(PID)
      + 
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          BTraceEngine

          +
          public BTraceEngine()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          newInstance

          +
          public static final BTraceEngine newInstance()
          +
        • +
        + + + +
          +
        • +

          createTask

          +
          public abstract BTraceTask createTask(int pid)
          +
          Abstract factory method for BTraceTask instances
          +
          +
          Parameters:
          +
          pid - The application PID to create the task for
          +
          Returns:
          +
          Returns a BTraceTask instance bound to the particular java process + or null if it is not possible to run BTrace against the application
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/api/BTraceSettings.html b/misc/btrace/javadoc/com/sun/btrace/api/BTraceSettings.html new file mode 100644 index 00000000..f6499610 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/api/BTraceSettings.html @@ -0,0 +1,308 @@ + + + + + +BTraceSettings (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.api
    +

    Class BTraceSettings

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.api.BTraceSettings
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public abstract class BTraceSettings
      +extends java.lang.Object
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          BTraceSettings

          +
          public BTraceSettings()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          isDebugMode

          +
          public abstract boolean isDebugMode()
          +
        • +
        + + + +
          +
        • +

          getDumpClassPath

          +
          public abstract java.lang.String getDumpClassPath()
          +
        • +
        + + + +
          +
        • +

          isDumpClasses

          +
          public abstract boolean isDumpClasses()
          +
        • +
        + + + +
          +
        • +

          getStatsd

          +
          public java.lang.String getStatsd()
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/api/BTraceTask.MessageDispatcher.html b/misc/btrace/javadoc/com/sun/btrace/api/BTraceTask.MessageDispatcher.html new file mode 100644 index 00000000..e5e02bba --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/api/BTraceTask.MessageDispatcher.html @@ -0,0 +1,366 @@ + + + + + +BTraceTask.MessageDispatcher (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.api
    +

    Class BTraceTask.MessageDispatcher

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.api.BTraceTask.MessageDispatcher
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.util.EventListener
      +
      +
      +
      Enclosing class:
      +
      BTraceTask
      +
      +
      +
      +
      public abstract static class BTraceTask.MessageDispatcher
      +extends java.lang.Object
      +implements java.util.EventListener
      +
      CommandListener interface exposes the BTrace commands received over + the wire to anyone interested
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        MessageDispatcher() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        voidonClassInstrumented(java.lang.String name) 
        voidonError(java.lang.Throwable cause) 
        voidonGrid(java.lang.String name, + java.util.List<java.lang.Object[]> data) 
        voidonNumberMap(java.lang.String name, + java.util.Map<java.lang.String,? extends java.lang.Number> data) 
        voidonNumberMessage(java.lang.String name, + java.lang.Number value) 
        voidonPrintMessage(java.lang.String message) 
        voidonStringMap(java.lang.String name, + java.util.Map<java.lang.String,java.lang.String> data) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          MessageDispatcher

          +
          public MessageDispatcher()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          onPrintMessage

          +
          public void onPrintMessage(java.lang.String message)
          +
        • +
        + + + +
          +
        • +

          onNumberMessage

          +
          public void onNumberMessage(java.lang.String name,
          +                            java.lang.Number value)
          +
        • +
        + + + +
          +
        • +

          onGrid

          +
          public void onGrid(java.lang.String name,
          +                   java.util.List<java.lang.Object[]> data)
          +
        • +
        + + + +
          +
        • +

          onNumberMap

          +
          public void onNumberMap(java.lang.String name,
          +                        java.util.Map<java.lang.String,? extends java.lang.Number> data)
          +
        • +
        + + + +
          +
        • +

          onStringMap

          +
          public void onStringMap(java.lang.String name,
          +                        java.util.Map<java.lang.String,java.lang.String> data)
          +
        • +
        + + + +
          +
        • +

          onClassInstrumented

          +
          public void onClassInstrumented(java.lang.String name)
          +
        • +
        + + + +
          +
        • +

          onError

          +
          public void onError(java.lang.Throwable cause)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/api/BTraceTask.State.html b/misc/btrace/javadoc/com/sun/btrace/api/BTraceTask.State.html new file mode 100644 index 00000000..8a41d0ba --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/api/BTraceTask.State.html @@ -0,0 +1,452 @@ + + + + + +BTraceTask.State (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.api
    +

    Enum BTraceTask.State

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • java.lang.Enum<BTraceTask.State>
      • +
      • +
          +
        • com.sun.btrace.api.BTraceTask.State
        • +
        +
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.io.Serializable, java.lang.Comparable<BTraceTask.State>
      +
      +
      +
      Enclosing class:
      +
      BTraceTask
      +
      +
      +
      +
      public static enum BTraceTask.State
      +extends java.lang.Enum<BTraceTask.State>
      +
      This enum represents the allowed states of the tracing task
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Enum Constant Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        Enum Constants 
        Enum Constant and Description
        ACCEPTED +
        The BTrace agent has accepted the script
        +
        COMPILED +
        The task script has just been compiled
        +
        COMPILING +
        Indicates that the BTrace compiler has started compiling
        +
        FAILED 
        FINISHED +
        Indicates an inactive task
        +
        INSTRUMENTING +
        The BTrace agent is going to instrument appropriate classes
        +
        NEW +
        This is the state of a newly created task
        +
        RUNNING +
        All instrumentation and initialization is done; task is running
        +
        STARTING +
        The task becomes STARTING immediately after calling its start()method
        +
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static BTraceTask.StatevalueOf(java.lang.String name) +
        Returns the enum constant of this type with the specified name.
        +
        static BTraceTask.State[]values() +
        Returns an array containing the constants of this enum type, in +the order they are declared.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Enum

          +clone, compareTo, equals, finalize, getDeclaringClass, hashCode, name, ordinal, toString, valueOf
        • +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +getClass, notify, notifyAll, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Enum Constant Detail

        + + + +
          +
        • +

          NEW

          +
          public static final BTraceTask.State NEW
          +
          This is the state of a newly created task
          +
        • +
        + + + +
          +
        • +

          STARTING

          +
          public static final BTraceTask.State STARTING
          +
          The task becomes STARTING immediately after calling its start()method
          +
        • +
        + + + +
          +
        • +

          COMPILING

          +
          public static final BTraceTask.State COMPILING
          +
          Indicates that the BTrace compiler has started compiling
          +
        • +
        + + + +
          +
        • +

          COMPILED

          +
          public static final BTraceTask.State COMPILED
          +
          The task script has just been compiled
          +
        • +
        + + + +
          +
        • +

          ACCEPTED

          +
          public static final BTraceTask.State ACCEPTED
          +
          The BTrace agent has accepted the script
          +
        • +
        + + + +
          +
        • +

          INSTRUMENTING

          +
          public static final BTraceTask.State INSTRUMENTING
          +
          The BTrace agent is going to instrument appropriate classes
          +
        • +
        + + + +
          +
        • +

          RUNNING

          +
          public static final BTraceTask.State RUNNING
          +
          All instrumentation and initialization is done; task is running
          +
        • +
        + + + +
          +
        • +

          FINISHED

          +
          public static final BTraceTask.State FINISHED
          +
          Indicates an inactive task
          +
        • +
        + + + + +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          values

          +
          public static BTraceTask.State[] values()
          +
          Returns an array containing the constants of this enum type, in +the order they are declared. This method may be used to iterate +over the constants as follows: +
          +for (BTraceTask.State c : BTraceTask.State.values())
          +    System.out.println(c);
          +
          +
          +
          Returns:
          +
          an array containing the constants of this enum type, in the order they are declared
          +
          +
        • +
        + + + +
          +
        • +

          valueOf

          +
          public static BTraceTask.State valueOf(java.lang.String name)
          +
          Returns the enum constant of this type with the specified name. +The string must match exactly an identifier used to declare an +enum constant in this type. (Extraneous whitespace characters are +not permitted.)
          +
          +
          Parameters:
          +
          name - the name of the enum constant to be returned.
          +
          Returns:
          +
          the enum constant with the specified name
          +
          Throws:
          +
          java.lang.IllegalArgumentException - if this enum type has no constant with the specified name
          +
          java.lang.NullPointerException - if the argument is null
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/api/BTraceTask.StateListener.html b/misc/btrace/javadoc/com/sun/btrace/api/BTraceTask.StateListener.html new file mode 100644 index 00000000..64f9ef28 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/api/BTraceTask.StateListener.html @@ -0,0 +1,236 @@ + + + + + +BTraceTask.StateListener (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.api
    +

    Interface BTraceTask.StateListener

    +
    +
    +
    +
      +
    • +
      +
      All Superinterfaces:
      +
      java.util.EventListener
      +
      +
      +
      Enclosing class:
      +
      BTraceTask
      +
      +
      +
      +
      public static interface BTraceTask.StateListener
      +extends java.util.EventListener
      +
      Simple state listener interface
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          stateChanged

          +
          void stateChanged(BTraceTask.State newState)
          +
          Called upon state change
          +
          +
          Parameters:
          +
          newState - New state
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/api/BTraceTask.html b/misc/btrace/javadoc/com/sun/btrace/api/BTraceTask.html new file mode 100644 index 00000000..e121b19e --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/api/BTraceTask.html @@ -0,0 +1,641 @@ + + + + + +BTraceTask (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.api
    +

    Class BTraceTask

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.api.BTraceTask
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Direct Known Subclasses:
      +
      BTraceTaskImpl
      +
      +
      +
      +
      public abstract class BTraceTask
      +extends java.lang.Object
      +
      This class represents a single BTrace script +

      + An instance of BTraceTask bound to a certain process can be obtained by calling +

      + BTraceEngine.sharedInstance().createTask(PID)
      + 
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          BTraceTask

          +
          public BTraceTask()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + + + + + + + + + + + + + + + + + +
          +
        • +

          start

          +
          public abstract void start()
          +
          Starts the injected code
          +
        • +
        + + + +
          +
        • +

          stop

          +
          public abstract void stop()
          +
          Stops the injected code
          +
        • +
        + + + +
          +
        • +

          getPid

          +
          public abstract int getPid()
          +
        • +
        + + + +
          +
        • +

          getScript

          +
          public abstract java.lang.String getScript()
          +
          Property getter
          +
          +
          Returns:
          +
          Returns the script source code
          +
          +
        • +
        + + + +
          +
        • +

          getName

          +
          public abstract java.lang.String getName()
          +
          Returns the name specified in BTrace annotation
          +
          +
          Returns:
          +
          Returns the name specified in BTrace annotation or NULL if not specified
          +
          +
        • +
        + + + +
          +
        • +

          setScript

          +
          public abstract void setScript(java.lang.String newValue)
          +
          Property setter
          +
          +
          Parameters:
          +
          newValue - The script source code to be used
          +
          +
        • +
        + + + +
          +
        • +

          getClassPath

          +
          public abstract java.lang.String getClassPath()
          +
          +
          Returns:
          +
          Returns the complete classpath for the task
          +
          +
        • +
        + + + +
          +
        • +

          isUnsafe

          +
          @Deprecated
          +public boolean isUnsafe()
          +
          Deprecated. Use isTrusted() instead
          +
          Checks whether the task requires to be run in BTrace Unsafe mode
          +
          +
          Returns:
          +
          Returns true if the BTrace task requires to be run in BTrace Unsafe mode
          +
          +
        • +
        + + + +
          +
        • +

          isTrusted

          +
          public boolean isTrusted()
          +
        • +
        + + + +
          +
        • +

          sendEvent

          +
          public abstract void sendEvent(java.lang.String event)
          +
          Sends a named event to the script server side
          +
          +
          Parameters:
          +
          event - The event to send
          +
          +
        • +
        + + + +
          +
        • +

          sendEvent

          +
          public abstract void sendEvent()
          +
          Sends an anonymous event to the script server side
          +
        • +
        + + + +
          +
        • +

          getNamedEvents

          +
          public abstract java.util.Set<java.lang.String> getNamedEvents()
          +
          A list of named events
          +
          +
          Returns:
          +
          Returns the list of all named events defined in the script
          +
          +
        • +
        + + + +
          +
        • +

          hasAnonymousEvents

          +
          public abstract boolean hasAnonymousEvents()
          +
          A flag indicating that the task has some anonymous events assigned
          +
          +
          Returns:
          +
          Returns TRUE if there are any anonymous events defined
          +
          +
        • +
        + + + +
          +
        • +

          hasEvents

          +
          public abstract boolean hasEvents()
          +
          Flag property getter
          +
          +
          Returns:
          +
          Returns true if the script has defined at least one @OnEvent probe
          +
          +
        • +
        + + + +
          +
        • +

          getInstrClasses

          +
          public abstract int getInstrClasses()
          +
          The number of classes the task needs to instruments
          +
          +
          Returns:
          +
          Returns the number of classes the task needs to instrument
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/api/impl/BTraceEngineImpl.html b/misc/btrace/javadoc/com/sun/btrace/api/impl/BTraceEngineImpl.html new file mode 100644 index 00000000..99f05a4b --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/api/impl/BTraceEngineImpl.html @@ -0,0 +1,294 @@ + + + + + +BTraceEngineImpl (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.api.impl
    +

    Class BTraceEngineImpl

    +
    +
    + +
    +
      +
    • +
      +
      +
      public class BTraceEngineImpl
      +extends BTraceEngine
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          BTraceEngineImpl

          +
          public BTraceEngineImpl()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          createTask

          +
          public BTraceTask createTask(int pid)
          +
          Description copied from class: BTraceEngine
          +
          Abstract factory method for BTraceTask instances
          +
          +
          Specified by:
          +
          createTask in class BTraceEngine
          +
          Parameters:
          +
          pid - The application PID to create the task for
          +
          Returns:
          +
          Returns a BTraceTask instance bound to the particular java process + or null if it is not possible to run BTrace against the application
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/api/impl/BTraceTaskImpl.html b/misc/btrace/javadoc/com/sun/btrace/api/impl/BTraceTaskImpl.html new file mode 100644 index 00000000..4ccb4542 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/api/impl/BTraceTaskImpl.html @@ -0,0 +1,769 @@ + + + + + +BTraceTaskImpl (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.api.impl
    +

    Class BTraceTaskImpl

    +
    +
    + +
    +
      +
    • +
      +
      +
      public class BTraceTaskImpl
      +extends BTraceTask
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          BTraceTaskImpl

          +
          public BTraceTaskImpl(int pid,
          +                      BTraceEngine engine)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getScript

          +
          public java.lang.String getScript()
          +
          Description copied from class: BTraceTask
          +
          Property getter
          +
          +
          Specified by:
          +
          getScript in class BTraceTask
          +
          Returns:
          +
          Returns the script source code
          +
          +
        • +
        + + + +
          +
        • +

          getName

          +
          public java.lang.String getName()
          +
          Description copied from class: BTraceTask
          +
          Returns the name specified in BTrace annotation
          +
          +
          Specified by:
          +
          getName in class BTraceTask
          +
          Returns:
          +
          Returns the name specified in BTrace annotation or NULL if not specified
          +
          +
        • +
        + + + +
          +
        • +

          setScript

          +
          public void setScript(java.lang.String newValue)
          +
          Description copied from class: BTraceTask
          +
          Property setter
          +
          +
          Specified by:
          +
          setScript in class BTraceTask
          +
          Parameters:
          +
          newValue - The script source code to be used
          +
          +
        • +
        + + + +
          +
        • +

          sendEvent

          +
          public void sendEvent(java.lang.String event)
          +
          Description copied from class: BTraceTask
          +
          Sends a named event to the script server side
          +
          +
          Specified by:
          +
          sendEvent in class BTraceTask
          +
          Parameters:
          +
          event - The event to send
          +
          +
        • +
        + + + +
          +
        • +

          sendEvent

          +
          public void sendEvent()
          +
          Description copied from class: BTraceTask
          +
          Sends an anonymous event to the script server side
          +
          +
          Specified by:
          +
          sendEvent in class BTraceTask
          +
          +
        • +
        + + + +
          +
        • +

          getNamedEvents

          +
          public java.util.Set<java.lang.String> getNamedEvents()
          +
          Description copied from class: BTraceTask
          +
          A list of named events
          +
          +
          Specified by:
          +
          getNamedEvents in class BTraceTask
          +
          Returns:
          +
          Returns the list of all named events defined in the script
          +
          +
        • +
        + + + +
          +
        • +

          hasAnonymousEvents

          +
          public boolean hasAnonymousEvents()
          +
          Description copied from class: BTraceTask
          +
          A flag indicating that the task has some anonymous events assigned
          +
          +
          Specified by:
          +
          hasAnonymousEvents in class BTraceTask
          +
          Returns:
          +
          Returns TRUE if there are any anonymous events defined
          +
          +
        • +
        + + + +
          +
        • +

          hasEvents

          +
          public boolean hasEvents()
          +
          Description copied from class: BTraceTask
          +
          Flag property getter
          +
          +
          Specified by:
          +
          hasEvents in class BTraceTask
          +
          Returns:
          +
          Returns true if the script has defined at least one @OnEvent probe
          +
          +
        • +
        + + + +
          +
        • +

          getPid

          +
          public int getPid()
          +
          +
          Specified by:
          +
          getPid in class BTraceTask
          +
          +
        • +
        + + + +
          +
        • +

          getState

          +
          protected BTraceTask.State getState()
          +
          Property getter
          +
          +
          Returns:
          +
          Returns the current state
          +
          +
        • +
        + + + +
          +
        • +

          getInstrClasses

          +
          public int getInstrClasses()
          +
          Description copied from class: BTraceTask
          +
          The number of classes the task needs to instruments
          +
          +
          Specified by:
          +
          getInstrClasses in class BTraceTask
          +
          Returns:
          +
          Returns the number of classes the task needs to instrument
          +
          +
        • +
        + + + + + + + + + + + + + + + + + + + +
          +
        • +

          start

          +
          public void start()
          +
          Starts the injected code using the attached BTraceEngine
          +
          +
          Specified by:
          +
          start in class BTraceTask
          +
          +
        • +
        + + + +
          +
        • +

          stop

          +
          public void stop()
          +
          Stops the injected code running on the attached BTraceEngine
          +
          +
          Specified by:
          +
          stop in class BTraceTask
          +
          +
        • +
        + + + +
          +
        • +

          onTaskStart

          +
          public void onTaskStart(BTraceTask task)
          +
          Called on task startup
          +
          +
          Parameters:
          +
          task - The task that has started up
          +
          See Also:
          +
          BTraceEngineImpl.StateListener.onTaskStart(BTraceTask)
          +
          +
        • +
        + + + +
          +
        • +

          onTaskStop

          +
          public void onTaskStop(BTraceTask task)
          +
          Called on task shutdown
          +
          +
          Parameters:
          +
          task - The task that has stopped
          +
          See Also:
          +
          BTraceEngineImpl.StateListener.onTaskStop(BTraceTask)
          +
          +
        • +
        + + + +
          +
        • +

          getClassPath

          +
          public java.lang.String getClassPath()
          +
          +
          Specified by:
          +
          getClassPath in class BTraceTask
          +
          Returns:
          +
          Returns the complete classpath for the task
          +
          +
        • +
        + + + +
          +
        • +

          isTrusted

          +
          public boolean isTrusted()
          +
          +
          Overrides:
          +
          isTrusted in class BTraceTask
          +
          +
        • +
        + + + +
          +
        • +

          equals

          +
          public boolean equals(java.lang.Object obj)
          +
          +
          Overrides:
          +
          equals in class java.lang.Object
          +
          +
        • +
        + + + +
          +
        • +

          hashCode

          +
          public int hashCode()
          +
          +
          Overrides:
          +
          hashCode in class java.lang.Object
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/api/impl/package-frame.html b/misc/btrace/javadoc/com/sun/btrace/api/impl/package-frame.html new file mode 100644 index 00000000..86d2d869 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/api/impl/package-frame.html @@ -0,0 +1,21 @@ + + + + + +com.sun.btrace.api.impl (btrace 1.3.11 API) + + + + + +

    com.sun.btrace.api.impl

    + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/api/impl/package-summary.html b/misc/btrace/javadoc/com/sun/btrace/api/impl/package-summary.html new file mode 100644 index 00000000..9ca36d2b --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/api/impl/package-summary.html @@ -0,0 +1,144 @@ + + + + + +com.sun.btrace.api.impl (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Package com.sun.btrace.api.impl

    +
    +
    + +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/api/impl/package-tree.html b/misc/btrace/javadoc/com/sun/btrace/api/impl/package-tree.html new file mode 100644 index 00000000..bbc2dbb4 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/api/impl/package-tree.html @@ -0,0 +1,144 @@ + + + + + +com.sun.btrace.api.impl Class Hierarchy (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Hierarchy For Package com.sun.btrace.api.impl

    +Package Hierarchies: + +
    +
    +

    Class Hierarchy

    + +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/api/package-frame.html b/misc/btrace/javadoc/com/sun/btrace/api/package-frame.html new file mode 100644 index 00000000..f80b052e --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/api/package-frame.html @@ -0,0 +1,32 @@ + + + + + +com.sun.btrace.api (btrace 1.3.11 API) + + + + + +

    com.sun.btrace.api

    + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/api/package-summary.html b/misc/btrace/javadoc/com/sun/btrace/api/package-summary.html new file mode 100644 index 00000000..824289cf --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/api/package-summary.html @@ -0,0 +1,206 @@ + + + + + +com.sun.btrace.api (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Package com.sun.btrace.api

    +
    +
    A public API for BTrace integration into VisualVM
    +
    +

    See: Description

    +
    +
    +
      +
    • + + + + + + + + + + + + +
      Interface Summary 
      InterfaceDescription
      BTraceTask.StateListener +
      Simple state listener interface
      +
      +
    • +
    • + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Class Summary 
      ClassDescription
      BTraceCompiler 
      BTraceEngine +
      This class serves as a factory for BTraceTask instances
      +
      BTraceSettings 
      BTraceTask +
      This class represents a single BTrace script
      +
      BTraceTask.MessageDispatcher +
      CommandListener interface exposes the BTrace commands received over + the wire to anyone interested
      +
      +
    • +
    • + + + + + + + + + + + + +
      Enum Summary 
      EnumDescription
      BTraceTask.State +
      This enum represents the allowed states of the tracing task
      +
      +
    • +
    + + + +

    Package com.sun.btrace.api Description

    +
    A public API for BTrace integration into VisualVM
    +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/api/package-tree.html b/misc/btrace/javadoc/com/sun/btrace/api/package-tree.html new file mode 100644 index 00000000..5880ac1a --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/api/package-tree.html @@ -0,0 +1,159 @@ + + + + + +com.sun.btrace.api Class Hierarchy (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Hierarchy For Package com.sun.btrace.api

    +Package Hierarchies: + +
    +
    +

    Class Hierarchy

    + +

    Interface Hierarchy

    + +

    Enum Hierarchy

    +
      +
    • java.lang.Object +
        +
      • java.lang.Enum<E> (implements java.lang.Comparable<T>, java.io.Serializable) + +
      • +
      +
    • +
    +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/client/Client.html b/misc/btrace/javadoc/com/sun/btrace/client/Client.html new file mode 100644 index 00000000..d4fccb39 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/client/Client.html @@ -0,0 +1,613 @@ + + + + + +Client (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.client
    +

    Class Client

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.client.Client
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public class Client
      +extends java.lang.Object
      +
      This class represents a BTrace client. This can be + used to create command line as well as a GUI based + BTrace clients. The BTrace compilation, traced JVM attach, + submission of compiled program and and I/O to the traced + JVM are handled by this class.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + + + + + + + +
        Constructors 
        Constructor and Description
        Client(int port) 
        Client(int port, + java.lang.String probeDescPath) 
        Client(int port, + java.lang.String outputFile, + java.lang.String probeDescPath, + boolean debug, + boolean trackRetransforms, + boolean trusted, + boolean dumpClasses, + java.lang.String dumpDir, + java.lang.String statsdDef) 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        voidattach(java.lang.String pid, + java.lang.String sysCp, + java.lang.String bootCp) +
        Attach the BTrace client to the given Java process.
        +
        voidattach(java.lang.String pid, + java.lang.String agentPath, + java.lang.String sysCp, + java.lang.String bootCp) +
        Attach the BTrace client to the given Java process.
        +
        voidclose() +
        Closes all connection state to the traced JVM.
        +
        byte[]compile(java.lang.String fileName, + java.lang.String classPath) 
        byte[]compile(java.lang.String fileName, + java.lang.String classPath, + java.io.PrintWriter err) 
        byte[]compile(java.lang.String fileName, + java.lang.String classPath, + java.io.PrintWriter err, + java.lang.String includePath) +
        Compiles given BTrace program using given classpath.
        +
        byte[]compile(java.lang.String fileName, + java.lang.String classPath, + java.lang.String includePath) +
        Compiles given BTrace program using given classpath.
        +
        voiddebugPrint(java.lang.String msg) 
        voidsendEvent() +
        Sends an EventCommand to the traced JVM.
        +
        voidsendEvent(java.lang.String name) +
        Sends an EventCommand to the traced JVM.
        +
        voidsendExit() +
        Sends ExitCommand to the traced JVM.
        +
        voidsendExit(int code) +
        Sends ExitCommand to the traced JVM.
        +
        voidsubmit(byte[] code, + java.lang.String[] args, + CommandListener listener) +
        Submits the compiled BTrace .class to the VM + attached and passes given command line arguments.
        +
        voidsubmit(java.lang.String fileName, + byte[] code, + java.lang.String[] args, + CommandListener listener) +
        Submits the compiled BTrace .class to the VM + attached and passes given command line arguments.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Client

          +
          public Client(int port)
          +
        • +
        + + + +
          +
        • +

          Client

          +
          public Client(int port,
          +              java.lang.String probeDescPath)
          +
        • +
        + + + +
          +
        • +

          Client

          +
          public Client(int port,
          +              java.lang.String outputFile,
          +              java.lang.String probeDescPath,
          +              boolean debug,
          +              boolean trackRetransforms,
          +              boolean trusted,
          +              boolean dumpClasses,
          +              java.lang.String dumpDir,
          +              java.lang.String statsdDef)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          compile

          +
          public byte[] compile(java.lang.String fileName,
          +                      java.lang.String classPath)
          +
        • +
        + + + +
          +
        • +

          compile

          +
          public byte[] compile(java.lang.String fileName,
          +                      java.lang.String classPath,
          +                      java.lang.String includePath)
          +
          Compiles given BTrace program using given classpath.
          +
        • +
        + + + +
          +
        • +

          compile

          +
          public byte[] compile(java.lang.String fileName,
          +                      java.lang.String classPath,
          +                      java.io.PrintWriter err)
          +
        • +
        + + + +
          +
        • +

          compile

          +
          public byte[] compile(java.lang.String fileName,
          +                      java.lang.String classPath,
          +                      java.io.PrintWriter err,
          +                      java.lang.String includePath)
          +
          Compiles given BTrace program using given classpath. + Errors and warning are written to given PrintWriter.
          +
        • +
        + + + +
          +
        • +

          attach

          +
          public void attach(java.lang.String pid,
          +                   java.lang.String sysCp,
          +                   java.lang.String bootCp)
          +            throws java.io.IOException
          +
          Attach the BTrace client to the given Java process. + Loads BTrace agent on the target process if not loaded + already.
          +
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          attach

          +
          public void attach(java.lang.String pid,
          +                   java.lang.String agentPath,
          +                   java.lang.String sysCp,
          +                   java.lang.String bootCp)
          +            throws java.io.IOException
          +
          Attach the BTrace client to the given Java process. + Loads BTrace agent on the target process if not loaded + already. Accepts the full path of the btrace agent jar. + Also, accepts system classpath and boot classpath optionally.
          +
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          submit

          +
          public void submit(java.lang.String fileName,
          +                   byte[] code,
          +                   java.lang.String[] args,
          +                   CommandListener listener)
          +            throws java.io.IOException
          +
          Submits the compiled BTrace .class to the VM + attached and passes given command line arguments. + Receives commands from the traced JVM and sends those + to the command listener provided.
          +
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          submit

          +
          public void submit(byte[] code,
          +                   java.lang.String[] args,
          +                   CommandListener listener)
          +            throws java.io.IOException
          +
          Submits the compiled BTrace .class to the VM + attached and passes given command line arguments. + Receives commands from the traced JVM and sends those + to the command listener provided.
          +
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          sendExit

          +
          public void sendExit()
          +              throws java.io.IOException
          +
          Sends ExitCommand to the traced JVM.
          +
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          sendExit

          +
          public void sendExit(int code)
          +              throws java.io.IOException
          +
          Sends ExitCommand to the traced JVM.
          +
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          sendEvent

          +
          public void sendEvent()
          +               throws java.io.IOException
          +
          Sends an EventCommand to the traced JVM.
          +
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          sendEvent

          +
          public void sendEvent(java.lang.String name)
          +               throws java.io.IOException
          +
          Sends an EventCommand to the traced JVM.
          +
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          close

          +
          public void close()
          +           throws java.io.IOException
          +
          Closes all connection state to the traced JVM.
          +
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          debugPrint

          +
          public void debugPrint(java.lang.String msg)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/client/Main.html b/misc/btrace/javadoc/com/sun/btrace/client/Main.html new file mode 100644 index 00000000..59018bbf --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/client/Main.html @@ -0,0 +1,338 @@ + + + + + +Main (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.client
    +

    Class Main

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.client.Main
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class Main
      +extends java.lang.Object
      +
      This is the main class for a simple command line + BTrace client. It is possible to create a GUI + client using the Client class.
      +
    • +
    +
    +
    +
      +
    • + + + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        Main() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static voidmain(java.lang.String[] args) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Detail

        + + + +
          +
        • +

          exiting

          +
          public static volatile boolean exiting
          +
        • +
        + + + +
          +
        • +

          TRACK_RETRANSFORM

          +
          public static final boolean TRACK_RETRANSFORM
          +
        • +
        + + + +
          +
        • +

          BTRACE_DEFAULT_PORT

          +
          public static final int BTRACE_DEFAULT_PORT
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Main

          +
          public Main()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          main

          +
          public static void main(java.lang.String[] args)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/client/ProbeDump.html b/misc/btrace/javadoc/com/sun/btrace/client/ProbeDump.html new file mode 100644 index 00000000..bada2472 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/client/ProbeDump.html @@ -0,0 +1,274 @@ + + + + + +ProbeDump (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.client
    +

    Class ProbeDump

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.client.ProbeDump
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public class ProbeDump
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        ProbeDump() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static voidmain(java.lang.String[] args) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          ProbeDump

          +
          public ProbeDump()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          main

          +
          public static void main(java.lang.String[] args)
          +                 throws java.lang.Exception
          +
          +
          Throws:
          +
          java.lang.Exception
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/client/package-frame.html b/misc/btrace/javadoc/com/sun/btrace/client/package-frame.html new file mode 100644 index 00000000..4e08a940 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/client/package-frame.html @@ -0,0 +1,22 @@ + + + + + +com.sun.btrace.client (btrace 1.3.11 API) + + + + + +

    com.sun.btrace.client

    +
    +

    Classes

    + +
    + + diff --git a/misc/btrace/javadoc/com/sun/btrace/client/package-summary.html b/misc/btrace/javadoc/com/sun/btrace/client/package-summary.html new file mode 100644 index 00000000..84c3f5c5 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/client/package-summary.html @@ -0,0 +1,153 @@ + + + + + +com.sun.btrace.client (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Package com.sun.btrace.client

    +
    +
    +
      +
    • + + + + + + + + + + + + + + + + + + + + +
      Class Summary 
      ClassDescription
      Client +
      This class represents a BTrace client.
      +
      Main +
      This is the main class for a simple command line + BTrace client.
      +
      ProbeDump 
      +
    • +
    +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/client/package-tree.html b/misc/btrace/javadoc/com/sun/btrace/client/package-tree.html new file mode 100644 index 00000000..20319629 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/client/package-tree.html @@ -0,0 +1,137 @@ + + + + + +com.sun.btrace.client Class Hierarchy (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Hierarchy For Package com.sun.btrace.client

    +Package Hierarchies: + +
    +
    +

    Class Hierarchy

    +
      +
    • java.lang.Object + +
    • +
    +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/comm/Command.html b/misc/btrace/javadoc/com/sun/btrace/comm/Command.html new file mode 100644 index 00000000..df085cfb --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/comm/Command.html @@ -0,0 +1,630 @@ + + + + + +Command (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.comm
    +

    Class Command

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.comm.Command
      • +
      +
    • +
    +
    + +
    +
    + +
    +
    +
      +
    • + + + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Command

          +
          protected Command(byte type)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          write

          +
          protected abstract void write(java.io.ObjectOutput out)
          +                       throws java.io.IOException
          +
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          read

          +
          protected abstract void read(java.io.ObjectInput in)
          +                      throws java.io.IOException,
          +                             java.lang.ClassNotFoundException
          +
          +
          Throws:
          +
          java.io.IOException
          +
          java.lang.ClassNotFoundException
          +
          +
        • +
        + + + +
          +
        • +

          getType

          +
          public byte getType()
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/comm/DataCommand.html b/misc/btrace/javadoc/com/sun/btrace/comm/DataCommand.html new file mode 100644 index 00000000..cb84e8d7 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/comm/DataCommand.html @@ -0,0 +1,347 @@ + + + + + +DataCommand (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.comm
    +

    Class DataCommand

    +
    +
    + +
    + +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Field Detail

        + + + +
          +
        • +

          name

          +
          protected java.lang.String name
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          DataCommand

          +
          public DataCommand(byte type,
          +                   java.lang.String name)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getName

          +
          public java.lang.String getName()
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/comm/ErrorCommand.html b/misc/btrace/javadoc/com/sun/btrace/comm/ErrorCommand.html new file mode 100644 index 00000000..3a07d78e --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/comm/ErrorCommand.html @@ -0,0 +1,385 @@ + + + + + +ErrorCommand (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.comm
    +

    Class ErrorCommand

    +
    +
    + +
    + +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          ErrorCommand

          +
          public ErrorCommand(java.lang.Throwable cause)
          +
        • +
        + + + +
          +
        • +

          ErrorCommand

          +
          protected ErrorCommand()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          write

          +
          protected void write(java.io.ObjectOutput out)
          +              throws java.io.IOException
          +
          +
          Specified by:
          +
          write in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          read

          +
          protected void read(java.io.ObjectInput in)
          +             throws java.io.IOException,
          +                    java.lang.ClassNotFoundException
          +
          +
          Specified by:
          +
          read in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          java.lang.ClassNotFoundException
          +
          +
        • +
        + + + +
          +
        • +

          getCause

          +
          public java.lang.Throwable getCause()
          +
        • +
        + + + +
          +
        • +

          print

          +
          public void print(java.io.PrintWriter out)
          +
          Description copied from interface: PrintableCommand
          +
          Print the command internal info
          +
          +
          Specified by:
          +
          print in interface PrintableCommand
          +
          Parameters:
          +
          out - the associated PrintWriter
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/comm/EventCommand.html b/misc/btrace/javadoc/com/sun/btrace/comm/EventCommand.html new file mode 100644 index 00000000..3432ecaa --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/comm/EventCommand.html @@ -0,0 +1,361 @@ + + + + + +EventCommand (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.comm
    +

    Class EventCommand

    +
    +
    + +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.io.Serializable
      +
      +
      +
      +
      public class EventCommand
      +extends Command
      +
      +
      See Also:
      +
      Serialized Form
      +
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          EventCommand

          +
          public EventCommand(java.lang.String event)
          +
        • +
        + + + +
          +
        • +

          EventCommand

          +
          protected EventCommand()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          write

          +
          protected void write(java.io.ObjectOutput out)
          +              throws java.io.IOException
          +
          +
          Specified by:
          +
          write in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          read

          +
          protected void read(java.io.ObjectInput in)
          +             throws java.lang.ClassNotFoundException,
          +                    java.io.IOException
          +
          +
          Specified by:
          +
          read in class Command
          +
          Throws:
          +
          java.lang.ClassNotFoundException
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          getEvent

          +
          public java.lang.String getEvent()
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/comm/ExitCommand.html b/misc/btrace/javadoc/com/sun/btrace/comm/ExitCommand.html new file mode 100644 index 00000000..845400fe --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/comm/ExitCommand.html @@ -0,0 +1,359 @@ + + + + + +ExitCommand (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.comm
    +

    Class ExitCommand

    +
    +
    + +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.io.Serializable
      +
      +
      +
      +
      public class ExitCommand
      +extends Command
      +
      +
      See Also:
      +
      Serialized Form
      +
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          ExitCommand

          +
          public ExitCommand(int exitCode)
          +
        • +
        + + + +
          +
        • +

          ExitCommand

          +
          protected ExitCommand()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          write

          +
          protected void write(java.io.ObjectOutput out)
          +              throws java.io.IOException
          +
          +
          Specified by:
          +
          write in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          read

          +
          protected void read(java.io.ObjectInput in)
          +             throws java.io.IOException
          +
          +
          Specified by:
          +
          read in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          getExitCode

          +
          public int getExitCode()
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/comm/GridDataCommand.html b/misc/btrace/javadoc/com/sun/btrace/comm/GridDataCommand.html new file mode 100644 index 00000000..819fb3b8 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/comm/GridDataCommand.html @@ -0,0 +1,444 @@ + + + + + +GridDataCommand (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.comm
    +

    Class GridDataCommand

    +
    +
    + +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      PrintableCommand, java.io.Serializable
      +
      +
      +
      +
      public class GridDataCommand
      +extends DataCommand
      +
      A data command that holds tabular data. + + The elements contained within the grid must be of type Number, String or HistogramData.
      +
      +
      See Also:
      +
      Serialized Form
      +
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + + + + + +
          +
        • +

          GridDataCommand

          +
          public GridDataCommand(java.lang.String name,
          +                       java.util.List<java.lang.Object[]> data)
          +
          Creates a new instance of GridDataCommand with implicit format
          +
          +
          Parameters:
          +
          name - The aggregation name
          +
          data - The aggregation data
          +
          +
        • +
        + + + +
          +
        • +

          GridDataCommand

          +
          public GridDataCommand(java.lang.String name,
          +                       java.util.List<java.lang.Object[]> data,
          +                       java.lang.String format)
          +
          Creates a new instance of GridDataCommand with explicit format
          +
          +
          Parameters:
          +
          name - The aggregation name
          +
          data - The aggregation data
          +
          format - The format to use. It mimics String.format(java.lang.String, java.lang.Object[]) behaviour + with the addition of the ability to address the key title as a 0-indexed item
          +
          See Also:
          +
          String.format(java.lang.String, java.lang.Object[])
          +
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getData

          +
          public java.util.List<java.lang.Object[]> getData()
          +
        • +
        + + + +
          +
        • +

          print

          +
          public void print(java.io.PrintWriter out)
          +
          Description copied from interface: PrintableCommand
          +
          Print the command internal info
          +
          +
          Parameters:
          +
          out - the associated PrintWriter
          +
          +
        • +
        + + + +
          +
        • +

          write

          +
          protected void write(java.io.ObjectOutput out)
          +              throws java.io.IOException
          +
          +
          Specified by:
          +
          write in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          read

          +
          protected void read(java.io.ObjectInput in)
          +             throws java.io.IOException,
          +                    java.lang.ClassNotFoundException
          +
          +
          Specified by:
          +
          read in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          java.lang.ClassNotFoundException
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/comm/InstrumentCommand.html b/misc/btrace/javadoc/com/sun/btrace/comm/InstrumentCommand.html new file mode 100644 index 00000000..9179de6b --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/comm/InstrumentCommand.html @@ -0,0 +1,410 @@ + + + + + +InstrumentCommand (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.comm
    +

    Class InstrumentCommand

    +
    +
    + +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.io.Serializable
      +
      +
      +
      +
      public class InstrumentCommand
      +extends Command
      +
      +
      See Also:
      +
      Serialized Form
      +
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          InstrumentCommand

          +
          public InstrumentCommand(byte[] code,
          +                         ArgsMap args,
          +                         DebugSupport debug)
          +
        • +
        + + + +
          +
        • +

          InstrumentCommand

          +
          public InstrumentCommand(byte[] code,
          +                         java.lang.String[] args,
          +                         DebugSupport debug)
          +
        • +
        + + + +
          +
        • +

          InstrumentCommand

          +
          public InstrumentCommand(byte[] code,
          +                         java.util.Map<java.lang.String,java.lang.String> args,
          +                         DebugSupport debug)
          +
        • +
        + + + +
          +
        • +

          InstrumentCommand

          +
          protected InstrumentCommand()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          write

          +
          protected void write(java.io.ObjectOutput out)
          +              throws java.io.IOException
          +
          +
          Specified by:
          +
          write in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          read

          +
          protected void read(java.io.ObjectInput in)
          +             throws java.io.IOException
          +
          +
          Specified by:
          +
          read in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          getCode

          +
          public byte[] getCode()
          +
        • +
        + + + +
          +
        • +

          getArguments

          +
          public ArgsMap getArguments()
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/comm/MessageCommand.html b/misc/btrace/javadoc/com/sun/btrace/comm/MessageCommand.html new file mode 100644 index 00000000..97b9060d --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/comm/MessageCommand.html @@ -0,0 +1,429 @@ + + + + + +MessageCommand (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.comm
    +

    Class MessageCommand

    +
    +
    + +
    + +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          MessageCommand

          +
          public MessageCommand(long time,
          +                      java.lang.String msg)
          +
        • +
        + + + +
          +
        • +

          MessageCommand

          +
          public MessageCommand(java.lang.String msg)
          +
        • +
        + + + +
          +
        • +

          MessageCommand

          +
          protected MessageCommand()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          write

          +
          protected void write(java.io.ObjectOutput out)
          +              throws java.io.IOException
          +
          +
          Specified by:
          +
          write in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          read

          +
          protected void read(java.io.ObjectInput in)
          +             throws java.lang.ClassNotFoundException,
          +                    java.io.IOException
          +
          +
          Specified by:
          +
          read in class Command
          +
          Throws:
          +
          java.lang.ClassNotFoundException
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          getTime

          +
          public long getTime()
          +
        • +
        + + + +
          +
        • +

          getMessage

          +
          public java.lang.String getMessage()
          +
        • +
        + + + +
          +
        • +

          print

          +
          public void print(java.io.PrintWriter out)
          +
          Description copied from interface: PrintableCommand
          +
          Print the command internal info
          +
          +
          Parameters:
          +
          out - the associated PrintWriter
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/comm/NumberDataCommand.html b/misc/btrace/javadoc/com/sun/btrace/comm/NumberDataCommand.html new file mode 100644 index 00000000..b45851a1 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/comm/NumberDataCommand.html @@ -0,0 +1,401 @@ + + + + + +NumberDataCommand (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.comm
    +

    Class NumberDataCommand

    +
    +
    + +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      PrintableCommand, java.io.Serializable
      +
      +
      +
      +
      public class NumberDataCommand
      +extends DataCommand
      +
      A simple data command that has one number value.
      +
      +
      See Also:
      +
      Serialized Form
      +
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          NumberDataCommand

          +
          public NumberDataCommand()
          +
        • +
        + + + +
          +
        • +

          NumberDataCommand

          +
          public NumberDataCommand(java.lang.String name,
          +                         java.lang.Number value)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          print

          +
          public void print(java.io.PrintWriter out)
          +
          Description copied from interface: PrintableCommand
          +
          Print the command internal info
          +
          +
          Parameters:
          +
          out - the associated PrintWriter
          +
          +
        • +
        + + + +
          +
        • +

          getValue

          +
          public java.lang.Number getValue()
          +
        • +
        + + + +
          +
        • +

          write

          +
          protected void write(java.io.ObjectOutput out)
          +              throws java.io.IOException
          +
          +
          Specified by:
          +
          write in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          read

          +
          protected void read(java.io.ObjectInput in)
          +             throws java.io.IOException,
          +                    java.lang.ClassNotFoundException
          +
          +
          Specified by:
          +
          read in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          java.lang.ClassNotFoundException
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/comm/NumberMapDataCommand.html b/misc/btrace/javadoc/com/sun/btrace/comm/NumberMapDataCommand.html new file mode 100644 index 00000000..62a91423 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/comm/NumberMapDataCommand.html @@ -0,0 +1,401 @@ + + + + + +NumberMapDataCommand (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.comm
    +

    Class NumberMapDataCommand

    +
    +
    + +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      PrintableCommand, java.io.Serializable
      +
      +
      +
      +
      public class NumberMapDataCommand
      +extends DataCommand
      +
      A data command that hold data of type Map<String, Number>.
      +
      +
      See Also:
      +
      Serialized Form
      +
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          NumberMapDataCommand

          +
          public NumberMapDataCommand()
          +
        • +
        + + + +
          +
        • +

          NumberMapDataCommand

          +
          public NumberMapDataCommand(java.lang.String name,
          +                            java.util.Map<java.lang.String,? extends java.lang.Number> data)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getData

          +
          public java.util.Map<java.lang.String,? extends java.lang.Number> getData()
          +
        • +
        + + + +
          +
        • +

          print

          +
          public void print(java.io.PrintWriter out)
          +
          Description copied from interface: PrintableCommand
          +
          Print the command internal info
          +
          +
          Parameters:
          +
          out - the associated PrintWriter
          +
          +
        • +
        + + + +
          +
        • +

          write

          +
          protected void write(java.io.ObjectOutput out)
          +              throws java.io.IOException
          +
          +
          Specified by:
          +
          write in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          read

          +
          protected void read(java.io.ObjectInput in)
          +             throws java.io.IOException,
          +                    java.lang.ClassNotFoundException
          +
          +
          Specified by:
          +
          read in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          java.lang.ClassNotFoundException
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/comm/OkayCommand.html b/misc/btrace/javadoc/com/sun/btrace/comm/OkayCommand.html new file mode 100644 index 00000000..1ce973c9 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/comm/OkayCommand.html @@ -0,0 +1,333 @@ + + + + + +OkayCommand (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.comm
    +

    Class OkayCommand

    +
    +
    + +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.io.Serializable
      +
      +
      +
      +
      public class OkayCommand
      +extends Command
      +
      +
      See Also:
      +
      Serialized Form
      +
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          OkayCommand

          +
          public OkayCommand()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          write

          +
          protected void write(java.io.ObjectOutput out)
          +              throws java.io.IOException
          +
          +
          Specified by:
          +
          write in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          read

          +
          protected void read(java.io.ObjectInput in)
          +             throws java.io.IOException,
          +                    java.lang.ClassNotFoundException
          +
          +
          Specified by:
          +
          read in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          java.lang.ClassNotFoundException
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/comm/PrintableCommand.html b/misc/btrace/javadoc/com/sun/btrace/comm/PrintableCommand.html new file mode 100644 index 00000000..a0dd751d --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/comm/PrintableCommand.html @@ -0,0 +1,232 @@ + + + + + +PrintableCommand (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.comm
    +

    Interface PrintableCommand

    +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + +
        All Methods Instance Methods Abstract Methods 
        Modifier and TypeMethod and Description
        voidprint(java.io.PrintWriter out) +
        Print the command internal info
        +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          print

          +
          void print(java.io.PrintWriter out)
          +
          Print the command internal info
          +
          +
          Parameters:
          +
          out - the associated PrintWriter
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/comm/RenameCommand.html b/misc/btrace/javadoc/com/sun/btrace/comm/RenameCommand.html new file mode 100644 index 00000000..13cc82b7 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/comm/RenameCommand.html @@ -0,0 +1,359 @@ + + + + + +RenameCommand (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.comm
    +

    Class RenameCommand

    +
    +
    + +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.io.Serializable
      +
      +
      +
      +
      public class RenameCommand
      +extends Command
      +
      +
      See Also:
      +
      Serialized Form
      +
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          RenameCommand

          +
          public RenameCommand(java.lang.String newName)
          +
        • +
        + + + +
          +
        • +

          RenameCommand

          +
          protected RenameCommand()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          write

          +
          protected void write(java.io.ObjectOutput out)
          +              throws java.io.IOException
          +
          +
          Specified by:
          +
          write in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          read

          +
          protected void read(java.io.ObjectInput in)
          +             throws java.io.IOException
          +
          +
          Specified by:
          +
          read in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          getNewName

          +
          public java.lang.String getNewName()
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/comm/RetransformClassNotification.html b/misc/btrace/javadoc/com/sun/btrace/comm/RetransformClassNotification.html new file mode 100644 index 00000000..4a26a7aa --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/comm/RetransformClassNotification.html @@ -0,0 +1,384 @@ + + + + + +RetransformClassNotification (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.comm
    +

    Class RetransformClassNotification

    +
    +
    + +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      PrintableCommand, java.io.Serializable
      +
      +
      +
      +
      public class RetransformClassNotification
      +extends Command
      +implements PrintableCommand
      +
      This command is sent out as a notification that a class + is going to be transformed
      +
      +
      See Also:
      +
      Serialized Form
      +
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          RetransformClassNotification

          +
          public RetransformClassNotification(java.lang.String className)
          +
        • +
        + + + +
          +
        • +

          RetransformClassNotification

          +
          public RetransformClassNotification()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          write

          +
          protected void write(java.io.ObjectOutput out)
          +              throws java.io.IOException
          +
          +
          Specified by:
          +
          write in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          read

          +
          protected void read(java.io.ObjectInput in)
          +             throws java.io.IOException,
          +                    java.lang.ClassNotFoundException
          +
          +
          Specified by:
          +
          read in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          java.lang.ClassNotFoundException
          +
          +
        • +
        + + + +
          +
        • +

          getClassName

          +
          public java.lang.String getClassName()
          +
        • +
        + + + +
          +
        • +

          print

          +
          public void print(java.io.PrintWriter out)
          +
          Description copied from interface: PrintableCommand
          +
          Print the command internal info
          +
          +
          Specified by:
          +
          print in interface PrintableCommand
          +
          Parameters:
          +
          out - the associated PrintWriter
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/comm/RetransformationStartNotification.html b/misc/btrace/javadoc/com/sun/btrace/comm/RetransformationStartNotification.html new file mode 100644 index 00000000..2cdfd972 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/comm/RetransformationStartNotification.html @@ -0,0 +1,361 @@ + + + + + +RetransformationStartNotification (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.comm
    +

    Class RetransformationStartNotification

    +
    +
    + +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.io.Serializable
      +
      +
      +
      +
      public class RetransformationStartNotification
      +extends Command
      +
      This command is sent out when the BTrace engine calls + Instrumentation.retransformClasses(Class[]) method. + It is followed by OkayCommand command when the retransformation ends.
      +
      +
      See Also:
      +
      Serialized Form
      +
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          RetransformationStartNotification

          +
          public RetransformationStartNotification()
          +
        • +
        + + + +
          +
        • +

          RetransformationStartNotification

          +
          public RetransformationStartNotification(int numClasses)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          write

          +
          protected void write(java.io.ObjectOutput out)
          +              throws java.io.IOException
          +
          +
          Specified by:
          +
          write in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          read

          +
          protected void read(java.io.ObjectInput in)
          +             throws java.io.IOException,
          +                    java.lang.ClassNotFoundException
          +
          +
          Specified by:
          +
          read in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          java.lang.ClassNotFoundException
          +
          +
        • +
        + + + +
          +
        • +

          getNumClasses

          +
          public int getNumClasses()
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/comm/SetSettingsCommand.html b/misc/btrace/javadoc/com/sun/btrace/comm/SetSettingsCommand.html new file mode 100644 index 00000000..a15728bd --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/comm/SetSettingsCommand.html @@ -0,0 +1,363 @@ + + + + + +SetSettingsCommand (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.comm
    +

    Class SetSettingsCommand

    +
    +
    + +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.io.Serializable
      +
      +
      +
      +
      public class SetSettingsCommand
      +extends Command
      +
      This command is used to remotely set custom settings + (trusted mode, debug, etc.)
      +
      +
      See Also:
      +
      Serialized Form
      +
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          SetSettingsCommand

          +
          public SetSettingsCommand(java.util.Map<java.lang.String,?> params)
          +
        • +
        + + + +
          +
        • +

          SetSettingsCommand

          +
          protected SetSettingsCommand()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getParams

          +
          public java.util.Map<java.lang.String,java.lang.Object> getParams()
          +
        • +
        + + + +
          +
        • +

          write

          +
          protected void write(java.io.ObjectOutput out)
          +              throws java.io.IOException
          +
          +
          Specified by:
          +
          write in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          read

          +
          protected void read(java.io.ObjectInput in)
          +             throws java.io.IOException,
          +                    java.lang.ClassNotFoundException
          +
          +
          Specified by:
          +
          read in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          java.lang.ClassNotFoundException
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/comm/StringMapDataCommand.html b/misc/btrace/javadoc/com/sun/btrace/comm/StringMapDataCommand.html new file mode 100644 index 00000000..3509d56f --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/comm/StringMapDataCommand.html @@ -0,0 +1,401 @@ + + + + + +StringMapDataCommand (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.comm
    +

    Class StringMapDataCommand

    +
    +
    + +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      PrintableCommand, java.io.Serializable
      +
      +
      +
      +
      public class StringMapDataCommand
      +extends DataCommand
      +
      A data command that hold data of type Map<String, String>.
      +
      +
      See Also:
      +
      Serialized Form
      +
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          StringMapDataCommand

          +
          public StringMapDataCommand()
          +
        • +
        + + + +
          +
        • +

          StringMapDataCommand

          +
          public StringMapDataCommand(java.lang.String name,
          +                            java.util.Map<java.lang.String,java.lang.String> data)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getData

          +
          public java.util.Map<java.lang.String,java.lang.String> getData()
          +
        • +
        + + + +
          +
        • +

          print

          +
          public void print(java.io.PrintWriter out)
          +
          Description copied from interface: PrintableCommand
          +
          Print the command internal info
          +
          +
          Parameters:
          +
          out - the associated PrintWriter
          +
          +
        • +
        + + + +
          +
        • +

          write

          +
          protected void write(java.io.ObjectOutput out)
          +              throws java.io.IOException
          +
          +
          Specified by:
          +
          write in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          read

          +
          protected void read(java.io.ObjectInput in)
          +             throws java.io.IOException,
          +                    java.lang.ClassNotFoundException
          +
          +
          Specified by:
          +
          read in class Command
          +
          Throws:
          +
          java.io.IOException
          +
          java.lang.ClassNotFoundException
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/comm/WireIO.html b/misc/btrace/javadoc/com/sun/btrace/comm/WireIO.html new file mode 100644 index 00000000..ff6bf84a --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/comm/WireIO.html @@ -0,0 +1,260 @@ + + + + + +WireIO (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.comm
    +

    Class WireIO

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.comm.WireIO
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public class WireIO
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static Commandread(java.io.ObjectInput in) 
        static voidwrite(java.io.ObjectOutput out, + Command cmd) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          read

          +
          public static Command read(java.io.ObjectInput in)
          +                    throws java.io.IOException
          +
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          write

          +
          public static void write(java.io.ObjectOutput out,
          +                         Command cmd)
          +                  throws java.io.IOException
          +
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/comm/package-frame.html b/misc/btrace/javadoc/com/sun/btrace/comm/package-frame.html new file mode 100644 index 00000000..1ffacc2d --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/comm/package-frame.html @@ -0,0 +1,40 @@ + + + + + +com.sun.btrace.comm (btrace 1.3.11 API) + + + + + +

    com.sun.btrace.comm

    + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/comm/package-summary.html b/misc/btrace/javadoc/com/sun/btrace/comm/package-summary.html new file mode 100644 index 00000000..10f32bc9 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/comm/package-summary.html @@ -0,0 +1,241 @@ + + + + + +com.sun.btrace.comm (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Package com.sun.btrace.comm

    +
    +
    + +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/comm/package-tree.html b/misc/btrace/javadoc/com/sun/btrace/comm/package-tree.html new file mode 100644 index 00000000..a4d704fb --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/comm/package-tree.html @@ -0,0 +1,161 @@ + + + + + +com.sun.btrace.comm Class Hierarchy (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Hierarchy For Package com.sun.btrace.comm

    +Package Hierarchies: + +
    +
    +

    Class Hierarchy

    + +

    Interface Hierarchy

    + +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/compiler/AnnotationSerializer.html b/misc/btrace/javadoc/com/sun/btrace/compiler/AnnotationSerializer.html new file mode 100644 index 00000000..47017bbd --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/compiler/AnnotationSerializer.html @@ -0,0 +1,271 @@ + + + + + +AnnotationSerializer (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.compiler
    +

    Class AnnotationSerializer

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.compiler.AnnotationSerializer
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public class AnnotationSerializer
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + + + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static voidserialize(com.sun.btrace.org.objectweb.asm.tree.AnnotationNode an, + java.lang.StringBuilder sb) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          AnnotationSerializer

          +
          public AnnotationSerializer()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          serialize

          +
          public static void serialize(com.sun.btrace.org.objectweb.asm.tree.AnnotationNode an,
          +                             java.lang.StringBuilder sb)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/compiler/Compiler.html b/misc/btrace/javadoc/com/sun/btrace/compiler/Compiler.html new file mode 100644 index 00000000..dfc5fa8d --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/compiler/Compiler.html @@ -0,0 +1,432 @@ + + + + + +Compiler (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.compiler
    +

    Class Compiler

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.compiler.Compiler
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public class Compiler
      +extends java.lang.Object
      +
      Compiler for a BTrace program. Note that a BTrace + program is a Java program that is specially annotated + and can *not* use many Java constructs (essentially java--). + We use JSR 199 API to compile BTrace program but validate + the program (for BTrace safety rules) using JSR 269 and + javac's Tree API.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Summary

        + + + + + + + + + + +
        Fields 
        Modifier and TypeField and Description
        java.util.List<java.lang.String>includeDirs 
        +
      • +
      + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + + + + + + + + + + +
        Constructors 
        Constructor and Description
        Compiler() 
        Compiler(boolean generatePack) 
        Compiler(java.lang.String includePath) 
        Compiler(java.lang.String includePath, + boolean generatePack) 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        java.util.Map<java.lang.String,byte[]>compile(java.io.File[] files, + java.io.Writer err, + java.lang.String sourcePath, + java.lang.String classPath) 
        java.util.Map<java.lang.String,byte[]>compile(java.io.File file, + java.io.Writer err, + java.lang.String sourcePath, + java.lang.String classPath) 
        java.util.Map<java.lang.String,byte[]>compile(java.lang.Iterable<? extends javax.tools.JavaFileObject> compUnits, + java.io.Writer err, + java.lang.String sourcePath, + java.lang.String classPath) 
        java.util.Map<java.lang.String,byte[]>compile(java.lang.String fileName, + java.lang.String source, + java.io.Writer err, + java.lang.String sourcePath, + java.lang.String classPath) 
        static voidmain(java.lang.String[] args) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Detail

        + + + +
          +
        • +

          includeDirs

          +
          public java.util.List<java.lang.String> includeDirs
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Compiler

          +
          public Compiler(java.lang.String includePath,
          +                boolean generatePack)
          +
        • +
        + + + +
          +
        • +

          Compiler

          +
          public Compiler(java.lang.String includePath)
          +
        • +
        + + + +
          +
        • +

          Compiler

          +
          public Compiler(boolean generatePack)
          +
        • +
        + + + +
          +
        • +

          Compiler

          +
          public Compiler()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          main

          +
          public static void main(java.lang.String[] args)
          +                 throws java.lang.Exception
          +
          +
          Throws:
          +
          java.lang.Exception
          +
          +
        • +
        + + + +
          +
        • +

          compile

          +
          public java.util.Map<java.lang.String,byte[]> compile(java.lang.String fileName,
          +                                                      java.lang.String source,
          +                                                      java.io.Writer err,
          +                                                      java.lang.String sourcePath,
          +                                                      java.lang.String classPath)
          +
        • +
        + + + +
          +
        • +

          compile

          +
          public java.util.Map<java.lang.String,byte[]> compile(java.io.File file,
          +                                                      java.io.Writer err,
          +                                                      java.lang.String sourcePath,
          +                                                      java.lang.String classPath)
          +
        • +
        + + + +
          +
        • +

          compile

          +
          public java.util.Map<java.lang.String,byte[]> compile(java.io.File[] files,
          +                                                      java.io.Writer err,
          +                                                      java.lang.String sourcePath,
          +                                                      java.lang.String classPath)
          +
        • +
        + + + +
          +
        • +

          compile

          +
          public java.util.Map<java.lang.String,byte[]> compile(java.lang.Iterable<? extends javax.tools.JavaFileObject> compUnits,
          +                                                      java.io.Writer err,
          +                                                      java.lang.String sourcePath,
          +                                                      java.lang.String classPath)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/compiler/ConcatenatingReader.html b/misc/btrace/javadoc/com/sun/btrace/compiler/ConcatenatingReader.html new file mode 100644 index 00000000..595141c3 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/compiler/ConcatenatingReader.html @@ -0,0 +1,456 @@ + + + + + +ConcatenatingReader (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.compiler
    +

    Class ConcatenatingReader

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • java.io.Reader
      • +
      • +
          +
        • java.io.FilterReader
        • +
        • +
            +
          • com.sun.btrace.compiler.ConcatenatingReader
          • +
          +
        • +
        +
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.io.Closeable, java.lang.AutoCloseable, java.lang.Readable
      +
      +
      +
      +
      public class ConcatenatingReader
      +extends java.io.FilterReader
      +
      This code is based on PCPP code from the GlueGen project. + + A Reader implementation which finds lines ending in the backslash + character ('\') and concatenates them with the next line.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Summary

        +
          +
        • + + +

          Fields inherited from class java.io.FilterReader

          +in
        • +
        +
          +
        • + + +

          Fields inherited from class java.io.Reader

          +lock
        • +
        +
      • +
      + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        ConcatenatingReader(java.io.BufferedReader in) +
        This class requires that the input reader be a BufferedReader so + it can do line-oriented operations.
        +
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        voidmark(int readAheadLimit) 
        booleanmarkSupported() 
        intread() 
        intread(char[] cbuf, + int off, + int len) 
        booleanready() 
        voidreset() 
        longskip(long n) 
        +
          +
        • + + +

          Methods inherited from class java.io.FilterReader

          +close
        • +
        +
          +
        • + + +

          Methods inherited from class java.io.Reader

          +read, read
        • +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          ConcatenatingReader

          +
          public ConcatenatingReader(java.io.BufferedReader in)
          +
          This class requires that the input reader be a BufferedReader so + it can do line-oriented operations.
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          read

          +
          public int read()
          +         throws java.io.IOException
          +
          +
          Overrides:
          +
          read in class java.io.FilterReader
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          markSupported

          +
          public boolean markSupported()
          +
          +
          Overrides:
          +
          markSupported in class java.io.FilterReader
          +
          +
        • +
        + + + +
          +
        • +

          mark

          +
          public void mark(int readAheadLimit)
          +          throws java.io.IOException
          +
          +
          Overrides:
          +
          mark in class java.io.FilterReader
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          reset

          +
          public void reset()
          +           throws java.io.IOException
          +
          +
          Overrides:
          +
          reset in class java.io.FilterReader
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          ready

          +
          public boolean ready()
          +              throws java.io.IOException
          +
          +
          Overrides:
          +
          ready in class java.io.FilterReader
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          read

          +
          public int read(char[] cbuf,
          +                int off,
          +                int len)
          +         throws java.io.IOException
          +
          +
          Overrides:
          +
          read in class java.io.FilterReader
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          skip

          +
          public long skip(long n)
          +          throws java.io.IOException
          +
          +
          Overrides:
          +
          skip in class java.io.FilterReader
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/compiler/MemoryJavaFileManager.html b/misc/btrace/javadoc/com/sun/btrace/compiler/MemoryJavaFileManager.html new file mode 100644 index 00000000..d0a1fbb4 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/compiler/MemoryJavaFileManager.html @@ -0,0 +1,423 @@ + + + + + +MemoryJavaFileManager (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.compiler
    +

    Class MemoryJavaFileManager

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • javax.tools.ForwardingJavaFileManager
      • +
      • +
          +
        • com.sun.btrace.compiler.MemoryJavaFileManager
        • +
        +
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.io.Closeable, java.io.Flushable, java.lang.AutoCloseable, javax.tools.JavaFileManager, javax.tools.OptionChecker
      +
      +
      +
      +
      public final class MemoryJavaFileManager
      +extends javax.tools.ForwardingJavaFileManager
      +
      JavaFileManager that keeps compiled .class bytes in memory. + And also can expose input .java "files" from Strings.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Nested Class Summary

        +
          +
        • + + +

          Nested classes/interfaces inherited from interface javax.tools.JavaFileManager

          +javax.tools.JavaFileManager.Location
        • +
        +
      • +
      + +
        +
      • + + +

        Field Summary

        +
          +
        • + + +

          Fields inherited from class javax.tools.ForwardingJavaFileManager

          +fileManager
        • +
        +
      • +
      + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        MemoryJavaFileManager(javax.tools.JavaFileManager fileManager, + java.util.List<java.lang.String> includeDirs) 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        voidclose() 
        voidflush() 
        java.util.Map<java.lang.String,byte[]>getClassBytes() 
        javax.tools.JavaFileObjectgetJavaFileForInput(javax.tools.JavaFileManager.Location location, + java.lang.String className, + javax.tools.JavaFileObject.Kind kind) 
        javax.tools.JavaFileObjectgetJavaFileForOutput(javax.tools.JavaFileManager.Location location, + java.lang.String className, + javax.tools.JavaFileObject.Kind kind, + javax.tools.FileObject sibling) 
        +
          +
        • + + +

          Methods inherited from class javax.tools.ForwardingJavaFileManager

          +getClassLoader, getFileForInput, getFileForOutput, handleOption, hasLocation, inferBinaryName, isSameFile, isSupportedOption, list
        • +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          MemoryJavaFileManager

          +
          public MemoryJavaFileManager(javax.tools.JavaFileManager fileManager,
          +                             java.util.List<java.lang.String> includeDirs)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getClassBytes

          +
          public java.util.Map<java.lang.String,byte[]> getClassBytes()
          +
        • +
        + + + +
          +
        • +

          close

          +
          public void close()
          +           throws java.io.IOException
          +
          +
          Specified by:
          +
          close in interface java.io.Closeable
          +
          Specified by:
          +
          close in interface java.lang.AutoCloseable
          +
          Specified by:
          +
          close in interface javax.tools.JavaFileManager
          +
          Overrides:
          +
          close in class javax.tools.ForwardingJavaFileManager
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          flush

          +
          public void flush()
          +           throws java.io.IOException
          +
          +
          Specified by:
          +
          flush in interface java.io.Flushable
          +
          Specified by:
          +
          flush in interface javax.tools.JavaFileManager
          +
          Overrides:
          +
          flush in class javax.tools.ForwardingJavaFileManager
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          getJavaFileForOutput

          +
          public javax.tools.JavaFileObject getJavaFileForOutput(javax.tools.JavaFileManager.Location location,
          +                                                       java.lang.String className,
          +                                                       javax.tools.JavaFileObject.Kind kind,
          +                                                       javax.tools.FileObject sibling)
          +                                                throws java.io.IOException
          +
          +
          Specified by:
          +
          getJavaFileForOutput in interface javax.tools.JavaFileManager
          +
          Overrides:
          +
          getJavaFileForOutput in class javax.tools.ForwardingJavaFileManager
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          getJavaFileForInput

          +
          public javax.tools.JavaFileObject getJavaFileForInput(javax.tools.JavaFileManager.Location location,
          +                                                      java.lang.String className,
          +                                                      javax.tools.JavaFileObject.Kind kind)
          +                                               throws java.io.IOException
          +
          +
          Specified by:
          +
          getJavaFileForInput in interface javax.tools.JavaFileManager
          +
          Overrides:
          +
          getJavaFileForInput in class javax.tools.ForwardingJavaFileManager
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/compiler/PCPP.html b/misc/btrace/javadoc/com/sun/btrace/compiler/PCPP.html new file mode 100644 index 00000000..23d30a8d --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/compiler/PCPP.html @@ -0,0 +1,317 @@ + + + + + +PCPP (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.compiler
    +

    Class PCPP

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.compiler.PCPP
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public class PCPP
      +extends java.lang.Object
      +
      A minimal pseudo-C-preprocessor derived from PCPP of the GlueGen project.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + + + + +
        Constructors 
        Constructor and Description
        PCPP(java.util.List includePaths) 
        PCPP(java.util.List includePaths, + java.io.Writer out) 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        java.lang.StringfindFile(java.lang.String filename) 
        static voidmain(java.lang.String[] args) 
        voidrun(java.io.Reader reader, + java.lang.String filename) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          PCPP

          +
          public PCPP(java.util.List includePaths)
          +
        • +
        + + + +
          +
        • +

          PCPP

          +
          public PCPP(java.util.List includePaths,
          +            java.io.Writer out)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          run

          +
          public void run(java.io.Reader reader,
          +                java.lang.String filename)
          +         throws java.io.IOException
          +
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        + + + +
          +
        • +

          main

          +
          public static void main(java.lang.String[] args)
          +
        • +
        + + + +
          +
        • +

          findFile

          +
          public java.lang.String findFile(java.lang.String filename)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/compiler/Postprocessor.html b/misc/btrace/javadoc/com/sun/btrace/compiler/Postprocessor.html new file mode 100644 index 00000000..f2ae34cb --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/compiler/Postprocessor.html @@ -0,0 +1,377 @@ + + + + + +Postprocessor (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.compiler
    +

    Class Postprocessor

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.org.objectweb.asm.ClassVisitor
      • +
      • +
          +
        • com.sun.btrace.compiler.Postprocessor
        • +
        +
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public class Postprocessor
      +extends com.sun.btrace.org.objectweb.asm.ClassVisitor
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Summary

        +
          +
        • + + +

          Fields inherited from class com.sun.btrace.org.objectweb.asm.ClassVisitor

          +api, cv
        • +
        +
      • +
      + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        Postprocessor(com.sun.btrace.org.objectweb.asm.ClassVisitor cv) 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        voidvisit(int version, + int access, + java.lang.String name, + java.lang.String signature, + java.lang.String superName, + java.lang.String[] interfaces) 
        voidvisitEnd() 
        com.sun.btrace.org.objectweb.asm.FieldVisitorvisitField(int access, + java.lang.String name, + java.lang.String desc, + java.lang.String signature, + java.lang.Object value) 
        com.sun.btrace.org.objectweb.asm.MethodVisitorvisitMethod(int access, + java.lang.String name, + java.lang.String desc, + java.lang.String signature, + java.lang.String[] exceptions) 
        +
          +
        • + + +

          Methods inherited from class com.sun.btrace.org.objectweb.asm.ClassVisitor

          +visitAnnotation, visitAttribute, visitInnerClass, visitOuterClass, visitSource, visitTypeAnnotation
        • +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Postprocessor

          +
          public Postprocessor(com.sun.btrace.org.objectweb.asm.ClassVisitor cv)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          visit

          +
          public void visit(int version,
          +                  int access,
          +                  java.lang.String name,
          +                  java.lang.String signature,
          +                  java.lang.String superName,
          +                  java.lang.String[] interfaces)
          +
          +
          Overrides:
          +
          visit in class com.sun.btrace.org.objectweb.asm.ClassVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitMethod

          +
          public com.sun.btrace.org.objectweb.asm.MethodVisitor visitMethod(int access,
          +                                                                  java.lang.String name,
          +                                                                  java.lang.String desc,
          +                                                                  java.lang.String signature,
          +                                                                  java.lang.String[] exceptions)
          +
          +
          Overrides:
          +
          visitMethod in class com.sun.btrace.org.objectweb.asm.ClassVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitField

          +
          public com.sun.btrace.org.objectweb.asm.FieldVisitor visitField(int access,
          +                                                                java.lang.String name,
          +                                                                java.lang.String desc,
          +                                                                java.lang.String signature,
          +                                                                java.lang.Object value)
          +
          +
          Overrides:
          +
          visitField in class com.sun.btrace.org.objectweb.asm.ClassVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitEnd

          +
          public void visitEnd()
          +
          +
          Overrides:
          +
          visitEnd in class com.sun.btrace.org.objectweb.asm.ClassVisitor
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/compiler/Verifier.html b/misc/btrace/javadoc/com/sun/btrace/compiler/Verifier.html new file mode 100644 index 00000000..1bf37ed2 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/compiler/Verifier.html @@ -0,0 +1,367 @@ + + + + + +Verifier (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.compiler
    +

    Class Verifier

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • javax.annotation.processing.AbstractProcessor
      • +
      • +
          +
        • com.sun.btrace.compiler.Verifier
        • +
        +
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      com.sun.source.util.TaskListener, javax.annotation.processing.Processor
      +
      +
      +
      +
      @SupportedAnnotationTypes(value="*")
      + @SupportedSourceVersion(value=RELEASE_7)
      +public class Verifier
      +extends javax.annotation.processing.AbstractProcessor
      +implements com.sun.source.util.TaskListener
      +
      An annotation processor that validates a BTrace program. + Safety rules (such as no loops, no new/throw etc.) are + enforced. This uses javac's Tree API in addition to JSR 269.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Summary

        +
          +
        • + + +

          Fields inherited from class javax.annotation.processing.AbstractProcessor

          +processingEnv
        • +
        +
      • +
      + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        Verifier() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        voidfinished(com.sun.source.util.TaskEvent e) 
        voidinit(javax.annotation.processing.ProcessingEnvironment pe) 
        booleanprocess(java.util.Set<? extends javax.lang.model.element.TypeElement> annotations, + javax.annotation.processing.RoundEnvironment roundEnv) 
        voidstarted(com.sun.source.util.TaskEvent e) 
        +
          +
        • + + +

          Methods inherited from class javax.annotation.processing.AbstractProcessor

          +getCompletions, getSupportedAnnotationTypes, getSupportedOptions, getSupportedSourceVersion, isInitialized
        • +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Verifier

          +
          public Verifier()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          init

          +
          public void init(javax.annotation.processing.ProcessingEnvironment pe)
          +
          +
          Specified by:
          +
          init in interface javax.annotation.processing.Processor
          +
          Overrides:
          +
          init in class javax.annotation.processing.AbstractProcessor
          +
          +
        • +
        + + + +
          +
        • +

          process

          +
          public boolean process(java.util.Set<? extends javax.lang.model.element.TypeElement> annotations,
          +                       javax.annotation.processing.RoundEnvironment roundEnv)
          +
          +
          Specified by:
          +
          process in interface javax.annotation.processing.Processor
          +
          Specified by:
          +
          process in class javax.annotation.processing.AbstractProcessor
          +
          +
        • +
        + + + +
          +
        • +

          started

          +
          public void started(com.sun.source.util.TaskEvent e)
          +
          +
          Specified by:
          +
          started in interface com.sun.source.util.TaskListener
          +
          +
        • +
        + + + +
          +
        • +

          finished

          +
          public void finished(com.sun.source.util.TaskEvent e)
          +
          +
          Specified by:
          +
          finished in interface com.sun.source.util.TaskListener
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/compiler/VerifierVisitor.html b/misc/btrace/javadoc/com/sun/btrace/compiler/VerifierVisitor.html new file mode 100644 index 00000000..531099d9 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/compiler/VerifierVisitor.html @@ -0,0 +1,695 @@ + + + + + +VerifierVisitor (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.compiler
    +

    Class VerifierVisitor

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.source.util.TreeScanner<java.lang.Boolean,java.lang.Void>
      • +
      • +
          +
        • com.sun.btrace.compiler.VerifierVisitor
        • +
        +
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      com.sun.source.tree.TreeVisitor<java.lang.Boolean,java.lang.Void>
      +
      +
      +
      +
      public class VerifierVisitor
      +extends com.sun.source.util.TreeScanner<java.lang.Boolean,java.lang.Void>
      +
      This class tree visitor validates a BTrace program's ClassTree.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        VerifierVisitor(Verifier verifier, + javax.lang.model.element.Element clzElement) 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        java.lang.BooleanvisitAssert(com.sun.source.tree.AssertTree node, + java.lang.Void v) 
        java.lang.BooleanvisitAssignment(com.sun.source.tree.AssignmentTree node, + java.lang.Void v) 
        java.lang.BooleanvisitCatch(com.sun.source.tree.CatchTree node, + java.lang.Void v) 
        java.lang.BooleanvisitClass(com.sun.source.tree.ClassTree node, + java.lang.Void v) 
        java.lang.BooleanvisitCompoundAssignment(com.sun.source.tree.CompoundAssignmentTree node, + java.lang.Void v) 
        java.lang.BooleanvisitDoWhileLoop(com.sun.source.tree.DoWhileLoopTree node, + java.lang.Void v) 
        java.lang.BooleanvisitEnhancedForLoop(com.sun.source.tree.EnhancedForLoopTree node, + java.lang.Void v) 
        java.lang.BooleanvisitForLoop(com.sun.source.tree.ForLoopTree node, + java.lang.Void v) 
        java.lang.BooleanvisitMemberSelect(com.sun.source.tree.MemberSelectTree node, + java.lang.Void v) 
        java.lang.BooleanvisitMethod(com.sun.source.tree.MethodTree node, + java.lang.Void v) 
        java.lang.BooleanvisitMethodInvocation(com.sun.source.tree.MethodInvocationTree node, + java.lang.Void v) 
        java.lang.BooleanvisitNewArray(com.sun.source.tree.NewArrayTree node, + java.lang.Void v) 
        java.lang.BooleanvisitNewClass(com.sun.source.tree.NewClassTree node, + java.lang.Void v) 
        java.lang.BooleanvisitOther(com.sun.source.tree.Tree node, + java.lang.Void v) 
        java.lang.BooleanvisitReturn(com.sun.source.tree.ReturnTree node, + java.lang.Void v) 
        java.lang.BooleanvisitSynchronized(com.sun.source.tree.SynchronizedTree node, + java.lang.Void v) 
        java.lang.BooleanvisitThrow(com.sun.source.tree.ThrowTree node, + java.lang.Void v) 
        java.lang.BooleanvisitTry(com.sun.source.tree.TryTree node, + java.lang.Void v) 
        java.lang.BooleanvisitVariable(com.sun.source.tree.VariableTree vt, + java.lang.Void p) 
        java.lang.BooleanvisitWhileLoop(com.sun.source.tree.WhileLoopTree node, + java.lang.Void v) 
        +
          +
        • + + +

          Methods inherited from class com.sun.source.util.TreeScanner

          +reduce, scan, scan, visitAnnotatedType, visitAnnotation, visitArrayAccess, visitArrayType, visitBinary, visitBlock, visitBreak, visitCase, visitCompilationUnit, visitConditionalExpression, visitContinue, visitEmptyStatement, visitErroneous, visitExpressionStatement, visitIdentifier, visitIf, visitImport, visitInstanceOf, visitIntersectionType, visitLabeledStatement, visitLambdaExpression, visitLiteral, visitMemberReference, visitModifiers, visitParameterizedType, visitParenthesized, visitPrimitiveType, visitSwitch, visitTypeCast, visitTypeParameter, visitUnary, visitUnionType, visitWildcard
        • +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          VerifierVisitor

          +
          public VerifierVisitor(Verifier verifier,
          +                       javax.lang.model.element.Element clzElement)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          visitMethodInvocation

          +
          public java.lang.Boolean visitMethodInvocation(com.sun.source.tree.MethodInvocationTree node,
          +                                               java.lang.Void v)
          +
          +
          Specified by:
          +
          visitMethodInvocation in interface com.sun.source.tree.TreeVisitor<java.lang.Boolean,java.lang.Void>
          +
          Overrides:
          +
          visitMethodInvocation in class com.sun.source.util.TreeScanner<java.lang.Boolean,java.lang.Void>
          +
          +
        • +
        + + + +
          +
        • +

          visitAssert

          +
          public java.lang.Boolean visitAssert(com.sun.source.tree.AssertTree node,
          +                                     java.lang.Void v)
          +
          +
          Specified by:
          +
          visitAssert in interface com.sun.source.tree.TreeVisitor<java.lang.Boolean,java.lang.Void>
          +
          Overrides:
          +
          visitAssert in class com.sun.source.util.TreeScanner<java.lang.Boolean,java.lang.Void>
          +
          +
        • +
        + + + +
          +
        • +

          visitAssignment

          +
          public java.lang.Boolean visitAssignment(com.sun.source.tree.AssignmentTree node,
          +                                         java.lang.Void v)
          +
          +
          Specified by:
          +
          visitAssignment in interface com.sun.source.tree.TreeVisitor<java.lang.Boolean,java.lang.Void>
          +
          Overrides:
          +
          visitAssignment in class com.sun.source.util.TreeScanner<java.lang.Boolean,java.lang.Void>
          +
          +
        • +
        + + + +
          +
        • +

          visitCompoundAssignment

          +
          public java.lang.Boolean visitCompoundAssignment(com.sun.source.tree.CompoundAssignmentTree node,
          +                                                 java.lang.Void v)
          +
          +
          Specified by:
          +
          visitCompoundAssignment in interface com.sun.source.tree.TreeVisitor<java.lang.Boolean,java.lang.Void>
          +
          Overrides:
          +
          visitCompoundAssignment in class com.sun.source.util.TreeScanner<java.lang.Boolean,java.lang.Void>
          +
          +
        • +
        + + + +
          +
        • +

          visitCatch

          +
          public java.lang.Boolean visitCatch(com.sun.source.tree.CatchTree node,
          +                                    java.lang.Void v)
          +
          +
          Specified by:
          +
          visitCatch in interface com.sun.source.tree.TreeVisitor<java.lang.Boolean,java.lang.Void>
          +
          Overrides:
          +
          visitCatch in class com.sun.source.util.TreeScanner<java.lang.Boolean,java.lang.Void>
          +
          +
        • +
        + + + +
          +
        • +

          visitClass

          +
          public java.lang.Boolean visitClass(com.sun.source.tree.ClassTree node,
          +                                    java.lang.Void v)
          +
          +
          Specified by:
          +
          visitClass in interface com.sun.source.tree.TreeVisitor<java.lang.Boolean,java.lang.Void>
          +
          Overrides:
          +
          visitClass in class com.sun.source.util.TreeScanner<java.lang.Boolean,java.lang.Void>
          +
          +
        • +
        + + + +
          +
        • +

          visitDoWhileLoop

          +
          public java.lang.Boolean visitDoWhileLoop(com.sun.source.tree.DoWhileLoopTree node,
          +                                          java.lang.Void v)
          +
          +
          Specified by:
          +
          visitDoWhileLoop in interface com.sun.source.tree.TreeVisitor<java.lang.Boolean,java.lang.Void>
          +
          Overrides:
          +
          visitDoWhileLoop in class com.sun.source.util.TreeScanner<java.lang.Boolean,java.lang.Void>
          +
          +
        • +
        + + + +
          +
        • +

          visitEnhancedForLoop

          +
          public java.lang.Boolean visitEnhancedForLoop(com.sun.source.tree.EnhancedForLoopTree node,
          +                                              java.lang.Void v)
          +
          +
          Specified by:
          +
          visitEnhancedForLoop in interface com.sun.source.tree.TreeVisitor<java.lang.Boolean,java.lang.Void>
          +
          Overrides:
          +
          visitEnhancedForLoop in class com.sun.source.util.TreeScanner<java.lang.Boolean,java.lang.Void>
          +
          +
        • +
        + + + +
          +
        • +

          visitForLoop

          +
          public java.lang.Boolean visitForLoop(com.sun.source.tree.ForLoopTree node,
          +                                      java.lang.Void v)
          +
          +
          Specified by:
          +
          visitForLoop in interface com.sun.source.tree.TreeVisitor<java.lang.Boolean,java.lang.Void>
          +
          Overrides:
          +
          visitForLoop in class com.sun.source.util.TreeScanner<java.lang.Boolean,java.lang.Void>
          +
          +
        • +
        + + + +
          +
        • +

          visitMethod

          +
          public java.lang.Boolean visitMethod(com.sun.source.tree.MethodTree node,
          +                                     java.lang.Void v)
          +
          +
          Specified by:
          +
          visitMethod in interface com.sun.source.tree.TreeVisitor<java.lang.Boolean,java.lang.Void>
          +
          Overrides:
          +
          visitMethod in class com.sun.source.util.TreeScanner<java.lang.Boolean,java.lang.Void>
          +
          +
        • +
        + + + +
          +
        • +

          visitNewArray

          +
          public java.lang.Boolean visitNewArray(com.sun.source.tree.NewArrayTree node,
          +                                       java.lang.Void v)
          +
          +
          Specified by:
          +
          visitNewArray in interface com.sun.source.tree.TreeVisitor<java.lang.Boolean,java.lang.Void>
          +
          Overrides:
          +
          visitNewArray in class com.sun.source.util.TreeScanner<java.lang.Boolean,java.lang.Void>
          +
          +
        • +
        + + + +
          +
        • +

          visitNewClass

          +
          public java.lang.Boolean visitNewClass(com.sun.source.tree.NewClassTree node,
          +                                       java.lang.Void v)
          +
          +
          Specified by:
          +
          visitNewClass in interface com.sun.source.tree.TreeVisitor<java.lang.Boolean,java.lang.Void>
          +
          Overrides:
          +
          visitNewClass in class com.sun.source.util.TreeScanner<java.lang.Boolean,java.lang.Void>
          +
          +
        • +
        + + + +
          +
        • +

          visitReturn

          +
          public java.lang.Boolean visitReturn(com.sun.source.tree.ReturnTree node,
          +                                     java.lang.Void v)
          +
          +
          Specified by:
          +
          visitReturn in interface com.sun.source.tree.TreeVisitor<java.lang.Boolean,java.lang.Void>
          +
          Overrides:
          +
          visitReturn in class com.sun.source.util.TreeScanner<java.lang.Boolean,java.lang.Void>
          +
          +
        • +
        + + + +
          +
        • +

          visitMemberSelect

          +
          public java.lang.Boolean visitMemberSelect(com.sun.source.tree.MemberSelectTree node,
          +                                           java.lang.Void v)
          +
          +
          Specified by:
          +
          visitMemberSelect in interface com.sun.source.tree.TreeVisitor<java.lang.Boolean,java.lang.Void>
          +
          Overrides:
          +
          visitMemberSelect in class com.sun.source.util.TreeScanner<java.lang.Boolean,java.lang.Void>
          +
          +
        • +
        + + + +
          +
        • +

          visitSynchronized

          +
          public java.lang.Boolean visitSynchronized(com.sun.source.tree.SynchronizedTree node,
          +                                           java.lang.Void v)
          +
          +
          Specified by:
          +
          visitSynchronized in interface com.sun.source.tree.TreeVisitor<java.lang.Boolean,java.lang.Void>
          +
          Overrides:
          +
          visitSynchronized in class com.sun.source.util.TreeScanner<java.lang.Boolean,java.lang.Void>
          +
          +
        • +
        + + + +
          +
        • +

          visitThrow

          +
          public java.lang.Boolean visitThrow(com.sun.source.tree.ThrowTree node,
          +                                    java.lang.Void v)
          +
          +
          Specified by:
          +
          visitThrow in interface com.sun.source.tree.TreeVisitor<java.lang.Boolean,java.lang.Void>
          +
          Overrides:
          +
          visitThrow in class com.sun.source.util.TreeScanner<java.lang.Boolean,java.lang.Void>
          +
          +
        • +
        + + + +
          +
        • +

          visitTry

          +
          public java.lang.Boolean visitTry(com.sun.source.tree.TryTree node,
          +                                  java.lang.Void v)
          +
          +
          Specified by:
          +
          visitTry in interface com.sun.source.tree.TreeVisitor<java.lang.Boolean,java.lang.Void>
          +
          Overrides:
          +
          visitTry in class com.sun.source.util.TreeScanner<java.lang.Boolean,java.lang.Void>
          +
          +
        • +
        + + + +
          +
        • +

          visitVariable

          +
          public java.lang.Boolean visitVariable(com.sun.source.tree.VariableTree vt,
          +                                       java.lang.Void p)
          +
          +
          Specified by:
          +
          visitVariable in interface com.sun.source.tree.TreeVisitor<java.lang.Boolean,java.lang.Void>
          +
          Overrides:
          +
          visitVariable in class com.sun.source.util.TreeScanner<java.lang.Boolean,java.lang.Void>
          +
          +
        • +
        + + + +
          +
        • +

          visitWhileLoop

          +
          public java.lang.Boolean visitWhileLoop(com.sun.source.tree.WhileLoopTree node,
          +                                        java.lang.Void v)
          +
          +
          Specified by:
          +
          visitWhileLoop in interface com.sun.source.tree.TreeVisitor<java.lang.Boolean,java.lang.Void>
          +
          Overrides:
          +
          visitWhileLoop in class com.sun.source.util.TreeScanner<java.lang.Boolean,java.lang.Void>
          +
          +
        • +
        + + + +
          +
        • +

          visitOther

          +
          public java.lang.Boolean visitOther(com.sun.source.tree.Tree node,
          +                                    java.lang.Void v)
          +
          +
          Specified by:
          +
          visitOther in interface com.sun.source.tree.TreeVisitor<java.lang.Boolean,java.lang.Void>
          +
          Overrides:
          +
          visitOther in class com.sun.source.util.TreeScanner<java.lang.Boolean,java.lang.Void>
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/compiler/package-frame.html b/misc/btrace/javadoc/com/sun/btrace/compiler/package-frame.html new file mode 100644 index 00000000..3d160056 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/compiler/package-frame.html @@ -0,0 +1,27 @@ + + + + + +com.sun.btrace.compiler (btrace 1.3.11 API) + + + + + +

    com.sun.btrace.compiler

    + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/compiler/package-summary.html b/misc/btrace/javadoc/com/sun/btrace/compiler/package-summary.html new file mode 100644 index 00000000..5ff8b60a --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/compiler/package-summary.html @@ -0,0 +1,180 @@ + + + + + +com.sun.btrace.compiler (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Package com.sun.btrace.compiler

    +
    +
    +
      +
    • + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Class Summary 
      ClassDescription
      AnnotationSerializer 
      Compiler +
      Compiler for a BTrace program.
      +
      ConcatenatingReader +
      This code is based on PCPP code from the GlueGen project.
      +
      MemoryJavaFileManager +
      JavaFileManager that keeps compiled .class bytes in memory.
      +
      PCPP +
      A minimal pseudo-C-preprocessor derived from PCPP of the GlueGen project.
      +
      Postprocessor 
      Verifier +
      An annotation processor that validates a BTrace program.
      +
      VerifierVisitor +
      This class tree visitor validates a BTrace program's ClassTree.
      +
      +
    • +
    +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/compiler/package-tree.html b/misc/btrace/javadoc/com/sun/btrace/compiler/package-tree.html new file mode 100644 index 00000000..6e777a79 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/compiler/package-tree.html @@ -0,0 +1,166 @@ + + + + + +com.sun.btrace.compiler Class Hierarchy (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Hierarchy For Package com.sun.btrace.compiler

    +Package Hierarchies: + +
    +
    +

    Class Hierarchy

    +
      +
    • java.lang.Object +
        +
      • javax.annotation.processing.AbstractProcessor (implements javax.annotation.processing.Processor) +
          +
        • com.sun.btrace.compiler.Verifier (implements com.sun.source.util.TaskListener)
        • +
        +
      • +
      • com.sun.btrace.compiler.AnnotationSerializer
      • +
      • com.sun.btrace.org.objectweb.asm.ClassVisitor + +
      • +
      • com.sun.btrace.compiler.Compiler
      • +
      • javax.tools.ForwardingJavaFileManager<M> (implements javax.tools.JavaFileManager) + +
      • +
      • com.sun.btrace.compiler.PCPP
      • +
      • java.io.Reader (implements java.io.Closeable, java.lang.Readable) + +
      • +
      • com.sun.source.util.TreeScanner<R,P> (implements com.sun.source.tree.TreeVisitor<R,P>) + +
      • +
      +
    • +
    +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/instr/MethodTracker.html b/misc/btrace/javadoc/com/sun/btrace/instr/MethodTracker.html new file mode 100644 index 00000000..7a1a472d --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/instr/MethodTracker.html @@ -0,0 +1,426 @@ + + + + + +MethodTracker (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.instr
    +

    Class MethodTracker

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.instr.MethodTracker
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class MethodTracker
      +extends java.lang.Object
      +
      Provides a centralized place to track the fundamental metrics for + method execution. + It is mostly called from the injected code to support sampling and timing.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        MethodTracker() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static longgetEndTs(int methodId) +
        Used when timing the method execution or in adaptive sampling.
        +
        static booleanhit(int methodId) +
        Records the invocation of a certain method and indicates whether + it should be traced or not (sampling).
        +
        static booleanhitAdaptive(int methodId) +
        Records the invocation of a certain method and indicates whether + it should be traced or not (sampling).
        +
        static longhitTimed(int methodId) +
        Records the invocation of a certain method alongside the timestamp + and indicates whether it should be traced or not (sampling).
        +
        static longhitTimedAdaptive(int methodId) +
        Records the invocation of a certain method alongside the timestamp + and indicates whether it should be traced or not (sampling).
        +
        static voidregisterCounter(int methodId, + int mean) +
        Creates a supporting structures for a new method id
        +
        static voidupdateEndTs(int methodId) +
        Used in adaptive sampling.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          MethodTracker

          +
          public MethodTracker()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          registerCounter

          +
          public static void registerCounter(int methodId,
          +                                   int mean)
          +
          Creates a supporting structures for a new method id
          +
          +
          Parameters:
          +
          methodId - The method id - generated by the MethodID class
          +
          mean - The sampler mean or 0 if not applicable
          +
          +
        • +
        + + + +
          +
        • +

          hit

          +
          public static boolean hit(int methodId)
          +
          Records the invocation of a certain method and indicates whether + it should be traced or not (sampling). + This method will be called when using the average sampling mode.
          +
          +
          Parameters:
          +
          methodId - The method id - generated by the MethodID class
          +
          Returns:
          +
          true if the invocation should be traced
          +
          +
        • +
        + + + +
          +
        • +

          hitTimed

          +
          public static long hitTimed(int methodId)
          +
          Records the invocation of a certain method alongside the timestamp + and indicates whether it should be traced or not (sampling). + This method will be called when using the average sampling mode.
          +
          +
          Parameters:
          +
          methodId - The method id - generated by the MethodID class
          +
          Returns:
          +
          a positive number (invocation time stamp) if the invocation should be traced
          +
          +
        • +
        + + + +
          +
        • +

          hitAdaptive

          +
          public static boolean hitAdaptive(int methodId)
          +
          Records the invocation of a certain method and indicates whether + it should be traced or not (sampling). + This method will be called when using the adaptive sampling mode.
          +
          +
          Parameters:
          +
          methodId - The method id - generated by the MethodID class
          +
          Returns:
          +
          true if the invocation should be traced
          +
          +
        • +
        + + + +
          +
        • +

          hitTimedAdaptive

          +
          public static long hitTimedAdaptive(int methodId)
          +
          Records the invocation of a certain method alongside the timestamp + and indicates whether it should be traced or not (sampling). + This method will be called when using the adaptive sampling mode.
          +
          +
          Parameters:
          +
          methodId - The method id - generated by the MethodID class
          +
          Returns:
          +
          a positive number (invocation time stamp) if the invocation should be traced
          +
          +
        • +
        + + + +
          +
        • +

          getEndTs

          +
          public static long getEndTs(int methodId)
          +
          Used when timing the method execution or in adaptive sampling. + To be used at the end of the sampled block.
          +
          +
          Parameters:
          +
          methodId - The method id generated by MethodID class
          +
          Returns:
          +
          The time stamp
          +
          +
        • +
        + + + +
          +
        • +

          updateEndTs

          +
          public static void updateEndTs(int methodId)
          +
          Used in adaptive sampling. + To be used at the end of the sampled block.
          +
          +
          Parameters:
          +
          methodId - The method id generated by MethodID class
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/instr/RandomIntProvider.html b/misc/btrace/javadoc/com/sun/btrace/instr/RandomIntProvider.html new file mode 100644 index 00000000..ecb1c7e1 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/instr/RandomIntProvider.html @@ -0,0 +1,288 @@ + + + + + +RandomIntProvider (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.instr
    +

    Class RandomIntProvider

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.instr.RandomIntProvider
      • +
      +
    • +
    +
    + +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          RandomIntProvider

          +
          protected RandomIntProvider()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          nextInt

          +
          public abstract int nextInt(int bound)
          +
        • +
        + + + + +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/instr/package-frame.html b/misc/btrace/javadoc/com/sun/btrace/instr/package-frame.html new file mode 100644 index 00000000..3857a57c --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/instr/package-frame.html @@ -0,0 +1,21 @@ + + + + + +com.sun.btrace.instr (btrace 1.3.11 API) + + + + + +

    com.sun.btrace.instr

    + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/instr/package-summary.html b/misc/btrace/javadoc/com/sun/btrace/instr/package-summary.html new file mode 100644 index 00000000..19062c89 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/instr/package-summary.html @@ -0,0 +1,147 @@ + + + + + +com.sun.btrace.instr (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Package com.sun.btrace.instr

    +
    +
    +
      +
    • + + + + + + + + + + + + + + + + +
      Class Summary 
      ClassDescription
      MethodTracker +
      Provides a centralized place to track the fundamental metrics for + method execution.
      +
      RandomIntProvider 
      +
    • +
    +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/instr/package-tree.html b/misc/btrace/javadoc/com/sun/btrace/instr/package-tree.html new file mode 100644 index 00000000..d0f04825 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/instr/package-tree.html @@ -0,0 +1,136 @@ + + + + + +com.sun.btrace.instr Class Hierarchy (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Hierarchy For Package com.sun.btrace.instr

    +Package Hierarchies: + +
    +
    +

    Class Hierarchy

    + +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/instr/random/SharedRandomIntProvider.html b/misc/btrace/javadoc/com/sun/btrace/instr/random/SharedRandomIntProvider.html new file mode 100644 index 00000000..c8559990 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/instr/random/SharedRandomIntProvider.html @@ -0,0 +1,285 @@ + + + + + +SharedRandomIntProvider (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.instr.random
    +

    Class SharedRandomIntProvider

    +
    +
    + +
    + +
    +
    +
      +
    • + + + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        intnextInt(int bound) 
        + +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          SharedRandomIntProvider

          +
          public SharedRandomIntProvider()
          +
        • +
        +
      • +
      + + +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/instr/random/ThreadLocalRandomIntProvider.html b/misc/btrace/javadoc/com/sun/btrace/instr/random/ThreadLocalRandomIntProvider.html new file mode 100644 index 00000000..a8c3e380 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/instr/random/ThreadLocalRandomIntProvider.html @@ -0,0 +1,285 @@ + + + + + +ThreadLocalRandomIntProvider (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.instr.random
    +

    Class ThreadLocalRandomIntProvider

    +
    +
    + +
    +
      +
    • +
      +
      +
      public final class ThreadLocalRandomIntProvider
      +extends RandomIntProvider
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          ThreadLocalRandomIntProvider

          +
          public ThreadLocalRandomIntProvider()
          +
        • +
        +
      • +
      + + +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/instr/random/package-frame.html b/misc/btrace/javadoc/com/sun/btrace/instr/random/package-frame.html new file mode 100644 index 00000000..87138582 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/instr/random/package-frame.html @@ -0,0 +1,21 @@ + + + + + +com.sun.btrace.instr.random (btrace 1.3.11 API) + + + + + +

    com.sun.btrace.instr.random

    + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/instr/random/package-summary.html b/misc/btrace/javadoc/com/sun/btrace/instr/random/package-summary.html new file mode 100644 index 00000000..d93deee1 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/instr/random/package-summary.html @@ -0,0 +1,144 @@ + + + + + +com.sun.btrace.instr.random (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Package com.sun.btrace.instr.random

    +
    +
    + +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/instr/random/package-tree.html b/misc/btrace/javadoc/com/sun/btrace/instr/random/package-tree.html new file mode 100644 index 00000000..9d705390 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/instr/random/package-tree.html @@ -0,0 +1,140 @@ + + + + + +com.sun.btrace.instr.random Class Hierarchy (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Hierarchy For Package com.sun.btrace.instr.random

    +Package Hierarchies: + +
    +
    +

    Class Hierarchy

    + +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/package-frame.html b/misc/btrace/javadoc/com/sun/btrace/package-frame.html new file mode 100644 index 00000000..951bda3c --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/package-frame.html @@ -0,0 +1,60 @@ + + + + + +com.sun.btrace (btrace 1.3.11 API) + + + + + +

    com.sun.btrace

    + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/package-summary.html b/misc/btrace/javadoc/com/sun/btrace/package-summary.html new file mode 100644 index 00000000..d3d9d9ec --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/package-summary.html @@ -0,0 +1,346 @@ + + + + + +com.sun.btrace (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Package com.sun.btrace

    +
    +
    + +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/package-tree.html b/misc/btrace/javadoc/com/sun/btrace/package-tree.html new file mode 100644 index 00000000..484dd145 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/package-tree.html @@ -0,0 +1,192 @@ + + + + + +com.sun.btrace Class Hierarchy (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Hierarchy For Package com.sun.btrace

    +Package Hierarchies: + +
    +
    +

    Class Hierarchy

    + +

    Interface Hierarchy

    + +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/profiling/MethodInvocationProfiler.html b/misc/btrace/javadoc/com/sun/btrace/profiling/MethodInvocationProfiler.html new file mode 100644 index 00000000..a4167656 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/profiling/MethodInvocationProfiler.html @@ -0,0 +1,422 @@ + + + + + +MethodInvocationProfiler (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.profiling
    +

    Class MethodInvocationProfiler

    +
    +
    + +
    + +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          MethodInvocationProfiler

          +
          public MethodInvocationProfiler(int expectedMethodCnt)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          recordEntry

          +
          public void recordEntry(java.lang.String blockName)
          +
          Description copied from class: Profiler
          +
          Records the event of entering an execution unit (eg. method)
          + Must be paired with a call to Profiler.recordExit(java.lang.String, long) + with the same blockName, eventually
          +
          +
          Specified by:
          +
          recordEntry in class Profiler
          +
          Parameters:
          +
          blockName - The execution unit identifier (eg. method FQN)
          +
          +
        • +
        + + + +
          +
        • +

          recordExit

          +
          public void recordExit(java.lang.String blockName,
          +                       long duration)
          +
          Description copied from class: Profiler
          +
          Records the event of exiting an execution unit (eg. method)
          + Must be preceded by a call to Profiler.recordEntry(java.lang.String) + with the same blockName
          +
          +
          Specified by:
          +
          recordExit in class Profiler
          +
          Parameters:
          +
          blockName - The execution unit identifier (eg. method FQN)
          +
          duration - Invocation duration in nanoseconds
          +
          +
        • +
        + + + +
          +
        • +

          reset

          +
          public void reset()
          +
          Description copied from class: Profiler
          +
          Resets all the collected data
          +
          +
          Specified by:
          +
          reset in class Profiler
          +
          +
        • +
        + + + +
          +
        • +

          snapshot

          +
          public Profiler.Snapshot snapshot(boolean reset)
          +
          Description copied from class: Profiler
          +
          Creates an immutable snapshot of the collected profiling data.
          + Makes it possible to reset the profiler after creating the snapshot, eventually
          +
          +
          Specified by:
          +
          snapshot in class Profiler
          +
          Parameters:
          +
          reset - Signals the profiler to perform reset right after getting the snapshot (in an atomic transaction)
          +
          Returns:
          +
          Returns the immutable Profiler.Snapshot instance
          +
          +
        • +
        + + + + +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/profiling/package-frame.html b/misc/btrace/javadoc/com/sun/btrace/profiling/package-frame.html new file mode 100644 index 00000000..9da0643c --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/profiling/package-frame.html @@ -0,0 +1,20 @@ + + + + + +com.sun.btrace.profiling (btrace 1.3.11 API) + + + + + +

    com.sun.btrace.profiling

    +
    +

    Classes

    + +
    + + diff --git a/misc/btrace/javadoc/com/sun/btrace/profiling/package-summary.html b/misc/btrace/javadoc/com/sun/btrace/profiling/package-summary.html new file mode 100644 index 00000000..19ec79a6 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/profiling/package-summary.html @@ -0,0 +1,142 @@ + + + + + +com.sun.btrace.profiling (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Package com.sun.btrace.profiling

    +
    +
    + +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/profiling/package-tree.html b/misc/btrace/javadoc/com/sun/btrace/profiling/package-tree.html new file mode 100644 index 00000000..f1372635 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/profiling/package-tree.html @@ -0,0 +1,139 @@ + + + + + +com.sun.btrace.profiling Class Hierarchy (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Hierarchy For Package com.sun.btrace.profiling

    +Package Hierarchies: + +
    +
    +

    Class Hierarchy

    + +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/Assembler.html b/misc/btrace/javadoc/com/sun/btrace/runtime/Assembler.html new file mode 100644 index 00000000..8edcc8e6 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/Assembler.html @@ -0,0 +1,900 @@ + + + + + +Assembler (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class Assembler

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.runtime.Assembler
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class Assembler
      +extends java.lang.Object
      +
      Convenient fluent wrapper over the ASM method visitor
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Assembler

          +
          public Assembler(com.sun.btrace.org.objectweb.asm.MethodVisitor mv,
          +                 MethodInstrumentorHelper mHelper)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          push

          +
          public Assembler push(int value)
          +
        • +
        + + + +
          +
        • +

          arrayLoad

          +
          public Assembler arrayLoad(com.sun.btrace.org.objectweb.asm.Type type)
          +
        • +
        + + + +
          +
        • +

          arrayStore

          +
          public Assembler arrayStore(com.sun.btrace.org.objectweb.asm.Type type)
          +
        • +
        + + + +
          +
        • +

          jump

          +
          public Assembler jump(int opcode,
          +                      com.sun.btrace.org.objectweb.asm.Label l)
          +
        • +
        + + + +
          +
        • +

          ldc

          +
          public Assembler ldc(java.lang.Object o)
          +
        • +
        + + + +
          +
        • +

          sub

          +
          public Assembler sub(com.sun.btrace.org.objectweb.asm.Type t)
          +
        • +
        + + + +
          +
        • +

          loadNull

          +
          public Assembler loadNull()
          +
        • +
        + + + +
          +
        • +

          loadLocal

          +
          public Assembler loadLocal(com.sun.btrace.org.objectweb.asm.Type type,
          +                           int index)
          +
        • +
        + + + +
          +
        • +

          storeLocal

          +
          public Assembler storeLocal(com.sun.btrace.org.objectweb.asm.Type type,
          +                            int index)
          +
        • +
        + + + +
          +
        • +

          storeField

          +
          public Assembler storeField(com.sun.btrace.org.objectweb.asm.Type owner,
          +                            java.lang.String name,
          +                            com.sun.btrace.org.objectweb.asm.Type t)
          +
        • +
        + + + +
          +
        • +

          storeStaticField

          +
          public Assembler storeStaticField(com.sun.btrace.org.objectweb.asm.Type owner,
          +                                  java.lang.String name,
          +                                  com.sun.btrace.org.objectweb.asm.Type t)
          +
        • +
        + + + +
          +
        • +

          loadField

          +
          public Assembler loadField(com.sun.btrace.org.objectweb.asm.Type owner,
          +                           java.lang.String name,
          +                           com.sun.btrace.org.objectweb.asm.Type t)
          +
        • +
        + + + +
          +
        • +

          loadStaticField

          +
          public Assembler loadStaticField(com.sun.btrace.org.objectweb.asm.Type owner,
          +                                 java.lang.String name,
          +                                 com.sun.btrace.org.objectweb.asm.Type t)
          +
        • +
        + + + + + + + + + + + + + + + + + + + + + + + +
          +
        • +

          dup2_x1

          +
          public Assembler dup2_x1()
          +
        • +
        + + + +
          +
        • +

          dup2_x2

          +
          public Assembler dup2_x2()
          +
        • +
        + + + + + + + +
          +
        • +

          newInstance

          +
          public Assembler newInstance(com.sun.btrace.org.objectweb.asm.Type t)
          +
        • +
        + + + +
          +
        • +

          newArray

          +
          public Assembler newArray(com.sun.btrace.org.objectweb.asm.Type t)
          +
        • +
        + + + +
          +
        • +

          dupArrayValue

          +
          public Assembler dupArrayValue(int arrayOpcode)
          +
        • +
        + + + +
          +
        • +

          dupReturnValue

          +
          public Assembler dupReturnValue(int returnOpcode)
          +
        • +
        + + + +
          +
        • +

          dupValue

          +
          public Assembler dupValue(com.sun.btrace.org.objectweb.asm.Type type)
          +
        • +
        + + + +
          +
        • +

          dupValue

          +
          public Assembler dupValue(java.lang.String desc)
          +
        • +
        + + + +
          +
        • +

          box

          +
          public Assembler box(com.sun.btrace.org.objectweb.asm.Type type)
          +
        • +
        + + + +
          +
        • +

          box

          +
          public Assembler box(java.lang.String desc)
          +
        • +
        + + + +
          +
        • +

          unbox

          +
          public Assembler unbox(com.sun.btrace.org.objectweb.asm.Type type)
          +
        • +
        + + + +
          +
        • +

          unbox

          +
          public Assembler unbox(java.lang.String desc)
          +
        • +
        + + + +
          +
        • +

          defaultValue

          +
          public Assembler defaultValue(java.lang.String desc)
          +
        • +
        + + + +
          +
        • +

          println

          +
          public Assembler println(java.lang.String msg)
          +
        • +
        + + + +
          +
        • +

          printObject

          +
          public Assembler printObject()
          +
        • +
        + + + +
          +
        • +

          invokeVirtual

          +
          public Assembler invokeVirtual(java.lang.String owner,
          +                               java.lang.String method,
          +                               java.lang.String desc)
          +
        • +
        + + + +
          +
        • +

          invokeSpecial

          +
          public Assembler invokeSpecial(java.lang.String owner,
          +                               java.lang.String method,
          +                               java.lang.String desc)
          +
        • +
        + + + +
          +
        • +

          invokeStatic

          +
          public Assembler invokeStatic(java.lang.String owner,
          +                              java.lang.String method,
          +                              java.lang.String desc)
          +
        • +
        + + + +
          +
        • +

          invokeInterface

          +
          public Assembler invokeInterface(java.lang.String owner,
          +                                 java.lang.String method,
          +                                 java.lang.String desc)
          +
        • +
        + + + +
          +
        • +

          getStatic

          +
          public Assembler getStatic(java.lang.String owner,
          +                           java.lang.String name,
          +                           java.lang.String desc)
          +
        • +
        + + + +
          +
        • +

          putStatic

          +
          public Assembler putStatic(java.lang.String owner,
          +                           java.lang.String name,
          +                           java.lang.String desc)
          +
        • +
        + + + +
          +
        • +

          label

          +
          public Assembler label(com.sun.btrace.org.objectweb.asm.Label l)
          +
        • +
        + + + +
          +
        • +

          addLevelCheck

          +
          public Assembler addLevelCheck(java.lang.String clsName,
          +                               Level level,
          +                               com.sun.btrace.org.objectweb.asm.Label jmp)
          +
        • +
        + + + +
          +
        • +

          addLevelCheck

          +
          public Assembler addLevelCheck(java.lang.String clsName,
          +                               Interval itv,
          +                               com.sun.btrace.org.objectweb.asm.Label jmp)
          +
        • +
        + + + +
          +
        • +

          compareLevel

          +
          public Assembler compareLevel(java.lang.String clsName,
          +                              Level level)
          +
          Compares the instrumentation level interval against the runtime value. +

          + If the runtime value is fitting the level interval there will be 0 + on stack upon return from this method. Otherwise there will be -1.

          +
          +
          Parameters:
          +
          clsName - The probe class name
          +
          level - The probe instrumentation level
          +
          Returns:
          +
          itself
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/BTraceMethodNode.html b/misc/btrace/javadoc/com/sun/btrace/runtime/BTraceMethodNode.html new file mode 100644 index 00000000..0a5ede22 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/BTraceMethodNode.html @@ -0,0 +1,489 @@ + + + + + +BTraceMethodNode (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class BTraceMethodNode

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.org.objectweb.asm.MethodVisitor
      • +
      • +
          +
        • com.sun.btrace.org.objectweb.asm.tree.MethodNode
        • +
        • +
            +
          • com.sun.btrace.runtime.BTraceMethodNode
          • +
          +
        • +
        +
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public class BTraceMethodNode
      +extends com.sun.btrace.org.objectweb.asm.tree.MethodNode
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Summary

        + + + + + + + + + + +
        Fields 
        Modifier and TypeField and Description
        static java.util.Comparator<com.sun.btrace.org.objectweb.asm.tree.MethodNode>COMPARATOR 
        +
          +
        • + + +

          Fields inherited from class com.sun.btrace.org.objectweb.asm.tree.MethodNode

          +access, annotationDefault, attrs, desc, exceptions, instructions, invisibleAnnotations, invisibleLocalVariableAnnotations, invisibleParameterAnnotations, invisibleTypeAnnotations, localVariables, maxLocals, maxStack, name, parameters, signature, tryCatchBlocks, visibleAnnotations, visibleLocalVariableAnnotations, visibleParameterAnnotations, visibleTypeAnnotations
        • +
        +
          +
        • + + +

          Fields inherited from class com.sun.btrace.org.objectweb.asm.MethodVisitor

          +api, mv
        • +
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        java.util.Set<BTraceMethodNode>getCallees() 
        java.util.Set<BTraceMethodNode>getCallers() 
        OnMethodgetOnMethod() 
        booleanisBcpRequired() 
        booleanisBTraceHandler() 
        booleanisSampled() 
        java.lang.StringtoString() 
        com.sun.btrace.org.objectweb.asm.AnnotationVisitorvisitAnnotation(java.lang.String type, + boolean visible) 
        voidvisitEnd() 
        voidvisitFieldInsn(int opcode, + java.lang.String owner, + java.lang.String name, + java.lang.String desc) 
        voidvisitMethodInsn(int opcode, + java.lang.String owner, + java.lang.String name, + java.lang.String desc, + boolean itf) 
        com.sun.btrace.org.objectweb.asm.AnnotationVisitorvisitParameterAnnotation(int parameter, + java.lang.String desc, + boolean visible) 
        +
          +
        • + + +

          Methods inherited from class com.sun.btrace.org.objectweb.asm.tree.MethodNode

          +accept, accept, check, getLabelNode, visitAnnotationDefault, visitAttribute, visitCode, visitFrame, visitIincInsn, visitInsn, visitInsnAnnotation, visitIntInsn, visitInvokeDynamicInsn, visitJumpInsn, visitLabel, visitLdcInsn, visitLineNumber, visitLocalVariable, visitLocalVariableAnnotation, visitLookupSwitchInsn, visitMaxs, visitMethodInsn, visitMultiANewArrayInsn, visitParameter, visitTableSwitchInsn, visitTryCatchAnnotation, visitTryCatchBlock, visitTypeAnnotation, visitTypeInsn, visitVarInsn
        • +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Detail

        + + + +
          +
        • +

          COMPARATOR

          +
          public static final java.util.Comparator<com.sun.btrace.org.objectweb.asm.tree.MethodNode> COMPARATOR
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          visitEnd

          +
          public void visitEnd()
          +
          +
          Overrides:
          +
          visitEnd in class com.sun.btrace.org.objectweb.asm.tree.MethodNode
          +
          +
        • +
        + + + +
          +
        • +

          visitAnnotation

          +
          public com.sun.btrace.org.objectweb.asm.AnnotationVisitor visitAnnotation(java.lang.String type,
          +                                                                          boolean visible)
          +
          +
          Overrides:
          +
          visitAnnotation in class com.sun.btrace.org.objectweb.asm.tree.MethodNode
          +
          +
        • +
        + + + +
          +
        • +

          visitParameterAnnotation

          +
          public com.sun.btrace.org.objectweb.asm.AnnotationVisitor visitParameterAnnotation(int parameter,
          +                                                                                   java.lang.String desc,
          +                                                                                   boolean visible)
          +
          +
          Overrides:
          +
          visitParameterAnnotation in class com.sun.btrace.org.objectweb.asm.tree.MethodNode
          +
          +
        • +
        + + + +
          +
        • +

          visitMethodInsn

          +
          public void visitMethodInsn(int opcode,
          +                            java.lang.String owner,
          +                            java.lang.String name,
          +                            java.lang.String desc,
          +                            boolean itf)
          +
          +
          Overrides:
          +
          visitMethodInsn in class com.sun.btrace.org.objectweb.asm.tree.MethodNode
          +
          +
        • +
        + + + +
          +
        • +

          visitFieldInsn

          +
          public void visitFieldInsn(int opcode,
          +                           java.lang.String owner,
          +                           java.lang.String name,
          +                           java.lang.String desc)
          +
          +
          Overrides:
          +
          visitFieldInsn in class com.sun.btrace.org.objectweb.asm.tree.MethodNode
          +
          +
        • +
        + + + +
          +
        • +

          isBcpRequired

          +
          public boolean isBcpRequired()
          +
        • +
        + + + +
          +
        • +

          isBTraceHandler

          +
          public boolean isBTraceHandler()
          +
        • +
        + + + +
          +
        • +

          getOnMethod

          +
          public OnMethod getOnMethod()
          +
        • +
        + + + +
          +
        • +

          isSampled

          +
          public boolean isSampled()
          +
        • +
        + + + + + + + + + + + +
          +
        • +

          toString

          +
          public java.lang.String toString()
          +
          +
          Overrides:
          +
          toString in class java.lang.Object
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/BTraceMethodVisitor.html b/misc/btrace/javadoc/com/sun/btrace/runtime/BTraceMethodVisitor.html new file mode 100644 index 00000000..a2cf7f49 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/BTraceMethodVisitor.html @@ -0,0 +1,373 @@ + + + + + +BTraceMethodVisitor (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class BTraceMethodVisitor

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.org.objectweb.asm.MethodVisitor
      • +
      • +
          +
        • com.sun.btrace.runtime.BTraceMethodVisitor
        • +
        +
      • +
      +
    • +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Field Summary

        +
          +
        • + + +

          Fields inherited from class com.sun.btrace.org.objectweb.asm.MethodVisitor

          +api, mv
        • +
        +
      • +
      + + + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        voidaddTryCatchHandler(com.sun.btrace.org.objectweb.asm.Label start, + com.sun.btrace.org.objectweb.asm.Label handler) 
        voidinsertFrameAppendStack(com.sun.btrace.org.objectweb.asm.Label l, + com.sun.btrace.org.objectweb.asm.Type... stack) 
        voidinsertFrameReplaceStack(com.sun.btrace.org.objectweb.asm.Label l, + com.sun.btrace.org.objectweb.asm.Type... stack) 
        voidinsertFrameSameStack(com.sun.btrace.org.objectweb.asm.Label l) 
        intstoreAsNew() 
        intstoreNewLocal(com.sun.btrace.org.objectweb.asm.Type t) 
        +
          +
        • + + +

          Methods inherited from class com.sun.btrace.org.objectweb.asm.MethodVisitor

          +visitAnnotation, visitAnnotationDefault, visitAttribute, visitCode, visitEnd, visitFieldInsn, visitFrame, visitIincInsn, visitInsn, visitInsnAnnotation, visitIntInsn, visitInvokeDynamicInsn, visitJumpInsn, visitLabel, visitLdcInsn, visitLineNumber, visitLocalVariable, visitLocalVariableAnnotation, visitLookupSwitchInsn, visitMaxs, visitMethodInsn, visitMethodInsn, visitMultiANewArrayInsn, visitParameter, visitParameterAnnotation, visitTableSwitchInsn, visitTryCatchAnnotation, visitTryCatchBlock, visitTypeAnnotation, visitTypeInsn, visitVarInsn
        • +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          BTraceMethodVisitor

          +
          public BTraceMethodVisitor(com.sun.btrace.org.objectweb.asm.MethodVisitor mv,
          +                           MethodInstrumentorHelper mHelper)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          storeAsNew

          +
          public final int storeAsNew()
          +
        • +
        + + + +
          +
        • +

          storeNewLocal

          +
          public final int storeNewLocal(com.sun.btrace.org.objectweb.asm.Type t)
          +
        • +
        + + + +
          +
        • +

          addTryCatchHandler

          +
          public final void addTryCatchHandler(com.sun.btrace.org.objectweb.asm.Label start,
          +                                     com.sun.btrace.org.objectweb.asm.Label handler)
          +
        • +
        + + + +
          +
        • +

          insertFrameReplaceStack

          +
          public void insertFrameReplaceStack(com.sun.btrace.org.objectweb.asm.Label l,
          +                                    com.sun.btrace.org.objectweb.asm.Type... stack)
          +
        • +
        + + + +
          +
        • +

          insertFrameAppendStack

          +
          public void insertFrameAppendStack(com.sun.btrace.org.objectweb.asm.Label l,
          +                                   com.sun.btrace.org.objectweb.asm.Type... stack)
          +
        • +
        + + + +
          +
        • +

          insertFrameSameStack

          +
          public void insertFrameSameStack(com.sun.btrace.org.objectweb.asm.Label l)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/BTraceProbe.html b/misc/btrace/javadoc/com/sun/btrace/runtime/BTraceProbe.html new file mode 100644 index 00000000..3bd17dfa --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/BTraceProbe.html @@ -0,0 +1,433 @@ + + + + + +BTraceProbe (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Interface BTraceProbe

    +
    +
    +
    + +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getApplicableHandlers

          +
          java.util.Collection<OnMethod> getApplicableHandlers(com.sun.btrace.runtime.BTraceClassReader cr)
          +
        • +
        + + + +
          +
        • +

          getFullBytecode

          +
          byte[] getFullBytecode()
          +
        • +
        + + + +
          +
        • +

          getDataHolderBytecode

          +
          byte[] getDataHolderBytecode()
          +
        • +
        + + + +
          +
        • +

          getClassName

          +
          java.lang.String getClassName()
          +
        • +
        + + + +
          +
        • +

          getClassName

          +
          java.lang.String getClassName(boolean internal)
          +
        • +
        + + + +
          +
        • +

          isClassRenamed

          +
          boolean isClassRenamed()
          +
        • +
        + + + +
          +
        • +

          isTransforming

          +
          boolean isTransforming()
          +
        • +
        + + + +
          +
        • +

          isVerified

          +
          boolean isVerified()
          +
        • +
        + + + +
          +
        • +

          notifyTransform

          +
          void notifyTransform(java.lang.String className)
          +
        • +
        + + + +
          +
        • +

          onmethods

          +
          java.lang.Iterable<OnMethod> onmethods()
          +
        • +
        + + + +
          +
        • +

          onprobes

          +
          java.lang.Iterable<OnProbe> onprobes()
          +
        • +
        + + + + + + + +
          +
        • +

          unregister

          +
          void unregister()
          +
        • +
        + + + +
          +
        • +

          willInstrument

          +
          boolean willInstrument(java.lang.Class clz)
          +
        • +
        + + + +
          +
        • +

          checkVerified

          +
          void checkVerified()
          +
        • +
        + + + +
          +
        • +

          copyHandlers

          +
          void copyHandlers(com.sun.btrace.org.objectweb.asm.ClassVisitor copyingVisitor)
          +
        • +
        + + + +
          +
        • +

          applyArgs

          +
          void applyArgs(ArgsMap argsMap)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/BTraceProbeFactory.html b/misc/btrace/javadoc/com/sun/btrace/runtime/BTraceProbeFactory.html new file mode 100644 index 00000000..1af66aa4 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/BTraceProbeFactory.html @@ -0,0 +1,327 @@ + + + + + +BTraceProbeFactory (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class BTraceProbeFactory

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.runtime.BTraceProbeFactory
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class BTraceProbeFactory
      +extends java.lang.Object
      +
      A factory class for BTraceProbeNode instances
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          BTraceProbeFactory

          +
          public BTraceProbeFactory(SharedSettings settings)
          +
        • +
        + + + +
          +
        • +

          BTraceProbeFactory

          +
          public BTraceProbeFactory(SharedSettings settings,
          +                          boolean canLoadPack)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          createProbe

          +
          public BTraceProbe createProbe(byte[] code)
          +
        • +
        + + + + + + + +
          +
        • +

          createProbe

          +
          public BTraceProbe createProbe(java.io.InputStream code)
          +
        • +
        + + + +
          +
        • +

          createProbe

          +
          public BTraceProbe createProbe(java.io.InputStream code,
          +                               ArgsMap argsMap)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/BTraceProbeNode.html b/misc/btrace/javadoc/com/sun/btrace/runtime/BTraceProbeNode.html new file mode 100644 index 00000000..ae57c1e0 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/BTraceProbeNode.html @@ -0,0 +1,664 @@ + + + + + +BTraceProbeNode (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class BTraceProbeNode

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.org.objectweb.asm.ClassVisitor
      • +
      • +
          +
        • com.sun.btrace.org.objectweb.asm.tree.ClassNode
        • +
        • +
            +
          • com.sun.btrace.runtime.BTraceProbeNode
          • +
          +
        • +
        +
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      BTraceProbe
      +
      +
      +
      +
      public final class BTraceProbeNode
      +extends com.sun.btrace.org.objectweb.asm.tree.ClassNode
      +implements BTraceProbe
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Summary

        +
          +
        • + + +

          Fields inherited from class com.sun.btrace.org.objectweb.asm.tree.ClassNode

          +access, attrs, fields, innerClasses, interfaces, invisibleAnnotations, invisibleTypeAnnotations, methods, name, outerClass, outerMethod, outerMethodDesc, signature, sourceDebug, sourceFile, superName, version, visibleAnnotations, visibleTypeAnnotations
        • +
        +
          +
        • + + +

          Fields inherited from class com.sun.btrace.org.objectweb.asm.ClassVisitor

          +api, cv
        • +
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        voidapplyArgs(ArgsMap argsMap) 
        voidcheckVerified() 
        voidcopyHandlers(com.sun.btrace.org.objectweb.asm.ClassVisitor copyingVisitor) 
        java.util.Collection<OnMethod>getApplicableHandlers(com.sun.btrace.runtime.BTraceClassReader cr) 
        java.lang.StringgetClassName() 
        java.lang.StringgetClassName(boolean internal) 
        byte[]getDataHolderBytecode() 
        byte[]getFullBytecode() 
        java.util.Collection<OnMethod>getOnMethods() 
        booleanisClassRenamed() 
        booleanisTransforming() 
        booleanisVerified() 
        voidnotifyTransform(java.lang.String className) 
        java.lang.Iterable<OnMethod>onmethods() 
        java.lang.Iterable<OnProbe>onprobes() 
        java.lang.Classregister(BTraceRuntime rt, + BTraceTransformer t) 
        java.lang.StringtoString() 
        voidunregister() 
        voidvisit(int version, + int access, + java.lang.String name, + java.lang.String sig, + java.lang.String superType, + java.lang.String[] itfcs) 
        com.sun.btrace.org.objectweb.asm.FieldVisitorvisitField(int access, + java.lang.String name, + java.lang.String desc, + java.lang.String signature, + java.lang.Object value) 
        com.sun.btrace.org.objectweb.asm.MethodVisitorvisitMethod(int access, + java.lang.String name, + java.lang.String desc, + java.lang.String sig, + java.lang.String[] exceptions) 
        booleanwillInstrument(java.lang.Class clz) 
        +
          +
        • + + +

          Methods inherited from class com.sun.btrace.org.objectweb.asm.tree.ClassNode

          +accept, check, visitAnnotation, visitAttribute, visitEnd, visitInnerClass, visitOuterClass, visitSource, visitTypeAnnotation
        • +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Method Detail

        + + + + + + + +
          +
        • +

          visit

          +
          public void visit(int version,
          +                  int access,
          +                  java.lang.String name,
          +                  java.lang.String sig,
          +                  java.lang.String superType,
          +                  java.lang.String[] itfcs)
          +
          +
          Overrides:
          +
          visit in class com.sun.btrace.org.objectweb.asm.tree.ClassNode
          +
          +
        • +
        + + + +
          +
        • +

          visitMethod

          +
          public com.sun.btrace.org.objectweb.asm.MethodVisitor visitMethod(int access,
          +                                                                  java.lang.String name,
          +                                                                  java.lang.String desc,
          +                                                                  java.lang.String sig,
          +                                                                  java.lang.String[] exceptions)
          +
          +
          Overrides:
          +
          visitMethod in class com.sun.btrace.org.objectweb.asm.tree.ClassNode
          +
          +
        • +
        + + + +
          +
        • +

          visitField

          +
          public com.sun.btrace.org.objectweb.asm.FieldVisitor visitField(int access,
          +                                                                java.lang.String name,
          +                                                                java.lang.String desc,
          +                                                                java.lang.String signature,
          +                                                                java.lang.Object value)
          +
          +
          Overrides:
          +
          visitField in class com.sun.btrace.org.objectweb.asm.tree.ClassNode
          +
          +
        • +
        + + + +
          +
        • +

          getApplicableHandlers

          +
          public java.util.Collection<OnMethod> getApplicableHandlers(com.sun.btrace.runtime.BTraceClassReader cr)
          +
          +
          Specified by:
          +
          getApplicableHandlers in interface BTraceProbe
          +
          +
        • +
        + + + + + + + +
          +
        • +

          getOnMethods

          +
          public java.util.Collection<OnMethod> getOnMethods()
          +
        • +
        + + + + + + + +
          +
        • +

          getClassName

          +
          public java.lang.String getClassName()
          +
          +
          Specified by:
          +
          getClassName in interface BTraceProbe
          +
          +
        • +
        + + + +
          +
        • +

          getClassName

          +
          public java.lang.String getClassName(boolean internal)
          +
          +
          Specified by:
          +
          getClassName in interface BTraceProbe
          +
          +
        • +
        + + + + + + + + + + + + + + + + + + + +
          +
        • +

          willInstrument

          +
          public boolean willInstrument(java.lang.Class clz)
          +
          +
          Specified by:
          +
          willInstrument in interface BTraceProbe
          +
          +
        • +
        + + + + + + + +
          +
        • +

          isVerified

          +
          public boolean isVerified()
          +
          +
          Specified by:
          +
          isVerified in interface BTraceProbe
          +
          +
        • +
        + + + +
          +
        • +

          notifyTransform

          +
          public void notifyTransform(java.lang.String className)
          +
          +
          Specified by:
          +
          notifyTransform in interface BTraceProbe
          +
          +
        • +
        + + + + + + + +
          +
        • +

          copyHandlers

          +
          public void copyHandlers(com.sun.btrace.org.objectweb.asm.ClassVisitor copyingVisitor)
          +
          +
          Specified by:
          +
          copyHandlers in interface BTraceProbe
          +
          +
        • +
        + + + + + + + +
          +
        • +

          toString

          +
          public java.lang.String toString()
          +
          +
          Overrides:
          +
          toString in class java.lang.Object
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/BTraceProbePersisted.html b/misc/btrace/javadoc/com/sun/btrace/runtime/BTraceProbePersisted.html new file mode 100644 index 00000000..34131894 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/BTraceProbePersisted.html @@ -0,0 +1,575 @@ + + + + + +BTraceProbePersisted (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class BTraceProbePersisted

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.runtime.BTraceProbePersisted
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      BTraceProbe
      +
      +
      +
      +
      public class BTraceProbePersisted
      +extends java.lang.Object
      +implements BTraceProbe
      +
    • +
    +
    +
    + +
    +
    + +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/BTraceProbeSupport.html b/misc/btrace/javadoc/com/sun/btrace/runtime/BTraceProbeSupport.html new file mode 100644 index 00000000..c0756617 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/BTraceProbeSupport.html @@ -0,0 +1,239 @@ + + + + + +BTraceProbeSupport (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class BTraceProbeSupport

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.runtime.BTraceProbeSupport
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class BTraceProbeSupport
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        java.lang.StringtoString() 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          toString

          +
          public java.lang.String toString()
          +
          +
          Overrides:
          +
          toString in class java.lang.Object
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/BTraceTransformer.html b/misc/btrace/javadoc/com/sun/btrace/runtime/BTraceTransformer.html new file mode 100644 index 00000000..3ca199c1 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/BTraceTransformer.html @@ -0,0 +1,324 @@ + + + + + +BTraceTransformer (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class BTraceTransformer

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.runtime.BTraceTransformer
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.lang.instrument.ClassFileTransformer
      +
      +
      +
      +
      public final class BTraceTransformer
      +extends java.lang.Object
      +implements java.lang.instrument.ClassFileTransformer
      +
      The single entry point for class transformation. +

      + When a class is to be transformed all the registered BTraceProbe instances are + asked for the appropriate instrumentation. When there are no registered probes or none of + the registered probes is able to instrument the class it will not be transformed.

      +
      +
      Since:
      +
      1.3.5
      +
      +
    • +
    +
    +
    +
      +
    • + + + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        voidregister(BTraceProbe p) 
        byte[]transform(java.lang.ClassLoader loader, + java.lang.String className, + java.lang.Class<?> classBeingRedefined, + java.security.ProtectionDomain protectionDomain, + byte[] classfileBuffer) 
        voidunregister(BTraceProbe p) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          BTraceTransformer

          +
          public BTraceTransformer(DebugSupport d)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          register

          +
          public final void register(BTraceProbe p)
          +
        • +
        + + + +
          +
        • +

          unregister

          +
          public final void unregister(BTraceProbe p)
          +
        • +
        + + + +
          +
        • +

          transform

          +
          public byte[] transform(java.lang.ClassLoader loader,
          +                        java.lang.String className,
          +                        java.lang.Class<?> classBeingRedefined,
          +                        java.security.ProtectionDomain protectionDomain,
          +                        byte[] classfileBuffer)
          +                 throws java.lang.instrument.IllegalClassFormatException
          +
          +
          Specified by:
          +
          transform in interface java.lang.instrument.ClassFileTransformer
          +
          Throws:
          +
          java.lang.instrument.IllegalClassFormatException
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/CallGraph.Edge.html b/misc/btrace/javadoc/com/sun/btrace/runtime/CallGraph.Edge.html new file mode 100644 index 00000000..ee50d0c4 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/CallGraph.Edge.html @@ -0,0 +1,309 @@ + + + + + +CallGraph.Edge (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class CallGraph.Edge

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.runtime.CallGraph.Edge
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing class:
      +
      CallGraph
      +
      +
      +
      +
      public static class CallGraph.Edge
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + + + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        voiddelete() 
        booleanequals(java.lang.Object obj) 
        inthashCode() 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, finalize, getClass, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + + + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          delete

          +
          public void delete()
          +
        • +
        + + + +
          +
        • +

          equals

          +
          public boolean equals(java.lang.Object obj)
          +
          +
          Overrides:
          +
          equals in class java.lang.Object
          +
          +
        • +
        + + + +
          +
        • +

          hashCode

          +
          public int hashCode()
          +
          +
          Overrides:
          +
          hashCode in class java.lang.Object
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/CallGraph.Node.html b/misc/btrace/javadoc/com/sun/btrace/runtime/CallGraph.Node.html new file mode 100644 index 00000000..61bc1840 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/CallGraph.Node.html @@ -0,0 +1,363 @@ + + + + + +CallGraph.Node (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class CallGraph.Node

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.runtime.CallGraph.Node
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing class:
      +
      CallGraph
      +
      +
      +
      +
      public static class CallGraph.Node
      +extends java.lang.Object
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Node

          +
          public Node(java.lang.String id)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + + + + + + + + + +
          +
        • +

          removeIncoming

          +
          public void removeIncoming(CallGraph.Edge e)
          +
        • +
        + + + +
          +
        • +

          removeOutgoing

          +
          public void removeOutgoing(CallGraph.Edge e)
          +
        • +
        + + + +
          +
        • +

          equals

          +
          public boolean equals(java.lang.Object obj)
          +
          +
          Overrides:
          +
          equals in class java.lang.Object
          +
          +
        • +
        + + + +
          +
        • +

          hashCode

          +
          public int hashCode()
          +
          +
          Overrides:
          +
          hashCode in class java.lang.Object
          +
          +
        • +
        + + + +
          +
        • +

          toString

          +
          public java.lang.String toString()
          +
          +
          Overrides:
          +
          toString in class java.lang.Object
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/CallGraph.html b/misc/btrace/javadoc/com/sun/btrace/runtime/CallGraph.html new file mode 100644 index 00000000..e0f16ff9 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/CallGraph.html @@ -0,0 +1,349 @@ + + + + + +CallGraph (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class CallGraph

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.runtime.CallGraph
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class CallGraph
      +extends java.lang.Object
      +
      This class allows building an arbitrary graph caller-callee relationship
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Nested Class Summary

        + + + + + + + + + + + + + + +
        Nested Classes 
        Modifier and TypeClass and Description
        static class CallGraph.Edge 
        static class CallGraph.Node 
        +
      • +
      + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        CallGraph() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        voidaddEdge(java.lang.String fromId, + java.lang.String toId) 
        voidaddStarting(CallGraph.Node n) 
        booleanhasCycle() 
        static java.lang.String[]method(java.lang.String methodId) 
        static java.lang.StringmethodId(java.lang.String name, + java.lang.String desc) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          CallGraph

          +
          public CallGraph()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          methodId

          +
          public static java.lang.String methodId(java.lang.String name,
          +                                        java.lang.String desc)
          +
        • +
        + + + +
          +
        • +

          method

          +
          public static java.lang.String[] method(java.lang.String methodId)
          +
        • +
        + + + +
          +
        • +

          addEdge

          +
          public void addEdge(java.lang.String fromId,
          +                    java.lang.String toId)
          +
        • +
        + + + + + + + +
          +
        • +

          hasCycle

          +
          public boolean hasCycle()
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/ClassCache.html b/misc/btrace/javadoc/com/sun/btrace/runtime/ClassCache.html new file mode 100644 index 00000000..c4110ea2 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/ClassCache.html @@ -0,0 +1,309 @@ + + + + + +ClassCache (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class ClassCache

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.runtime.ClassCache
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class ClassCache
      +extends java.lang.Object
      +
      A simple class cache holding ClassInfo instances and being + searchable either by Class or a tuple of (className, classLoader)
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        ClassCache() 
        +
      • +
      + + +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          ClassCache

          +
          public ClassCache()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getInstance

          +
          public static ClassCache getInstance()
          +
        • +
        + + + +
          +
        • +

          get

          +
          public ClassInfo get(java.lang.Class clz)
          +
        • +
        + + + +
          +
        • +

          get

          +
          public ClassInfo get(java.lang.ClassLoader cl,
          +                     java.lang.String className)
          +
          Returns a cached ClassInfo value. + If the corresponding value has not been cached yet then it is + created and put into the cache.
          +
          +
          Parameters:
          +
          cl - The associated ClassLoader
          +
          className - The Java class name or internal class name
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/ClassFilter.html b/misc/btrace/javadoc/com/sun/btrace/runtime/ClassFilter.html new file mode 100644 index 00000000..4072ec70 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/ClassFilter.html @@ -0,0 +1,341 @@ + + + + + +ClassFilter (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class ClassFilter

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.runtime.ClassFilter
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public class ClassFilter
      +extends java.lang.Object
      +
      This class checks whether a given target class + matches at least one probe specified in a BTrace + class.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        ClassFilter(java.lang.Iterable<OnMethod> onMethods) 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        booleanisCandidate(java.lang.Class target) 
        booleanisNameMatching(java.lang.String clzName) 
        static booleanisSensitiveClass(java.lang.String name) 
        static booleanisSubTypeOf(java.lang.Class clazz, + java.lang.String typeName) 
        static booleanisSubTypeOf(java.lang.String typeA, + java.lang.ClassLoader loader, + java.lang.String... types) +
        Return whether given Class typeA is subtype of any of the + given type names.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          ClassFilter

          +
          public ClassFilter(java.lang.Iterable<OnMethod> onMethods)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          isCandidate

          +
          public boolean isCandidate(java.lang.Class target)
          +
        • +
        + + + +
          +
        • +

          isNameMatching

          +
          public boolean isNameMatching(java.lang.String clzName)
          +
        • +
        + + + +
          +
        • +

          isSubTypeOf

          +
          public static boolean isSubTypeOf(java.lang.Class clazz,
          +                                  java.lang.String typeName)
          +
        • +
        + + + +
          +
        • +

          isSubTypeOf

          +
          public static boolean isSubTypeOf(java.lang.String typeA,
          +                                  java.lang.ClassLoader loader,
          +                                  java.lang.String... types)
          +
          Return whether given Class typeA is subtype of any of the + given type names.
          +
          +
          Parameters:
          +
          typeA - the type to check
          +
          loader - the classloader for loading the type (my be null)
          +
          types - any requested supertypes
          +
          +
        • +
        + + + +
          +
        • +

          isSensitiveClass

          +
          public static boolean isSensitiveClass(java.lang.String name)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/ClassInfo.html b/misc/btrace/javadoc/com/sun/btrace/runtime/ClassInfo.html new file mode 100644 index 00000000..7d595b07 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/ClassInfo.html @@ -0,0 +1,363 @@ + + + + + +ClassInfo (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class ClassInfo

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.runtime.ClassInfo
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class ClassInfo
      +extends java.lang.Object
      +
      Arbitrary class info type allowing access to supertype information + also for not-already-loaded classes.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        booleanequals(java.lang.Object obj) 
        java.lang.StringgetClassName() +
        Class ID = internal class name
        +
        java.lang.StringgetJavaClassName() 
        java.lang.StringgetLoaderId() +
        Associated class loader string representation as returned by cl.toString() or "<null>"
        +
        java.util.Collection<ClassInfo>getSupertypes(boolean onlyDirect) +
        Retrieves supertypes (including interfaces)
        +
        inthashCode() 
        booleanisInterface() 
        java.lang.StringtoString() 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, finalize, getClass, notify, notifyAll, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getSupertypes

          +
          public java.util.Collection<ClassInfo> getSupertypes(boolean onlyDirect)
          +
          Retrieves supertypes (including interfaces)
          +
          +
          Parameters:
          +
          onlyDirect - only immediate supertype and implemented interfaces
          +
          Returns:
          +
          supertypes (including interfaces)
          +
          +
        • +
        + + + +
          +
        • +

          getLoaderId

          +
          public java.lang.String getLoaderId()
          +
          Associated class loader string representation as returned by cl.toString() or "<null>"
          +
          +
          Returns:
          +
          associated class loader id
          +
          +
        • +
        + + + +
          +
        • +

          getClassName

          +
          public java.lang.String getClassName()
          +
          Class ID = internal class name
          +
          +
          Returns:
          +
          internal class name
          +
          +
        • +
        + + + +
          +
        • +

          getJavaClassName

          +
          public java.lang.String getJavaClassName()
          +
        • +
        + + + +
          +
        • +

          isInterface

          +
          public boolean isInterface()
          +
        • +
        + + + +
          +
        • +

          hashCode

          +
          public int hashCode()
          +
          +
          Overrides:
          +
          hashCode in class java.lang.Object
          +
          +
        • +
        + + + +
          +
        • +

          equals

          +
          public boolean equals(java.lang.Object obj)
          +
          +
          Overrides:
          +
          equals in class java.lang.Object
          +
          +
        • +
        + + + +
          +
        • +

          toString

          +
          public java.lang.String toString()
          +
          +
          Overrides:
          +
          toString in class java.lang.Object
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/Constants.html b/misc/btrace/javadoc/com/sun/btrace/runtime/Constants.html new file mode 100644 index 00000000..42386f14 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/Constants.html @@ -0,0 +1,1926 @@ + + + + + +Constants (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class Constants

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.runtime.Constants
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public abstract class Constants
      +extends java.lang.Object
      +
      Constants shared by few classes.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Field Detail

        + + + +
          +
        • +

          BTRACE_METHOD_PREFIX

          +
          public static final java.lang.String BTRACE_METHOD_PREFIX
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          CONSTRUCTOR

          +
          public static final java.lang.String CONSTRUCTOR
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          CLASS_INITIALIZER

          +
          public static final java.lang.String CLASS_INITIALIZER
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          NULL_TYPE

          +
          public static final com.sun.btrace.org.objectweb.asm.Type NULL_TYPE
          +
        • +
        + + + +
          +
        • +

          TOP_TYPE

          +
          public static final com.sun.btrace.org.objectweb.asm.Type TOP_TYPE
          +
        • +
        + + + +
          +
        • +

          VOIDREF_TYPE

          +
          public static final com.sun.btrace.org.objectweb.asm.Type VOIDREF_TYPE
          +
        • +
        + + + +
          +
        • +

          OBJECT_INTERNAL

          +
          public static final java.lang.String OBJECT_INTERNAL
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          OBJECT_DESC

          +
          public static final java.lang.String OBJECT_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          OBJECT_TYPE

          +
          public static final com.sun.btrace.org.objectweb.asm.Type OBJECT_TYPE
          +
        • +
        + + + +
          +
        • +

          ANYTYPE_INTERNAL

          +
          public static final java.lang.String ANYTYPE_INTERNAL
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ANYTYPE_DESC

          +
          public static final java.lang.String ANYTYPE_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          ANYTYPE_TYPE

          +
          public static final com.sun.btrace.org.objectweb.asm.Type ANYTYPE_TYPE
          +
        • +
        + + + +
          +
        • +

          CLASS_DESC

          +
          public static final java.lang.String CLASS_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          CLASS_TYPE

          +
          public static final com.sun.btrace.org.objectweb.asm.Type CLASS_TYPE
          +
        • +
        + + + +
          +
        • +

          STRING_INTERNAL

          +
          public static final java.lang.String STRING_INTERNAL
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          STRING_DESC

          +
          public static final java.lang.String STRING_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          STRING_TYPE

          +
          public static final com.sun.btrace.org.objectweb.asm.Type STRING_TYPE
          +
        • +
        + + + +
          +
        • +

          STRING_BUILDER_INTERNAL

          +
          public static final java.lang.String STRING_BUILDER_INTERNAL
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          STRING_BUILDER_DESC

          +
          public static final java.lang.String STRING_BUILDER_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          STRING_BUILDER_TYPE

          +
          public static final com.sun.btrace.org.objectweb.asm.Type STRING_BUILDER_TYPE
          +
        • +
        + + + + + + + +
          +
        • +

          BOOLEAN_DESC

          +
          public static final java.lang.String BOOLEAN_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + + + + + +
          +
        • +

          THROWABLE_INTERNAL

          +
          public static final java.lang.String THROWABLE_INTERNAL
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          THROWABLE_DESC

          +
          public static final java.lang.String THROWABLE_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          THROWABLE_TYPE

          +
          public static final com.sun.btrace.org.objectweb.asm.Type THROWABLE_TYPE
          +
        • +
        + + + +
          +
        • +

          BTRACERT_INTERNAL

          +
          public static final java.lang.String BTRACERT_INTERNAL
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          BTRACERT_DESC

          +
          public static final java.lang.String BTRACERT_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          BTRACERT_TYPE

          +
          public static final com.sun.btrace.org.objectweb.asm.Type BTRACERT_TYPE
          +
        • +
        + + + +
          +
        • +

          THREAD_LOCAL_INTERNAL

          +
          public static final java.lang.String THREAD_LOCAL_INTERNAL
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          THREAD_LOCAL_DESC

          +
          public static final java.lang.String THREAD_LOCAL_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          THREAD_LOCAL_TYPE

          +
          public static final com.sun.btrace.org.objectweb.asm.Type THREAD_LOCAL_TYPE
          +
        • +
        + + + +
          +
        • +

          BTRACE_UTILS

          +
          public static final java.lang.String BTRACE_UTILS
          +
        • +
        + + + +
          +
        • +

          SERVICE

          +
          public static final java.lang.String SERVICE
          +
        • +
        + + + +
          +
        • +

          BTRACE_DESC

          +
          public static final java.lang.String BTRACE_DESC
          +
        • +
        + + + +
          +
        • +

          ONMETHOD_DESC

          +
          public static final java.lang.String ONMETHOD_DESC
          +
        • +
        + + + +
          +
        • +

          BTRACE_PROBECLASSNAME_DESC

          +
          public static final java.lang.String BTRACE_PROBECLASSNAME_DESC
          +
        • +
        + + + +
          +
        • +

          BTRACE_PROBEMETHODNAME_DESC

          +
          public static final java.lang.String BTRACE_PROBEMETHODNAME_DESC
          +
        • +
        + + + +
          +
        • +

          ONTIMER_DESC

          +
          public static final java.lang.String ONTIMER_DESC
          +
        • +
        + + + +
          +
        • +

          ONEVENT_DESC

          +
          public static final java.lang.String ONEVENT_DESC
          +
        • +
        + + + +
          +
        • +

          ONEXIT_DESC

          +
          public static final java.lang.String ONEXIT_DESC
          +
        • +
        + + + +
          +
        • +

          ONERROR_DESC

          +
          public static final java.lang.String ONERROR_DESC
          +
        • +
        + + + +
          +
        • +

          ONLOWMEMORY_DESC

          +
          public static final java.lang.String ONLOWMEMORY_DESC
          +
        • +
        + + + +
          +
        • +

          SAMPLED_DESC

          +
          public static final java.lang.String SAMPLED_DESC
          +
        • +
        + + + +
          +
        • +

          SAMPLER_DESC

          +
          public static final java.lang.String SAMPLER_DESC
          +
        • +
        + + + +
          +
        • +

          ONPROBE_DESC

          +
          public static final java.lang.String ONPROBE_DESC
          +
        • +
        + + + +
          +
        • +

          LOCATION_DESC

          +
          public static final java.lang.String LOCATION_DESC
          +
        • +
        + + + +
          +
        • +

          LEVEL_DESC

          +
          public static final java.lang.String LEVEL_DESC
          +
        • +
        + + + +
          +
        • +

          WHERE_DESC

          +
          public static final java.lang.String WHERE_DESC
          +
        • +
        + + + +
          +
        • +

          KIND_DESC

          +
          public static final java.lang.String KIND_DESC
          +
        • +
        + + + +
          +
        • +

          INJECTED_DESC

          +
          public static final java.lang.String INJECTED_DESC
          +
        • +
        + + + +
          +
        • +

          RETURN_DESC

          +
          public static final java.lang.String RETURN_DESC
          +
        • +
        + + + +
          +
        • +

          SELF_DESC

          +
          public static final java.lang.String SELF_DESC
          +
        • +
        + + + +
          +
        • +

          TARGETMETHOD_DESC

          +
          public static final java.lang.String TARGETMETHOD_DESC
          +
        • +
        + + + +
          +
        • +

          TARGETINSTANCE_DESC

          +
          public static final java.lang.String TARGETINSTANCE_DESC
          +
        • +
        + + + +
          +
        • +

          DURATION_DESC

          +
          public static final java.lang.String DURATION_DESC
          +
        • +
        + + + +
          +
        • +

          ARGSMAP_DESC

          +
          public static final java.lang.String ARGSMAP_DESC
          +
        • +
        + + + +
          +
        • +

          REGEX_SPECIFIER

          +
          public static final java.util.regex.Pattern REGEX_SPECIFIER
          +
        • +
        + + + +
          +
        • +

          JAVA_LANG_THREAD_LOCAL

          +
          public static final java.lang.String JAVA_LANG_THREAD_LOCAL
          +
        • +
        + + + +
          +
        • +

          JAVA_LANG_THREAD_LOCAL_GET

          +
          public static final java.lang.String JAVA_LANG_THREAD_LOCAL_GET
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          JAVA_LANG_THREAD_LOCAL_GET_DESC

          +
          public static final java.lang.String JAVA_LANG_THREAD_LOCAL_GET_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          JAVA_LANG_THREAD_LOCAL_SET

          +
          public static final java.lang.String JAVA_LANG_THREAD_LOCAL_SET
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          JAVA_LANG_THREAD_LOCAL_SET_DESC

          +
          public static final java.lang.String JAVA_LANG_THREAD_LOCAL_SET_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          NUMBER_INTERNAL

          +
          public static final java.lang.String NUMBER_INTERNAL
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          INTEGER_BOXED_INTERNAL

          +
          public static final java.lang.String INTEGER_BOXED_INTERNAL
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          INTEGER_BOXED_DESC

          +
          public static final java.lang.String INTEGER_BOXED_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          SHORT_BOXED_INTERNAL

          +
          public static final java.lang.String SHORT_BOXED_INTERNAL
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          SHORT_BOXED_DESC

          +
          public static final java.lang.String SHORT_BOXED_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          LONG_BOXED_INTERNAL

          +
          public static final java.lang.String LONG_BOXED_INTERNAL
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          LONG_BOXED_DESC

          +
          public static final java.lang.String LONG_BOXED_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          FLOAT_BOXED_INTERNAL

          +
          public static final java.lang.String FLOAT_BOXED_INTERNAL
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          FLOAT_BOXED_DESC

          +
          public static final java.lang.String FLOAT_BOXED_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          DOUBLE_BOXED_INTERNAL

          +
          public static final java.lang.String DOUBLE_BOXED_INTERNAL
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          DOUBLE_BOXED_DESC

          +
          public static final java.lang.String DOUBLE_BOXED_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          BYTE_BOXED_INTERNAL

          +
          public static final java.lang.String BYTE_BOXED_INTERNAL
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          BYTE_BOXED_DESC

          +
          public static final java.lang.String BYTE_BOXED_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          BOOLEAN_BOXED_INTERNAL

          +
          public static final java.lang.String BOOLEAN_BOXED_INTERNAL
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          BOOLEAN_BOXED_DESC

          +
          public static final java.lang.String BOOLEAN_BOXED_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          CHARACTER_BOXED_INTERNAL

          +
          public static final java.lang.String CHARACTER_BOXED_INTERNAL
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          CHARACTER_BOXED_DESC

          +
          public static final java.lang.String CHARACTER_BOXED_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          BOX_VALUEOF

          +
          public static final java.lang.String BOX_VALUEOF
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          BOX_BOOLEAN_DESC

          +
          public static final java.lang.String BOX_BOOLEAN_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          BOX_CHARACTER_DESC

          +
          public static final java.lang.String BOX_CHARACTER_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          BOX_BYTE_DESC

          +
          public static final java.lang.String BOX_BYTE_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          BOX_SHORT_DESC

          +
          public static final java.lang.String BOX_SHORT_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          BOX_INTEGER_DESC

          +
          public static final java.lang.String BOX_INTEGER_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          BOX_LONG_DESC

          +
          public static final java.lang.String BOX_LONG_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          BOX_FLOAT_DESC

          +
          public static final java.lang.String BOX_FLOAT_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          BOX_DOUBLE_DESC

          +
          public static final java.lang.String BOX_DOUBLE_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          BOOLEAN_VALUE

          +
          public static final java.lang.String BOOLEAN_VALUE
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          CHAR_VALUE

          +
          public static final java.lang.String CHAR_VALUE
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          BYTE_VALUE

          +
          public static final java.lang.String BYTE_VALUE
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          SHORT_VALUE

          +
          public static final java.lang.String SHORT_VALUE
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + + + + + +
          +
        • +

          LONG_VALUE

          +
          public static final java.lang.String LONG_VALUE
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          FLOAT_VALUE

          +
          public static final java.lang.String FLOAT_VALUE
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          DOUBLE_VALUE

          +
          public static final java.lang.String DOUBLE_VALUE
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          BOOLEAN_VALUE_DESC

          +
          public static final java.lang.String BOOLEAN_VALUE_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          CHAR_VALUE_DESC

          +
          public static final java.lang.String CHAR_VALUE_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          BYTE_VALUE_DESC

          +
          public static final java.lang.String BYTE_VALUE_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          SHORT_VALUE_DESC

          +
          public static final java.lang.String SHORT_VALUE_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          INT_VALUE_DESC

          +
          public static final java.lang.String INT_VALUE_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          LONG_VALUE_DESC

          +
          public static final java.lang.String LONG_VALUE_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          FLOAT_VALUE_DESC

          +
          public static final java.lang.String FLOAT_VALUE_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          DOUBLE_VALUE_DESC

          +
          public static final java.lang.String DOUBLE_VALUE_DESC
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          EMBEDDED_BTRACE_SECTION_HEADER

          +
          public static final java.lang.String EMBEDDED_BTRACE_SECTION_HEADER
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          BTRACE_LEVEL_FLD

          +
          public static final java.lang.String BTRACE_LEVEL_FLD
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Constants

          +
          public Constants()
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/InstrumentUtils.html b/misc/btrace/javadoc/com/sun/btrace/runtime/InstrumentUtils.html new file mode 100644 index 00000000..baf65688 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/InstrumentUtils.html @@ -0,0 +1,429 @@ + + + + + +InstrumentUtils (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class InstrumentUtils

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.runtime.InstrumentUtils
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class InstrumentUtils
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        InstrumentUtils() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static voidaccept(com.sun.btrace.runtime.BTraceClassReader reader, + com.sun.btrace.org.objectweb.asm.ClassVisitor visitor) 
        static voidaccept(com.sun.btrace.runtime.BTraceClassReader reader, + com.sun.btrace.org.objectweb.asm.ClassVisitor visitor, + int flags) 
        static java.lang.StringarrayDescriptorFor(int typeCode) 
        static voidcollectHierarchyClosure(java.lang.ClassLoader cl, + java.lang.String type, + java.util.Set<java.lang.String> closure, + boolean useInternal) +
        Collects the type hierarchy into the provided list, sorted from the actual type to root.
        +
        static voidcollectHierarchyClosure(java.lang.ClassLoader cl, + java.lang.String type, + java.util.Set<java.lang.String> closure, + boolean useInternal, + boolean ifcs) +
        Collects the type hierarchy into the provided list, sorted from the actual type to root.
        +
        static booleanisAssignable(com.sun.btrace.org.objectweb.asm.Type[] args1, + com.sun.btrace.org.objectweb.asm.Type[] args2, + java.lang.ClassLoader cl, + boolean exactTypeCheck) 
        static booleanisAssignable(com.sun.btrace.org.objectweb.asm.Type left, + com.sun.btrace.org.objectweb.asm.Type right, + java.lang.ClassLoader cl, + boolean exactTypeCheck) 
        static com.sun.btrace.org.objectweb.asm.ClassWriternewClassWriter() 
        static com.sun.btrace.org.objectweb.asm.ClassWriternewClassWriter(boolean computeFrames) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          InstrumentUtils

          +
          public InstrumentUtils()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          collectHierarchyClosure

          +
          public static void collectHierarchyClosure(java.lang.ClassLoader cl,
          +                                           java.lang.String type,
          +                                           java.util.Set<java.lang.String> closure,
          +                                           boolean useInternal)
          +
          Collects the type hierarchy into the provided list, sorted from the actual type to root. + Common superclasses may be present multiple times (eg. java.lang.Object) + It will use the associated classloader to locate the class file resources.
          +
          +
          Parameters:
          +
          cl - the associated classloader
          +
          type - the type to compute the hierarchy closure for (either Java or internal name format)
          +
          closure - the ordered set to store the closure in
          +
          useInternal - should internal types names be used in the closure
          +
          +
        • +
        + + + +
          +
        • +

          collectHierarchyClosure

          +
          public static void collectHierarchyClosure(java.lang.ClassLoader cl,
          +                                           java.lang.String type,
          +                                           java.util.Set<java.lang.String> closure,
          +                                           boolean useInternal,
          +                                           boolean ifcs)
          +
          Collects the type hierarchy into the provided list, sorted from the actual type to root. + Common superclasses may be present multiple times (eg. java.lang.Object) + It will use the associated classloader to locate the class file resources.
          +
          +
          Parameters:
          +
          cl - the associated classloader
          +
          type - the type to compute the hierarchy closure for (either Java or internal name format)
          +
          closure - the ordered set to store the closure in
          +
          useInternal - should internal types names be used in the closure
          +
          +
        • +
        + + + +
          +
        • +

          isAssignable

          +
          public static boolean isAssignable(com.sun.btrace.org.objectweb.asm.Type left,
          +                                   com.sun.btrace.org.objectweb.asm.Type right,
          +                                   java.lang.ClassLoader cl,
          +                                   boolean exactTypeCheck)
          +
        • +
        + + + +
          +
        • +

          isAssignable

          +
          public static boolean isAssignable(com.sun.btrace.org.objectweb.asm.Type[] args1,
          +                                   com.sun.btrace.org.objectweb.asm.Type[] args2,
          +                                   java.lang.ClassLoader cl,
          +                                   boolean exactTypeCheck)
          +
        • +
        + + + +
          +
        • +

          arrayDescriptorFor

          +
          public static java.lang.String arrayDescriptorFor(int typeCode)
          +
        • +
        + + + +
          +
        • +

          accept

          +
          public static void accept(com.sun.btrace.runtime.BTraceClassReader reader,
          +                          com.sun.btrace.org.objectweb.asm.ClassVisitor visitor)
          +
        • +
        + + + +
          +
        • +

          accept

          +
          public static void accept(com.sun.btrace.runtime.BTraceClassReader reader,
          +                          com.sun.btrace.org.objectweb.asm.ClassVisitor visitor,
          +                          int flags)
          +
        • +
        + + + +
          +
        • +

          newClassWriter

          +
          public static com.sun.btrace.org.objectweb.asm.ClassWriter newClassWriter()
          +
        • +
        + + + +
          +
        • +

          newClassWriter

          +
          public static com.sun.btrace.org.objectweb.asm.ClassWriter newClassWriter(boolean computeFrames)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/InstrumentingClassVisitor.html b/misc/btrace/javadoc/com/sun/btrace/runtime/InstrumentingClassVisitor.html new file mode 100644 index 00000000..147df1d1 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/InstrumentingClassVisitor.html @@ -0,0 +1,371 @@ + + + + + +InstrumentingClassVisitor (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class InstrumentingClassVisitor

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.org.objectweb.asm.ClassVisitor
      • +
      • +
          +
        • com.sun.btrace.runtime.InstrumentingClassVisitor
        • +
        +
      • +
      +
    • +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Field Summary

        +
          +
        • + + +

          Fields inherited from class com.sun.btrace.org.objectweb.asm.ClassVisitor

          +api, cv
        • +
        +
      • +
      + + + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        MethodInstrumentorHelpermethodHelper() 
        voidvisit(int version, + int access, + java.lang.String name, + java.lang.String signature, + java.lang.String superName, + java.lang.String[] ifcs) 
        InstrumentingMethodVisitorvisitMethod(int access, + java.lang.String name, + java.lang.String desc, + java.lang.String sig, + java.lang.String[] exceptions) 
        +
          +
        • + + +

          Methods inherited from class com.sun.btrace.org.objectweb.asm.ClassVisitor

          +visitAnnotation, visitAttribute, visitEnd, visitField, visitInnerClass, visitOuterClass, visitSource, visitTypeAnnotation
        • +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          InstrumentingClassVisitor

          +
          public InstrumentingClassVisitor(int i)
          +
        • +
        + + + +
          +
        • +

          InstrumentingClassVisitor

          +
          public InstrumentingClassVisitor(int i,
          +                                 com.sun.btrace.org.objectweb.asm.ClassVisitor cv)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          visit

          +
          public void visit(int version,
          +                  int access,
          +                  java.lang.String name,
          +                  java.lang.String signature,
          +                  java.lang.String superName,
          +                  java.lang.String[] ifcs)
          +
          +
          Overrides:
          +
          visit in class com.sun.btrace.org.objectweb.asm.ClassVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitMethod

          +
          public InstrumentingMethodVisitor visitMethod(int access,
          +                                              java.lang.String name,
          +                                              java.lang.String desc,
          +                                              java.lang.String sig,
          +                                              java.lang.String[] exceptions)
          +
          +
          Overrides:
          +
          visitMethod in class com.sun.btrace.org.objectweb.asm.ClassVisitor
          +
          +
        • +
        + + + + +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/InstrumentingMethodVisitor.html b/misc/btrace/javadoc/com/sun/btrace/runtime/InstrumentingMethodVisitor.html new file mode 100644 index 00000000..8781e29b --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/InstrumentingMethodVisitor.html @@ -0,0 +1,825 @@ + + + + + +InstrumentingMethodVisitor (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class InstrumentingMethodVisitor

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.org.objectweb.asm.MethodVisitor
      • +
      • +
          +
        • com.sun.btrace.runtime.InstrumentingMethodVisitor
        • +
        +
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      MethodInstrumentorHelper
      +
      +
      +
      +
      public final class InstrumentingMethodVisitor
      +extends com.sun.btrace.org.objectweb.asm.MethodVisitor
      +implements MethodInstrumentorHelper
      +
      A method visitor providing support for introducing new local variables in bytecode + recomputing stackmap frames as necessary. It also provides an API for downstream + visitors to hint insertion of stackmap frames at required locations.
      +
    • +
    +
    +
    +
      +
    • + + + +
        +
      • + + +

        Field Summary

        +
          +
        • + + +

          Fields inherited from class com.sun.btrace.org.objectweb.asm.MethodVisitor

          +api, mv
        • +
        +
      • +
      + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        InstrumentingMethodVisitor(int access, + java.lang.String owner, + java.lang.String name, + java.lang.String desc, + com.sun.btrace.org.objectweb.asm.MethodVisitor mv) 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        voidaddTryCatchHandler(com.sun.btrace.org.objectweb.asm.Label start, + com.sun.btrace.org.objectweb.asm.Label handler) 
        voidinsertFrameAppendStack(com.sun.btrace.org.objectweb.asm.Label l, + com.sun.btrace.org.objectweb.asm.Type... stackTypes) 
        voidinsertFrameReplaceStack(com.sun.btrace.org.objectweb.asm.Label l, + com.sun.btrace.org.objectweb.asm.Type... stackTypes) 
        voidinsertFrameSameStack(com.sun.btrace.org.objectweb.asm.Label l) 
        intnewVar(com.sun.btrace.org.objectweb.asm.Type t) 
        intstoreAsNew() 
        voidvisitFieldInsn(int opcode, + java.lang.String owner, + java.lang.String name, + java.lang.String desc) 
        voidvisitFrame(int type, + int nLocal, + java.lang.Object[] local, + int nStack, + java.lang.Object[] stack) 
        voidvisitIincInsn(int var, + int increment) 
        voidvisitInsn(int opcode) 
        voidvisitIntInsn(int opcode, + int operand) 
        voidvisitInvokeDynamicInsn(java.lang.String name, + java.lang.String desc, + com.sun.btrace.org.objectweb.asm.Handle handle, + java.lang.Object... bsmArgs) 
        voidvisitJumpInsn(int opcode, + com.sun.btrace.org.objectweb.asm.Label label) 
        voidvisitLabel(com.sun.btrace.org.objectweb.asm.Label label) 
        voidvisitLdcInsn(java.lang.Object o) 
        voidvisitLocalVariable(java.lang.String name, + java.lang.String desc, + java.lang.String signature, + com.sun.btrace.org.objectweb.asm.Label start, + com.sun.btrace.org.objectweb.asm.Label end, + int index) 
        com.sun.btrace.org.objectweb.asm.AnnotationVisitorvisitLocalVariableAnnotation(int typeRef, + com.sun.btrace.org.objectweb.asm.TypePath typePath, + com.sun.btrace.org.objectweb.asm.Label[] start, + com.sun.btrace.org.objectweb.asm.Label[] end, + int[] index, + java.lang.String desc, + boolean visible) 
        voidvisitLookupSwitchInsn(com.sun.btrace.org.objectweb.asm.Label label, + int[] ints, + com.sun.btrace.org.objectweb.asm.Label[] labels) 
        voidvisitMaxs(int maxStack, + int maxLocals) 
        voidvisitMethodInsn(int opcode, + java.lang.String owner, + java.lang.String name, + java.lang.String desc, + boolean itfc) 
        voidvisitMultiANewArrayInsn(java.lang.String type, + int dims) 
        voidvisitTableSwitchInsn(int i, + int i1, + com.sun.btrace.org.objectweb.asm.Label label, + com.sun.btrace.org.objectweb.asm.Label... labels) 
        voidvisitTryCatchBlock(com.sun.btrace.org.objectweb.asm.Label start, + com.sun.btrace.org.objectweb.asm.Label end, + com.sun.btrace.org.objectweb.asm.Label handler, + java.lang.String exception) 
        voidvisitTypeInsn(int opcode, + java.lang.String type) 
        voidvisitVarInsn(int opcode, + int var) 
        +
          +
        • + + +

          Methods inherited from class com.sun.btrace.org.objectweb.asm.MethodVisitor

          +visitAnnotation, visitAnnotationDefault, visitAttribute, visitCode, visitEnd, visitInsnAnnotation, visitLineNumber, visitMethodInsn, visitParameter, visitParameterAnnotation, visitTryCatchAnnotation, visitTypeAnnotation
        • +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          InstrumentingMethodVisitor

          +
          public InstrumentingMethodVisitor(int access,
          +                                  java.lang.String owner,
          +                                  java.lang.String name,
          +                                  java.lang.String desc,
          +                                  com.sun.btrace.org.objectweb.asm.MethodVisitor mv)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          visitFrame

          +
          public void visitFrame(int type,
          +                       int nLocal,
          +                       java.lang.Object[] local,
          +                       int nStack,
          +                       java.lang.Object[] stack)
          +
          +
          Overrides:
          +
          visitFrame in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitMultiANewArrayInsn

          +
          public void visitMultiANewArrayInsn(java.lang.String type,
          +                                    int dims)
          +
          +
          Overrides:
          +
          visitMultiANewArrayInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitLookupSwitchInsn

          +
          public void visitLookupSwitchInsn(com.sun.btrace.org.objectweb.asm.Label label,
          +                                  int[] ints,
          +                                  com.sun.btrace.org.objectweb.asm.Label[] labels)
          +
          +
          Overrides:
          +
          visitLookupSwitchInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitTableSwitchInsn

          +
          public void visitTableSwitchInsn(int i,
          +                                 int i1,
          +                                 com.sun.btrace.org.objectweb.asm.Label label,
          +                                 com.sun.btrace.org.objectweb.asm.Label... labels)
          +
          +
          Overrides:
          +
          visitTableSwitchInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitLdcInsn

          +
          public void visitLdcInsn(java.lang.Object o)
          +
          +
          Overrides:
          +
          visitLdcInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitJumpInsn

          +
          public void visitJumpInsn(int opcode,
          +                          com.sun.btrace.org.objectweb.asm.Label label)
          +
          +
          Overrides:
          +
          visitJumpInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitInvokeDynamicInsn

          +
          public void visitInvokeDynamicInsn(java.lang.String name,
          +                                   java.lang.String desc,
          +                                   com.sun.btrace.org.objectweb.asm.Handle handle,
          +                                   java.lang.Object... bsmArgs)
          +
          +
          Overrides:
          +
          visitInvokeDynamicInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitMethodInsn

          +
          public void visitMethodInsn(int opcode,
          +                            java.lang.String owner,
          +                            java.lang.String name,
          +                            java.lang.String desc,
          +                            boolean itfc)
          +
          +
          Overrides:
          +
          visitMethodInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitFieldInsn

          +
          public void visitFieldInsn(int opcode,
          +                           java.lang.String owner,
          +                           java.lang.String name,
          +                           java.lang.String desc)
          +
          +
          Overrides:
          +
          visitFieldInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitTypeInsn

          +
          public void visitTypeInsn(int opcode,
          +                          java.lang.String type)
          +
          +
          Overrides:
          +
          visitTypeInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitVarInsn

          +
          public void visitVarInsn(int opcode,
          +                         int var)
          +
          +
          Overrides:
          +
          visitVarInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitIntInsn

          +
          public void visitIntInsn(int opcode,
          +                         int operand)
          +
          +
          Overrides:
          +
          visitIntInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitInsn

          +
          public void visitInsn(int opcode)
          +
          +
          Overrides:
          +
          visitInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitIincInsn

          +
          public void visitIincInsn(int var,
          +                          int increment)
          +
          +
          Overrides:
          +
          visitIincInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitLocalVariable

          +
          public void visitLocalVariable(java.lang.String name,
          +                               java.lang.String desc,
          +                               java.lang.String signature,
          +                               com.sun.btrace.org.objectweb.asm.Label start,
          +                               com.sun.btrace.org.objectweb.asm.Label end,
          +                               int index)
          +
          +
          Overrides:
          +
          visitLocalVariable in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitLocalVariableAnnotation

          +
          public com.sun.btrace.org.objectweb.asm.AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
          +                                                                                       com.sun.btrace.org.objectweb.asm.TypePath typePath,
          +                                                                                       com.sun.btrace.org.objectweb.asm.Label[] start,
          +                                                                                       com.sun.btrace.org.objectweb.asm.Label[] end,
          +                                                                                       int[] index,
          +                                                                                       java.lang.String desc,
          +                                                                                       boolean visible)
          +
          +
          Overrides:
          +
          visitLocalVariableAnnotation in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitTryCatchBlock

          +
          public void visitTryCatchBlock(com.sun.btrace.org.objectweb.asm.Label start,
          +                               com.sun.btrace.org.objectweb.asm.Label end,
          +                               com.sun.btrace.org.objectweb.asm.Label handler,
          +                               java.lang.String exception)
          +
          +
          Overrides:
          +
          visitTryCatchBlock in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitLabel

          +
          public void visitLabel(com.sun.btrace.org.objectweb.asm.Label label)
          +
          +
          Overrides:
          +
          visitLabel in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitMaxs

          +
          public void visitMaxs(int maxStack,
          +                      int maxLocals)
          +
          +
          Overrides:
          +
          visitMaxs in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          insertFrameReplaceStack

          +
          public final void insertFrameReplaceStack(com.sun.btrace.org.objectweb.asm.Label l,
          +                                          com.sun.btrace.org.objectweb.asm.Type... stackTypes)
          +
          +
          Specified by:
          +
          insertFrameReplaceStack in interface MethodInstrumentorHelper
          +
          +
        • +
        + + + +
          +
        • +

          insertFrameAppendStack

          +
          public void insertFrameAppendStack(com.sun.btrace.org.objectweb.asm.Label l,
          +                                   com.sun.btrace.org.objectweb.asm.Type... stackTypes)
          +
          +
          Specified by:
          +
          insertFrameAppendStack in interface MethodInstrumentorHelper
          +
          +
        • +
        + + + + + + + +
          +
        • +

          addTryCatchHandler

          +
          public void addTryCatchHandler(com.sun.btrace.org.objectweb.asm.Label start,
          +                               com.sun.btrace.org.objectweb.asm.Label handler)
          +
          +
          Specified by:
          +
          addTryCatchHandler in interface MethodInstrumentorHelper
          +
          +
        • +
        + + + + + + + +
          +
        • +

          newVar

          +
          public final int newVar(com.sun.btrace.org.objectweb.asm.Type t)
          +
          +
          Specified by:
          +
          newVar in interface MethodInstrumentorHelper
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/Instrumentor.html b/misc/btrace/javadoc/com/sun/btrace/runtime/Instrumentor.html new file mode 100644 index 00000000..a9df0902 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/Instrumentor.html @@ -0,0 +1,333 @@ + + + + + +Instrumentor (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class Instrumentor

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.org.objectweb.asm.ClassVisitor
      • +
      • +
          +
        • com.sun.btrace.runtime.Instrumentor
        • +
        +
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public class Instrumentor
      +extends com.sun.btrace.org.objectweb.asm.ClassVisitor
      +
      This instruments a probed class with BTrace probe + action class.
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Summary

        +
          +
        • + + +

          Fields inherited from class com.sun.btrace.org.objectweb.asm.ClassVisitor

          +api, cv
        • +
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        booleanhasMatch() 
        voidvisit(int version, + int access, + java.lang.String name, + java.lang.String signature, + java.lang.String superName, + java.lang.String[] interfaces) 
        voidvisitEnd() 
        com.sun.btrace.org.objectweb.asm.MethodVisitorvisitMethod(int access, + java.lang.String name, + java.lang.String desc, + java.lang.String signature, + java.lang.String[] exceptions) 
        +
          +
        • + + +

          Methods inherited from class com.sun.btrace.org.objectweb.asm.ClassVisitor

          +visitAnnotation, visitAttribute, visitField, visitInnerClass, visitOuterClass, visitSource, visitTypeAnnotation
        • +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          hasMatch

          +
          public final boolean hasMatch()
          +
        • +
        + + + +
          +
        • +

          visit

          +
          public void visit(int version,
          +                  int access,
          +                  java.lang.String name,
          +                  java.lang.String signature,
          +                  java.lang.String superName,
          +                  java.lang.String[] interfaces)
          +
          +
          Overrides:
          +
          visit in class com.sun.btrace.org.objectweb.asm.ClassVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitMethod

          +
          public com.sun.btrace.org.objectweb.asm.MethodVisitor visitMethod(int access,
          +                                                                  java.lang.String name,
          +                                                                  java.lang.String desc,
          +                                                                  java.lang.String signature,
          +                                                                  java.lang.String[] exceptions)
          +
          +
          Overrides:
          +
          visitMethod in class com.sun.btrace.org.objectweb.asm.ClassVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitEnd

          +
          public void visitEnd()
          +
          +
          Overrides:
          +
          visitEnd in class com.sun.btrace.org.objectweb.asm.ClassVisitor
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/Level.html b/misc/btrace/javadoc/com/sun/btrace/runtime/Level.html new file mode 100644 index 00000000..93f4b747 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/Level.html @@ -0,0 +1,282 @@ + + + + + +Level (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class Level

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.runtime.Level
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public class Level
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        Level() 
        +
      • +
      + + +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Level

          +
          public Level()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getValue

          +
          public Interval getValue()
          +
        • +
        + + + +
          +
        • +

          fromString

          +
          public static Level fromString(java.lang.String s)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/Location.html b/misc/btrace/javadoc/com/sun/btrace/runtime/Location.html new file mode 100644 index 00000000..23f0d62c --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/Location.html @@ -0,0 +1,462 @@ + + + + + +Location (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class Location

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.runtime.Location
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public class Location
      +extends java.lang.Object
      +
      This class is used to store data of the annotation + com.sun.btrace.annotations.Location. We can not read the + Location annotation using reflection API [because we strip + @OnMethod annotated methods before defineClass]. Instead, + we read Location annotation while parsing the BTrace class and + store the data in an instance of this class. Please note that + the get/set methods have to be in sync with Location annotation.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Location

          +
          public Location()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          setClazz

          +
          public void setClazz(java.lang.String clazz)
          +
        • +
        + + + +
          +
        • +

          getClazz

          +
          public java.lang.String getClazz()
          +
        • +
        + + + +
          +
        • +

          setMethod

          +
          public void setMethod(java.lang.String method)
          +
        • +
        + + + +
          +
        • +

          getMethod

          +
          public java.lang.String getMethod()
          +
        • +
        + + + +
          +
        • +

          setField

          +
          public void setField(java.lang.String field)
          +
        • +
        + + + +
          +
        • +

          getField

          +
          public java.lang.String getField()
          +
        • +
        + + + +
          +
        • +

          setLine

          +
          public void setLine(int line)
          +
        • +
        + + + +
          +
        • +

          getLine

          +
          public int getLine()
          +
        • +
        + + + +
          +
        • +

          setType

          +
          public void setType(java.lang.String type)
          +
        • +
        + + + +
          +
        • +

          getType

          +
          public java.lang.String getType()
          +
        • +
        + + + +
          +
        • +

          setValue

          +
          public void setValue(Kind value)
          +
        • +
        + + + +
          +
        • +

          getValue

          +
          public Kind getValue()
          +
        • +
        + + + +
          +
        • +

          setWhere

          +
          public void setWhere(Where where)
          +
        • +
        + + + +
          +
        • +

          getWhere

          +
          public Where getWhere()
          +
        • +
        + + + +
          +
        • +

          toString

          +
          public java.lang.String toString()
          +
          +
          Overrides:
          +
          toString in class java.lang.Object
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/MethodInstrumentorHelper.Accessor.html b/misc/btrace/javadoc/com/sun/btrace/runtime/MethodInstrumentorHelper.Accessor.html new file mode 100644 index 00000000..6b79e572 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/MethodInstrumentorHelper.Accessor.html @@ -0,0 +1,227 @@ + + + + + +MethodInstrumentorHelper.Accessor (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Interface MethodInstrumentorHelper.Accessor

    +
    +
    +
    + +
    +
    + +
    +
    + +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/MethodInstrumentorHelper.html b/misc/btrace/javadoc/com/sun/btrace/runtime/MethodInstrumentorHelper.html new file mode 100644 index 00000000..a5d52294 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/MethodInstrumentorHelper.html @@ -0,0 +1,313 @@ + + + + + +MethodInstrumentorHelper (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Interface MethodInstrumentorHelper

    +
    +
    +
    + +
    +
    +
      +
    • + + + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Abstract Methods 
        Modifier and TypeMethod and Description
        voidaddTryCatchHandler(com.sun.btrace.org.objectweb.asm.Label start, + com.sun.btrace.org.objectweb.asm.Label handler) 
        voidinsertFrameAppendStack(com.sun.btrace.org.objectweb.asm.Label l, + com.sun.btrace.org.objectweb.asm.Type... stack) 
        voidinsertFrameReplaceStack(com.sun.btrace.org.objectweb.asm.Label l, + com.sun.btrace.org.objectweb.asm.Type... stack) 
        voidinsertFrameSameStack(com.sun.btrace.org.objectweb.asm.Label l) 
        intnewVar(com.sun.btrace.org.objectweb.asm.Type t) 
        intstoreAsNew() 
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          insertFrameReplaceStack

          +
          void insertFrameReplaceStack(com.sun.btrace.org.objectweb.asm.Label l,
          +                             com.sun.btrace.org.objectweb.asm.Type... stack)
          +
        • +
        + + + +
          +
        • +

          insertFrameAppendStack

          +
          void insertFrameAppendStack(com.sun.btrace.org.objectweb.asm.Label l,
          +                            com.sun.btrace.org.objectweb.asm.Type... stack)
          +
        • +
        + + + +
          +
        • +

          insertFrameSameStack

          +
          void insertFrameSameStack(com.sun.btrace.org.objectweb.asm.Label l)
          +
        • +
        + + + +
          +
        • +

          addTryCatchHandler

          +
          void addTryCatchHandler(com.sun.btrace.org.objectweb.asm.Label start,
          +                        com.sun.btrace.org.objectweb.asm.Label handler)
          +
        • +
        + + + +
          +
        • +

          newVar

          +
          int newVar(com.sun.btrace.org.objectweb.asm.Type t)
          +
        • +
        + + + +
          +
        • +

          storeAsNew

          +
          int storeAsNew()
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/OnMethod.html b/misc/btrace/javadoc/com/sun/btrace/runtime/OnMethod.html new file mode 100644 index 00000000..aad51ddb --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/OnMethod.html @@ -0,0 +1,930 @@ + + + + + +OnMethod (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class OnMethod

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.runtime.OnMethod
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class OnMethod
      +extends java.lang.Object
      +
      This class is used to store data of the annotation + com.sun.btrace.annotations.OnMethod. We can not read the + OnMethod annotation using reflection API [because we strip + @OnMethod annotated methods before defineClass]. Instead, + we read OnMethod annotation while parsing the BTrace class and + store the data in an instance of this class. Please note that + the get/set methods have to be in sync with OnMethod annotation.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + + + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          copyFrom

          +
          public void copyFrom(OnMethod other)
          +
        • +
        + + + +
          +
        • +

          getClazz

          +
          public java.lang.String getClazz()
          +
        • +
        + + + +
          +
        • +

          setClazz

          +
          public void setClazz(java.lang.String clazz)
          +
        • +
        + + + +
          +
        • +

          getMethod

          +
          public java.lang.String getMethod()
          +
        • +
        + + + +
          +
        • +

          setMethod

          +
          public void setMethod(java.lang.String method)
          +
        • +
        + + + +
          +
        • +

          isExactTypeMatch

          +
          public boolean isExactTypeMatch()
          +
        • +
        + + + +
          +
        • +

          setExactTypeMatch

          +
          public void setExactTypeMatch(boolean exactTypeMatch)
          +
        • +
        + + + +
          +
        • +

          getType

          +
          public java.lang.String getType()
          +
        • +
        + + + +
          +
        • +

          setType

          +
          public void setType(java.lang.String type)
          +
        • +
        + + + +
          +
        • +

          getLocation

          +
          public Location getLocation()
          +
        • +
        + + + +
          +
        • +

          setLocation

          +
          public void setLocation(Location loc)
          +
        • +
        + + + +
          +
        • +

          getTargetName

          +
          public java.lang.String getTargetName()
          +
        • +
        + + + +
          +
        • +

          setTargetName

          +
          public void setTargetName(java.lang.String name)
          +
        • +
        + + + +
          +
        • +

          getTargetDescriptor

          +
          public java.lang.String getTargetDescriptor()
          +
        • +
        + + + +
          +
        • +

          setTargetDescriptor

          +
          public void setTargetDescriptor(java.lang.String desc)
          +
        • +
        + + + +
          +
        • +

          setSamplerKind

          +
          public void setSamplerKind(Sampled.Sampler kind)
          +
        • +
        + + + + + + + +
          +
        • +

          setSamplerMean

          +
          public void setSamplerMean(int mean)
          +
        • +
        + + + +
          +
        • +

          getSamplerMean

          +
          public int getSamplerMean()
          +
        • +
        + + + +
          +
        • +

          getLevel

          +
          public Level getLevel()
          +
        • +
        + + + +
          +
        • +

          setLevel

          +
          public void setLevel(Level level)
          +
        • +
        + + + + + + + +
          +
        • +

          isClassRegexMatcher

          +
          public boolean isClassRegexMatcher()
          +
        • +
        + + + +
          +
        • +

          isMethodRegexMatcher

          +
          public boolean isMethodRegexMatcher()
          +
        • +
        + + + +
          +
        • +

          isClassAnnotationMatcher

          +
          public boolean isClassAnnotationMatcher()
          +
        • +
        + + + +
          +
        • +

          isMethodAnnotationMatcher

          +
          public boolean isMethodAnnotationMatcher()
          +
        • +
        + + + +
          +
        • +

          isSubtypeMatcher

          +
          public boolean isSubtypeMatcher()
          +
        • +
        + + + +
          +
        • +

          isCalled

          +
          public boolean isCalled()
          +
        • +
        + + + +
          +
        • +

          setCalled

          +
          public void setCalled()
          +
        • +
        + + + +
          +
        • +

          toString

          +
          public java.lang.String toString()
          +
          +
          Overrides:
          +
          toString in class java.lang.Object
          +
          +
        • +
        + + + +
          +
        • +

          getSelfParameter

          +
          public final int getSelfParameter()
          +
        • +
        + + + +
          +
        • +

          setSelfParameter

          +
          public final void setSelfParameter(int selfParameter)
          +
        • +
        + + + +
          +
        • +

          getClassNameParameter

          +
          public final int getClassNameParameter()
          +
        • +
        + + + +
          +
        • +

          setClassNameParameter

          +
          public final void setClassNameParameter(int classNameParameter)
          +
        • +
        + + + +
          +
        • +

          getMethodParameter

          +
          public final int getMethodParameter()
          +
        • +
        + + + +
          +
        • +

          setMethodParameter

          +
          public final void setMethodParameter(int methodParameter)
          +
        • +
        + + + +
          +
        • +

          isMethodFqn

          +
          public final boolean isMethodFqn()
          +
        • +
        + + + +
          +
        • +

          setMethodFqn

          +
          public final void setMethodFqn(boolean val)
          +
        • +
        + + + +
          +
        • +

          isTargetMethodOrFieldFqn

          +
          public final boolean isTargetMethodOrFieldFqn()
          +
        • +
        + + + +
          +
        • +

          setTargetMethodOrFieldFqn

          +
          public final void setTargetMethodOrFieldFqn(boolean val)
          +
        • +
        + + + +
          +
        • +

          getReturnParameter

          +
          public final int getReturnParameter()
          +
        • +
        + + + +
          +
        • +

          setReturnParameter

          +
          public final void setReturnParameter(int returnParameter)
          +
        • +
        + + + +
          +
        • +

          getTargetMethodOrFieldParameter

          +
          public final int getTargetMethodOrFieldParameter()
          +
        • +
        + + + +
          +
        • +

          setTargetMethodOrFieldParameter

          +
          public final void setTargetMethodOrFieldParameter(int calledMethodParameter)
          +
        • +
        + + + +
          +
        • +

          getTargetInstanceParameter

          +
          public final int getTargetInstanceParameter()
          +
        • +
        + + + +
          +
        • +

          setTargetInstanceParameter

          +
          public final void setTargetInstanceParameter(int calledInstanceParameter)
          +
        • +
        + + + +
          +
        • +

          getDurationParameter

          +
          public final int getDurationParameter()
          +
        • +
        + + + +
          +
        • +

          setDurationParameter

          +
          public final void setDurationParameter(int durationParameter)
          +
        • +
        + + + +
          +
        • +

          copyFrom

          +
          public final void copyFrom(com.sun.btrace.runtime.SpecialParameterHolder other)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/OnProbe.html b/misc/btrace/javadoc/com/sun/btrace/runtime/OnProbe.html new file mode 100644 index 00000000..7a2e433c --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/OnProbe.html @@ -0,0 +1,678 @@ + + + + + +OnProbe (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class OnProbe

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.runtime.OnProbe
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class OnProbe
      +extends java.lang.Object
      +
      This class is used to store data of the annotation + com.sun.btrace.annotations.OnProbe. We can not read the + OnMethod annotation using reflection API [because we strip + @OnProbe annotated methods before defineClass]. Instead, + we read OnProbe annotation while parsing the BTrace class and + store the data in an instance of this class. Please note that + the get/set methods have to be in sync with OnProbe annotation.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + + + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getNamespace

          +
          public java.lang.String getNamespace()
          +
        • +
        + + + +
          +
        • +

          setNamespace

          +
          public void setNamespace(java.lang.String namespace)
          +
        • +
        + + + +
          +
        • +

          getName

          +
          public java.lang.String getName()
          +
        • +
        + + + +
          +
        • +

          setName

          +
          public void setName(java.lang.String name)
          +
        • +
        + + + +
          +
        • +

          getTargetName

          +
          public java.lang.String getTargetName()
          +
        • +
        + + + +
          +
        • +

          setTargetName

          +
          public void setTargetName(java.lang.String name)
          +
        • +
        + + + +
          +
        • +

          getTargetDescriptor

          +
          public java.lang.String getTargetDescriptor()
          +
        • +
        + + + +
          +
        • +

          setTargetDescriptor

          +
          public void setTargetDescriptor(java.lang.String desc)
          +
        • +
        + + + +
          +
        • +

          getOnMethods

          +
          public java.util.Collection<OnMethod> getOnMethods()
          +
        • +
        + + + +
          +
        • +

          setOnMethods

          +
          public void setOnMethods(java.util.Collection<OnMethod> om)
          +
        • +
        + + + +
          +
        • +

          copyFrom

          +
          public void copyFrom(OnProbe other)
          +
        • +
        + + + + + + + +
          +
        • +

          getSelfParameter

          +
          public final int getSelfParameter()
          +
        • +
        + + + +
          +
        • +

          setSelfParameter

          +
          public final void setSelfParameter(int selfParameter)
          +
        • +
        + + + +
          +
        • +

          getClassNameParameter

          +
          public final int getClassNameParameter()
          +
        • +
        + + + +
          +
        • +

          setClassNameParameter

          +
          public final void setClassNameParameter(int classNameParameter)
          +
        • +
        + + + +
          +
        • +

          getMethodParameter

          +
          public final int getMethodParameter()
          +
        • +
        + + + +
          +
        • +

          setMethodParameter

          +
          public final void setMethodParameter(int methodParameter)
          +
        • +
        + + + +
          +
        • +

          isMethodFqn

          +
          public final boolean isMethodFqn()
          +
        • +
        + + + +
          +
        • +

          setMethodFqn

          +
          public final void setMethodFqn(boolean val)
          +
        • +
        + + + +
          +
        • +

          isTargetMethodOrFieldFqn

          +
          public final boolean isTargetMethodOrFieldFqn()
          +
        • +
        + + + +
          +
        • +

          setTargetMethodOrFieldFqn

          +
          public final void setTargetMethodOrFieldFqn(boolean val)
          +
        • +
        + + + +
          +
        • +

          getReturnParameter

          +
          public final int getReturnParameter()
          +
        • +
        + + + +
          +
        • +

          setReturnParameter

          +
          public final void setReturnParameter(int returnParameter)
          +
        • +
        + + + +
          +
        • +

          getTargetMethodOrFieldParameter

          +
          public final int getTargetMethodOrFieldParameter()
          +
        • +
        + + + +
          +
        • +

          setTargetMethodOrFieldParameter

          +
          public final void setTargetMethodOrFieldParameter(int calledMethodParameter)
          +
        • +
        + + + +
          +
        • +

          getTargetInstanceParameter

          +
          public final int getTargetInstanceParameter()
          +
        • +
        + + + +
          +
        • +

          setTargetInstanceParameter

          +
          public final void setTargetInstanceParameter(int calledInstanceParameter)
          +
        • +
        + + + +
          +
        • +

          getDurationParameter

          +
          public final int getDurationParameter()
          +
        • +
        + + + +
          +
        • +

          setDurationParameter

          +
          public final void setDurationParameter(int durationParameter)
          +
        • +
        + + + +
          +
        • +

          copyFrom

          +
          public final void copyFrom(com.sun.btrace.runtime.SpecialParameterHolder other)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/ProbeDescriptor.html b/misc/btrace/javadoc/com/sun/btrace/runtime/ProbeDescriptor.html new file mode 100644 index 00000000..59423454 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/ProbeDescriptor.html @@ -0,0 +1,321 @@ + + + + + +ProbeDescriptor (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class ProbeDescriptor

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.runtime.ProbeDescriptor
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public class ProbeDescriptor
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        ProbeDescriptor() 
        +
      • +
      + + +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          ProbeDescriptor

          +
          public ProbeDescriptor()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getNamespace

          +
          public java.lang.String getNamespace()
          +
        • +
        + + + +
          +
        • +

          setNamespace

          +
          public void setNamespace(java.lang.String namespace)
          +
        • +
        + + + +
          +
        • +

          getProbes

          +
          public java.util.Collection<OnProbe> getProbes()
          +
        • +
        + + + +
          +
        • +

          setProbes

          +
          public void setProbes(java.util.Collection<OnProbe> probes)
          +
        • +
        + + + +
          +
        • +

          findProbe

          +
          public OnProbe findProbe(java.lang.String name)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/TypeUtils.html b/misc/btrace/javadoc/com/sun/btrace/runtime/TypeUtils.html new file mode 100644 index 00000000..061638df --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/TypeUtils.html @@ -0,0 +1,483 @@ + + + + + +TypeUtils (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class TypeUtils

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.runtime.TypeUtils
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class TypeUtils
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Summary

        + + + + + + + + + + + + + + +
        Fields 
        Modifier and TypeField and Description
        static com.sun.btrace.org.objectweb.asm.TypeanyTypeArray 
        static com.sun.btrace.org.objectweb.asm.TypeobjectArrayType 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static java.lang.StringdeclarationToDescriptor(java.lang.String decl) 
        static java.lang.StringdescriptorToSimplified(java.lang.String desc, + java.lang.String owner, + java.lang.String name) 
        static com.sun.btrace.org.objectweb.asm.TypegetArrayType(int arrayOpcode) 
        static com.sun.btrace.org.objectweb.asm.TypegetElementType(int arrayOpcode) 
        static java.lang.StringgetJavaType(java.lang.String desc) 
        static booleanisAnyType(com.sun.btrace.org.objectweb.asm.Type t) 
        static booleanisAnyTypeArray(com.sun.btrace.org.objectweb.asm.Type t) 
        static booleanisArray(com.sun.btrace.org.objectweb.asm.Type t) 
        static booleanisObject(com.sun.btrace.org.objectweb.asm.Type t) 
        static booleanisObjectOrAnyType(com.sun.btrace.org.objectweb.asm.Type t) 
        static booleanisPrimitive(java.lang.String typeDesc) 
        static booleanisPrimitive(com.sun.btrace.org.objectweb.asm.Type t) 
        static booleanisString(com.sun.btrace.org.objectweb.asm.Type t) 
        static booleanisThrowable(com.sun.btrace.org.objectweb.asm.Type t) 
        static booleanisVoid(com.sun.btrace.org.objectweb.asm.Type t) 
        static java.lang.StringobjectOrArrayType(java.lang.String type) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Detail

        + + + +
          +
        • +

          objectArrayType

          +
          public static final com.sun.btrace.org.objectweb.asm.Type objectArrayType
          +
        • +
        + + + +
          +
        • +

          anyTypeArray

          +
          public static final com.sun.btrace.org.objectweb.asm.Type anyTypeArray
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          isPrimitive

          +
          public static boolean isPrimitive(java.lang.String typeDesc)
          +
        • +
        + + + +
          +
        • +

          isPrimitive

          +
          public static boolean isPrimitive(com.sun.btrace.org.objectweb.asm.Type t)
          +
        • +
        + + + +
          +
        • +

          isAnyType

          +
          public static boolean isAnyType(com.sun.btrace.org.objectweb.asm.Type t)
          +
        • +
        + + + +
          +
        • +

          isAnyTypeArray

          +
          public static boolean isAnyTypeArray(com.sun.btrace.org.objectweb.asm.Type t)
          +
        • +
        + + + +
          +
        • +

          isObject

          +
          public static boolean isObject(com.sun.btrace.org.objectweb.asm.Type t)
          +
        • +
        + + + +
          +
        • +

          isObjectOrAnyType

          +
          public static boolean isObjectOrAnyType(com.sun.btrace.org.objectweb.asm.Type t)
          +
        • +
        + + + +
          +
        • +

          isString

          +
          public static boolean isString(com.sun.btrace.org.objectweb.asm.Type t)
          +
        • +
        + + + +
          +
        • +

          isArray

          +
          public static boolean isArray(com.sun.btrace.org.objectweb.asm.Type t)
          +
        • +
        + + + +
          +
        • +

          isThrowable

          +
          public static boolean isThrowable(com.sun.btrace.org.objectweb.asm.Type t)
          +
        • +
        + + + +
          +
        • +

          isVoid

          +
          public static boolean isVoid(com.sun.btrace.org.objectweb.asm.Type t)
          +
        • +
        + + + +
          +
        • +

          getArrayType

          +
          public static com.sun.btrace.org.objectweb.asm.Type getArrayType(int arrayOpcode)
          +
        • +
        + + + +
          +
        • +

          getElementType

          +
          public static com.sun.btrace.org.objectweb.asm.Type getElementType(int arrayOpcode)
          +
        • +
        + + + +
          +
        • +

          declarationToDescriptor

          +
          public static java.lang.String declarationToDescriptor(java.lang.String decl)
          +
        • +
        + + + +
          +
        • +

          descriptorToSimplified

          +
          public static java.lang.String descriptorToSimplified(java.lang.String desc,
          +                                                      java.lang.String owner,
          +                                                      java.lang.String name)
          +
        • +
        + + + +
          +
        • +

          getJavaType

          +
          public static java.lang.String getJavaType(java.lang.String desc)
          +
        • +
        + + + +
          +
        • +

          objectOrArrayType

          +
          public static java.lang.String objectOrArrayType(java.lang.String type)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/Verifier.html b/misc/btrace/javadoc/com/sun/btrace/runtime/Verifier.html new file mode 100644 index 00000000..0edd3d7f --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/Verifier.html @@ -0,0 +1,512 @@ + + + + + +Verifier (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime
    +

    Class Verifier

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.org.objectweb.asm.ClassVisitor
      • +
      • +
          +
        • com.sun.btrace.runtime.Verifier
        • +
        +
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public class Verifier
      +extends com.sun.btrace.org.objectweb.asm.ClassVisitor
      +
      This class verifies that a BTrace program is safe + and well-formed. + Also it fills the onMethods and onProbes structures with the data taken from + the annotations
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Summary

        +
          +
        • + + +

          Fields inherited from class com.sun.btrace.org.objectweb.asm.ClassVisitor

          +api, cv
        • +
        +
      • +
      + + + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        java.lang.StringgetClassName() 
        booleanisClassRenamed() 
        static voidreportError(java.lang.String err) 
        static voidreportError(java.lang.String err, + java.lang.String msg) 
        voidvisit(int version, + int access, + java.lang.String name, + java.lang.String signature, + java.lang.String superName, + java.lang.String[] interfaces) 
        com.sun.btrace.org.objectweb.asm.AnnotationVisitorvisitAnnotation(java.lang.String type, + boolean visible) 
        voidvisitEnd() 
        com.sun.btrace.org.objectweb.asm.FieldVisitorvisitField(int access, + java.lang.String name, + java.lang.String desc, + java.lang.String signature, + java.lang.Object value) 
        voidvisitInnerClass(java.lang.String name, + java.lang.String outerName, + java.lang.String innerName, + int access) 
        com.sun.btrace.org.objectweb.asm.MethodVisitorvisitMethod(int access, + java.lang.String methodName, + java.lang.String methodDesc, + java.lang.String signature, + java.lang.String[] exceptions) 
        voidvisitOuterClass(java.lang.String owner, + java.lang.String name, + java.lang.String desc) 
        +
          +
        • + + +

          Methods inherited from class com.sun.btrace.org.objectweb.asm.ClassVisitor

          +visitAttribute, visitSource, visitTypeAnnotation
        • +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + + + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          isClassRenamed

          +
          public boolean isClassRenamed()
          +
        • +
        + + + +
          +
        • +

          getClassName

          +
          public java.lang.String getClassName()
          +
        • +
        + + + +
          +
        • +

          visitEnd

          +
          public void visitEnd()
          +
          +
          Overrides:
          +
          visitEnd in class com.sun.btrace.org.objectweb.asm.ClassVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visit

          +
          public void visit(int version,
          +                  int access,
          +                  java.lang.String name,
          +                  java.lang.String signature,
          +                  java.lang.String superName,
          +                  java.lang.String[] interfaces)
          +
          +
          Overrides:
          +
          visit in class com.sun.btrace.org.objectweb.asm.ClassVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitAnnotation

          +
          public com.sun.btrace.org.objectweb.asm.AnnotationVisitor visitAnnotation(java.lang.String type,
          +                                                                          boolean visible)
          +
          +
          Overrides:
          +
          visitAnnotation in class com.sun.btrace.org.objectweb.asm.ClassVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitField

          +
          public com.sun.btrace.org.objectweb.asm.FieldVisitor visitField(int access,
          +                                                                java.lang.String name,
          +                                                                java.lang.String desc,
          +                                                                java.lang.String signature,
          +                                                                java.lang.Object value)
          +
          +
          Overrides:
          +
          visitField in class com.sun.btrace.org.objectweb.asm.ClassVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitInnerClass

          +
          public void visitInnerClass(java.lang.String name,
          +                            java.lang.String outerName,
          +                            java.lang.String innerName,
          +                            int access)
          +
          +
          Overrides:
          +
          visitInnerClass in class com.sun.btrace.org.objectweb.asm.ClassVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitMethod

          +
          public com.sun.btrace.org.objectweb.asm.MethodVisitor visitMethod(int access,
          +                                                                  java.lang.String methodName,
          +                                                                  java.lang.String methodDesc,
          +                                                                  java.lang.String signature,
          +                                                                  java.lang.String[] exceptions)
          +
          +
          Overrides:
          +
          visitMethod in class com.sun.btrace.org.objectweb.asm.ClassVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitOuterClass

          +
          public void visitOuterClass(java.lang.String owner,
          +                            java.lang.String name,
          +                            java.lang.String desc)
          +
          +
          Overrides:
          +
          visitOuterClass in class com.sun.btrace.org.objectweb.asm.ClassVisitor
          +
          +
        • +
        + + + +
          +
        • +

          reportError

          +
          public static void reportError(java.lang.String err)
          +
        • +
        + + + +
          +
        • +

          reportError

          +
          public static void reportError(java.lang.String err,
          +                               java.lang.String msg)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/instr/ArrayAccessInstrumentor.html b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/ArrayAccessInstrumentor.html new file mode 100644 index 00000000..c4a92dc3 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/ArrayAccessInstrumentor.html @@ -0,0 +1,433 @@ + + + + + +ArrayAccessInstrumentor (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime.instr
    +

    Class ArrayAccessInstrumentor

    +
    +
    + +
    +
      +
    • +
      +
      +
      public class ArrayAccessInstrumentor
      +extends MethodInstrumentor
      +
      This visitor helps in inserting code whenever + an array access is done. Code to insert on array + access may be decided by derived class. By default, + this class inserts code to print array access.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          ArrayAccessInstrumentor

          +
          public ArrayAccessInstrumentor(java.lang.ClassLoader cl,
          +                               com.sun.btrace.org.objectweb.asm.MethodVisitor mv,
          +                               MethodInstrumentorHelper mHelper,
          +                               java.lang.String parentClz,
          +                               java.lang.String superClz,
          +                               int access,
          +                               java.lang.String name,
          +                               java.lang.String desc)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + + + + + +
          +
        • +

          locationTypeMatches

          +
          protected final boolean locationTypeMatches(Location loc,
          +                                            com.sun.btrace.org.objectweb.asm.Type arrtype,
          +                                            com.sun.btrace.org.objectweb.asm.Type itemType)
          +
        • +
        + + + +
          +
        • +

          onBeforeArrayLoad

          +
          protected void onBeforeArrayLoad(int opcode)
          +
        • +
        + + + +
          +
        • +

          onAfterArrayLoad

          +
          protected void onAfterArrayLoad(int opcode)
          +
        • +
        + + + +
          +
        • +

          onBeforeArrayStore

          +
          protected void onBeforeArrayStore(int opcode)
          +
        • +
        + + + +
          +
        • +

          onAfterArrayStore

          +
          protected void onAfterArrayStore(int opcode)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/instr/ArrayAllocInstrumentor.html b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/ArrayAllocInstrumentor.html new file mode 100644 index 00000000..7be359d0 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/ArrayAllocInstrumentor.html @@ -0,0 +1,434 @@ + + + + + +ArrayAllocInstrumentor (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime.instr
    +

    Class ArrayAllocInstrumentor

    +
    +
    + +
    +
      +
    • +
      +
      +
      public class ArrayAllocInstrumentor
      +extends MethodInstrumentor
      +
      This visitor helps in inserting code whenever an array + is allocated. The code to insert on method entry may be + decided by derived class. By default, this class inserts + code to print allocated array objects.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          ArrayAllocInstrumentor

          +
          public ArrayAllocInstrumentor(java.lang.ClassLoader cl,
          +                              com.sun.btrace.org.objectweb.asm.MethodVisitor mv,
          +                              MethodInstrumentorHelper mHelper,
          +                              java.lang.String parentClz,
          +                              java.lang.String superClz,
          +                              int access,
          +                              java.lang.String name,
          +                              java.lang.String desc)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          visitIntInsn

          +
          public void visitIntInsn(int opcode,
          +                         int operand)
          +
          +
          Overrides:
          +
          visitIntInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitTypeInsn

          +
          public void visitTypeInsn(int opcode,
          +                          java.lang.String desc)
          +
          +
          Overrides:
          +
          visitTypeInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitMultiANewArrayInsn

          +
          public void visitMultiANewArrayInsn(java.lang.String desc,
          +                                    int dims)
          +
          +
          Overrides:
          +
          visitMultiANewArrayInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          onBeforeArrayNew

          +
          protected void onBeforeArrayNew(java.lang.String desc,
          +                                int dims)
          +
        • +
        + + + +
          +
        • +

          onAfterArrayNew

          +
          protected void onAfterArrayNew(java.lang.String desc,
          +                               int dims)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/instr/CatchInstrumentor.html b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/CatchInstrumentor.html new file mode 100644 index 00000000..681c56a6 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/CatchInstrumentor.html @@ -0,0 +1,400 @@ + + + + + +CatchInstrumentor (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime.instr
    +

    Class CatchInstrumentor

    +
    +
    + +
    +
      +
    • +
      +
      +
      public class CatchInstrumentor
      +extends MethodInstrumentor
      +
      This visitor helps in inserting code whenever an exception + is caught or finally block is reached. The code to insert on + exception catch or finally may be decided by derived class. + By default, this class inserts code to print a message.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          CatchInstrumentor

          +
          public CatchInstrumentor(java.lang.ClassLoader cl,
          +                         com.sun.btrace.org.objectweb.asm.MethodVisitor mv,
          +                         MethodInstrumentorHelper mHelper,
          +                         java.lang.String parentClz,
          +                         java.lang.String superClz,
          +                         int access,
          +                         java.lang.String name,
          +                         java.lang.String desc)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          visitLabel

          +
          public void visitLabel(com.sun.btrace.org.objectweb.asm.Label label)
          +
          +
          Overrides:
          +
          visitLabel in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitTryCatchBlock

          +
          public void visitTryCatchBlock(com.sun.btrace.org.objectweb.asm.Label start,
          +                               com.sun.btrace.org.objectweb.asm.Label end,
          +                               com.sun.btrace.org.objectweb.asm.Label handler,
          +                               java.lang.String type)
          +
          +
          Overrides:
          +
          visitTryCatchBlock in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          onCatch

          +
          protected void onCatch(java.lang.String type)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/instr/ErrorReturnInstrumentor.html b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/ErrorReturnInstrumentor.html new file mode 100644 index 00000000..e290e47b --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/ErrorReturnInstrumentor.html @@ -0,0 +1,453 @@ + + + + + +ErrorReturnInstrumentor (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime.instr
    +

    Class ErrorReturnInstrumentor

    +
    +
    + +
    +
      +
    • +
      +
      Direct Known Subclasses:
      +
      MethodEntryExitInstrumentor
      +
      +
      +
      +
      public class ErrorReturnInstrumentor
      +extends MethodReturnInstrumentor
      +
      This visitor helps in inserting code whenever a method + "returns" because of an exception (i.e., no exception + handler in the method and so it's frame poped). The code + to insert on method error return may be decided by derived + class. By default, this class inserts code to print message + to say "no handler here".
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          ErrorReturnInstrumentor

          +
          public ErrorReturnInstrumentor(java.lang.ClassLoader cl,
          +                               com.sun.btrace.org.objectweb.asm.MethodVisitor mv,
          +                               MethodInstrumentorHelper mHelper,
          +                               java.lang.String parentClz,
          +                               java.lang.String superClz,
          +                               int access,
          +                               java.lang.String name,
          +                               java.lang.String desc)
          +
        • +
        +
      • +
      + + +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/instr/FieldAccessInstrumentor.html b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/FieldAccessInstrumentor.html new file mode 100644 index 00000000..be87dac7 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/FieldAccessInstrumentor.html @@ -0,0 +1,474 @@ + + + + + +FieldAccessInstrumentor (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime.instr
    +

    Class FieldAccessInstrumentor

    +
    +
    + +
    +
      +
    • +
      +
      +
      public class FieldAccessInstrumentor
      +extends MethodInstrumentor
      +
      This visitor helps in inserting code whenever an field access + is done. The code to insert on field access may be decided by + derived class. By default, this class inserts code to print + the field access.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Field Detail

        + + + +
          +
        • +

          isStaticAccess

          +
          protected boolean isStaticAccess
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          FieldAccessInstrumentor

          +
          public FieldAccessInstrumentor(java.lang.ClassLoader cl,
          +                               com.sun.btrace.org.objectweb.asm.MethodVisitor mv,
          +                               MethodInstrumentorHelper mHelper,
          +                               java.lang.String parentClz,
          +                               java.lang.String superClz,
          +                               int access,
          +                               java.lang.String name,
          +                               java.lang.String desc)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          visitFieldInsn

          +
          public void visitFieldInsn(int opcode,
          +                           java.lang.String owner,
          +                           java.lang.String name,
          +                           java.lang.String desc)
          +
          +
          Overrides:
          +
          visitFieldInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          onBeforeGetField

          +
          protected void onBeforeGetField(int opcode,
          +                                java.lang.String owner,
          +                                java.lang.String name,
          +                                java.lang.String desc)
          +
        • +
        + + + +
          +
        • +

          onAfterGetField

          +
          protected void onAfterGetField(int opcode,
          +                               java.lang.String owner,
          +                               java.lang.String name,
          +                               java.lang.String desc)
          +
        • +
        + + + +
          +
        • +

          onBeforePutField

          +
          protected void onBeforePutField(int opcode,
          +                                java.lang.String owner,
          +                                java.lang.String name,
          +                                java.lang.String desc)
          +
        • +
        + + + +
          +
        • +

          onAfterPutField

          +
          protected void onAfterPutField(int opcode,
          +                               java.lang.String owner,
          +                               java.lang.String name,
          +                               java.lang.String desc)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/instr/LineNumberInstrumentor.html b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/LineNumberInstrumentor.html new file mode 100644 index 00000000..3eaec1a7 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/LineNumberInstrumentor.html @@ -0,0 +1,392 @@ + + + + + +LineNumberInstrumentor (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime.instr
    +

    Class LineNumberInstrumentor

    +
    +
    + +
    +
      +
    • +
      +
      +
      public class LineNumberInstrumentor
      +extends MethodInstrumentor
      +
      This visitor helps in inserting code whenever a source + line is reached. The code to insert on line number may + be decided by derived class. By default, this class + inserts code to print the line.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          LineNumberInstrumentor

          +
          public LineNumberInstrumentor(java.lang.ClassLoader cl,
          +                              com.sun.btrace.org.objectweb.asm.MethodVisitor mv,
          +                              MethodInstrumentorHelper mHelper,
          +                              java.lang.String parentClz,
          +                              java.lang.String superClz,
          +                              int access,
          +                              java.lang.String name,
          +                              java.lang.String desc)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          visitLineNumber

          +
          public void visitLineNumber(int line,
          +                            com.sun.btrace.org.objectweb.asm.Label start)
          +
          +
          Overrides:
          +
          visitLineNumber in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          onBeforeLine

          +
          protected void onBeforeLine(int line)
          +
        • +
        + + + +
          +
        • +

          onAfterLine

          +
          protected void onAfterLine(int line)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/instr/MethodCallInstrumentor.html b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/MethodCallInstrumentor.html new file mode 100644 index 00000000..8b6ccc25 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/MethodCallInstrumentor.html @@ -0,0 +1,423 @@ + + + + + +MethodCallInstrumentor (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime.instr
    +

    Class MethodCallInstrumentor

    +
    +
    + +
    +
      +
    • +
      +
      +
      public class MethodCallInstrumentor
      +extends MethodInstrumentor
      +
      This visitor helps in inserting code whenever a method call + is done. The code to insert on method calls may be decided by + derived class. By default, this class inserts code to print + the called method.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          MethodCallInstrumentor

          +
          public MethodCallInstrumentor(java.lang.ClassLoader cl,
          +                              com.sun.btrace.org.objectweb.asm.MethodVisitor mv,
          +                              MethodInstrumentorHelper mHelper,
          +                              java.lang.String parentClz,
          +                              java.lang.String superClz,
          +                              int access,
          +                              java.lang.String name,
          +                              java.lang.String desc)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          visitMethodInsn

          +
          public void visitMethodInsn(int opcode,
          +                            java.lang.String owner,
          +                            java.lang.String name,
          +                            java.lang.String desc,
          +                            boolean iface)
          +
          +
          Overrides:
          +
          visitMethodInsn in class MethodInstrumentor
          +
          +
        • +
        + + + +
          +
        • +

          onBeforeCallMethod

          +
          protected void onBeforeCallMethod(int opcode,
          +                                  java.lang.String owner,
          +                                  java.lang.String name,
          +                                  java.lang.String desc)
          +
        • +
        + + + +
          +
        • +

          onAfterCallMethod

          +
          protected void onAfterCallMethod(int opcode,
          +                                 java.lang.String owner,
          +                                 java.lang.String name,
          +                                 java.lang.String desc)
          +
        • +
        + + + +
          +
        • +

          getCallId

          +
          protected int getCallId()
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/instr/MethodEntryExitInstrumentor.html b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/MethodEntryExitInstrumentor.html new file mode 100644 index 00000000..34860727 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/MethodEntryExitInstrumentor.html @@ -0,0 +1,396 @@ + + + + + +MethodEntryExitInstrumentor (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime.instr
    +

    Class MethodEntryExitInstrumentor

    +
    +
    + +
    +
      +
    • +
      +
      Direct Known Subclasses:
      +
      SynchronizedInstrumentor
      +
      +
      +
      +
      public class MethodEntryExitInstrumentor
      +extends ErrorReturnInstrumentor
      +
      Instruments method entry and exit points. For exit, both normal and abnormal + (exception) return points are instrumented. Subclasses can decide what code + is inserted at entry/exit points.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          MethodEntryExitInstrumentor

          +
          public MethodEntryExitInstrumentor(java.lang.ClassLoader cl,
          +                                   com.sun.btrace.org.objectweb.asm.MethodVisitor mv,
          +                                   MethodInstrumentorHelper mHelper,
          +                                   java.lang.String parentClz,
          +                                   java.lang.String superClz,
          +                                   int access,
          +                                   java.lang.String name,
          +                                   java.lang.String desc)
          +
        • +
        +
      • +
      + + +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/instr/MethodEntryInstrumentor.html b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/MethodEntryInstrumentor.html new file mode 100644 index 00000000..4485ee05 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/MethodEntryInstrumentor.html @@ -0,0 +1,381 @@ + + + + + +MethodEntryInstrumentor (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime.instr
    +

    Class MethodEntryInstrumentor

    +
    +
    + +
    +
      +
    • +
      +
      Direct Known Subclasses:
      +
      MethodReturnInstrumentor
      +
      +
      +
      +
      public class MethodEntryInstrumentor
      +extends MethodInstrumentor
      +
      This visitor helps in inserting code whenever a method + is entered. The code to insert on method entry may be + decided by derived class. By default, this class inserts + code to print name and signature of the method entered.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          MethodEntryInstrumentor

          +
          public MethodEntryInstrumentor(java.lang.ClassLoader cl,
          +                               com.sun.btrace.org.objectweb.asm.MethodVisitor mv,
          +                               MethodInstrumentorHelper mHelper,
          +                               java.lang.String parentClz,
          +                               java.lang.String superClz,
          +                               int access,
          +                               java.lang.String name,
          +                               java.lang.String desc)
          +
        • +
        +
      • +
      + + +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/instr/MethodInstrumentor.AnyTypeArgProvider.html b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/MethodInstrumentor.AnyTypeArgProvider.html new file mode 100644 index 00000000..e4237f4d --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/MethodInstrumentor.AnyTypeArgProvider.html @@ -0,0 +1,326 @@ + + + + + +MethodInstrumentor.AnyTypeArgProvider (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime.instr
    +

    Class MethodInstrumentor.AnyTypeArgProvider

    +
    +
    + +
    + +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          AnyTypeArgProvider

          +
          public AnyTypeArgProvider(Assembler asm,
          +                          int index,
          +                          int basePtr)
          +
        • +
        + + + +
          +
        • +

          AnyTypeArgProvider

          +
          public AnyTypeArgProvider(Assembler asm,
          +                          int index,
          +                          int basePtr,
          +                          com.sun.btrace.org.objectweb.asm.Type[] argTypes)
          +
        • +
        +
      • +
      + + +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/instr/MethodInstrumentor.ArgumentProvider.html b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/MethodInstrumentor.ArgumentProvider.html new file mode 100644 index 00000000..3f588a0c --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/MethodInstrumentor.ArgumentProvider.html @@ -0,0 +1,341 @@ + + + + + +MethodInstrumentor.ArgumentProvider (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime.instr
    +

    Class MethodInstrumentor.ArgumentProvider

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.runtime.instr.MethodInstrumentor.ArgumentProvider
      • +
      +
    • +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Field Summary

        + + + + + + + + + + +
        Fields 
        Modifier and TypeField and Description
        protected Assemblerasm 
        +
      • +
      + + + + +
    • +
    +
    +
    +
      +
    • + + + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          ArgumentProvider

          +
          public ArgumentProvider(Assembler asm,
          +                        int index)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getIndex

          +
          public int getIndex()
          +
        • +
        + + + +
          +
        • +

          provide

          +
          public final void provide()
          +
        • +
        + + + +
          +
        • +

          doProvide

          +
          protected abstract void doProvide()
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/instr/MethodInstrumentor.ValidationResult.html b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/MethodInstrumentor.ValidationResult.html new file mode 100644 index 00000000..b5acddde --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/MethodInstrumentor.ValidationResult.html @@ -0,0 +1,409 @@ + + + + + +MethodInstrumentor.ValidationResult (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime.instr
    +

    Class MethodInstrumentor.ValidationResult

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.runtime.instr.MethodInstrumentor.ValidationResult
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Enclosing class:
      +
      MethodInstrumentor
      +
      +
      +
      +
      protected static final class MethodInstrumentor.ValidationResult
      +extends java.lang.Object
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + + + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          ValidationResult

          +
          public ValidationResult(boolean valid,
          +                        int[] argsIndex)
          +
        • +
        + + + +
          +
        • +

          ValidationResult

          +
          public ValidationResult(boolean valid)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getArgIdx

          +
          public int getArgIdx(int ptr)
          +
        • +
        + + + +
          +
        • +

          getArgCnt

          +
          public int getArgCnt()
          +
        • +
        + + + +
          +
        • +

          isAny

          +
          public boolean isAny()
          +
        • +
        + + + +
          +
        • +

          isValid

          +
          public boolean isValid()
          +
        • +
        + + + +
          +
        • +

          equals

          +
          public boolean equals(java.lang.Object obj)
          +
          +
          Overrides:
          +
          equals in class java.lang.Object
          +
          +
        • +
        + + + +
          +
        • +

          hashCode

          +
          public int hashCode()
          +
          +
          Overrides:
          +
          hashCode in class java.lang.Object
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/instr/MethodInstrumentor.html b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/MethodInstrumentor.html new file mode 100644 index 00000000..654b2029 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/MethodInstrumentor.html @@ -0,0 +1,890 @@ + + + + + +MethodInstrumentor (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime.instr
    +

    Class MethodInstrumentor

    +
    +
    + +
    + +
    +
    + +
    +
    +
      +
    • + + + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          MethodInstrumentor

          +
          public MethodInstrumentor(java.lang.ClassLoader cl,
          +                          com.sun.btrace.org.objectweb.asm.MethodVisitor mv,
          +                          MethodInstrumentorHelper mHelper,
          +                          java.lang.String parentClz,
          +                          java.lang.String superClz,
          +                          int access,
          +                          java.lang.String name,
          +                          java.lang.String desc)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          visitMethodPrologue

          +
          protected void visitMethodPrologue()
          +
        • +
        + + + +
          +
        • +

          visitCode

          +
          public final void visitCode()
          +
          +
          Overrides:
          +
          visitCode in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitMethodInsn

          +
          public void visitMethodInsn(int opcode,
          +                            java.lang.String owner,
          +                            java.lang.String name,
          +                            java.lang.String desc,
          +                            boolean iface)
          +
          +
          Overrides:
          +
          visitMethodInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitInsn

          +
          public void visitInsn(int opcode)
          +
          +
          Overrides:
          +
          visitInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          getAccess

          +
          public int getAccess()
          +
        • +
        + + + +
          +
        • +

          getName

          +
          public final java.lang.String getName()
          +
        • +
        + + + +
          +
        • +

          getName

          +
          public final java.lang.String getName(boolean fqn)
          +
        • +
        + + + +
          +
        • +

          getSkipLabel

          +
          public final com.sun.btrace.org.objectweb.asm.Label getSkipLabel()
          +
        • +
        + + + +
          +
        • +

          setSkipLabel

          +
          public final void setSkipLabel(com.sun.btrace.org.objectweb.asm.Label skipLabel)
          +
        • +
        + + + +
          +
        • +

          getDescriptor

          +
          public final java.lang.String getDescriptor()
          +
        • +
        + + + +
          +
        • +

          getReturnType

          +
          public final com.sun.btrace.org.objectweb.asm.Type getReturnType()
          +
        • +
        + + + +
          +
        • +

          addExtraTypeInfo

          +
          protected void addExtraTypeInfo(int index,
          +                                com.sun.btrace.org.objectweb.asm.Type type)
          +
        • +
        + + + + + + + + + + + +
          +
        • +

          loadThis

          +
          public void loadThis()
          +
        • +
        + + + +
          +
        • +

          backupStack

          +
          public int[] backupStack(com.sun.btrace.org.objectweb.asm.Type[] methodArgTypes,
          +                         boolean isStatic)
          +
        • +
        + + + +
          +
        • +

          restoreStack

          +
          public void restoreStack(int[] backupArgsIndexes,
          +                         boolean isStatic)
          +
        • +
        + + + +
          +
        • +

          restoreStack

          +
          public void restoreStack(int[] backupArgsIndexes,
          +                         com.sun.btrace.org.objectweb.asm.Type[] methodArgTypes,
          +                         boolean isStatic)
          +
        • +
        + + + + + + + +
          +
        • +

          localVarArg

          +
          protected final MethodInstrumentor.ArgumentProvider localVarArg(int index,
          +                                                                com.sun.btrace.org.objectweb.asm.Type type,
          +                                                                int ptr,
          +                                                                boolean boxValue)
          +
        • +
        + + + + + + + + + + + + + + + + + + + +
          +
        • +

          isStatic

          +
          protected final boolean isStatic()
          +
        • +
        + + + +
          +
        • +

          isConstructor

          +
          protected final boolean isConstructor()
          +
        • +
        + + + +
          +
        • +

          returnValue

          +
          public void returnValue()
          +
        • +
        + + + +
          +
        • +

          getParentClz

          +
          protected java.lang.String getParentClz()
          +
        • +
        + + + +
          +
        • +

          getSuperClz

          +
          protected java.lang.String getSuperClz()
          +
        • +
        + + + +
          +
        • +

          validateArguments

          +
          protected MethodInstrumentor.ValidationResult validateArguments(OnMethod om,
          +                                                                com.sun.btrace.org.objectweb.asm.Type[] actionArgTypes,
          +                                                                com.sun.btrace.org.objectweb.asm.Type[] methodArgTypes)
          +
        • +
        + + + +
          +
        • +

          levelCheck

          +
          protected com.sun.btrace.org.objectweb.asm.Label levelCheck(OnMethod om,
          +                                                            java.lang.String className)
          +
        • +
        + + + +
          +
        • +

          levelCheckBefore

          +
          protected com.sun.btrace.org.objectweb.asm.Label levelCheckBefore(OnMethod om,
          +                                                                  java.lang.String className)
          +
        • +
        + + + +
          +
        • +

          levelCheckAfter

          +
          protected com.sun.btrace.org.objectweb.asm.Label levelCheckAfter(OnMethod om,
          +                                                                 java.lang.String className)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/instr/MethodReturnInstrumentor.html b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/MethodReturnInstrumentor.html new file mode 100644 index 00000000..0cbcddae --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/MethodReturnInstrumentor.html @@ -0,0 +1,393 @@ + + + + + +MethodReturnInstrumentor (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime.instr
    +

    Class MethodReturnInstrumentor

    +
    +
    + +
    +
      +
    • +
      +
      Direct Known Subclasses:
      +
      ErrorReturnInstrumentor
      +
      +
      +
      +
      public class MethodReturnInstrumentor
      +extends MethodEntryInstrumentor
      +
      This visitor helps in inserting code whenever a method + call returns. The code to insert on method return may be + decided by derived class. By default, this class inserts + code to print name and signature of the method returned.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          MethodReturnInstrumentor

          +
          public MethodReturnInstrumentor(java.lang.ClassLoader cl,
          +                                com.sun.btrace.org.objectweb.asm.MethodVisitor mv,
          +                                MethodInstrumentorHelper mHelper,
          +                                java.lang.String parentClz,
          +                                java.lang.String superClz,
          +                                int access,
          +                                java.lang.String name,
          +                                java.lang.String desc)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + + + + + +
          +
        • +

          onMethodReturn

          +
          protected void onMethodReturn(int opcode)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/instr/ObjectAllocInstrumentor.html b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/ObjectAllocInstrumentor.html new file mode 100644 index 00000000..71d18b02 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/ObjectAllocInstrumentor.html @@ -0,0 +1,445 @@ + + + + + +ObjectAllocInstrumentor (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime.instr
    +

    Class ObjectAllocInstrumentor

    +
    +
    + +
    +
      +
    • +
      +
      +
      public class ObjectAllocInstrumentor
      +extends MethodInstrumentor
      +
      This visitor helps in inserting code whenever an object + is allocated. The code to insert on object alloc may be + decided by derived class. By default, this class inserts + code to print a message.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          ObjectAllocInstrumentor

          +
          public ObjectAllocInstrumentor(java.lang.ClassLoader cl,
          +                               com.sun.btrace.org.objectweb.asm.MethodVisitor mv,
          +                               MethodInstrumentorHelper mHelper,
          +                               java.lang.String parentClz,
          +                               java.lang.String superClz,
          +                               int access,
          +                               java.lang.String name,
          +                               java.lang.String desc)
          +
        • +
        + + + +
          +
        • +

          ObjectAllocInstrumentor

          +
          public ObjectAllocInstrumentor(java.lang.ClassLoader cl,
          +                               com.sun.btrace.org.objectweb.asm.MethodVisitor mv,
          +                               MethodInstrumentorHelper mHelper,
          +                               java.lang.String parentClz,
          +                               java.lang.String superClz,
          +                               int access,
          +                               java.lang.String name,
          +                               java.lang.String desc,
          +                               boolean needsInitialization)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          visitTypeInsn

          +
          public void visitTypeInsn(int opcode,
          +                          java.lang.String desc)
          +
          +
          Overrides:
          +
          visitTypeInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitMethodInsn

          +
          public void visitMethodInsn(int opcode,
          +                            java.lang.String owner,
          +                            java.lang.String name,
          +                            java.lang.String desc,
          +                            boolean iface)
          +
          +
          Overrides:
          +
          visitMethodInsn in class MethodInstrumentor
          +
          +
        • +
        + + + +
          +
        • +

          beforeObjectNew

          +
          protected void beforeObjectNew(java.lang.String desc)
          +
        • +
        + + + +
          +
        • +

          afterObjectNew

          +
          protected void afterObjectNew(java.lang.String desc)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/instr/SynchronizedInstrumentor.html b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/SynchronizedInstrumentor.html new file mode 100644 index 00000000..47fccec6 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/SynchronizedInstrumentor.html @@ -0,0 +1,535 @@ + + + + + +SynchronizedInstrumentor (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime.instr
    +

    Class SynchronizedInstrumentor

    +
    +
    + +
    +
      +
    • +
      +
      +
      public class SynchronizedInstrumentor
      +extends MethodEntryExitInstrumentor
      +
      This visitor helps in inserting code whenever a synchronized + method or block is about to be entered/exited. The code to insert on + synchronized method or block entry/exit may be decided by derived class. + By default, this class inserts code to print a message.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Field Detail

        + + + +
          +
        • +

          isStatic

          +
          protected final boolean isStatic
          +
        • +
        + + + +
          +
        • +

          isSyncMethod

          +
          protected final boolean isSyncMethod
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          SynchronizedInstrumentor

          +
          public SynchronizedInstrumentor(java.lang.ClassLoader cl,
          +                                com.sun.btrace.org.objectweb.asm.MethodVisitor mv,
          +                                MethodInstrumentorHelper mHelper,
          +                                java.lang.String parentClz,
          +                                java.lang.String superClz,
          +                                int access,
          +                                java.lang.String name,
          +                                java.lang.String desc)
          +
        • +
        +
      • +
      + + +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/instr/ThrowInstrumentor.html b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/ThrowInstrumentor.html new file mode 100644 index 00000000..789b7d26 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/ThrowInstrumentor.html @@ -0,0 +1,378 @@ + + + + + +ThrowInstrumentor (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime.instr
    +

    Class ThrowInstrumentor

    +
    +
    + +
    +
      +
    • +
      +
      +
      public class ThrowInstrumentor
      +extends MethodInstrumentor
      +
      This visitor helps in inserting code whenever an + exception is about to be thrown. The code to insert + on exception throw may be decided by derived class. + By default, this class inserts code to print stack + trace of the exception thrown.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          ThrowInstrumentor

          +
          public ThrowInstrumentor(java.lang.ClassLoader cl,
          +                         com.sun.btrace.org.objectweb.asm.MethodVisitor mv,
          +                         MethodInstrumentorHelper mHelper,
          +                         java.lang.String parentClz,
          +                         java.lang.String superClz,
          +                         int access,
          +                         java.lang.String name,
          +                         java.lang.String desc)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + + + + + +
          +
        • +

          onThrow

          +
          protected void onThrow()
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/instr/TypeCheckInstrumentor.html b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/TypeCheckInstrumentor.html new file mode 100644 index 00000000..497bd7ea --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/TypeCheckInstrumentor.html @@ -0,0 +1,396 @@ + + + + + +TypeCheckInstrumentor (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.runtime.instr
    +

    Class TypeCheckInstrumentor

    +
    +
    + +
    +
      +
    • +
      +
      +
      public class TypeCheckInstrumentor
      +extends MethodInstrumentor
      +
      This class helps in inserting code whenever a type check + (instanceof or checkcast) is done. The code to insert on + type check may be decided by derived class. By default, + this class inserts code to print message.
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          TypeCheckInstrumentor

          +
          public TypeCheckInstrumentor(java.lang.ClassLoader cl,
          +                             com.sun.btrace.org.objectweb.asm.MethodVisitor mv,
          +                             MethodInstrumentorHelper mHelper,
          +                             java.lang.String parentClz,
          +                             java.lang.String superClz,
          +                             int access,
          +                             java.lang.String name,
          +                             java.lang.String desc)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          visitTypeInsn

          +
          public void visitTypeInsn(int opcode,
          +                          java.lang.String desc)
          +
          +
          Overrides:
          +
          visitTypeInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          onBeforeTypeCheck

          +
          protected void onBeforeTypeCheck(int opcode,
          +                                 java.lang.String desc)
          +
        • +
        + + + +
          +
        • +

          onAfterTypeCheck

          +
          protected void onAfterTypeCheck(int opcode,
          +                                java.lang.String desc)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/instr/package-frame.html b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/package-frame.html new file mode 100644 index 00000000..405fe9f6 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/package-frame.html @@ -0,0 +1,36 @@ + + + + + +com.sun.btrace.runtime.instr (btrace 1.3.11 API) + + + + + +

    com.sun.btrace.runtime.instr

    + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/instr/package-summary.html b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/package-summary.html new file mode 100644 index 00000000..853bf5ee --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/package-summary.html @@ -0,0 +1,248 @@ + + + + + +com.sun.btrace.runtime.instr (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Package com.sun.btrace.runtime.instr

    +
    +
    + +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/instr/package-tree.html b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/package-tree.html new file mode 100644 index 00000000..4d90a3c3 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/instr/package-tree.html @@ -0,0 +1,178 @@ + + + + + +com.sun.btrace.runtime.instr Class Hierarchy (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Hierarchy For Package com.sun.btrace.runtime.instr

    +Package Hierarchies: + +
    +
    +

    Class Hierarchy

    + +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/package-frame.html b/misc/btrace/javadoc/com/sun/btrace/runtime/package-frame.html new file mode 100644 index 00000000..3fbcbaec --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/package-frame.html @@ -0,0 +1,51 @@ + + + + + +com.sun.btrace.runtime (btrace 1.3.11 API) + + + + + +

    com.sun.btrace.runtime

    + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/package-summary.html b/misc/btrace/javadoc/com/sun/btrace/runtime/package-summary.html new file mode 100644 index 00000000..7156817c --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/package-summary.html @@ -0,0 +1,301 @@ + + + + + +com.sun.btrace.runtime (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Package com.sun.btrace.runtime

    +
    +
    + +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/runtime/package-tree.html b/misc/btrace/javadoc/com/sun/btrace/runtime/package-tree.html new file mode 100644 index 00000000..5484ef3c --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/runtime/package-tree.html @@ -0,0 +1,182 @@ + + + + + +com.sun.btrace.runtime Class Hierarchy (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Hierarchy For Package com.sun.btrace.runtime

    +Package Hierarchies: + +
    +
    +

    Class Hierarchy

    + +

    Interface Hierarchy

    + +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/services/api/Service.html b/misc/btrace/javadoc/com/sun/btrace/services/api/Service.html new file mode 100644 index 00000000..5c4fcbc8 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/services/api/Service.html @@ -0,0 +1,336 @@ + + + + + +Service (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.services.api
    +

    Class Service

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.services.api.Service
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class Service
      +extends java.lang.Object
      +
      A service factory to be used to get access to the services locally + inside one particular method. The instantiated services are referenced + as local variables. +

      + For script-wide service instantiation use Injected annotation.

      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        Service() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static <S extends RuntimeService>
        S
        runtime(java.lang.Class<S> clz) +
        Creates a BTrace runtime aware service
        +
        static <S extends SimpleService>
        S
        simple(java.lang.Class<S> clz) +
        Creates a simple service via the default 0-argument constructor
        +
        static <S extends SimpleService>
        S
        simple(java.lang.String factoryMethod, + java.lang.Class<S> clz) +
        Creates a simple service via the provided factory method
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Service

          +
          public Service()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          runtime

          +
          public static <S extends RuntimeService> S runtime(java.lang.Class<S> clz)
          +
          Creates a BTrace runtime aware service
          +
          +
          Type Parameters:
          +
          S - service type
          +
          Parameters:
          +
          clz - service class
          +
          Returns:
          +
          The instance of service of the required type
          +
          +
        • +
        + + + +
          +
        • +

          simple

          +
          public static <S extends SimpleService> S simple(java.lang.Class<S> clz)
          +
          Creates a simple service via the default 0-argument constructor
          +
          +
          Type Parameters:
          +
          S - service type
          +
          Parameters:
          +
          clz - service class
          +
          Returns:
          +
          The instance of service of the required type
          +
          +
        • +
        + + + +
          +
        • +

          simple

          +
          public static <S extends SimpleService> S simple(java.lang.String factoryMethod,
          +                                                 java.lang.Class<S> clz)
          +
          Creates a simple service via the provided factory method
          +
          +
          Type Parameters:
          +
          S - service type
          +
          Parameters:
          +
          factoryMethod - factory method to use; it must be a static method declared by the service class
          +
          clz - service class
          +
          Returns:
          +
          The instance of service of the required type
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/services/api/package-frame.html b/misc/btrace/javadoc/com/sun/btrace/services/api/package-frame.html new file mode 100644 index 00000000..c92165e9 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/services/api/package-frame.html @@ -0,0 +1,20 @@ + + + + + +com.sun.btrace.services.api (btrace 1.3.11 API) + + + + + +

    com.sun.btrace.services.api

    +
    +

    Classes

    + +
    + + diff --git a/misc/btrace/javadoc/com/sun/btrace/services/api/package-summary.html b/misc/btrace/javadoc/com/sun/btrace/services/api/package-summary.html new file mode 100644 index 00000000..088338bc --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/services/api/package-summary.html @@ -0,0 +1,143 @@ + + + + + +com.sun.btrace.services.api (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Package com.sun.btrace.services.api

    +
    +
    +
      +
    • + + + + + + + + + + + + +
      Class Summary 
      ClassDescription
      Service +
      A service factory to be used to get access to the services locally + inside one particular method.
      +
      +
    • +
    +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/services/api/package-tree.html b/misc/btrace/javadoc/com/sun/btrace/services/api/package-tree.html new file mode 100644 index 00000000..5d0fe190 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/services/api/package-tree.html @@ -0,0 +1,135 @@ + + + + + +com.sun.btrace.services.api Class Hierarchy (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Hierarchy For Package com.sun.btrace.services.api

    +Package Hierarchies: + +
    +
    +

    Class Hierarchy

    +
      +
    • java.lang.Object +
        +
      • com.sun.btrace.services.api.Service
      • +
      +
    • +
    +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/services/impl/Printer.html b/misc/btrace/javadoc/com/sun/btrace/services/impl/Printer.html new file mode 100644 index 00000000..c65bbf22 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/services/impl/Printer.html @@ -0,0 +1,323 @@ + + + + + +Printer (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.services.impl
    +

    Class Printer

    +
    +
    + +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      BTraceService
      +
      +
      +
      +
      public final class Printer
      +extends RuntimeService
      +
      A very rudimentary printer service. +

      + Currently, this is a showcase for how to implement a BTraceService. + It might be extended to a grown-up printer service later on.

      +
    • +
    +
    +
    +
      +
    • + + + + + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        voidprint(java.lang.String str) 
        voidprintln() 
        voidprintln(java.lang.String str) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + + + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          print

          +
          public void print(java.lang.String str)
          +
        • +
        + + + +
          +
        • +

          println

          +
          public void println(java.lang.String str)
          +
        • +
        + + + +
          +
        • +

          println

          +
          public void println()
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/services/impl/Statsd.AlertType.html b/misc/btrace/javadoc/com/sun/btrace/services/impl/Statsd.AlertType.html new file mode 100644 index 00000000..61dee9f7 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/services/impl/Statsd.AlertType.html @@ -0,0 +1,367 @@ + + + + + +Statsd.AlertType (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.services.impl
    +

    Enum Statsd.AlertType

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • java.lang.Enum<Statsd.AlertType>
      • +
      • +
          +
        • com.sun.btrace.services.impl.Statsd.AlertType
        • +
        +
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.io.Serializable, java.lang.Comparable<Statsd.AlertType>
      +
      +
      +
      Enclosing class:
      +
      Statsd
      +
      +
      +
      +
      public static enum Statsd.AlertType
      +extends java.lang.Enum<Statsd.AlertType>
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Enum Constant Summary

        + + + + + + + + + + + + + + + + + +
        Enum Constants 
        Enum Constant and Description
        ERROR 
        INFO 
        SUCCESS 
        WARNING 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static Statsd.AlertTypevalueOf(java.lang.String name) +
        Returns the enum constant of this type with the specified name.
        +
        static Statsd.AlertType[]values() +
        Returns an array containing the constants of this enum type, in +the order they are declared.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Enum

          +clone, compareTo, equals, finalize, getDeclaringClass, hashCode, name, ordinal, toString, valueOf
        • +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +getClass, notify, notifyAll, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + + + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          values

          +
          public static Statsd.AlertType[] values()
          +
          Returns an array containing the constants of this enum type, in +the order they are declared. This method may be used to iterate +over the constants as follows: +
          +for (Statsd.AlertType c : Statsd.AlertType.values())
          +    System.out.println(c);
          +
          +
          +
          Returns:
          +
          an array containing the constants of this enum type, in the order they are declared
          +
          +
        • +
        + + + +
          +
        • +

          valueOf

          +
          public static Statsd.AlertType valueOf(java.lang.String name)
          +
          Returns the enum constant of this type with the specified name. +The string must match exactly an identifier used to declare an +enum constant in this type. (Extraneous whitespace characters are +not permitted.)
          +
          +
          Parameters:
          +
          name - the name of the enum constant to be returned.
          +
          Returns:
          +
          the enum constant with the specified name
          +
          Throws:
          +
          java.lang.IllegalArgumentException - if this enum type has no constant with the specified name
          +
          java.lang.NullPointerException - if the argument is null
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/services/impl/Statsd.Priority.html b/misc/btrace/javadoc/com/sun/btrace/services/impl/Statsd.Priority.html new file mode 100644 index 00000000..9b5ef8b9 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/services/impl/Statsd.Priority.html @@ -0,0 +1,343 @@ + + + + + +Statsd.Priority (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.services.impl
    +

    Enum Statsd.Priority

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • java.lang.Enum<Statsd.Priority>
      • +
      • +
          +
        • com.sun.btrace.services.impl.Statsd.Priority
        • +
        +
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.io.Serializable, java.lang.Comparable<Statsd.Priority>
      +
      +
      +
      Enclosing class:
      +
      Statsd
      +
      +
      +
      +
      public static enum Statsd.Priority
      +extends java.lang.Enum<Statsd.Priority>
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Enum Constant Summary

        + + + + + + + + + + + +
        Enum Constants 
        Enum Constant and Description
        LOW 
        NORMAL 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static Statsd.PriorityvalueOf(java.lang.String name) +
        Returns the enum constant of this type with the specified name.
        +
        static Statsd.Priority[]values() +
        Returns an array containing the constants of this enum type, in +the order they are declared.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Enum

          +clone, compareTo, equals, finalize, getDeclaringClass, hashCode, name, ordinal, toString, valueOf
        • +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +getClass, notify, notifyAll, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + + + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          values

          +
          public static Statsd.Priority[] values()
          +
          Returns an array containing the constants of this enum type, in +the order they are declared. This method may be used to iterate +over the constants as follows: +
          +for (Statsd.Priority c : Statsd.Priority.values())
          +    System.out.println(c);
          +
          +
          +
          Returns:
          +
          an array containing the constants of this enum type, in the order they are declared
          +
          +
        • +
        + + + +
          +
        • +

          valueOf

          +
          public static Statsd.Priority valueOf(java.lang.String name)
          +
          Returns the enum constant of this type with the specified name. +The string must match exactly an identifier used to declare an +enum constant in this type. (Extraneous whitespace characters are +not permitted.)
          +
          +
          Parameters:
          +
          name - the name of the enum constant to be returned.
          +
          Returns:
          +
          the enum constant with the specified name
          +
          Throws:
          +
          java.lang.IllegalArgumentException - if this enum type has no constant with the specified name
          +
          java.lang.NullPointerException - if the argument is null
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/services/impl/Statsd.html b/misc/btrace/javadoc/com/sun/btrace/services/impl/Statsd.html new file mode 100644 index 00000000..cdefe48d --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/services/impl/Statsd.html @@ -0,0 +1,1001 @@ + + + + + +Statsd (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.services.impl
    +

    Class Statsd

    +
    +
    + +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      BTraceService
      +
      +
      +
      +
      public final class Statsd
      +extends SimpleService
      +
      A simple way to submit statsd metrics. +

      + Use the following code to obtain an instance: +

      + 
      +  @Injected(factoryMethod = "getInstance")
      +   private static Statsd s;
      + 
      + 
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Nested Class Summary

        + + + + + + + + + + + + + + +
        Nested Classes 
        Modifier and TypeClass and Description
        static class Statsd.AlertType 
        static class Statsd.Priority 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Static Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        voidcount(java.lang.String name, + long count) +
        Adjusts the specified counter by a given delta.
        +
        voidcount(java.lang.String name, + long count, + double sampleRate) +
        Adjusts the specified counter by a given delta.
        +
        voidcount(java.lang.String name, + long count, + double sampleRate, + java.lang.String tags) +
        Adjusts the specified counter by a given delta.
        +
        voidcount(java.lang.String name, + long count, + java.lang.String tags) +
        Adjusts the specified counter by a given delta.
        +
        voiddecrement(java.lang.String name) +
        Decrease the given counter by 1
        +
        voiddecrement(java.lang.String name, + double sampleRate) +
        Decrease the given counter by 1
        +
        voiddecrement(java.lang.String name, + double sampleRate, + java.lang.String tags) +
        Decrease the given counter by 1
        +
        voiddecrement(java.lang.String name, + java.lang.String tags) +
        Decrease the given counter by 1
        +
        voidevent(java.lang.String title, + java.lang.String text) +
        Sends an event to a DogStatsD compatible collector
        +
        voidevent(java.lang.String title, + java.lang.String text, + long timestamp, + java.lang.String host, + java.lang.String group, + java.lang.String sourceType, + Statsd.Priority priority, + Statsd.AlertType alertType, + java.lang.String tags) +
        Sends an event to a DogStatsD compatible collector
        +
        voidevent(java.lang.String title, + java.lang.String text, + java.lang.String tags) +
        Sends an event to a DogStatsD compatible collector
        +
        voidgauge(java.lang.String name, + long value) +
        Sets the specified gauge to a given value.
        +
        voidgauge(java.lang.String name, + long value, + java.lang.String tags) +
        Sets the specified gauge to a given value.
        +
        static StatsdgetInstance() 
        voidhisto(java.lang.String name, + long value) +
        Adds a value to the named histogram.
        +
        voidhisto(java.lang.String name, + long value, + double sampleRate) +
        Adds a value to the named histogram.
        +
        voidhisto(java.lang.String name, + long value, + double sampleRate, + java.lang.String tags) +
        Adds a value to the named histogram.
        +
        voidhisto(java.lang.String name, + long value, + java.lang.String tags) +
        Adds a value to the named histogram.
        +
        voidincrement(java.lang.String name) +
        Increase the given counter by 1
        +
        voidincrement(java.lang.String name, + double sampleRate) +
        Increase the given counter by 1
        +
        voidincrement(java.lang.String name, + double sampleRate, + java.lang.String tags) +
        Increase the given counter by 1
        +
        voidincrement(java.lang.String name, + java.lang.String tags) +
        Increase the given counter by 1
        +
        voidtime(java.lang.String name, + long value) +
        Records the timing information for the specified metric.
        +
        voidtime(java.lang.String name, + long value, + double sampleRate) +
        Records the timing information for the specified metric.
        +
        voidtime(java.lang.String name, + long value, + double sampleRate, + java.lang.String tags) +
        Records the timing information for the specified metric.
        +
        voidtime(java.lang.String name, + long value, + java.lang.String tags) +
        Records the timing information for the specified metric.
        +
        voidunique(java.lang.String name, + java.lang.String id) +
        StatsD supports counting unique occurrences of events between flushes.
        +
        voidunique(java.lang.String name, + java.lang.String id, + java.lang.String tags) +
        StatsD supports counting unique occurrences of events between flushes.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getInstance

          +
          public static Statsd getInstance()
          +
        • +
        + + + +
          +
        • +

          increment

          +
          public void increment(java.lang.String name)
          +
          Increase the given counter by 1
          +
          +
          Parameters:
          +
          name - the counter name
          +
          +
        • +
        + + + +
          +
        • +

          increment

          +
          public void increment(java.lang.String name,
          +                      java.lang.String tags)
          +
          Increase the given counter by 1
          +
          +
          Parameters:
          +
          name - the counter name
          +
          tags - Only for DogStatsD compatible collectors. + Assigned comma delimited tags. A tag value is delimited by colon.
          +
          +
        • +
        + + + +
          +
        • +

          increment

          +
          public void increment(java.lang.String name,
          +                      double sampleRate)
          +
          Increase the given counter by 1
          +
          +
          Parameters:
          +
          name - the counter name
          +
          sampleRate - the sampling rate being employed. For example, a rate of 0.1 would + tell StatsD that this counter is being sent + sampled every 1/10th of the time.
          +
          +
        • +
        + + + +
          +
        • +

          increment

          +
          public void increment(java.lang.String name,
          +                      double sampleRate,
          +                      java.lang.String tags)
          +
          Increase the given counter by 1
          +
          +
          Parameters:
          +
          name - the counter name
          +
          sampleRate - the sampling rate being employed. For example, a rate of 0.1 would + tell StatsD that this counter is being sent + sampled every 1/10th of the time.
          +
          tags - Only for DogStatsD compatible collectors. + Assigned comma delimited tags. A tag value is delimited by colon.
          +
          +
        • +
        + + + +
          +
        • +

          decrement

          +
          public void decrement(java.lang.String name)
          +
          Decrease the given counter by 1
          +
          +
          Parameters:
          +
          name - the counter name
          +
          +
        • +
        + + + +
          +
        • +

          decrement

          +
          public void decrement(java.lang.String name,
          +                      java.lang.String tags)
          +
          Decrease the given counter by 1
          +
          +
          Parameters:
          +
          name - the counter name
          +
          tags - Only for DogStatsD compatible collectors. + Assigned comma delimited tags. A tag value is delimited by colon.
          +
          +
        • +
        + + + +
          +
        • +

          decrement

          +
          public void decrement(java.lang.String name,
          +                      double sampleRate)
          +
          Decrease the given counter by 1
          +
          +
          Parameters:
          +
          name - the counter name
          +
          sampleRate - the sampling rate being employed. For example, a rate of 0.1 would + tell StatsD that this counter is being sent + sampled every 1/10th of the time.
          +
          +
        • +
        + + + +
          +
        • +

          decrement

          +
          public void decrement(java.lang.String name,
          +                      double sampleRate,
          +                      java.lang.String tags)
          +
          Decrease the given counter by 1
          +
          +
          Parameters:
          +
          name - the counter name
          +
          sampleRate - the sampling rate being employed. For example, a rate of 0.1 would + tell StatsD that this counter is being sent + sampled every 1/10th of the time.
          +
          tags - Only for DogStatsD compatible collectors. + Assigned comma delimited tags. A tag value is delimited by colon.
          +
          +
        • +
        + + + +
          +
        • +

          count

          +
          public void count(java.lang.String name,
          +                  long count)
          +
          Adjusts the specified counter by a given delta.
          +
          +
          Parameters:
          +
          name - the name of the counter to adjust
          +
          count - the counter value
          +
          +
        • +
        + + + +
          +
        • +

          count

          +
          public void count(java.lang.String name,
          +                  long count,
          +                  java.lang.String tags)
          +
          Adjusts the specified counter by a given delta.
          +
          +
          Parameters:
          +
          name - the name of the counter to adjust
          +
          count - the counter value
          +
          tags - Only for DogStatsD compatible collectors. + Assigned comma delimited tags. A tag value is delimited by colon.
          +
          +
        • +
        + + + +
          +
        • +

          count

          +
          public void count(java.lang.String name,
          +                  long count,
          +                  double sampleRate)
          +
          Adjusts the specified counter by a given delta.
          +
          +
          Parameters:
          +
          name - the name of the counter to adjust
          +
          count - the counter value
          +
          sampleRate - the sampling rate being employed. For example, a rate of 0.1 would + tell StatsD that this counter is being sent + sampled every 1/10th of the time.
          +
          +
        • +
        + + + +
          +
        • +

          count

          +
          public void count(java.lang.String name,
          +                  long count,
          +                  double sampleRate,
          +                  java.lang.String tags)
          +
          Adjusts the specified counter by a given delta.
          +
          +
          Parameters:
          +
          name - the name of the counter to adjust
          +
          count - the counter value
          +
          sampleRate - the sampling rate being employed. For example, a rate of 0.1 would + tell StatsD that this counter is being sent + sampled every 1/10th of the time.
          +
          tags - Only for DogStatsD compatible collectors. + Assigned comma delimited tags. A tag value is delimited by colon.
          +
          +
        • +
        + + + +
          +
        • +

          gauge

          +
          public void gauge(java.lang.String name,
          +                  long value)
          +
          Sets the specified gauge to a given value.
          +
          +
          Parameters:
          +
          name - the name of the gauge to set
          +
          value - the value to set the gauge to
          +
          +
        • +
        + + + +
          +
        • +

          gauge

          +
          public void gauge(java.lang.String name,
          +                  long value,
          +                  java.lang.String tags)
          +
          Sets the specified gauge to a given value.
          +
          +
          Parameters:
          +
          name - the name of the gauge to set
          +
          value - the value to set the gauge to
          +
          tags - Only for DogStatsD compatible collectors. + Assigned comma delimited tags. A tag value is delimited by colon.
          +
          +
        • +
        + + + +
          +
        • +

          time

          +
          public void time(java.lang.String name,
          +                 long value)
          +
          Records the timing information for the specified metric.
          +
          +
          Parameters:
          +
          name - the metric name
          +
          value - the measured time
          +
          +
        • +
        + + + +
          +
        • +

          time

          +
          public void time(java.lang.String name,
          +                 long value,
          +                 double sampleRate)
          +
          Records the timing information for the specified metric.
          +
          +
          Parameters:
          +
          name - the metric name
          +
          value - the measured time
          +
          sampleRate - the sampling rate being employed. For example, a rate of 0.1 would + tell StatsD that this metric timing is being sent + sampled every 1/10th of the time.
          +
          +
        • +
        + + + +
          +
        • +

          time

          +
          public void time(java.lang.String name,
          +                 long value,
          +                 java.lang.String tags)
          +
          Records the timing information for the specified metric.
          +
          +
          Parameters:
          +
          name - the metric name
          +
          value - the measured time
          +
          tags - Only for DogStatsD compatible collectors. + Assigned comma delimited tags. A tag value is delimited by colon.
          +
          +
        • +
        + + + +
          +
        • +

          time

          +
          public void time(java.lang.String name,
          +                 long value,
          +                 double sampleRate,
          +                 java.lang.String tags)
          +
          Records the timing information for the specified metric.
          +
          +
          Parameters:
          +
          name - the metric name
          +
          value - the measured time
          +
          sampleRate - the sampling rate being employed. For example, a rate of 0.1 would + tell StatsD that this metric timing is being sent + sampled every 1/10th of the time.
          +
          tags - Only for DogStatsD compatible collectors. + Assigned comma delimited tags. A tag value is delimited by colon.
          +
          +
        • +
        + + + +
          +
        • +

          histo

          +
          public void histo(java.lang.String name,
          +                  long value)
          +
          Adds a value to the named histogram.
          +
          +
          Parameters:
          +
          name - the histogram name
          +
          value - the measured value
          +
          +
        • +
        + + + +
          +
        • +

          histo

          +
          public void histo(java.lang.String name,
          +                  long value,
          +                  double sampleRate)
          +
          Adds a value to the named histogram.
          +
          +
          Parameters:
          +
          name - the histogram name
          +
          value - the measured value
          +
          sampleRate - the sampling rate being employed. For example, a rate of 0.1 would + tell StatsD that this metric value is being sent + sampled every 1/10th of the time.
          +
          +
        • +
        + + + +
          +
        • +

          histo

          +
          public void histo(java.lang.String name,
          +                  long value,
          +                  java.lang.String tags)
          +
          Adds a value to the named histogram.
          +
          +
          Parameters:
          +
          name - the histogram name
          +
          value - the measured value
          +
          tags - Only for DogStatsD compatible collectors. + Assigned comma delimited tags. A tag value is delimited by colon.
          +
          +
        • +
        + + + +
          +
        • +

          histo

          +
          public void histo(java.lang.String name,
          +                  long value,
          +                  double sampleRate,
          +                  java.lang.String tags)
          +
          Adds a value to the named histogram.
          +
          +
          Parameters:
          +
          name - the histogram name
          +
          value - the measured value
          +
          sampleRate - the sampling rate being employed. For example, a rate of 0.1 would + tell StatsD that this metric value is being sent + sampled every 1/10th of the time.
          +
          tags - Only for DogStatsD compatible collectors. + Assigned comma delimited tags. A tag value is delimited by colon.
          +
          +
        • +
        + + + +
          +
        • +

          unique

          +
          public void unique(java.lang.String name,
          +                   java.lang.String id,
          +                   java.lang.String tags)
          +
          StatsD supports counting unique occurrences of events between flushes. + Call this method to records an occurrence of the specified named event.
          +
          +
          Parameters:
          +
          name - the name of the set
          +
          id - the value to be added to the set
          +
          tags - Only for DogStatsD compatible collectors. + Assigned comma delimited tags. A tag value is delimited by colon.
          +
          +
        • +
        + + + +
          +
        • +

          unique

          +
          public void unique(java.lang.String name,
          +                   java.lang.String id)
          +
          StatsD supports counting unique occurrences of events between flushes. + Call this method to records an occurrence of the specified named event.
          +
          +
          Parameters:
          +
          name - the name of the set
          +
          id - the value to be added to the set
          +
          +
        • +
        + + + +
          +
        • +

          event

          +
          public void event(java.lang.String title,
          +                  java.lang.String text)
          +
          Sends an event to a DogStatsD compatible collector
          +
          +
          Parameters:
          +
          title - event name
          +
          text - event text
          +
          +
        • +
        + + + +
          +
        • +

          event

          +
          public void event(java.lang.String title,
          +                  java.lang.String text,
          +                  java.lang.String tags)
          +
          Sends an event to a DogStatsD compatible collector
          +
          +
          Parameters:
          +
          title - The event name
          +
          text - The event text
          +
          tags - Assigned comma delimited tags. A tag value is delimited by colon.
          +
          +
        • +
        + + + +
          +
        • +

          event

          +
          public void event(java.lang.String title,
          +                  java.lang.String text,
          +                  long timestamp,
          +                  java.lang.String host,
          +                  java.lang.String group,
          +                  java.lang.String sourceType,
          +                  Statsd.Priority priority,
          +                  Statsd.AlertType alertType,
          +                  java.lang.String tags)
          +
          Sends an event to a DogStatsD compatible collector
          +
          +
          Parameters:
          +
          title - event name
          +
          text - event text
          +
          timestamp - Assign a timestamp to the event. + 0 means the current date
          +
          host - Assign a hostname to the event. + May be null
          +
          group - Assign an aggregation key to the event, to group it with some others. + May be null
          +
          sourceType - Assign a source type to the event. + May be null
          +
          priority - Statsd.Priority - may be null for NORMAL
          +
          alertType - Statsd.AlertType - may be null for INFO
          +
          tags - Assigned comma delimited tags. A tag value is delimited by colon.
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/services/impl/package-frame.html b/misc/btrace/javadoc/com/sun/btrace/services/impl/package-frame.html new file mode 100644 index 00000000..7f50085b --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/services/impl/package-frame.html @@ -0,0 +1,26 @@ + + + + + +com.sun.btrace.services.impl (btrace 1.3.11 API) + + + + + +

    com.sun.btrace.services.impl

    +
    +

    Classes

    + +

    Enums

    + +
    + + diff --git a/misc/btrace/javadoc/com/sun/btrace/services/impl/package-summary.html b/misc/btrace/javadoc/com/sun/btrace/services/impl/package-summary.html new file mode 100644 index 00000000..38087ac5 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/services/impl/package-summary.html @@ -0,0 +1,167 @@ + + + + + +com.sun.btrace.services.impl (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Package com.sun.btrace.services.impl

    +
    +
    +
      +
    • + + + + + + + + + + + + + + + + +
      Class Summary 
      ClassDescription
      Printer +
      A very rudimentary printer service.
      +
      Statsd +
      A simple way to submit statsd metrics.
      +
      +
    • +
    • + + + + + + + + + + + + + + + + +
      Enum Summary 
      EnumDescription
      Statsd.AlertType 
      Statsd.Priority 
      +
    • +
    +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/services/impl/package-tree.html b/misc/btrace/javadoc/com/sun/btrace/services/impl/package-tree.html new file mode 100644 index 00000000..ce5f86a2 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/services/impl/package-tree.html @@ -0,0 +1,157 @@ + + + + + +com.sun.btrace.services.impl Class Hierarchy (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Hierarchy For Package com.sun.btrace.services.impl

    +Package Hierarchies: + +
    +
    +

    Class Hierarchy

    + +

    Enum Hierarchy

    +
      +
    • java.lang.Object +
        +
      • java.lang.Enum<E> (implements java.lang.Comparable<T>, java.io.Serializable) + +
      • +
      +
    • +
    +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/services/spi/BTraceService.html b/misc/btrace/javadoc/com/sun/btrace/services/spi/BTraceService.html new file mode 100644 index 00000000..eabcca4c --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/services/spi/BTraceService.html @@ -0,0 +1,169 @@ + + + + + +BTraceService (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.services.spi
    +

    Interface BTraceService

    +
    +
    +
    + +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/services/spi/RuntimeService.html b/misc/btrace/javadoc/com/sun/btrace/services/spi/RuntimeService.html new file mode 100644 index 00000000..f423f9c9 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/services/spi/RuntimeService.html @@ -0,0 +1,280 @@ + + + + + +RuntimeService (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.services.spi
    +

    Class RuntimeService

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.services.spi.RuntimeService
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      BTraceService
      +
      +
      +
      Direct Known Subclasses:
      +
      Printer
      +
      +
      +
      +
      public abstract class RuntimeService
      +extends java.lang.Object
      +implements BTraceService
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Summary

        + + + + + + + + + + +
        Fields 
        Modifier and TypeField and Description
        protected BTraceRuntimert 
        +
      • +
      + + + +
        +
      • + + +

        Method Summary

        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    + +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/services/spi/SimpleService.html b/misc/btrace/javadoc/com/sun/btrace/services/spi/SimpleService.html new file mode 100644 index 00000000..0ca2ee26 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/services/spi/SimpleService.html @@ -0,0 +1,244 @@ + + + + + +SimpleService (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.services.spi
    +

    Class SimpleService

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.services.spi.SimpleService
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      BTraceService
      +
      +
      +
      Direct Known Subclasses:
      +
      Statsd
      +
      +
      +
      +
      public abstract class SimpleService
      +extends java.lang.Object
      +implements BTraceService
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        SimpleService() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          SimpleService

          +
          public SimpleService()
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/services/spi/package-frame.html b/misc/btrace/javadoc/com/sun/btrace/services/spi/package-frame.html new file mode 100644 index 00000000..b64a1cfe --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/services/spi/package-frame.html @@ -0,0 +1,25 @@ + + + + + +com.sun.btrace.services.spi (btrace 1.3.11 API) + + + + + +

    com.sun.btrace.services.spi

    +
    +

    Interfaces

    + +

    Classes

    + +
    + + diff --git a/misc/btrace/javadoc/com/sun/btrace/services/spi/package-summary.html b/misc/btrace/javadoc/com/sun/btrace/services/spi/package-summary.html new file mode 100644 index 00000000..64599e27 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/services/spi/package-summary.html @@ -0,0 +1,159 @@ + + + + + +com.sun.btrace.services.spi (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Package com.sun.btrace.services.spi

    +
    +
    + +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/services/spi/package-tree.html b/misc/btrace/javadoc/com/sun/btrace/services/spi/package-tree.html new file mode 100644 index 00000000..7404385b --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/services/spi/package-tree.html @@ -0,0 +1,140 @@ + + + + + +com.sun.btrace.services.spi Class Hierarchy (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Hierarchy For Package com.sun.btrace.services.spi

    +Package Hierarchies: + +
    +
    +

    Class Hierarchy

    + +

    Interface Hierarchy

    + +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/shared/ErrorHandler.html b/misc/btrace/javadoc/com/sun/btrace/shared/ErrorHandler.html new file mode 100644 index 00000000..629a5868 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/shared/ErrorHandler.html @@ -0,0 +1,310 @@ + + + + + +ErrorHandler (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.shared
    +

    Class ErrorHandler

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.shared.ErrorHandler
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class ErrorHandler
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Summary

        + + + + + + + + + + +
        Fields 
        Modifier and TypeField and Description
        java.lang.Stringmethod 
        +
      • +
      + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        ErrorHandler(java.lang.String method) 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        java.lang.reflect.MethodgetMethod(java.lang.Class clz) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Detail

        + + + +
          +
        • +

          method

          +
          public final java.lang.String method
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          ErrorHandler

          +
          public ErrorHandler(java.lang.String method)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getMethod

          +
          public java.lang.reflect.Method getMethod(java.lang.Class clz)
          +                                   throws java.lang.NoSuchMethodException
          +
          +
          Throws:
          +
          java.lang.NoSuchMethodException
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/shared/EventHandler.html b/misc/btrace/javadoc/com/sun/btrace/shared/EventHandler.html new file mode 100644 index 00000000..e2a72ec2 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/shared/EventHandler.html @@ -0,0 +1,342 @@ + + + + + +EventHandler (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.shared
    +

    Class EventHandler

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.shared.EventHandler
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class EventHandler
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Summary

        + + + + + + + + + + + + + + +
        Fields 
        Modifier and TypeField and Description
        static java.lang.StringALL_EVENTS 
        java.lang.Stringmethod 
        +
      • +
      + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        EventHandler(java.lang.String method, + java.lang.String event) 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        java.lang.StringgetEvent() 
        java.lang.reflect.MethodgetMethod(java.lang.Class clz) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Detail

        + + + +
          +
        • +

          ALL_EVENTS

          +
          public static final java.lang.String ALL_EVENTS
          +
          +
          See Also:
          +
          Constant Field Values
          +
          +
        • +
        + + + +
          +
        • +

          method

          +
          public final java.lang.String method
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          EventHandler

          +
          public EventHandler(java.lang.String method,
          +                    java.lang.String event)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getEvent

          +
          public java.lang.String getEvent()
          +
        • +
        + + + +
          +
        • +

          getMethod

          +
          public java.lang.reflect.Method getMethod(java.lang.Class clz)
          +                                   throws java.lang.NoSuchMethodException
          +
          +
          Throws:
          +
          java.lang.NoSuchMethodException
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/shared/ExitHandler.html b/misc/btrace/javadoc/com/sun/btrace/shared/ExitHandler.html new file mode 100644 index 00000000..7c456d21 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/shared/ExitHandler.html @@ -0,0 +1,310 @@ + + + + + +ExitHandler (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.shared
    +

    Class ExitHandler

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.shared.ExitHandler
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public class ExitHandler
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Summary

        + + + + + + + + + + +
        Fields 
        Modifier and TypeField and Description
        java.lang.Stringmethod 
        +
      • +
      + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        ExitHandler(java.lang.String method) 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        java.lang.reflect.MethodgetMethod(java.lang.Class clz) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Detail

        + + + +
          +
        • +

          method

          +
          public final java.lang.String method
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          ExitHandler

          +
          public ExitHandler(java.lang.String method)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getMethod

          +
          public java.lang.reflect.Method getMethod(java.lang.Class clz)
          +                                   throws java.lang.NoSuchMethodException
          +
          +
          Throws:
          +
          java.lang.NoSuchMethodException
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/shared/LowMemoryHandler.html b/misc/btrace/javadoc/com/sun/btrace/shared/LowMemoryHandler.html new file mode 100644 index 00000000..e6bf3663 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/shared/LowMemoryHandler.html @@ -0,0 +1,394 @@ + + + + + +LowMemoryHandler (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.shared
    +

    Class LowMemoryHandler

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.shared.LowMemoryHandler
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class LowMemoryHandler
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + + + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        LowMemoryHandler(java.lang.String method, + java.lang.String pool, + long threshold, + java.lang.String thresholdProperty, + boolean trackUsage) 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        java.lang.reflect.MethodgetMethod(java.lang.Class clz) 
        voidinvoke(java.lang.Class clz, + java.lang.Object... args) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Detail

        + + + +
          +
        • +

          method

          +
          public final java.lang.String method
          +
        • +
        + + + +
          +
        • +

          pool

          +
          public final java.lang.String pool
          +
        • +
        + + + +
          +
        • +

          thresholdProperty

          +
          public final java.lang.String thresholdProperty
          +
        • +
        + + + +
          +
        • +

          threshold

          +
          public final long threshold
          +
        • +
        + + + +
          +
        • +

          trackUsage

          +
          public final boolean trackUsage
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          LowMemoryHandler

          +
          public LowMemoryHandler(java.lang.String method,
          +                        java.lang.String pool,
          +                        long threshold,
          +                        java.lang.String thresholdProperty,
          +                        boolean trackUsage)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getMethod

          +
          public java.lang.reflect.Method getMethod(java.lang.Class clz)
          +                                   throws java.lang.NoSuchMethodException
          +
          +
          Throws:
          +
          java.lang.NoSuchMethodException
          +
          +
        • +
        + + + +
          +
        • +

          invoke

          +
          public void invoke(java.lang.Class clz,
          +                   java.lang.Object... args)
          +            throws java.lang.NoSuchMethodException,
          +                   java.lang.IllegalAccessException,
          +                   java.lang.reflect.InvocationTargetException
          +
          +
          Throws:
          +
          java.lang.NoSuchMethodException
          +
          java.lang.IllegalAccessException
          +
          java.lang.reflect.InvocationTargetException
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/shared/MethodSerializer.html b/misc/btrace/javadoc/com/sun/btrace/shared/MethodSerializer.html new file mode 100644 index 00000000..10c43744 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/shared/MethodSerializer.html @@ -0,0 +1,274 @@ + + + + + +MethodSerializer (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.shared
    +

    Class MethodSerializer

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.shared.MethodSerializer
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public class MethodSerializer
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        MethodSerializer() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static byte[]serialize(com.sun.btrace.org.objectweb.asm.tree.MethodNode mn) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          MethodSerializer

          +
          public MethodSerializer()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          serialize

          +
          public static byte[] serialize(com.sun.btrace.org.objectweb.asm.tree.MethodNode mn)
          +                        throws java.io.IOException
          +
          +
          Throws:
          +
          java.io.IOException
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/shared/TimerHandler.html b/misc/btrace/javadoc/com/sun/btrace/shared/TimerHandler.html new file mode 100644 index 00000000..0f8103a7 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/shared/TimerHandler.html @@ -0,0 +1,340 @@ + + + + + +TimerHandler (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.shared
    +

    Class TimerHandler

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.shared.TimerHandler
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class TimerHandler
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Summary

        + + + + + + + + + + + + + + + + + + +
        Fields 
        Modifier and TypeField and Description
        java.lang.Stringmethod 
        longperiod 
        java.lang.StringperiodArg 
        +
      • +
      + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        TimerHandler(java.lang.String method, + long period, + java.lang.String periodArg) 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        java.lang.reflect.MethodgetMethod(java.lang.Class clz) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Detail

        + + + +
          +
        • +

          method

          +
          public final java.lang.String method
          +
        • +
        + + + +
          +
        • +

          period

          +
          public final long period
          +
        • +
        + + + +
          +
        • +

          periodArg

          +
          public final java.lang.String periodArg
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          TimerHandler

          +
          public TimerHandler(java.lang.String method,
          +                    long period,
          +                    java.lang.String periodArg)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getMethod

          +
          public java.lang.reflect.Method getMethod(java.lang.Class clz)
          +                                   throws java.lang.NoSuchMethodException
          +
          +
          Throws:
          +
          java.lang.NoSuchMethodException
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/shared/package-frame.html b/misc/btrace/javadoc/com/sun/btrace/shared/package-frame.html new file mode 100644 index 00000000..007103cb --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/shared/package-frame.html @@ -0,0 +1,25 @@ + + + + + +com.sun.btrace.shared (btrace 1.3.11 API) + + + + + +

    com.sun.btrace.shared

    + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/shared/package-summary.html b/misc/btrace/javadoc/com/sun/btrace/shared/package-summary.html new file mode 100644 index 00000000..55f07ec1 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/shared/package-summary.html @@ -0,0 +1,160 @@ + + + + + +com.sun.btrace.shared (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Package com.sun.btrace.shared

    +
    +
    + +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/shared/package-tree.html b/misc/btrace/javadoc/com/sun/btrace/shared/package-tree.html new file mode 100644 index 00000000..b5997d02 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/shared/package-tree.html @@ -0,0 +1,140 @@ + + + + + +com.sun.btrace.shared Class Hierarchy (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Hierarchy For Package com.sun.btrace.shared

    +Package Hierarchies: + +
    +
    +

    Class Hierarchy

    + +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/spi/BTraceCompilerFactory.html b/misc/btrace/javadoc/com/sun/btrace/spi/BTraceCompilerFactory.html new file mode 100644 index 00000000..f5263f5a --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/spi/BTraceCompilerFactory.html @@ -0,0 +1,223 @@ + + + + + +BTraceCompilerFactory (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.spi
    +

    Interface BTraceCompilerFactory

    +
    +
    +
    + +
    +
    + +
    +
    + +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/spi/BTraceSettingsProvider.html b/misc/btrace/javadoc/com/sun/btrace/spi/BTraceSettingsProvider.html new file mode 100644 index 00000000..17238ce7 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/spi/BTraceSettingsProvider.html @@ -0,0 +1,223 @@ + + + + + +BTraceSettingsProvider (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.spi
    +

    Interface BTraceSettingsProvider

    +
    +
    +
    + +
    +
    + +
    +
    + +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/spi/BaseBTraceCompiler.html b/misc/btrace/javadoc/com/sun/btrace/spi/BaseBTraceCompiler.html new file mode 100644 index 00000000..e1fd7171 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/spi/BaseBTraceCompiler.html @@ -0,0 +1,340 @@ + + + + + +BaseBTraceCompiler (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.spi
    +

    Class BaseBTraceCompiler

    +
    +
    + +
    + +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          BaseBTraceCompiler

          +
          public BaseBTraceCompiler(BTraceTask task)
          +
        • +
        +
      • +
      + + +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/spi/ClasspathProvider.html b/misc/btrace/javadoc/com/sun/btrace/spi/ClasspathProvider.html new file mode 100644 index 00000000..922ce8f4 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/spi/ClasspathProvider.html @@ -0,0 +1,255 @@ + + + + + +ClasspathProvider (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.spi
    +

    Interface ClasspathProvider

    +
    +
    +
    +
      +
    • +
      +
      +
      public interface ClasspathProvider
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + + + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getClasspath

          +
          java.util.Collection<java.lang.String> getClasspath(BTraceTask task)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/spi/OutputProvider.html b/misc/btrace/javadoc/com/sun/btrace/spi/OutputProvider.html new file mode 100644 index 00000000..07b8fd09 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/spi/OutputProvider.html @@ -0,0 +1,268 @@ + + + + + +OutputProvider (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.spi
    +

    Interface OutputProvider

    +
    +
    +
    +
      +
    • +
      +
      +
      public interface OutputProvider
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + + + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getStdOut

          +
          java.io.PrintWriter getStdOut(BTraceTask task)
          +
        • +
        + + + +
          +
        • +

          getStdErr

          +
          java.io.PrintWriter getStdErr(BTraceTask task)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/spi/PortLocator.html b/misc/btrace/javadoc/com/sun/btrace/spi/PortLocator.html new file mode 100644 index 00000000..33cd6ace --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/spi/PortLocator.html @@ -0,0 +1,280 @@ + + + + + +PortLocator (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.spi
    +

    Interface PortLocator

    +
    +
    +
    +
      +
    • +
      +
      All Known Implementing Classes:
      +
      PortLocatorImpl
      +
      +
      +
      +
      public interface PortLocator
      +
    • +
    +
    +
    + +
    +
    + +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/spi/impl/BTraceCompilerFactoryImpl.html b/misc/btrace/javadoc/com/sun/btrace/spi/impl/BTraceCompilerFactoryImpl.html new file mode 100644 index 00000000..a61b4621 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/spi/impl/BTraceCompilerFactoryImpl.html @@ -0,0 +1,278 @@ + + + + + +BTraceCompilerFactoryImpl (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.spi.impl
    +

    Class BTraceCompilerFactoryImpl

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.spi.impl.BTraceCompilerFactoryImpl
      • +
      +
    • +
    +
    + +
    +
    + +
    +
    + +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/spi/impl/BTraceSettingsProviderImpl.html b/misc/btrace/javadoc/com/sun/btrace/spi/impl/BTraceSettingsProviderImpl.html new file mode 100644 index 00000000..427e2561 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/spi/impl/BTraceSettingsProviderImpl.html @@ -0,0 +1,278 @@ + + + + + +BTraceSettingsProviderImpl (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.spi.impl
    +

    Class BTraceSettingsProviderImpl

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.spi.impl.BTraceSettingsProviderImpl
      • +
      +
    • +
    +
    + +
    +
    + +
    +
    + +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/spi/impl/PortLocatorImpl.html b/misc/btrace/javadoc/com/sun/btrace/spi/impl/PortLocatorImpl.html new file mode 100644 index 00000000..93fc9605 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/spi/impl/PortLocatorImpl.html @@ -0,0 +1,293 @@ + + + + + +PortLocatorImpl (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.spi.impl
    +

    Class PortLocatorImpl

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.spi.impl.PortLocatorImpl
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      PortLocator
      +
      +
      +
      +
      public final class PortLocatorImpl
      +extends java.lang.Object
      +implements PortLocator
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          PortLocatorImpl

          +
          public PortLocatorImpl()
          +
        • +
        +
      • +
      + + +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/spi/impl/package-frame.html b/misc/btrace/javadoc/com/sun/btrace/spi/impl/package-frame.html new file mode 100644 index 00000000..35a20f4d --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/spi/impl/package-frame.html @@ -0,0 +1,22 @@ + + + + + +com.sun.btrace.spi.impl (btrace 1.3.11 API) + + + + + +

    com.sun.btrace.spi.impl

    + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/spi/impl/package-summary.html b/misc/btrace/javadoc/com/sun/btrace/spi/impl/package-summary.html new file mode 100644 index 00000000..52ec1d9b --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/spi/impl/package-summary.html @@ -0,0 +1,148 @@ + + + + + +com.sun.btrace.spi.impl (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Package com.sun.btrace.spi.impl

    +
    +
    + +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/spi/impl/package-tree.html b/misc/btrace/javadoc/com/sun/btrace/spi/impl/package-tree.html new file mode 100644 index 00000000..f4b2da87 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/spi/impl/package-tree.html @@ -0,0 +1,137 @@ + + + + + +com.sun.btrace.spi.impl Class Hierarchy (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Hierarchy For Package com.sun.btrace.spi.impl

    +Package Hierarchies: + +
    +
    +

    Class Hierarchy

    + +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/spi/package-frame.html b/misc/btrace/javadoc/com/sun/btrace/spi/package-frame.html new file mode 100644 index 00000000..5b1145fc --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/spi/package-frame.html @@ -0,0 +1,28 @@ + + + + + +com.sun.btrace.spi (btrace 1.3.11 API) + + + + + +

    com.sun.btrace.spi

    + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/spi/package-summary.html b/misc/btrace/javadoc/com/sun/btrace/spi/package-summary.html new file mode 100644 index 00000000..2183f2dc --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/spi/package-summary.html @@ -0,0 +1,171 @@ + + + + + +com.sun.btrace.spi (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Package com.sun.btrace.spi

    +
    +
    + +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/spi/package-tree.html b/misc/btrace/javadoc/com/sun/btrace/spi/package-tree.html new file mode 100644 index 00000000..381cdebd --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/spi/package-tree.html @@ -0,0 +1,147 @@ + + + + + +com.sun.btrace.spi Class Hierarchy (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Hierarchy For Package com.sun.btrace.spi

    +Package Hierarchies: + +
    +
    +

    Class Hierarchy

    + +

    Interface Hierarchy

    + +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/util/Interval.html b/misc/btrace/javadoc/com/sun/btrace/util/Interval.html new file mode 100644 index 00000000..4c0755e2 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/util/Interval.html @@ -0,0 +1,513 @@ + + + + + +Interval (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.util
    +

    Class Interval

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.util.Interval
      • +
      +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.lang.Comparable<Interval>
      +
      +
      +
      +
      public class Interval
      +extends java.lang.Object
      +implements java.lang.Comparable<Interval>
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Interval

          +
          public Interval(int a,
          +                int b)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getA

          +
          public int getA()
          +
        • +
        + + + +
          +
        • +

          getB

          +
          public int getB()
          +
        • +
        + + + +
          +
        • +

          eq

          +
          public static Interval eq(int value)
          +
        • +
        + + + +
          +
        • +

          ge

          +
          public static Interval ge(int value)
          +
        • +
        + + + +
          +
        • +

          gt

          +
          public static Interval gt(int value)
          +
        • +
        + + + +
          +
        • +

          le

          +
          public static Interval le(int value)
          +
        • +
        + + + +
          +
        • +

          lt

          +
          public static Interval lt(int value)
          +
        • +
        + + + +
          +
        • +

          all

          +
          public static Interval all()
          +
        • +
        + + + +
          +
        • +

          none

          +
          public static Interval none()
          +
        • +
        + + + +
          +
        • +

          isAll

          +
          public boolean isAll()
          +
        • +
        + + + +
          +
        • +

          isNone

          +
          public boolean isNone()
          +
        • +
        + + + +
          +
        • +

          union

          +
          public static java.util.List<Interval> union(java.util.Collection<Interval> intervals)
          +
        • +
        + + + +
          +
        • +

          invert

          +
          public static java.util.List<Interval> invert(java.util.Collection<Interval> intervals)
          +
        • +
        + + + +
          +
        • +

          compareTo

          +
          public int compareTo(Interval o)
          +
          +
          Specified by:
          +
          compareTo in interface java.lang.Comparable<Interval>
          +
          +
        • +
        + + + +
          +
        • +

          hashCode

          +
          public int hashCode()
          +
          +
          Overrides:
          +
          hashCode in class java.lang.Object
          +
          +
        • +
        + + + +
          +
        • +

          equals

          +
          public boolean equals(java.lang.Object obj)
          +
          +
          Overrides:
          +
          equals in class java.lang.Object
          +
          +
        • +
        + + + +
          +
        • +

          toString

          +
          public java.lang.String toString()
          +
          +
          Overrides:
          +
          toString in class java.lang.Object
          +
          +
        • +
        + + + +
          +
        • +

          fromString

          +
          public static Interval fromString(java.lang.String s)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/util/LongMap.html b/misc/btrace/javadoc/com/sun/btrace/util/LongMap.html new file mode 100644 index 00000000..2a6368e1 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/util/LongMap.html @@ -0,0 +1,353 @@ + + + + + +LongMap (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.util
    +

    Class LongMap<T>

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.util.LongMap<T>
      • +
      +
    • +
    +
    +
      +
    • +
      +
      Type Parameters:
      +
      T - The value type
      +
      +
      +
      +
      public final class LongMap<T>
      +extends java.lang.Object
      +
      AVL tree based map implementation for long values as keys
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Summary

        + + + + + + + + + + +
        Fields 
        Modifier and TypeField and Description
        intlength 
        +
      • +
      + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        LongMap() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        Tget(long id) 
        voidput(long id, + T load) 
        Tremove(long id) 
        java.util.Collection<T>values() 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Detail

        + + + +
          +
        • +

          length

          +
          public int length
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          LongMap

          +
          public LongMap()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + + + +
          +
        • +

          put

          +
          public void put(long id,
          +                T load)
          +
        • +
        + + + +
          +
        • +

          get

          +
          public T get(long id)
          +
        • +
        + + + +
          +
        • +

          remove

          +
          public T remove(long id)
          +
        • +
        + + + +
          +
        • +

          values

          +
          public java.util.Collection<T> values()
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/util/Messages.html b/misc/btrace/javadoc/com/sun/btrace/util/Messages.html new file mode 100644 index 00000000..fba71ee1 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/util/Messages.html @@ -0,0 +1,250 @@ + + + + + +Messages (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.util
    +

    Class Messages

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.util.Messages
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class Messages
      +extends java.lang.Object
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static java.lang.Stringformat(java.lang.String key, + java.lang.Object... args) 
        static java.lang.Stringget(java.lang.String key) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          get

          +
          public static java.lang.String get(java.lang.String key)
          +
        • +
        + + + +
          +
        • +

          format

          +
          public static java.lang.String format(java.lang.String key,
          +                                      java.lang.Object... args)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/util/MethodID.html b/misc/btrace/javadoc/com/sun/btrace/util/MethodID.html new file mode 100644 index 00000000..afe52541 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/util/MethodID.html @@ -0,0 +1,296 @@ + + + + + +MethodID (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.util
    +

    Class MethodID

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.util.MethodID
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public class MethodID
      +extends java.lang.Object
      +
      A factory class for shared method ids
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        MethodID() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static intgetMethodId(java.lang.String methodTag) +
        Generates a unique method id based on the provided method tag
        +
        static intgetMethodId(java.lang.String className, + java.lang.String method, + java.lang.String desc) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          MethodID

          +
          public MethodID()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getMethodId

          +
          public static int getMethodId(java.lang.String methodTag)
          +
          Generates a unique method id based on the provided method tag
          +
          +
          Parameters:
          +
          methodTag - The tag used to distinguish between methods
          +
          Returns:
          +
          An ID belonging to the provided method tag
          +
          +
        • +
        + + + +
          +
        • +

          getMethodId

          +
          public static int getMethodId(java.lang.String className,
          +                              java.lang.String method,
          +                              java.lang.String desc)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/util/PrefixMap.html b/misc/btrace/javadoc/com/sun/btrace/util/PrefixMap.html new file mode 100644 index 00000000..994b6495 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/util/PrefixMap.html @@ -0,0 +1,283 @@ + + + + + +PrefixMap (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.util
    +

    Class PrefixMap

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.util.PrefixMap
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public class PrefixMap
      +extends java.lang.Object
      +
      Simplified trie-based prefix map
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        PrefixMap() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        voidadd(java.lang.CharSequence val) 
        booleancontains(java.lang.CharSequence val) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          PrefixMap

          +
          public PrefixMap()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          add

          +
          public void add(java.lang.CharSequence val)
          +
        • +
        + + + +
          +
        • +

          contains

          +
          public boolean contains(java.lang.CharSequence val)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/util/package-frame.html b/misc/btrace/javadoc/com/sun/btrace/util/package-frame.html new file mode 100644 index 00000000..148b5932 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/util/package-frame.html @@ -0,0 +1,24 @@ + + + + + +com.sun.btrace.util (btrace 1.3.11 API) + + + + + +

    com.sun.btrace.util

    + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/util/package-summary.html b/misc/btrace/javadoc/com/sun/btrace/util/package-summary.html new file mode 100644 index 00000000..ecedc518 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/util/package-summary.html @@ -0,0 +1,162 @@ + + + + + +com.sun.btrace.util (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Package com.sun.btrace.util

    +
    +
    +
      +
    • + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Class Summary 
      ClassDescription
      Interval 
      LongMap<T> +
      AVL tree based map implementation for long values as keys
      +
      Messages 
      MethodID +
      A factory class for shared method ids
      +
      PrefixMap +
      Simplified trie-based prefix map
      +
      +
    • +
    +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/util/package-tree.html b/misc/btrace/javadoc/com/sun/btrace/util/package-tree.html new file mode 100644 index 00000000..12950de2 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/util/package-tree.html @@ -0,0 +1,139 @@ + + + + + +com.sun.btrace.util Class Hierarchy (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Hierarchy For Package com.sun.btrace.util

    +Package Hierarchies: + +
    +
    +

    Class Hierarchy

    +
      +
    • java.lang.Object + +
    • +
    +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/util/templates/BTraceTemplates.html b/misc/btrace/javadoc/com/sun/btrace/util/templates/BTraceTemplates.html new file mode 100644 index 00000000..0f159af9 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/util/templates/BTraceTemplates.html @@ -0,0 +1,291 @@ + + + + + +BTraceTemplates (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.util.templates
    +

    Class BTraceTemplates

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.util.templates.BTraceTemplates
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class BTraceTemplates
      +extends java.lang.Object
      +
      A central place for bytecode templates
      +
      +
      Since:
      +
      1.3
      +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        BTraceTemplates() 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static TemplategetTemplate(java.lang.String owner, + java.lang.String name, + java.lang.String sig) 
        static voidregisterTemplates(Template... templates) 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          BTraceTemplates

          +
          public BTraceTemplates()
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          registerTemplates

          +
          public static void registerTemplates(Template... templates)
          +
        • +
        + + + +
          +
        • +

          getTemplate

          +
          public static Template getTemplate(java.lang.String owner,
          +                                   java.lang.String name,
          +                                   java.lang.String sig)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/util/templates/BaseTemplateExpander.html b/misc/btrace/javadoc/com/sun/btrace/util/templates/BaseTemplateExpander.html new file mode 100644 index 00000000..abca8807 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/util/templates/BaseTemplateExpander.html @@ -0,0 +1,344 @@ + + + + + +BaseTemplateExpander (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.util.templates
    +

    Class BaseTemplateExpander

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.util.templates.BaseTemplateExpander
      • +
      +
    • +
    +
    + +
    +
    + +
    +
    + +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/util/templates/Template.html b/misc/btrace/javadoc/com/sun/btrace/util/templates/Template.html new file mode 100644 index 00000000..711cfdac --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/util/templates/Template.html @@ -0,0 +1,451 @@ + + + + + +Template (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.util.templates
    +

    Class Template

    +
    +
    +
      +
    • java.lang.Object
    • +
    • +
        +
      • com.sun.btrace.util.templates.Template
      • +
      +
    • +
    +
    +
      +
    • +
      +
      +
      public final class Template
      +extends java.lang.Object
      +
      A template descriptor
      +
      +
      Since:
      +
      1.3
      +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + + + + +
        Constructors 
        Constructor and Description
        Template(java.lang.String name, + java.lang.String sig) 
        Template(java.lang.String name, + java.lang.String sig, + java.lang.String... tags) 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        Templateduplicate() 
        booleanequals(java.lang.Object obj) 
        java.lang.StringgetName() 
        java.lang.StringgetOwner() 
        java.lang.StringgetSig() 
        java.util.Map<java.lang.String,java.lang.String>getTagMap() 
        java.util.Set<java.lang.String>getTags() 
        inthashCode() 
        voidinsert(com.sun.btrace.org.objectweb.asm.MethodVisitor mv) 
        voidinsert(com.sun.btrace.org.objectweb.asm.MethodVisitor mv, + java.util.Set<java.lang.String> tags) 
        voidinsert(com.sun.btrace.org.objectweb.asm.MethodVisitor mv, + java.lang.String... tags) 
        java.lang.StringtoString() 
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, finalize, getClass, notify, notifyAll, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          Template

          +
          public Template(java.lang.String name,
          +                java.lang.String sig)
          +
        • +
        + + + +
          +
        • +

          Template

          +
          public Template(java.lang.String name,
          +                java.lang.String sig,
          +                java.lang.String... tags)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          getOwner

          +
          public java.lang.String getOwner()
          +
        • +
        + + + +
          +
        • +

          getName

          +
          public java.lang.String getName()
          +
        • +
        + + + +
          +
        • +

          getSig

          +
          public java.lang.String getSig()
          +
        • +
        + + + +
          +
        • +

          insert

          +
          public void insert(com.sun.btrace.org.objectweb.asm.MethodVisitor mv)
          +
        • +
        + + + +
          +
        • +

          insert

          +
          public void insert(com.sun.btrace.org.objectweb.asm.MethodVisitor mv,
          +                   java.lang.String... tags)
          +
        • +
        + + + +
          +
        • +

          insert

          +
          public void insert(com.sun.btrace.org.objectweb.asm.MethodVisitor mv,
          +                   java.util.Set<java.lang.String> tags)
          +
        • +
        + + + +
          +
        • +

          getTags

          +
          public java.util.Set<java.lang.String> getTags()
          +
        • +
        + + + +
          +
        • +

          getTagMap

          +
          public java.util.Map<java.lang.String,java.lang.String> getTagMap()
          +
        • +
        + + + +
          +
        • +

          hashCode

          +
          public int hashCode()
          +
          +
          Overrides:
          +
          hashCode in class java.lang.Object
          +
          +
        • +
        + + + +
          +
        • +

          equals

          +
          public boolean equals(java.lang.Object obj)
          +
          +
          Overrides:
          +
          equals in class java.lang.Object
          +
          +
        • +
        + + + +
          +
        • +

          toString

          +
          public java.lang.String toString()
          +
          +
          Overrides:
          +
          toString in class java.lang.Object
          +
          +
        • +
        + + + +
          +
        • +

          duplicate

          +
          public final Template duplicate()
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/util/templates/TemplateExpander.Consumer.html b/misc/btrace/javadoc/com/sun/btrace/util/templates/TemplateExpander.Consumer.html new file mode 100644 index 00000000..05cf10a7 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/util/templates/TemplateExpander.Consumer.html @@ -0,0 +1,226 @@ + + + + + +TemplateExpander.Consumer (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.util.templates
    +

    Interface TemplateExpander.Consumer<T>

    +
    +
    +
    +
      +
    • +
      +
      Enclosing interface:
      +
      TemplateExpander
      +
      +
      +
      +
      public static interface TemplateExpander.Consumer<T>
      +
      A knockoff of the java.util.function.Consumer interface for pre-8 usage
      +
    • +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Method Detail

        + + + + + +
          +
        • +

          consume

          +
          void consume(T visitor)
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/util/templates/TemplateExpander.Result.html b/misc/btrace/javadoc/com/sun/btrace/util/templates/TemplateExpander.Result.html new file mode 100644 index 00000000..bb5298a0 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/util/templates/TemplateExpander.Result.html @@ -0,0 +1,361 @@ + + + + + +TemplateExpander.Result (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.util.templates
    +

    Enum TemplateExpander.Result

    +
    +
    +
      +
    • java.lang.Object
    • +
    • + +
    • +
    +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      java.io.Serializable, java.lang.Comparable<TemplateExpander.Result>
      +
      +
      +
      Enclosing interface:
      +
      TemplateExpander
      +
      +
      +
      +
      public static enum TemplateExpander.Result
      +extends java.lang.Enum<TemplateExpander.Result>
      +
      The result of expansion +
        +
      • EXPANDED = expander has claimed and expanded the template
      • +
      • CLAIMED = expander has claimed the template but didn't expand it
      • +
      • IGNORED = expander has not claimed the template
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Enum Constant Summary

        + + + + + + + + + + + + + + +
        Enum Constants 
        Enum Constant and Description
        CLAIMED 
        EXPANDED 
        IGNORED 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + +
        All Methods Static Methods Concrete Methods 
        Modifier and TypeMethod and Description
        static TemplateExpander.ResultvalueOf(java.lang.String name) +
        Returns the enum constant of this type with the specified name.
        +
        static TemplateExpander.Result[]values() +
        Returns an array containing the constants of this enum type, in +the order they are declared.
        +
        +
          +
        • + + +

          Methods inherited from class java.lang.Enum

          +clone, compareTo, equals, finalize, getDeclaringClass, hashCode, name, ordinal, toString, valueOf
        • +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +getClass, notify, notifyAll, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + + + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          values

          +
          public static TemplateExpander.Result[] values()
          +
          Returns an array containing the constants of this enum type, in +the order they are declared. This method may be used to iterate +over the constants as follows: +
          +for (TemplateExpander.Result c : TemplateExpander.Result.values())
          +    System.out.println(c);
          +
          +
          +
          Returns:
          +
          an array containing the constants of this enum type, in the order they are declared
          +
          +
        • +
        + + + +
          +
        • +

          valueOf

          +
          public static TemplateExpander.Result valueOf(java.lang.String name)
          +
          Returns the enum constant of this type with the specified name. +The string must match exactly an identifier used to declare an +enum constant in this type. (Extraneous whitespace characters are +not permitted.)
          +
          +
          Parameters:
          +
          name - the name of the enum constant to be returned.
          +
          Returns:
          +
          the enum constant with the specified name
          +
          Throws:
          +
          java.lang.IllegalArgumentException - if this enum type has no constant with the specified name
          +
          java.lang.NullPointerException - if the argument is null
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/util/templates/TemplateExpander.html b/misc/btrace/javadoc/com/sun/btrace/util/templates/TemplateExpander.html new file mode 100644 index 00000000..0912df26 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/util/templates/TemplateExpander.html @@ -0,0 +1,288 @@ + + + + + +TemplateExpander (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.util.templates
    +

    Interface TemplateExpander

    +
    +
    +
    + +
    +
    +
      +
    • + +
        +
      • + + +

        Nested Class Summary

        + + + + + + + + + + + + + + +
        Nested Classes 
        Modifier and TypeInterface and Description
        static interface TemplateExpander.Consumer<T> +
        A knockoff of the java.util.function.Consumer interface for pre-8 usage
        +
        static class TemplateExpander.Result +
        The result of expansion + + EXPANDED = expander has claimed and expanded the template + CLAIMED = expander has claimed the template but didn't expand it + IGNORED = expander has not claimed the template +
        +
        +
      • +
      + + +
    • +
    +
    +
    + +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/util/templates/TemplateExpanderVisitor.html b/misc/btrace/javadoc/com/sun/btrace/util/templates/TemplateExpanderVisitor.html new file mode 100644 index 00000000..f79e5eae --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/util/templates/TemplateExpanderVisitor.html @@ -0,0 +1,966 @@ + + + + + +TemplateExpanderVisitor (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.util.templates
    +

    Class TemplateExpanderVisitor

    +
    +
    + +
    +
      +
    • +
      +
      +
      public class TemplateExpanderVisitor
      +extends BTraceMethodVisitor
      +
      An ASM visitor providing customized template expansion
      +
      +
      Since:
      +
      1.3
      +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Field Summary

        +
          +
        • + + +

          Fields inherited from class com.sun.btrace.org.objectweb.asm.MethodVisitor

          +api, mv
        • +
        +
      • +
      + +
        +
      • + + +

        Constructor Summary

        + + + + + + + + +
        Constructors 
        Constructor and Description
        TemplateExpanderVisitor(com.sun.btrace.org.objectweb.asm.MethodVisitor mv, + MethodInstrumentorHelper mHelper, + java.lang.String className, + java.lang.String methodName, + java.lang.String desc) 
        +
      • +
      + +
        +
      • + + +

        Method Summary

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        All Methods Instance Methods Concrete Methods 
        Modifier and TypeMethod and Description
        Assemblerasm() 
        voidexpand(TemplateExpander.Consumer<TemplateExpanderVisitor> f) 
        java.lang.StringgetClassName() 
        java.lang.StringgetDesc() 
        java.lang.StringgetMethodName() 
        com.sun.btrace.org.objectweb.asm.AnnotationVisitorvisitAnnotation(java.lang.String string, + boolean bln) 
        com.sun.btrace.org.objectweb.asm.AnnotationVisitorvisitAnnotationDefault() 
        voidvisitAttribute(com.sun.btrace.org.objectweb.asm.Attribute atrbt) 
        voidvisitCode() 
        voidvisitEnd() 
        voidvisitFieldInsn(int i, + java.lang.String string, + java.lang.String string1, + java.lang.String string2) 
        voidvisitIincInsn(int i, + int i1) 
        voidvisitInsn(int i) 
        com.sun.btrace.org.objectweb.asm.AnnotationVisitorvisitInsnAnnotation(int i, + com.sun.btrace.org.objectweb.asm.TypePath tp, + java.lang.String string, + boolean bln) 
        voidvisitIntInsn(int i, + int i1) 
        voidvisitInvokeDynamicInsn(java.lang.String string, + java.lang.String string1, + com.sun.btrace.org.objectweb.asm.Handle handle, + java.lang.Object... os) 
        voidvisitJumpInsn(int i, + com.sun.btrace.org.objectweb.asm.Label label) 
        voidvisitLabel(com.sun.btrace.org.objectweb.asm.Label label) 
        voidvisitLdcInsn(java.lang.Object o) 
        voidvisitLineNumber(int i, + com.sun.btrace.org.objectweb.asm.Label label) 
        voidvisitLocalVariable(java.lang.String string, + java.lang.String string1, + java.lang.String string2, + com.sun.btrace.org.objectweb.asm.Label label, + com.sun.btrace.org.objectweb.asm.Label label1, + int i) 
        com.sun.btrace.org.objectweb.asm.AnnotationVisitorvisitLocalVariableAnnotation(int i, + com.sun.btrace.org.objectweb.asm.TypePath tp, + com.sun.btrace.org.objectweb.asm.Label[] labels, + com.sun.btrace.org.objectweb.asm.Label[] labels1, + int[] ints, + java.lang.String string, + boolean bln) 
        voidvisitLookupSwitchInsn(com.sun.btrace.org.objectweb.asm.Label label, + int[] ints, + com.sun.btrace.org.objectweb.asm.Label[] labels) 
        voidvisitMaxs(int stack, + int locals) 
        voidvisitMethodInsn(int opcode, + java.lang.String owner, + java.lang.String name, + java.lang.String desc, + boolean isIface) 
        voidvisitMultiANewArrayInsn(java.lang.String string, + int i) 
        voidvisitParameter(java.lang.String string, + int i) 
        com.sun.btrace.org.objectweb.asm.AnnotationVisitorvisitParameterAnnotation(int i, + java.lang.String string, + boolean bln) 
        voidvisitTableSwitchInsn(int i, + int i1, + com.sun.btrace.org.objectweb.asm.Label label, + com.sun.btrace.org.objectweb.asm.Label... labels) 
        com.sun.btrace.org.objectweb.asm.AnnotationVisitorvisitTryCatchAnnotation(int i, + com.sun.btrace.org.objectweb.asm.TypePath tp, + java.lang.String string, + boolean bln) 
        voidvisitTryCatchBlock(com.sun.btrace.org.objectweb.asm.Label label, + com.sun.btrace.org.objectweb.asm.Label label1, + com.sun.btrace.org.objectweb.asm.Label label2, + java.lang.String string) 
        com.sun.btrace.org.objectweb.asm.AnnotationVisitorvisitTypeAnnotation(int i, + com.sun.btrace.org.objectweb.asm.TypePath tp, + java.lang.String string, + boolean bln) 
        voidvisitTypeInsn(int i, + java.lang.String string) 
        voidvisitVarInsn(int opcode, + int var) 
        + +
          +
        • + + +

          Methods inherited from class com.sun.btrace.org.objectweb.asm.MethodVisitor

          +visitFrame, visitMethodInsn
        • +
        +
          +
        • + + +

          Methods inherited from class java.lang.Object

          +clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
        • +
        +
      • +
      +
    • +
    +
    +
    +
      +
    • + +
        +
      • + + +

        Constructor Detail

        + + + +
          +
        • +

          TemplateExpanderVisitor

          +
          public TemplateExpanderVisitor(com.sun.btrace.org.objectweb.asm.MethodVisitor mv,
          +                               MethodInstrumentorHelper mHelper,
          +                               java.lang.String className,
          +                               java.lang.String methodName,
          +                               java.lang.String desc)
          +
        • +
        +
      • +
      + +
        +
      • + + +

        Method Detail

        + + + + + + + +
          +
        • +

          visitCode

          +
          public void visitCode()
          +
          +
          Overrides:
          +
          visitCode in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitMethodInsn

          +
          public void visitMethodInsn(int opcode,
          +                            java.lang.String owner,
          +                            java.lang.String name,
          +                            java.lang.String desc,
          +                            boolean isIface)
          +
          +
          Overrides:
          +
          visitMethodInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitVarInsn

          +
          public void visitVarInsn(int opcode,
          +                         int var)
          +
          +
          Overrides:
          +
          visitVarInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitMultiANewArrayInsn

          +
          public void visitMultiANewArrayInsn(java.lang.String string,
          +                                    int i)
          +
          +
          Overrides:
          +
          visitMultiANewArrayInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitLookupSwitchInsn

          +
          public void visitLookupSwitchInsn(com.sun.btrace.org.objectweb.asm.Label label,
          +                                  int[] ints,
          +                                  com.sun.btrace.org.objectweb.asm.Label[] labels)
          +
          +
          Overrides:
          +
          visitLookupSwitchInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitTableSwitchInsn

          +
          public void visitTableSwitchInsn(int i,
          +                                 int i1,
          +                                 com.sun.btrace.org.objectweb.asm.Label label,
          +                                 com.sun.btrace.org.objectweb.asm.Label... labels)
          +
          +
          Overrides:
          +
          visitTableSwitchInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitIincInsn

          +
          public void visitIincInsn(int i,
          +                          int i1)
          +
          +
          Overrides:
          +
          visitIincInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitLdcInsn

          +
          public void visitLdcInsn(java.lang.Object o)
          +
          +
          Overrides:
          +
          visitLdcInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitJumpInsn

          +
          public void visitJumpInsn(int i,
          +                          com.sun.btrace.org.objectweb.asm.Label label)
          +
          +
          Overrides:
          +
          visitJumpInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitInvokeDynamicInsn

          +
          public void visitInvokeDynamicInsn(java.lang.String string,
          +                                   java.lang.String string1,
          +                                   com.sun.btrace.org.objectweb.asm.Handle handle,
          +                                   java.lang.Object... os)
          +
          +
          Overrides:
          +
          visitInvokeDynamicInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitFieldInsn

          +
          public void visitFieldInsn(int i,
          +                           java.lang.String string,
          +                           java.lang.String string1,
          +                           java.lang.String string2)
          +
          +
          Overrides:
          +
          visitFieldInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitTypeInsn

          +
          public void visitTypeInsn(int i,
          +                          java.lang.String string)
          +
          +
          Overrides:
          +
          visitTypeInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitIntInsn

          +
          public void visitIntInsn(int i,
          +                         int i1)
          +
          +
          Overrides:
          +
          visitIntInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitInsn

          +
          public void visitInsn(int i)
          +
          +
          Overrides:
          +
          visitInsn in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitLineNumber

          +
          public void visitLineNumber(int i,
          +                            com.sun.btrace.org.objectweb.asm.Label label)
          +
          +
          Overrides:
          +
          visitLineNumber in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitLocalVariableAnnotation

          +
          public com.sun.btrace.org.objectweb.asm.AnnotationVisitor visitLocalVariableAnnotation(int i,
          +                                                                                       com.sun.btrace.org.objectweb.asm.TypePath tp,
          +                                                                                       com.sun.btrace.org.objectweb.asm.Label[] labels,
          +                                                                                       com.sun.btrace.org.objectweb.asm.Label[] labels1,
          +                                                                                       int[] ints,
          +                                                                                       java.lang.String string,
          +                                                                                       boolean bln)
          +
          +
          Overrides:
          +
          visitLocalVariableAnnotation in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitLocalVariable

          +
          public void visitLocalVariable(java.lang.String string,
          +                               java.lang.String string1,
          +                               java.lang.String string2,
          +                               com.sun.btrace.org.objectweb.asm.Label label,
          +                               com.sun.btrace.org.objectweb.asm.Label label1,
          +                               int i)
          +
          +
          Overrides:
          +
          visitLocalVariable in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitTryCatchAnnotation

          +
          public com.sun.btrace.org.objectweb.asm.AnnotationVisitor visitTryCatchAnnotation(int i,
          +                                                                                  com.sun.btrace.org.objectweb.asm.TypePath tp,
          +                                                                                  java.lang.String string,
          +                                                                                  boolean bln)
          +
          +
          Overrides:
          +
          visitTryCatchAnnotation in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitTryCatchBlock

          +
          public void visitTryCatchBlock(com.sun.btrace.org.objectweb.asm.Label label,
          +                               com.sun.btrace.org.objectweb.asm.Label label1,
          +                               com.sun.btrace.org.objectweb.asm.Label label2,
          +                               java.lang.String string)
          +
          +
          Overrides:
          +
          visitTryCatchBlock in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitInsnAnnotation

          +
          public com.sun.btrace.org.objectweb.asm.AnnotationVisitor visitInsnAnnotation(int i,
          +                                                                              com.sun.btrace.org.objectweb.asm.TypePath tp,
          +                                                                              java.lang.String string,
          +                                                                              boolean bln)
          +
          +
          Overrides:
          +
          visitInsnAnnotation in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitLabel

          +
          public void visitLabel(com.sun.btrace.org.objectweb.asm.Label label)
          +
          +
          Overrides:
          +
          visitLabel in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitAttribute

          +
          public void visitAttribute(com.sun.btrace.org.objectweb.asm.Attribute atrbt)
          +
          +
          Overrides:
          +
          visitAttribute in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitParameterAnnotation

          +
          public com.sun.btrace.org.objectweb.asm.AnnotationVisitor visitParameterAnnotation(int i,
          +                                                                                   java.lang.String string,
          +                                                                                   boolean bln)
          +
          +
          Overrides:
          +
          visitParameterAnnotation in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitTypeAnnotation

          +
          public com.sun.btrace.org.objectweb.asm.AnnotationVisitor visitTypeAnnotation(int i,
          +                                                                              com.sun.btrace.org.objectweb.asm.TypePath tp,
          +                                                                              java.lang.String string,
          +                                                                              boolean bln)
          +
          +
          Overrides:
          +
          visitTypeAnnotation in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitAnnotation

          +
          public com.sun.btrace.org.objectweb.asm.AnnotationVisitor visitAnnotation(java.lang.String string,
          +                                                                          boolean bln)
          +
          +
          Overrides:
          +
          visitAnnotation in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitAnnotationDefault

          +
          public com.sun.btrace.org.objectweb.asm.AnnotationVisitor visitAnnotationDefault()
          +
          +
          Overrides:
          +
          visitAnnotationDefault in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitParameter

          +
          public void visitParameter(java.lang.String string,
          +                           int i)
          +
          +
          Overrides:
          +
          visitParameter in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitEnd

          +
          public void visitEnd()
          +
          +
          Overrides:
          +
          visitEnd in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          visitMaxs

          +
          public void visitMaxs(int stack,
          +                      int locals)
          +
          +
          Overrides:
          +
          visitMaxs in class com.sun.btrace.org.objectweb.asm.MethodVisitor
          +
          +
        • +
        + + + +
          +
        • +

          getClassName

          +
          public java.lang.String getClassName()
          +
        • +
        + + + +
          +
        • +

          getMethodName

          +
          public java.lang.String getMethodName()
          +
        • +
        + + + +
          +
        • +

          getDesc

          +
          public java.lang.String getDesc()
          +
        • +
        + + + + +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/util/templates/impl/MethodTrackingExpander.html b/misc/btrace/javadoc/com/sun/btrace/util/templates/impl/MethodTrackingExpander.html new file mode 100644 index 00000000..5c93f675 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/util/templates/impl/MethodTrackingExpander.html @@ -0,0 +1,568 @@ + + + + + +MethodTrackingExpander (btrace 1.3.11 API) + + + + + + + + + + + + +
    +
    com.sun.btrace.util.templates.impl
    +

    Class MethodTrackingExpander

    +
    +
    + +
    +
      +
    • +
      +
      All Implemented Interfaces:
      +
      TemplateExpander
      +
      +
      +
      +
      public class MethodTrackingExpander
      +extends BaseTemplateExpander
      +
      This expander takes care of macros related to all the sampling and timing functionality
      +
    • +
    +
    +
    + +
    +
    + +
    +
    + + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/util/templates/impl/package-frame.html b/misc/btrace/javadoc/com/sun/btrace/util/templates/impl/package-frame.html new file mode 100644 index 00000000..27082bc2 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/util/templates/impl/package-frame.html @@ -0,0 +1,20 @@ + + + + + +com.sun.btrace.util.templates.impl (btrace 1.3.11 API) + + + + + +

    com.sun.btrace.util.templates.impl

    +
    +

    Classes

    + +
    + + diff --git a/misc/btrace/javadoc/com/sun/btrace/util/templates/impl/package-summary.html b/misc/btrace/javadoc/com/sun/btrace/util/templates/impl/package-summary.html new file mode 100644 index 00000000..1c8a6f5e --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/util/templates/impl/package-summary.html @@ -0,0 +1,142 @@ + + + + + +com.sun.btrace.util.templates.impl (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Package com.sun.btrace.util.templates.impl

    +
    +
    +
      +
    • + + + + + + + + + + + + +
      Class Summary 
      ClassDescription
      MethodTrackingExpander +
      This expander takes care of macros related to all the sampling and timing functionality
      +
      +
    • +
    +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/util/templates/impl/package-tree.html b/misc/btrace/javadoc/com/sun/btrace/util/templates/impl/package-tree.html new file mode 100644 index 00000000..6803fec9 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/util/templates/impl/package-tree.html @@ -0,0 +1,139 @@ + + + + + +com.sun.btrace.util.templates.impl Class Hierarchy (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Hierarchy For Package com.sun.btrace.util.templates.impl

    +Package Hierarchies: + +
    +
    +

    Class Hierarchy

    + +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/util/templates/package-frame.html b/misc/btrace/javadoc/com/sun/btrace/util/templates/package-frame.html new file mode 100644 index 00000000..676e24fa --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/util/templates/package-frame.html @@ -0,0 +1,32 @@ + + + + + +com.sun.btrace.util.templates (btrace 1.3.11 API) + + + + + +

    com.sun.btrace.util.templates

    + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/util/templates/package-summary.html b/misc/btrace/javadoc/com/sun/btrace/util/templates/package-summary.html new file mode 100644 index 00000000..c81df17f --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/util/templates/package-summary.html @@ -0,0 +1,205 @@ + + + + + +com.sun.btrace.util.templates (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Package com.sun.btrace.util.templates

    +
    +
    +
      +
    • + + + + + + + + + + + + + + + + +
      Interface Summary 
      InterfaceDescription
      TemplateExpander +
      An interface to be implemented by the template expanders
      +
      TemplateExpander.Consumer<T> +
      A knockoff of the java.util.function.Consumer interface for pre-8 usage
      +
      +
    • +
    • + + + + + + + + + + + + + + + + + + + + + + + + +
      Class Summary 
      ClassDescription
      BaseTemplateExpander +
      A generic base class for TemplateExpander implementations
      +
      BTraceTemplates +
      A central place for bytecode templates
      +
      Template +
      A template descriptor
      +
      TemplateExpanderVisitor +
      An ASM visitor providing customized template expansion
      +
      +
    • +
    • + + + + + + + + + + + + +
      Enum Summary 
      EnumDescription
      TemplateExpander.Result +
      The result of expansion + + EXPANDED = expander has claimed and expanded the template + CLAIMED = expander has claimed the template but didn't expand it + IGNORED = expander has not claimed the template +
      +
      +
    • +
    +
    + + + + + + diff --git a/misc/btrace/javadoc/com/sun/btrace/util/templates/package-tree.html b/misc/btrace/javadoc/com/sun/btrace/util/templates/package-tree.html new file mode 100644 index 00000000..e1b1f2e5 --- /dev/null +++ b/misc/btrace/javadoc/com/sun/btrace/util/templates/package-tree.html @@ -0,0 +1,163 @@ + + + + + +com.sun.btrace.util.templates Class Hierarchy (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Hierarchy For Package com.sun.btrace.util.templates

    +Package Hierarchies: + +
    +
    +

    Class Hierarchy

    + +

    Interface Hierarchy

    + +

    Enum Hierarchy

    +
      +
    • java.lang.Object +
        +
      • java.lang.Enum<E> (implements java.lang.Comparable<T>, java.io.Serializable) + +
      • +
      +
    • +
    +
    + + + + + + diff --git a/misc/btrace/javadoc/constant-values.html b/misc/btrace/javadoc/constant-values.html new file mode 100644 index 00000000..469c8a6f --- /dev/null +++ b/misc/btrace/javadoc/constant-values.html @@ -0,0 +1,1043 @@ + + + + + +Constant Field Values (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Constant Field Values

    +

    Contents

    + +
    +
    + + +

    com.sun.*

    + +
      +
    • + + + + + + + + + + + + + + +
      com.sun.btrace.agent.Main 
      Modifier and TypeConstant FieldValue
      + +public static final intBTRACE_DEFAULT_PORT2020
      +
    • +
    +
      +
    • + + + + + + + + + + + + + + +
      com.sun.btrace.annotations.Sampled 
      Modifier and TypeConstant FieldValue
      + +public static final intMEAN_DEFAULT10
      +
    • +
    +
      +
    • + + + + + + + + + + + + + + +
      com.sun.btrace.client.Main 
      Modifier and TypeConstant FieldValue
      + +public static final intBTRACE_DEFAULT_PORT2020
      +
    • +
    + + +
      +
    • + + + + + + + + + + + + + + +
      com.sun.btrace.shared.EventHandler 
      Modifier and TypeConstant FieldValue
      + +public static final java.lang.StringALL_EVENTS""
      +
    • +
    +
      +
    • + + + + + + + + + + + + + + + + + + + +
      com.sun.btrace.spi.PortLocator 
      Modifier and TypeConstant FieldValue
      + +public static final intDEFAULT_PORT2020
      + +public static final java.lang.StringPORT_PROPERTY"btrace.port"
      +
    • +
    +
      +
    • + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      com.sun.btrace.util.templates.impl.MethodTrackingExpander 
      Modifier and TypeConstant FieldValue
      + +public static final java.lang.String$LEVEL"level"
      + +public static final java.lang.String$MEAN"mean"
      + +public static final java.lang.String$METHODID"methodid"
      + +public static final java.lang.String$SAMPLER"sampler"
      + +public static final java.lang.String$TIMED"timed"
      +
    • +
    +
    + + + + + + diff --git a/misc/btrace/javadoc/deprecated-list.html b/misc/btrace/javadoc/deprecated-list.html new file mode 100644 index 00000000..d4e0bb47 --- /dev/null +++ b/misc/btrace/javadoc/deprecated-list.html @@ -0,0 +1,197 @@ + + + + + +Deprecated List (btrace 1.3.11 API) + + + + + + + + +
    + + + + + + + +
    + + + +
    + + + + + + + + + + + +
    + +
    + + + + + + + +
    + + + + diff --git a/misc/btrace/javadoc/help-doc.html b/misc/btrace/javadoc/help-doc.html new file mode 100644 index 00000000..dbb0c471 --- /dev/null +++ b/misc/btrace/javadoc/help-doc.html @@ -0,0 +1,223 @@ + + + + + +API Help (btrace 1.3.11 API) + + + + + + + + +
    + + + + + + + +
    + + +
    +

    How This API Document Is Organized

    +
    This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.
    +
    +
    +
      +
    • +

      Overview

      +

      The Overview page is the front page of this API document and provides a list of all packages with a summary for each. This page can also contain an overall description of the set of packages.

      +
    • +
    • +

      Package

      +

      Each package has a page that contains a list of its classes and interfaces, with a summary for each. This page can contain six categories:

      +
        +
      • Interfaces (italic)
      • +
      • Classes
      • +
      • Enums
      • +
      • Exceptions
      • +
      • Errors
      • +
      • Annotation Types
      • +
      +
    • +
    • +

      Class/Interface

      +

      Each class, interface, nested class and nested interface has its own separate page. Each of these pages has three sections consisting of a class/interface description, summary tables, and detailed member descriptions:

      +
        +
      • Class inheritance diagram
      • +
      • Direct Subclasses
      • +
      • All Known Subinterfaces
      • +
      • All Known Implementing Classes
      • +
      • Class/interface declaration
      • +
      • Class/interface description
      • +
      +
        +
      • Nested Class Summary
      • +
      • Field Summary
      • +
      • Constructor Summary
      • +
      • Method Summary
      • +
      +
        +
      • Field Detail
      • +
      • Constructor Detail
      • +
      • Method Detail
      • +
      +

      Each summary entry contains the first sentence from the detailed description for that item. The summary entries are alphabetical, while the detailed descriptions are in the order they appear in the source code. This preserves the logical groupings established by the programmer.

      +
    • +
    • +

      Annotation Type

      +

      Each annotation type has its own separate page with the following sections:

      +
        +
      • Annotation Type declaration
      • +
      • Annotation Type description
      • +
      • Required Element Summary
      • +
      • Optional Element Summary
      • +
      • Element Detail
      • +
      +
    • +
    • +

      Enum

      +

      Each enum has its own separate page with the following sections:

      +
        +
      • Enum declaration
      • +
      • Enum description
      • +
      • Enum Constant Summary
      • +
      • Enum Constant Detail
      • +
      +
    • +
    • +

      Tree (Class Hierarchy)

      +

      There is a Class Hierarchy page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. The classes are organized by inheritance structure starting with java.lang.Object. The interfaces do not inherit from java.lang.Object.

      +
        +
      • When viewing the Overview page, clicking on "Tree" displays the hierarchy for all packages.
      • +
      • When viewing a particular package, class or interface page, clicking "Tree" displays the hierarchy for only that package.
      • +
      +
    • +
    • +

      Deprecated API

      +

      The Deprecated API page lists all of the API that have been deprecated. A deprecated API is not recommended for use, generally due to improvements, and a replacement API is usually given. Deprecated APIs may be removed in future implementations.

      +
    • +
    • +

      Index

      +

      The Index contains an alphabetic list of all classes, interfaces, constructors, methods, and fields.

      +
    • +
    • +

      Prev/Next

      +

      These links take you to the next or previous class, interface, package, or related page.

      +
    • +
    • +

      Frames/No Frames

      +

      These links show and hide the HTML frames. All pages are available with or without frames.

      +
    • +
    • +

      All Classes

      +

      The All Classes link shows all classes and interfaces except non-static nested types.

      +
    • +
    • +

      Serialized Form

      +

      Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description.

      +
    • +
    • +

      Constant Field Values

      +

      The Constant Field Values page lists the static final fields and their values.

      +
    • +
    +This help file applies to API documentation generated using the standard doclet.
    + +
    + + + + + + + +
    + + + + diff --git a/misc/btrace/javadoc/index-all.html b/misc/btrace/javadoc/index-all.html new file mode 100644 index 00000000..37118662 --- /dev/null +++ b/misc/btrace/javadoc/index-all.html @@ -0,0 +1,6357 @@ + + + + + +Index (btrace 1.3.11 API) + + + + + + + + +
    + + + + + + + +
    + + +
    $ A B C D E F G H I J K L M N O P R S T U V W  + + +

    $

    +
    +
    $(int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns n'th command line argument.
    +
    +
    $(String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a command line argument value for the given key.
    +
    +
    $(int) - Static method in class com.sun.btrace.BTraceUtils.Sys
    +
    +
    Returns n'th command line argument.
    +
    +
    $(String) - Static method in class com.sun.btrace.BTraceUtils.Sys
    +
    +
    Returns a command line argument value for the given key.
    +
    +
    $length() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the number of command line arguments.
    +
    +
    $length() - Static method in class com.sun.btrace.BTraceUtils.Sys
    +
    +
    Returns the number of command line arguments.
    +
    +
    $LEVEL - Static variable in class com.sun.btrace.util.templates.impl.MethodTrackingExpander
    +
     
    +
    $MEAN - Static variable in class com.sun.btrace.util.templates.impl.MethodTrackingExpander
    +
     
    +
    $METHODID - Static variable in class com.sun.btrace.util.templates.impl.MethodTrackingExpander
    +
     
    +
    $SAMPLER - Static variable in class com.sun.btrace.util.templates.impl.MethodTrackingExpander
    +
     
    +
    $TIMED - Static variable in class com.sun.btrace.util.templates.impl.MethodTrackingExpander
    +
     
    +
    + + + +

    A

    +
    +
    accept(BTraceClassReader, ClassVisitor) - Static method in class com.sun.btrace.runtime.InstrumentUtils
    +
     
    +
    accept(BTraceClassReader, ClassVisitor, int) - Static method in class com.sun.btrace.runtime.InstrumentUtils
    +
     
    +
    accessFlags(Class) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the access flags of the given Class.
    +
    +
    accessFlags(Field) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the access flags of the given Field.
    +
    +
    accessFlags(Class) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Returns the access flags of the given Class.
    +
    +
    accessFlags(Field) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Returns the access flags of the given Field.
    +
    +
    add(long) - Method in class com.sun.btrace.aggregation.Aggregation
    +
    +
    Adds an item of data to the aggregation with an empty key.
    +
    +
    add(AggregationKey, long) - Method in class com.sun.btrace.aggregation.Aggregation
    +
    +
    Adds an item of data to the aggregation with the specified grouping key.
    +
    +
    add(long) - Method in interface com.sun.btrace.aggregation.AggregationValue
    +
    +
    Adds a data item to the aggregated value.
    +
    +
    add(V) - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    add(CharSequence) - Method in class com.sun.btrace.util.PrefixMap
    +
     
    +
    addAll(Collection<? extends V>) - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    addAndGet(AtomicInteger, int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Atomically adds the given value to the current value.
    +
    +
    addAndGet(AtomicLong, long) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Atomically adds the given value to the current value.
    +
    +
    addAndGet(AtomicInteger, int) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Atomically adds the given value to the current value.
    +
    +
    addAndGet(AtomicLong, long) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Atomically adds the given value to the current value.
    +
    +
    addEdge(Object, Object) - Method in class com.sun.btrace.DOTWriter
    +
     
    +
    addEdge(Object, Object, String) - Method in class com.sun.btrace.DOTWriter
    +
     
    +
    addEdge(Object, int, Object, int) - Method in class com.sun.btrace.DOTWriter
    +
     
    +
    addEdge(Object, int, Object, int, String) - Method in class com.sun.btrace.DOTWriter
    +
     
    +
    addEdge(String, String) - Method in class com.sun.btrace.runtime.CallGraph
    +
     
    +
    addExtraTypeInfo(int, Type) - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    addFirst(V) - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    addIncoming(CallGraph.Edge) - Method in class com.sun.btrace.runtime.CallGraph.Node
    +
     
    +
    addLast(V) - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    addLast(Deque<V>, V) - Static method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    addLast(Deque<V>, V) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    addLast(Deque<V>, V) - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    addLevelCheck(String, Level, Label) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    addLevelCheck(String, Interval, Label) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    addMessageDispatcher(BTraceTask.MessageDispatcher) - Method in class com.sun.btrace.api.BTraceTask
    +
     
    +
    addMessageDispatcher(BTraceTask.MessageDispatcher) - Method in class com.sun.btrace.api.impl.BTraceTaskImpl
    +
    +
    Dispatcher management
    +
    +
    addNode(String, Object) - Method in class com.sun.btrace.DOTWriter
    +
     
    +
    addNodes(Object...) - Method in class com.sun.btrace.DOTWriter
    +
     
    +
    addOutgoing(CallGraph.Edge) - Method in class com.sun.btrace.runtime.CallGraph.Node
    +
     
    +
    addStarting(CallGraph.Node) - Method in class com.sun.btrace.runtime.CallGraph
    +
     
    +
    addStateListener(BTraceTask.StateListener) - Method in class com.sun.btrace.api.BTraceTask
    +
    +
    Listener management
    +
    +
    addStateListener(BTraceTask.StateListener) - Method in class com.sun.btrace.api.impl.BTraceTaskImpl
    +
    +
    Listener management
    +
    +
    addToAggregation(Aggregation, long) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Adds a value to the aggregation with no grouping key.
    +
    +
    addToAggregation(Aggregation, AggregationKey, long) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Adds a value to the aggregation with a grouping key.
    +
    +
    addToAggregation(Aggregation, long) - Static method in class com.sun.btrace.BTraceUtils.Aggregations
    +
    +
    Adds a value to the aggregation with no grouping key.
    +
    +
    addToAggregation(Aggregation, AggregationKey, long) - Static method in class com.sun.btrace.BTraceUtils.Aggregations
    +
    +
    Adds a value to the aggregation with a grouping key.
    +
    +
    addTryCatchHandler(Label, Label) - Method in class com.sun.btrace.runtime.BTraceMethodVisitor
    +
     
    +
    addTryCatchHandler(Label, Label) - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    addTryCatchHandler(Label, Label) - Method in interface com.sun.btrace.runtime.MethodInstrumentorHelper
    +
     
    +
    afterObjectNew(String) - Method in class com.sun.btrace.runtime.instr.ObjectAllocInstrumentor
    +
     
    +
    agentmain(String, Instrumentation) - Static method in class com.sun.btrace.agent.Main
    +
     
    +
    Aggregation - Class in com.sun.btrace.aggregation
    +
    +
    BTrace stores the results of aggregating functions in an Aggregation.
    +
    +
    Aggregation(AggregationFunction) - Constructor for class com.sun.btrace.aggregation.Aggregation
    +
    +
    Creates an aggregation.
    +
    +
    AggregationFunction - Enum in com.sun.btrace.aggregation
    +
    +
    The type of aggregation functions.
    +
    +
    AggregationKey - Class in com.sun.btrace.aggregation
    +
    +
    A key identifying an element of data in an aggregation.
    +
    +
    AggregationKey(Object[]) - Constructor for class com.sun.btrace.aggregation.AggregationKey
    +
     
    +
    Aggregations() - Constructor for class com.sun.btrace.BTraceUtils.Aggregations
    +
     
    +
    AggregationValue - Interface in com.sun.btrace.aggregation
    +
    +
    An element of aggregated data stored in an Aggregation.
    +
    +
    all() - Static method in class com.sun.btrace.util.Interval
    +
     
    +
    ALL_EVENTS - Static variable in class com.sun.btrace.shared.EventHandler
    +
     
    +
    AnnotationSerializer - Class in com.sun.btrace.compiler
    +
     
    +
    AnnotationSerializer() - Constructor for class com.sun.btrace.compiler.AnnotationSerializer
    +
     
    +
    ANY - Static variable in class com.sun.btrace.runtime.instr.MethodInstrumentor.ValidationResult
    +
     
    +
    AnyType - Interface in com.sun.btrace
    +
    +
    This interface type is used in BTrace programs + to tell that any reference type [object or array] + is allowed in the place where it is used.
    +
    +
    ANYTYPE_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    ANYTYPE_INTERNAL - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    ANYTYPE_TYPE - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    anytypeArg(int, int) - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    anytypeArg(int, int, Type...) - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    AnyTypeArgProvider(Assembler, int, int) - Constructor for class com.sun.btrace.runtime.instr.MethodInstrumentor.AnyTypeArgProvider
    +
     
    +
    AnyTypeArgProvider(Assembler, int, int, Type[]) - Constructor for class com.sun.btrace.runtime.instr.MethodInstrumentor.AnyTypeArgProvider
    +
     
    +
    anyTypeArray - Static variable in class com.sun.btrace.runtime.TypeUtils
    +
     
    +
    append(Appendable, String) - Static method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    append(Appendable, String) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    Appends a string to an appendable buffer created by BTraceUtils.Strings.newStringBuilder()
    +
    +
    applyArgs(ArgsMap) - Method in interface com.sun.btrace.runtime.BTraceProbe
    +
     
    +
    applyArgs(ArgsMap) - Method in class com.sun.btrace.runtime.BTraceProbeNode
    +
     
    +
    applyArgs(ArgsMap) - Method in class com.sun.btrace.runtime.BTraceProbePersisted
    +
     
    +
    ArgsMap - Class in com.sun.btrace
    +
    +
    A simple argument map wrapper allowing indexed access
    +
    +
    ArgsMap(Map<String, String>, DebugSupport) - Constructor for class com.sun.btrace.ArgsMap
    +
     
    +
    ArgsMap(String[], DebugSupport) - Constructor for class com.sun.btrace.ArgsMap
    +
     
    +
    ArgsMap() - Constructor for class com.sun.btrace.ArgsMap
    +
     
    +
    ArgsMap(int, DebugSupport) - Constructor for class com.sun.btrace.ArgsMap
    +
     
    +
    ARGSMAP_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    ArgumentProvider(Assembler, int) - Constructor for class com.sun.btrace.runtime.instr.MethodInstrumentor.ArgumentProvider
    +
     
    +
    ArrayAccessInstrumentor - Class in com.sun.btrace.runtime.instr
    +
    +
    This visitor helps in inserting code whenever + an array access is done.
    +
    +
    ArrayAccessInstrumentor(ClassLoader, MethodVisitor, MethodInstrumentorHelper, String, String, int, String, String) - Constructor for class com.sun.btrace.runtime.instr.ArrayAccessInstrumentor
    +
     
    +
    ArrayAllocInstrumentor - Class in com.sun.btrace.runtime.instr
    +
    +
    This visitor helps in inserting code whenever an array + is allocated.
    +
    +
    ArrayAllocInstrumentor(ClassLoader, MethodVisitor, MethodInstrumentorHelper, String, String, int, String, String) - Constructor for class com.sun.btrace.runtime.instr.ArrayAllocInstrumentor
    +
     
    +
    arrayDescriptorFor(int) - Static method in class com.sun.btrace.runtime.InstrumentUtils
    +
     
    +
    arrayLimit(int) - Method in class com.sun.btrace.DOTWriter
    +
     
    +
    arrayLoad(Type) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    arrayStore(Type) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    asm - Variable in class com.sun.btrace.runtime.instr.MethodInstrumentor.ArgumentProvider
    +
     
    +
    asm - Variable in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    asm() - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    Assembler - Class in com.sun.btrace.runtime
    +
    +
    Convenient fluent wrapper over the ASM method visitor
    +
    +
    Assembler(MethodVisitor, MethodInstrumentorHelper) - Constructor for class com.sun.btrace.runtime.Assembler
    +
     
    +
    Atomic() - Constructor for class com.sun.btrace.BTraceUtils.Atomic
    +
     
    +
    attach(String, String, String) - Method in class com.sun.btrace.client.Client
    +
    +
    Attach the BTrace client to the given Java process.
    +
    +
    attach(String, String, String, String) - Method in class com.sun.btrace.client.Client
    +
    +
    Attach the BTrace client to the given Java process.
    +
    +
    availableProcessors() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the number of processors available to the Java virtual machine.
    +
    +
    availableProcessors() - Static method in class com.sun.btrace.BTraceUtils.Sys.Env
    +
    +
    Returns the number of processors available to the Java virtual machine.
    +
    +
    + + + +

    B

    +
    +
    backupStack(Type[], boolean) - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    BaseBTraceCompiler - Class in com.sun.btrace.spi
    +
     
    +
    BaseBTraceCompiler(BTraceTask) - Constructor for class com.sun.btrace.spi.BaseBTraceCompiler
    +
     
    +
    BaseTemplateExpander - Class in com.sun.btrace.util.templates
    +
    +
    A generic base class for TemplateExpander implementations
    +
    +
    BaseTemplateExpander(Template...) - Constructor for class com.sun.btrace.util.templates.BaseTemplateExpander
    +
     
    +
    beforeObjectNew(String) - Method in class com.sun.btrace.runtime.instr.ObjectAllocInstrumentor
    +
     
    +
    blockName - Variable in class com.sun.btrace.Profiler.Record
    +
     
    +
    BOOLEAN_BOXED_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BOOLEAN_BOXED_INTERNAL - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BOOLEAN_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BOOLEAN_VALUE - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BOOLEAN_VALUE_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    bootClassPath() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the boot class path that is used by the bootstrap class loader + to search for class files.
    +
    +
    bootClassPath() - Static method in class com.sun.btrace.BTraceUtils.Sys.VM
    +
    +
    Returns the boot class path that is used by the bootstrap class loader + to search for class files.
    +
    +
    box(boolean) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a Boolean instance representing the specified + boolean value.
    +
    +
    box(char) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a Character instance representing the specified + char value.
    +
    +
    box(byte) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a Byte instance representing the specified + byte value.
    +
    +
    box(short) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a Short instance representing the specified + short value.
    +
    +
    box(int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a Integer instance representing the specified + int value.
    +
    +
    box(long) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a Long instance representing the specified + long value.
    +
    +
    box(float) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a Float instance representing the specified + float value.
    +
    +
    box(double) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a Double instance representing the specified + double value.
    +
    +
    box(boolean) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns a Boolean instance representing the specified + boolean value.
    +
    +
    box(char) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns a Character instance representing the specified + char value.
    +
    +
    box(byte) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns a Byte instance representing the specified + byte value.
    +
    +
    box(short) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns a Short instance representing the specified + short value.
    +
    +
    box(int) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns a Integer instance representing the specified + int value.
    +
    +
    box(long) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns a Long instance representing the specified + long value.
    +
    +
    box(float) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns a Float instance representing the specified + float value.
    +
    +
    box(double) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns a Double instance representing the specified + double value.
    +
    +
    box(Type) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    box(String) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    BOX_BOOLEAN_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BOX_BYTE_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BOX_CHARACTER_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BOX_DOUBLE_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BOX_FLOAT_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BOX_INTEGER_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BOX_LONG_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BOX_SHORT_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BOX_VALUEOF - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BTrace - Annotation Type in com.sun.btrace.annotations
    +
    +
    Top-level annotation that identifies a BTrace + class.
    +
    +
    BTRACE_DEFAULT_PORT - Static variable in class com.sun.btrace.agent.Main
    +
     
    +
    BTRACE_DEFAULT_PORT - Static variable in class com.sun.btrace.client.Main
    +
     
    +
    BTRACE_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BTRACE_LEVEL_FLD - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BTRACE_METHOD_PREFIX - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BTRACE_PROBECLASSNAME_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BTRACE_PROBEMETHODNAME_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BTRACE_UTILS - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BTraceCollection<T> - Interface in com.sun.btrace
    +
    +
    Marker interface for BTrace defined collections
    +
    +
    BTraceCompiler - Class in com.sun.btrace.api
    +
     
    +
    BTraceCompiler() - Constructor for class com.sun.btrace.api.BTraceCompiler
    +
     
    +
    BTraceCompilerFactory - Interface in com.sun.btrace.spi
    +
     
    +
    BTraceCompilerFactoryImpl - Class in com.sun.btrace.spi.impl
    +
     
    +
    BTraceCompilerFactoryImpl() - Constructor for class com.sun.btrace.spi.impl.BTraceCompilerFactoryImpl
    +
     
    +
    BTraceDeque<V> - Class in com.sun.btrace
    +
     
    +
    BTraceDeque(Deque<V>) - Constructor for class com.sun.btrace.BTraceDeque
    +
     
    +
    BTraceEngine - Class in com.sun.btrace.api
    +
    +
    This class serves as a factory for BTraceTask instances
    +
    +
    BTraceEngine() - Constructor for class com.sun.btrace.api.BTraceEngine
    +
     
    +
    BTraceEngineImpl - Class in com.sun.btrace.api.impl
    +
     
    +
    BTraceEngineImpl() - Constructor for class com.sun.btrace.api.impl.BTraceEngineImpl
    +
     
    +
    BTraceMBean - Class in com.sun.btrace
    +
    +
    This is a simple DynamicMBean implementation that exposes the static + fields of BTrace class as attributes.
    +
    +
    BTraceMBean(Class) - Constructor for class com.sun.btrace.BTraceMBean
    +
     
    +
    BTraceMethodNode - Class in com.sun.btrace.runtime
    +
     
    +
    BTraceMethodVisitor - Class in com.sun.btrace.runtime
    +
     
    +
    BTraceMethodVisitor(MethodVisitor, MethodInstrumentorHelper) - Constructor for class com.sun.btrace.runtime.BTraceMethodVisitor
    +
     
    +
    BTraceProbe - Interface in com.sun.btrace.runtime
    +
     
    +
    BTraceProbeFactory - Class in com.sun.btrace.runtime
    +
    +
    A factory class for BTraceProbeNode instances
    +
    +
    BTraceProbeFactory(SharedSettings) - Constructor for class com.sun.btrace.runtime.BTraceProbeFactory
    +
     
    +
    BTraceProbeFactory(SharedSettings, boolean) - Constructor for class com.sun.btrace.runtime.BTraceProbeFactory
    +
     
    +
    BTraceProbeNode - Class in com.sun.btrace.runtime
    +
     
    +
    BTraceProbePersisted - Class in com.sun.btrace.runtime
    +
     
    +
    BTraceProbeSupport - Class in com.sun.btrace.runtime
    +
     
    +
    BTRACERT_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BTRACERT_INTERNAL - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BTRACERT_TYPE - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BTraceRuntime - Class in com.sun.btrace
    +
    +
    Helper class used by BTrace built-in functions and + also acts runtime "manager" for a specific BTrace client + and sends Commands to the CommandListener passed.
    +
    +
    BTraceRuntime(String, ArgsMap, CommandListener, DebugSupport, Instrumentation) - Constructor for class com.sun.btrace.BTraceRuntime
    +
     
    +
    BTraceService - Interface in com.sun.btrace.services.spi
    +
     
    +
    BTraceSettings - Class in com.sun.btrace.api
    +
     
    +
    BTraceSettings() - Constructor for class com.sun.btrace.api.BTraceSettings
    +
     
    +
    BTraceSettingsProvider - Interface in com.sun.btrace.spi
    +
     
    +
    BTraceSettingsProviderImpl - Class in com.sun.btrace.spi.impl
    +
     
    +
    BTraceSettingsProviderImpl() - Constructor for class com.sun.btrace.spi.impl.BTraceSettingsProviderImpl
    +
     
    +
    BTraceTask - Class in com.sun.btrace.api
    +
    +
    This class represents a single BTrace script
    +
    +
    BTraceTask() - Constructor for class com.sun.btrace.api.BTraceTask
    +
     
    +
    BTraceTask.MessageDispatcher - Class in com.sun.btrace.api
    +
    +
    CommandListener interface exposes the BTrace commands received over + the wire to anyone interested
    +
    +
    BTraceTask.State - Enum in com.sun.btrace.api
    +
    +
    This enum represents the allowed states of the tracing task
    +
    +
    BTraceTask.StateListener - Interface in com.sun.btrace.api
    +
    +
    Simple state listener interface
    +
    +
    BTraceTaskImpl - Class in com.sun.btrace.api.impl
    +
     
    +
    BTraceTaskImpl(int, BTraceEngine) - Constructor for class com.sun.btrace.api.impl.BTraceTaskImpl
    +
     
    +
    BTraceTemplates - Class in com.sun.btrace.util.templates
    +
    +
    A central place for bytecode templates
    +
    +
    BTraceTemplates() - Constructor for class com.sun.btrace.util.templates.BTraceTemplates
    +
     
    +
    BTraceTransformer - Class in com.sun.btrace.runtime
    +
    +
    The single entry point for class transformation.
    +
    +
    BTraceTransformer(DebugSupport) - Constructor for class com.sun.btrace.runtime.BTraceTransformer
    +
     
    +
    BTraceUtils - Class in com.sun.btrace
    +
    +
    This class is an all-in-one wrapper for BTrace DSL methods
    +
    +
    BTraceUtils.Aggregations - Class in com.sun.btrace
    +
     
    +
    BTraceUtils.Atomic - Class in com.sun.btrace
    +
     
    +
    BTraceUtils.Collections - Class in com.sun.btrace
    +
     
    +
    BTraceUtils.Counters - Class in com.sun.btrace
    +
     
    +
    BTraceUtils.D - Class in com.sun.btrace
    +
     
    +
    BTraceUtils.Export - Class in com.sun.btrace
    +
     
    +
    BTraceUtils.Numbers - Class in com.sun.btrace
    +
     
    +
    BTraceUtils.Profiling - Class in com.sun.btrace
    +
    +
    Profiling support.
    +
    +
    BTraceUtils.References - Class in com.sun.btrace
    +
     
    +
    BTraceUtils.Reflective - Class in com.sun.btrace
    +
     
    +
    BTraceUtils.Speculation - Class in com.sun.btrace
    +
     
    +
    BTraceUtils.Strings - Class in com.sun.btrace
    +
     
    +
    BTraceUtils.Sys - Class in com.sun.btrace
    +
     
    +
    BTraceUtils.Sys.Env - Class in com.sun.btrace
    +
     
    +
    BTraceUtils.Sys.Memory - Class in com.sun.btrace
    +
     
    +
    BTraceUtils.Sys.VM - Class in com.sun.btrace
    +
     
    +
    BTraceUtils.Threads - Class in com.sun.btrace
    +
    +
    Namespaced methods
    +
    +
    BTraceUtils.Time - Class in com.sun.btrace
    +
     
    +
    BYTE_BOXED_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BYTE_BOXED_INTERNAL - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BYTE_VALUE - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    BYTE_VALUE_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    + + + +

    C

    +
    +
    CallGraph - Class in com.sun.btrace.runtime
    +
    +
    This class allows building an arbitrary graph caller-callee relationship
    +
    +
    CallGraph() - Constructor for class com.sun.btrace.runtime.CallGraph
    +
     
    +
    CallGraph.Edge - Class in com.sun.btrace.runtime
    +
     
    +
    CallGraph.Node - Class in com.sun.btrace.runtime
    +
     
    +
    CatchInstrumentor - Class in com.sun.btrace.runtime.instr
    +
    +
    This visitor helps in inserting code whenever an exception + is caught or finally block is reached.
    +
    +
    CatchInstrumentor(ClassLoader, MethodVisitor, MethodInstrumentorHelper, String, String, int, String, String) - Constructor for class com.sun.btrace.runtime.instr.CatchInstrumentor
    +
     
    +
    CHAR_VALUE - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    CHAR_VALUE_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    CHARACTER_BOXED_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    CHARACTER_BOXED_INTERNAL - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    checkVerified() - Method in interface com.sun.btrace.runtime.BTraceProbe
    +
     
    +
    checkVerified() - Method in class com.sun.btrace.runtime.BTraceProbeNode
    +
     
    +
    checkVerified() - Method in class com.sun.btrace.runtime.BTraceProbePersisted
    +
     
    +
    CLASS_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    CLASS_INITIALIZER - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    CLASS_TYPE - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    ClassCache - Class in com.sun.btrace.runtime
    +
    +
    A simple class cache holding ClassInfo instances and being + searchable either by Class or a tuple of (className, classLoader)
    +
    +
    ClassCache() - Constructor for class com.sun.btrace.runtime.ClassCache
    +
     
    +
    ClassFilter - Class in com.sun.btrace.runtime
    +
    +
    This class checks whether a given target class + matches at least one probe specified in a BTrace + class.
    +
    +
    ClassFilter(Iterable<OnMethod>) - Constructor for class com.sun.btrace.runtime.ClassFilter
    +
     
    +
    classForName(String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns Class object for given class name.
    +
    +
    classForName(String, ClassLoader) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the Class for the given class name + using the given class loader.
    +
    +
    classForName(String) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Returns Class object for given class name.
    +
    +
    classForName(String, ClassLoader) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Returns the Class for the given class name + using the given class loader.
    +
    +
    ClassInfo - Class in com.sun.btrace.runtime
    +
    +
    Arbitrary class info type allowing access to supertype information + also for not-already-loaded classes.
    +
    +
    classOf(Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the runtime class of the given Object.
    +
    +
    classOf(Object) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Returns the runtime class of the given Object.
    +
    +
    classPath() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the Java class path that is used by the system class loader + to search for class files.
    +
    +
    classPath() - Static method in class com.sun.btrace.BTraceUtils.Sys.VM
    +
    +
    Returns the Java class path that is used by the system class loader + to search for class files.
    +
    +
    ClasspathProvider - Interface in com.sun.btrace.spi
    +
     
    +
    clear() - Method in class com.sun.btrace.aggregation.Aggregation
    +
    +
    Resets all values in the aggregation to their default.
    +
    +
    clear() - Method in interface com.sun.btrace.aggregation.AggregationValue
    +
    +
    Removes all data items previously added.
    +
    +
    clear() - Method in class com.sun.btrace.ArgsMap
    +
     
    +
    clear() - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    clear(Deque<V>) - Static method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    clear(Map<K, V>) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    clear(Map<K, V>) - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    clearAggregation(Aggregation) - Static method in class com.sun.btrace.BTraceUtils.Aggregations
    +
    +
    Resets values within the aggregation to the default.
    +
    +
    clearAggregation(Aggregation) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Resets values within the aggregation to the default.
    +
    +
    Client - Class in com.sun.btrace.client
    +
    +
    This class represents a BTrace client.
    +
    +
    Client(int) - Constructor for class com.sun.btrace.client.Client
    +
     
    +
    Client(int, String) - Constructor for class com.sun.btrace.client.Client
    +
     
    +
    Client(int, String, String, boolean, boolean, boolean, boolean, String, String) - Constructor for class com.sun.btrace.client.Client
    +
     
    +
    clone() - Method in class com.sun.btrace.aggregation.Aggregation
    +
     
    +
    clone() - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    close() - Method in class com.sun.btrace.client.Client
    +
    +
    Closes all connection state to the traced JVM.
    +
    +
    close() - Method in class com.sun.btrace.compiler.MemoryJavaFileManager
    +
     
    +
    close() - Method in class com.sun.btrace.DOTWriter
    +
     
    +
    CMD_QUEUE_LIMIT_KEY - Static variable in class com.sun.btrace.BTraceRuntime
    +
     
    +
    collectHierarchyClosure(ClassLoader, String, Set<String>, boolean) - Static method in class com.sun.btrace.runtime.InstrumentUtils
    +
    +
    Collects the type hierarchy into the provided list, sorted from the actual type to root.
    +
    +
    collectHierarchyClosure(ClassLoader, String, Set<String>, boolean, boolean) - Static method in class com.sun.btrace.runtime.InstrumentUtils
    +
    +
    Collects the type hierarchy into the provided list, sorted from the actual type to root.
    +
    +
    Collections() - Constructor for class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    com.sun.btrace - package com.sun.btrace
    +
     
    +
    com.sun.btrace.agent - package com.sun.btrace.agent
    +
     
    +
    com.sun.btrace.aggregation - package com.sun.btrace.aggregation
    +
     
    +
    com.sun.btrace.annotations - package com.sun.btrace.annotations
    +
     
    +
    com.sun.btrace.api - package com.sun.btrace.api
    +
    +
    A public API for BTrace integration into VisualVM
    +
    +
    com.sun.btrace.api.impl - package com.sun.btrace.api.impl
    +
     
    +
    com.sun.btrace.client - package com.sun.btrace.client
    +
     
    +
    com.sun.btrace.comm - package com.sun.btrace.comm
    +
     
    +
    com.sun.btrace.compiler - package com.sun.btrace.compiler
    +
     
    +
    com.sun.btrace.instr - package com.sun.btrace.instr
    +
     
    +
    com.sun.btrace.instr.random - package com.sun.btrace.instr.random
    +
     
    +
    com.sun.btrace.profiling - package com.sun.btrace.profiling
    +
     
    +
    com.sun.btrace.runtime - package com.sun.btrace.runtime
    +
     
    +
    com.sun.btrace.runtime.instr - package com.sun.btrace.runtime.instr
    +
     
    +
    com.sun.btrace.services.api - package com.sun.btrace.services.api
    +
     
    +
    com.sun.btrace.services.impl - package com.sun.btrace.services.impl
    +
     
    +
    com.sun.btrace.services.spi - package com.sun.btrace.services.spi
    +
     
    +
    com.sun.btrace.shared - package com.sun.btrace.shared
    +
     
    +
    com.sun.btrace.spi - package com.sun.btrace.spi
    +
     
    +
    com.sun.btrace.spi.impl - package com.sun.btrace.spi.impl
    +
     
    +
    com.sun.btrace.util - package com.sun.btrace.util
    +
     
    +
    com.sun.btrace.util.templates - package com.sun.btrace.util.templates
    +
     
    +
    com.sun.btrace.util.templates.impl - package com.sun.btrace.util.templates.impl
    +
     
    +
    Command - Class in com.sun.btrace.comm
    +
     
    +
    Command(byte) - Constructor for class com.sun.btrace.comm.Command
    +
     
    +
    CommandListener - Interface in com.sun.btrace
    +
    +
    Callback interface called to notify wire + protocol commands.
    +
    +
    commit(int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Commits the speculative buffer associated with id.
    +
    +
    commit(int) - Static method in class com.sun.btrace.BTraceUtils.Speculation
    +
    +
    Commits the speculative buffer associated with id.
    +
    +
    committed(MemoryUsage) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the amount of memory in bytes that is committed for the Java + virtual machine to use.
    +
    +
    committed(MemoryUsage) - Static method in class com.sun.btrace.BTraceUtils.Sys.Memory
    +
    +
    Returns the amount of memory in bytes that is committed for the Java + virtual machine to use.
    +
    +
    COMPARATOR - Static variable in class com.sun.btrace.Profiler.Record
    +
     
    +
    COMPARATOR - Static variable in class com.sun.btrace.runtime.BTraceMethodNode
    +
     
    +
    compare(Object, Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Indicates whether two given objects are "equal to" one another.
    +
    +
    compareAndSet(AtomicInteger, int, int) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Atomically sets the value of given AtomitInteger to the given + updated value if the current value == the expected value.
    +
    +
    compareAndSet(AtomicLong, long, long) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Atomically sets the value to the given updated value + if the current value == the expected value.
    +
    +
    compareAndSet(AtomicInteger, int, int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Atomically sets the value of given AtomitInteger to the given + updated value if the current value == the expected value.
    +
    +
    compareAndSet(AtomicLong, long, long) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Atomically sets the value to the given updated value + if the current value == the expected value.
    +
    +
    compareLevel(String, Level) - Method in class com.sun.btrace.runtime.Assembler
    +
    +
    Compares the instrumentation level interval against the runtime value.
    +
    +
    compareTo(String, String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Compares two strings lexicographically.
    +
    +
    compareTo(String, String) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    Compares two strings lexicographically.
    +
    +
    compareTo(Interval) - Method in class com.sun.btrace.util.Interval
    +
     
    +
    compareToIgnoreCase(String, String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Compares two strings lexicographically, ignoring case + differences.
    +
    +
    compareToIgnoreCase(String, String) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    Compares two strings lexicographically, ignoring case + differences.
    +
    +
    compile(String, String) - Method in class com.sun.btrace.api.BTraceCompiler
    +
     
    +
    compile(String, String, Writer) - Method in class com.sun.btrace.api.BTraceCompiler
    +
     
    +
    compile(String, String) - Method in class com.sun.btrace.client.Client
    +
     
    +
    compile(String, String, String) - Method in class com.sun.btrace.client.Client
    +
    +
    Compiles given BTrace program using given classpath.
    +
    +
    compile(String, String, PrintWriter) - Method in class com.sun.btrace.client.Client
    +
     
    +
    compile(String, String, PrintWriter, String) - Method in class com.sun.btrace.client.Client
    +
    +
    Compiles given BTrace program using given classpath.
    +
    +
    compile(String, String, Writer, String, String) - Method in class com.sun.btrace.compiler.Compiler
    +
     
    +
    compile(File, Writer, String, String) - Method in class com.sun.btrace.compiler.Compiler
    +
     
    +
    compile(File[], Writer, String, String) - Method in class com.sun.btrace.compiler.Compiler
    +
     
    +
    compile(Iterable<? extends JavaFileObject>, Writer, String, String) - Method in class com.sun.btrace.compiler.Compiler
    +
     
    +
    compile(String, String, Writer) - Method in class com.sun.btrace.spi.BaseBTraceCompiler
    +
     
    +
    Compiler - Class in com.sun.btrace.compiler
    +
    +
    Compiler for a BTrace program.
    +
    +
    Compiler(String, boolean) - Constructor for class com.sun.btrace.compiler.Compiler
    +
     
    +
    Compiler(String) - Constructor for class com.sun.btrace.compiler.Compiler
    +
     
    +
    Compiler(boolean) - Constructor for class com.sun.btrace.compiler.Compiler
    +
     
    +
    Compiler() - Constructor for class com.sun.btrace.compiler.Compiler
    +
     
    +
    concat(String, String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Concatenates the specified strings together.
    +
    +
    concat(String, String) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    Concatenates the specified strings together.
    +
    +
    ConcatenatingReader - Class in com.sun.btrace.compiler
    +
    +
    This code is based on PCPP code from the GlueGen project.
    +
    +
    ConcatenatingReader(BufferedReader) - Constructor for class com.sun.btrace.compiler.ConcatenatingReader
    +
    +
    This class requires that the input reader be a BufferedReader so + it can do line-oriented operations.
    +
    +
    Constants - Class in com.sun.btrace.runtime
    +
    +
    Constants shared by few classes.
    +
    +
    Constants() - Constructor for class com.sun.btrace.runtime.Constants
    +
     
    +
    constArg(int, Object) - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    CONSTRUCTOR - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    consume(T) - Method in interface com.sun.btrace.util.templates.TemplateExpander.Consumer
    +
     
    +
    contains(Object) - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    contains(Collection<E>, Object) - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    contains(Object[], Object) - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    contains(Collection<E>, Object) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    contains(Object[], Object) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    contains(CharSequence) - Method in class com.sun.btrace.util.PrefixMap
    +
     
    +
    containsAll(Collection<?>) - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    containsKey(String) - Method in class com.sun.btrace.ArgsMap
    +
     
    +
    containsKey(Map<K, V>, K) - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    containsKey(Map<K, V>, K) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    containsValue(Map<K, V>, V) - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    containsValue(Map<K, V>, V) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    contextClassLoader() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the current context class loader
    +
    +
    contextClassLoader() - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Returns the current context class loader
    +
    +
    copy(Map<K, V>, Map<K, V>) - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    copy(Collection<V>, Collection<V>) - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    copyFrom(OnMethod) - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    copyFrom(OnProbe) - Method in class com.sun.btrace.runtime.OnProbe
    +
     
    +
    copyHandlers(ClassVisitor) - Method in interface com.sun.btrace.runtime.BTraceProbe
    +
     
    +
    copyHandlers(ClassVisitor) - Method in class com.sun.btrace.runtime.BTraceProbeNode
    +
     
    +
    copyHandlers(ClassVisitor) - Method in class com.sun.btrace.runtime.BTraceProbePersisted
    +
     
    +
    count(String, long) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Adjusts the specified counter by a given delta.
    +
    +
    count(String, long, String) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Adjusts the specified counter by a given delta.
    +
    +
    count(String, long, double) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Adjusts the specified counter by a given delta.
    +
    +
    count(String, long, double, String) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Adjusts the specified counter by a given delta.
    +
    +
    Counters() - Constructor for class com.sun.btrace.BTraceUtils.Counters
    +
     
    +
    createProbe(byte[]) - Method in class com.sun.btrace.runtime.BTraceProbeFactory
    +
     
    +
    createProbe(byte[], ArgsMap) - Method in class com.sun.btrace.runtime.BTraceProbeFactory
    +
     
    +
    createProbe(InputStream) - Method in class com.sun.btrace.runtime.BTraceProbeFactory
    +
     
    +
    createProbe(InputStream, ArgsMap) - Method in class com.sun.btrace.runtime.BTraceProbeFactory
    +
     
    +
    createTask(int) - Method in class com.sun.btrace.api.BTraceEngine
    +
    +
    Abstract factory method for BTraceTask instances
    +
    +
    createTask(int) - Method in class com.sun.btrace.api.impl.BTraceEngineImpl
    +
     
    +
    currentThread() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a reference to the currently executing thread object.
    +
    +
    currentThread() - Static method in class com.sun.btrace.BTraceUtils.Threads
    +
    +
    Returns a reference to the currently executing thread object.
    +
    +
    currentThreadCpuTime() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the total CPU time for the current thread in nanoseconds.
    +
    +
    currentThreadCpuTime() - Static method in class com.sun.btrace.BTraceUtils.Sys.VM
    +
    +
    Returns the total CPU time for the current thread in nanoseconds.
    +
    +
    currentThreadUserTime() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the CPU time that the current thread has executed + in user mode in nanoseconds.
    +
    +
    currentThreadUserTime() - Static method in class com.sun.btrace.BTraceUtils.Sys.VM
    +
    +
    Returns the CPU time that the current thread has executed + in user mode in nanoseconds.
    +
    +
    customize(Properties) - Method in class com.sun.btrace.DOTWriter
    +
     
    +
    + + + +

    D

    +
    +
    D() - Constructor for class com.sun.btrace.BTraceUtils.D
    +
     
    +
    daemonThreadCount() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the current number of live daemon threads.
    +
    +
    daemonThreadCount() - Static method in class com.sun.btrace.BTraceUtils.Sys.VM
    +
    +
    Returns the current number of live daemon threads.
    +
    +
    DataCommand - Class in com.sun.btrace.comm
    +
    +
    Command that carries arbitrary "result/output" data.
    +
    +
    DataCommand(byte, String) - Constructor for class com.sun.btrace.comm.DataCommand
    +
     
    +
    deadlocks() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints the Java level deadlocks detected (if any).
    +
    +
    deadlocks(boolean) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints deadlocks detected (if any).
    +
    +
    deadlocks() - Static method in class com.sun.btrace.BTraceUtils.Threads
    +
    +
    Prints the Java level deadlocks detected (if any).
    +
    +
    deadlocks(boolean) - Static method in class com.sun.btrace.BTraceUtils.Threads
    +
    +
    Prints deadlocks detected (if any).
    +
    +
    debug(String) - Method in class com.sun.btrace.DebugSupport
    +
     
    +
    debug(Throwable) - Method in class com.sun.btrace.DebugSupport
    +
     
    +
    DEBUG_KEY - Static variable in class com.sun.btrace.SharedSettings
    +
     
    +
    debugPrint(String) - Method in class com.sun.btrace.client.Client
    +
     
    +
    DebugSupport - Class in com.sun.btrace
    +
    +
    Centralized support for logging various debug information.
    +
    +
    DebugSupport(SharedSettings) - Constructor for class com.sun.btrace.DebugSupport
    +
     
    +
    declarationToDescriptor(String) - Static method in class com.sun.btrace.runtime.TypeUtils
    +
     
    +
    declaringClass(Field) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the Class object representing the class or interface + that declares the field represented by the given Field object.
    +
    +
    declaringClass(Field) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Returns the Class object representing the class or interface + that declares the field represented by the given Field object.
    +
    +
    decrement(String) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Decrease the given counter by 1
    +
    +
    decrement(String, String) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Decrease the given counter by 1
    +
    +
    decrement(String, double) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Decrease the given counter by 1
    +
    +
    decrement(String, double, String) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Decrease the given counter by 1
    +
    +
    decrementAndGet(AtomicInteger) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Atomically decrements by one the current value of given AtomicInteger.
    +
    +
    decrementAndGet(AtomicLong) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Atomically decrements by one the current value.
    +
    +
    decrementAndGet(AtomicInteger) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Atomically decrements by one the current value of given AtomicInteger.
    +
    +
    decrementAndGet(AtomicLong) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Atomically decrements by one the current value.
    +
    +
    DEFAULT - Static variable in interface com.sun.btrace.spi.OutputProvider
    +
     
    +
    DEFAULT_PORT - Static variable in interface com.sun.btrace.spi.PortLocator
    +
     
    +
    defaultValue(String) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    defineClass(byte[]) - Method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    defineClass(byte[], boolean) - Method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    delete() - Method in class com.sun.btrace.runtime.CallGraph.Edge
    +
     
    +
    deref(Reference) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the given reference object's referent.
    +
    +
    deref(Reference) - Static method in class com.sun.btrace.BTraceUtils.References
    +
    +
    Returns the given reference object's referent.
    +
    +
    descendingIterator() - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    descriptorToSimplified(String, String, String) - Static method in class com.sun.btrace.runtime.TypeUtils
    +
     
    +
    discard(int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Discards the speculative buffer associated with id.
    +
    +
    discard(int) - Static method in class com.sun.btrace.BTraceUtils.Speculation
    +
    +
    Discards the speculative buffer associated with id.
    +
    +
    displayLinks(boolean) - Method in class com.sun.btrace.DOTWriter
    +
     
    +
    displayStatics(boolean) - Method in class com.sun.btrace.DOTWriter
    +
     
    +
    doProvide() - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor.AnyTypeArgProvider
    +
     
    +
    doProvide() - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor.ArgumentProvider
    +
     
    +
    DOTWriter - Class in com.sun.btrace
    +
    +
    Library for constructing a dot file format file containing the state of select + objects in the current running application.
    +
    +
    DOTWriter(String) - Constructor for class com.sun.btrace.DOTWriter
    +
     
    +
    DOTWRITER_PREFIX - Static variable in class com.sun.btrace.DOTWriter
    +
     
    +
    DOUBLE_BOXED_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    DOUBLE_BOXED_INTERNAL - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    DOUBLE_VALUE - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    DOUBLE_VALUE_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    DTrace - Annotation Type in com.sun.btrace.annotations
    +
    +
    Annotation for BTrace program to associate a D-script with it.
    +
    +
    dtraceProbe(String, String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    BTrace to DTrace communication chennal.
    +
    +
    dtraceProbe(String, String, int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    BTrace to DTrace communication chennal.
    +
    +
    dtraceProbe(String, String, int, int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    BTrace to DTrace communication channel.
    +
    +
    DTraceRef - Annotation Type in com.sun.btrace.annotations
    +
    +
    Annotation for BTrace program to associate a D-script with it.
    +
    +
    DUMP_DIR_KEY - Static variable in class com.sun.btrace.SharedSettings
    +
     
    +
    dumpClass(String, byte[]) - Method in class com.sun.btrace.DebugSupport
    +
     
    +
    dumpHeap(String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Dump the snapshot of the Java heap to a file in hprof + binary format.
    +
    +
    dumpHeap(String, boolean) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Dump the snapshot of the Java heap to a file in hprof + binary format.
    +
    +
    dumpHeap(String) - Static method in class com.sun.btrace.BTraceUtils.Sys.Memory
    +
    +
    Dump the snapshot of the Java heap to a file in hprof + binary format.
    +
    +
    dumpHeap(String, boolean) - Static method in class com.sun.btrace.BTraceUtils.Sys.Memory
    +
    +
    Dump the snapshot of the Java heap to a file in hprof + binary format.
    +
    +
    dup() - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    dup2() - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    dup2_x1() - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    dup2_x2() - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    dup_x1() - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    dup_x2() - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    dupArrayValue(int) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    duplicate() - Method in class com.sun.btrace.Profiler.Record
    +
     
    +
    duplicate() - Method in class com.sun.btrace.util.templates.Template
    +
     
    +
    dupReturnValue(int) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    dupValue(Type) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    dupValue(String) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    Duration - Annotation Type in com.sun.btrace.annotations
    +
    +
    It is used to mark a probe method argument as the receiver of the duration value
    + Applicable only for OnMethod annotation with Location value + of Kind.RETURN or Kind.ERROR
    +
    +
    DURATION - Static variable in class com.sun.btrace.util.templates.impl.MethodTrackingExpander
    +
    +
    Will insert the code to obtain the execution duration.
    +
    +
    DURATION_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    + + + +

    E

    +
    +
    Edge(CallGraph.Node, CallGraph.Node) - Constructor for class com.sun.btrace.runtime.CallGraph.Edge
    +
     
    +
    element() - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    ELSE_SAMPLE - Static variable in class com.sun.btrace.util.templates.impl.MethodTrackingExpander
    +
    +
    Will create the jump target for the else part of the condition + generated by MethodTrackingExpander.TEST_SAMPLE template.
    +
    +
    EMBEDDED_BTRACE_SECTION_HEADER - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    EMPTY - Static variable in interface com.sun.btrace.spi.ClasspathProvider
    +
     
    +
    endsWith(String, String) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    endsWith(String, String) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
     
    +
    enter(BTraceRuntime) - Static method in class com.sun.btrace.BTraceRuntime
    +
    +
    Enter method is called by every probed method just + before the probe actions start.
    +
    +
    enter() - Static method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    ENTRY - Static variable in class com.sun.btrace.util.templates.impl.MethodTrackingExpander
    +
    +
    Will provide necessary calls to enable sampling and timing + the method or method call.
    +
    +
    Env() - Constructor for class com.sun.btrace.BTraceUtils.Sys.Env
    +
     
    +
    eq(int) - Static method in class com.sun.btrace.util.Interval
    +
     
    +
    equals(Object) - Method in class com.sun.btrace.aggregation.AggregationKey
    +
     
    +
    equals(Object) - Method in class com.sun.btrace.api.impl.BTraceTaskImpl
    +
     
    +
    equals(Object) - Method in class com.sun.btrace.ArgsMap
    +
     
    +
    equals(Object) - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    equals(Object) - Method in class com.sun.btrace.Profiler.Record
    +
     
    +
    equals(Object) - Method in class com.sun.btrace.runtime.CallGraph.Edge
    +
     
    +
    equals(Object) - Method in class com.sun.btrace.runtime.CallGraph.Node
    +
     
    +
    equals(Object) - Method in class com.sun.btrace.runtime.ClassInfo
    +
     
    +
    equals(Object) - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor.ValidationResult
    +
     
    +
    equals(Object) - Method in class com.sun.btrace.util.Interval
    +
     
    +
    equals(Object) - Method in class com.sun.btrace.util.templates.Template
    +
     
    +
    ERROR - Static variable in class com.sun.btrace.comm.Command
    +
     
    +
    ErrorCommand - Class in com.sun.btrace.comm
    +
     
    +
    ErrorCommand(Throwable) - Constructor for class com.sun.btrace.comm.ErrorCommand
    +
     
    +
    ErrorCommand() - Constructor for class com.sun.btrace.comm.ErrorCommand
    +
     
    +
    ErrorHandler - Class in com.sun.btrace.shared
    +
     
    +
    ErrorHandler(String) - Constructor for class com.sun.btrace.shared.ErrorHandler
    +
     
    +
    ErrorReturnInstrumentor - Class in com.sun.btrace.runtime.instr
    +
    +
    This visitor helps in inserting code whenever a method + "returns" because of an exception (i.e., no exception + handler in the method and so it's frame poped).
    +
    +
    ErrorReturnInstrumentor(ClassLoader, MethodVisitor, MethodInstrumentorHelper, String, String, int, String, String) - Constructor for class com.sun.btrace.runtime.instr.ErrorReturnInstrumentor
    +
     
    +
    EVENT - Static variable in class com.sun.btrace.comm.Command
    +
     
    +
    event(String, String) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Sends an event to a DogStatsD compatible collector
    +
    +
    event(String, String, String) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Sends an event to a DogStatsD compatible collector
    +
    +
    event(String, String, long, String, String, String, Statsd.Priority, Statsd.AlertType, String) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Sends an event to a DogStatsD compatible collector
    +
    +
    EventCommand - Class in com.sun.btrace.comm
    +
     
    +
    EventCommand(String) - Constructor for class com.sun.btrace.comm.EventCommand
    +
     
    +
    EventCommand() - Constructor for class com.sun.btrace.comm.EventCommand
    +
     
    +
    EventHandler - Class in com.sun.btrace.shared
    +
     
    +
    EventHandler(String, String) - Constructor for class com.sun.btrace.shared.EventHandler
    +
     
    +
    excludeClasses(Class...) - Method in class com.sun.btrace.DOTWriter
    +
     
    +
    excludeClassNames(Pattern) - Method in class com.sun.btrace.DOTWriter
    +
     
    +
    excludeObjects(Object...) - Method in class com.sun.btrace.DOTWriter
    +
     
    +
    exit(int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Exits the BTrace session -- note that the particular client's tracing + session exits and not the observed/traced program! After exit call, + the trace action method terminates immediately and no other probe action + method (of that client) will be called after that.
    +
    +
    exit() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    This is same as exit(int) except that the exit code + is zero.
    +
    +
    exit(int) - Static method in class com.sun.btrace.BTraceUtils.Sys
    +
    +
    Exits the BTrace session -- note that the particular client's tracing + session exits and not the observed/traced program! After exit call, + the trace action method terminates immediately and no other probe action + method (of that client) will be called after that.
    +
    +
    exit() - Static method in class com.sun.btrace.BTraceUtils.Sys
    +
    +
    This is same as exit(int) except that the exit code + is zero.
    +
    +
    EXIT - Static variable in class com.sun.btrace.comm.Command
    +
     
    +
    EXIT - Static variable in class com.sun.btrace.util.templates.impl.MethodTrackingExpander
    +
    +
    This must be inserted at the exit point when using adaptive sampling.
    +
    +
    ExitCommand - Class in com.sun.btrace.comm
    +
     
    +
    ExitCommand(int) - Constructor for class com.sun.btrace.comm.ExitCommand
    +
     
    +
    ExitCommand() - Constructor for class com.sun.btrace.comm.ExitCommand
    +
     
    +
    ExitHandler - Class in com.sun.btrace.shared
    +
     
    +
    ExitHandler(String) - Constructor for class com.sun.btrace.shared.ExitHandler
    +
     
    +
    exiting - Static variable in class com.sun.btrace.client.Main
    +
     
    +
    exp(double) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns Euler's number e raised to the power of a + double value.
    +
    +
    exp(double) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns Euler's number e raised to the power of a + double value.
    +
    +
    expand(TemplateExpanderVisitor, Template) - Method in class com.sun.btrace.util.templates.BaseTemplateExpander
    +
     
    +
    expand(TemplateExpanderVisitor, Template) - Method in interface com.sun.btrace.util.templates.TemplateExpander
    +
    +
    The expander identifies and, possibly, expands the given template
    +
    +
    expand(TemplateExpander.Consumer<TemplateExpanderVisitor>) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    expandCollections(boolean) - Method in class com.sun.btrace.DOTWriter
    +
     
    +
    expandTemplate(TemplateExpanderVisitor, Template) - Method in class com.sun.btrace.util.templates.BaseTemplateExpander
    +
     
    +
    expandTemplate(TemplateExpanderVisitor, Template) - Method in class com.sun.btrace.util.templates.impl.MethodTrackingExpander
    +
     
    +
    Export - Annotation Type in com.sun.btrace.annotations
    +
    +
    BTrace fields with this annotation are exposed to + out-of-process tools using mechanisms such as jvmstat.
    +
    +
    Export() - Constructor for class com.sun.btrace.BTraceUtils.Export
    +
     
    +
    + + + +

    F

    +
    +
    field(Class, String, boolean) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a Field object that reflects the specified declared + field of the class or interface represented by the given Class + object.
    +
    +
    field(Class, String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a Field object that reflects the specified declared + field of the class or interface represented by the given Class + object.
    +
    +
    field(String, String, boolean) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a Field object that reflects the specified declared + field of the class or interface represented by the given Class + object.
    +
    +
    field(String, String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a Field object that reflects the specified declared + field of the class or interface represented by the given Class + object.
    +
    +
    field(Class, String, boolean) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Returns a Field object that reflects the specified declared + field of the class or interface represented by the given Class + object.
    +
    +
    field(Class, String) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Returns a Field object that reflects the specified declared + field of the class or interface represented by the given Class + object.
    +
    +
    field(String, String, boolean) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Returns a Field object that reflects the specified declared + field of the class or interface represented by the given Class + object.
    +
    +
    field(String, String) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Returns a Field object that reflects the specified declared + field of the class or interface represented by the given Class + object.
    +
    +
    FieldAccessInstrumentor - Class in com.sun.btrace.runtime.instr
    +
    +
    This visitor helps in inserting code whenever an field access + is done.
    +
    +
    FieldAccessInstrumentor(ClassLoader, MethodVisitor, MethodInstrumentorHelper, String, String, int, String, String) - Constructor for class com.sun.btrace.runtime.instr.FieldAccessInstrumentor
    +
     
    +
    fieldLimit(int) - Method in class com.sun.btrace.DOTWriter
    +
     
    +
    FILEROLL_INTERVAL_KEY - Static variable in class com.sun.btrace.SharedSettings
    +
     
    +
    FILEROLL_MAXROLLS_KEY - Static variable in class com.sun.btrace.SharedSettings
    +
     
    +
    finalizationCount() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the approximate number of objects for + which finalization is pending.
    +
    +
    finalizationCount() - Static method in class com.sun.btrace.BTraceUtils.Sys.Memory
    +
    +
    Returns the approximate number of objects for + which finalization is pending.
    +
    +
    findFile(String) - Method in class com.sun.btrace.compiler.PCPP
    +
     
    +
    findProbe(String) - Method in class com.sun.btrace.runtime.ProbeDescriptor
    +
     
    +
    finished(TaskEvent) - Method in class com.sun.btrace.compiler.Verifier
    +
     
    +
    FIRST_COMMAND - Static variable in class com.sun.btrace.comm.Command
    +
     
    +
    FLOAT_BOXED_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    FLOAT_BOXED_INTERNAL - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    FLOAT_VALUE - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    FLOAT_VALUE_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    flush() - Method in class com.sun.btrace.compiler.MemoryJavaFileManager
    +
     
    +
    forClass(Class, TimerHandler[], EventHandler[], ErrorHandler[], ExitHandler[], LowMemoryHandler[]) - Static method in class com.sun.btrace.BTraceRuntime
    +
    +
    One instance of BTraceRuntime is created per-client.
    +
    +
    format(String, Object...) - Static method in class com.sun.btrace.util.Messages
    +
     
    +
    freeMemory() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the amount of free memory in the Java Virtual Machine.
    +
    +
    freeMemory() - Static method in class com.sun.btrace.BTraceUtils.Sys.Memory
    +
    +
    Returns the amount of free memory in the Java Virtual Machine.
    +
    +
    from(BTraceProbe) - Static method in class com.sun.btrace.runtime.BTraceProbePersisted
    +
     
    +
    from(Map<String, Object>) - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    from(SharedSettings) - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    fromString(String) - Static method in class com.sun.btrace.runtime.Level
    +
     
    +
    fromString(String) - Static method in class com.sun.btrace.util.Interval
    +
     
    +
    + + + +

    G

    +
    +
    gauge(String, long) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Sets the specified gauge to a given value.
    +
    +
    gauge(String, long, String) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Sets the specified gauge to a given value.
    +
    +
    gc() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Runs the garbage collector.
    +
    +
    gc() - Static method in class com.sun.btrace.BTraceUtils.Sys.Memory
    +
    +
    Runs the garbage collector.
    +
    +
    ge(int) - Static method in class com.sun.btrace.util.Interval
    +
     
    +
    get(String) - Method in class com.sun.btrace.ArgsMap
    +
     
    +
    get(int) - Method in class com.sun.btrace.ArgsMap
    +
     
    +
    get(AtomicInteger) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Gets the current value of the given AtomicInteger.
    +
    +
    get(AtomicLong) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Gets the current value the given AtomicLong.
    +
    +
    get(Map<K, V>, K) - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    get(Field) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Gets the value of a static reference field.
    +
    +
    get(Field, Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Gets the value of an instance reference field.
    +
    +
    get(Map<K, V>, K) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    get(AtomicInteger) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Gets the current value of the given AtomicInteger.
    +
    +
    get(AtomicLong) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Gets the current value the given AtomicLong.
    +
    +
    get(Field) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of a static reference field.
    +
    +
    get(Field, Object) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of an instance reference field.
    +
    +
    get(String, Object) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of an instance reference field.
    +
    +
    get(Class) - Method in class com.sun.btrace.runtime.ClassCache
    +
     
    +
    get(ClassLoader, String) - Method in class com.sun.btrace.runtime.ClassCache
    +
    +
    Returns a cached ClassInfo value.
    +
    +
    get(long) - Method in class com.sun.btrace.util.LongMap
    +
     
    +
    get(String) - Static method in class com.sun.btrace.util.Messages
    +
     
    +
    getA() - Method in class com.sun.btrace.util.Interval
    +
     
    +
    getAccess() - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    getAgentJarPath() - Method in class com.sun.btrace.api.BTraceCompiler
    +
     
    +
    getAgentJarPath() - Method in class com.sun.btrace.spi.BaseBTraceCompiler
    +
     
    +
    getAndAdd(AtomicInteger, int) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Atomically adds the given value to the current value.
    +
    +
    getAndAdd(AtomicLong, long) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Atomically adds the given value to the current value.
    +
    +
    getAndAdd(AtomicInteger, int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Atomically adds the given value to the current value.
    +
    +
    getAndAdd(AtomicLong, long) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Atomically adds the given value to the current value.
    +
    +
    getAndDecrement(AtomicInteger) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Atomically decrements by one the current value of given AtomicInteger.
    +
    +
    getAndDecrement(AtomicLong) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Atomically decrements by one the current value.
    +
    +
    getAndDecrement(AtomicInteger) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Atomically decrements by one the current value of given AtomicInteger.
    +
    +
    getAndDecrement(AtomicLong) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Atomically decrements by one the current value.
    +
    +
    getAndIncrement(AtomicInteger) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Atomically increments by one the current value of given AtomicInteger.
    +
    +
    getAndIncrement(AtomicLong) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Atomically increments by one the current value.
    +
    +
    getAndIncrement(AtomicInteger) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Atomically increments by one the current value of given AtomicInteger.
    +
    +
    getAndIncrement(AtomicLong) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Atomically increments by one the current value.
    +
    +
    getAndSet(AtomicInteger, int) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Atomically sets to the given value and returns the old value.
    +
    +
    getAndSet(AtomicLong, long) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Atomically sets to the given value and returns the old value.
    +
    +
    getAndSet(AtomicInteger, int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Atomically sets to the given value and returns the old value.
    +
    +
    getAndSet(AtomicLong, long) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Atomically sets to the given value and returns the old value.
    +
    +
    getApplicableHandlers(BTraceClassReader) - Method in interface com.sun.btrace.runtime.BTraceProbe
    +
     
    +
    getApplicableHandlers(BTraceClassReader) - Method in class com.sun.btrace.runtime.BTraceProbeNode
    +
     
    +
    getApplicableHandlers(BTraceClassReader) - Method in class com.sun.btrace.runtime.BTraceProbePersisted
    +
     
    +
    getArgCnt() - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor.ValidationResult
    +
     
    +
    getArgIdx(int) - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor.ValidationResult
    +
     
    +
    getArguments() - Method in class com.sun.btrace.comm.InstrumentCommand
    +
     
    +
    getArrayType(int) - Static method in class com.sun.btrace.runtime.TypeUtils
    +
     
    +
    getAttribute(String) - Method in class com.sun.btrace.BTraceMBean
    +
     
    +
    getAttributes(String[]) - Method in class com.sun.btrace.BTraceMBean
    +
     
    +
    getB() - Method in class com.sun.btrace.util.Interval
    +
     
    +
    getBoolean(Field) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Gets the value of a static boolean field.
    +
    +
    getBoolean(Field, Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Gets the value of an instance boolean field.
    +
    +
    getBoolean(Field) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of a static boolean field.
    +
    +
    getBoolean(Field, Object) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of an instance boolean field.
    +
    +
    getBoolean(String, Object) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of an instance boolean field.
    +
    +
    getBooleanStatic(String, Class) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of a static boolean field.
    +
    +
    getByte(Field) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Gets the value of a static byte field.
    +
    +
    getByte(Field, Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Gets the value of an instance byte field.
    +
    +
    getByte(Field) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of a static byte field.
    +
    +
    getByte(Field, Object) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of an instance byte field.
    +
    +
    getByte(String, Object) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of an instance byte field.
    +
    +
    getByteStatic(String, Class) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of a static byte field.
    +
    +
    getCallees() - Method in class com.sun.btrace.runtime.BTraceMethodNode
    +
     
    +
    getCallers() - Method in class com.sun.btrace.runtime.BTraceMethodNode
    +
     
    +
    getCallId() - Method in class com.sun.btrace.runtime.instr.MethodCallInstrumentor
    +
     
    +
    getCause() - Method in class com.sun.btrace.comm.ErrorCommand
    +
     
    +
    getChar(Field) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Gets the value of a static char field.
    +
    +
    getChar(Field, Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Gets the value of an instance char field.
    +
    +
    getChar(Field) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of a static char field.
    +
    +
    getChar(Field, Object) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of an instance char field.
    +
    +
    getChar(String, Object) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of an instance char field.
    +
    +
    getCharStatic(String, Class) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of a static char field.
    +
    +
    getClassBytes() - Method in class com.sun.btrace.compiler.MemoryJavaFileManager
    +
     
    +
    getClassName() - Method in class com.sun.btrace.comm.RetransformClassNotification
    +
     
    +
    getClassName() - Method in interface com.sun.btrace.runtime.BTraceProbe
    +
     
    +
    getClassName(boolean) - Method in interface com.sun.btrace.runtime.BTraceProbe
    +
     
    +
    getClassName() - Method in class com.sun.btrace.runtime.BTraceProbeNode
    +
     
    +
    getClassName(boolean) - Method in class com.sun.btrace.runtime.BTraceProbeNode
    +
     
    +
    getClassName() - Method in class com.sun.btrace.runtime.BTraceProbePersisted
    +
     
    +
    getClassName(boolean) - Method in class com.sun.btrace.runtime.BTraceProbePersisted
    +
     
    +
    getClassName() - Method in class com.sun.btrace.runtime.ClassInfo
    +
    +
    Class ID = internal class name
    +
    +
    getClassName() - Method in class com.sun.btrace.runtime.Verifier
    +
     
    +
    getClassName() - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    getClassPath() - Method in class com.sun.btrace.api.BTraceTask
    +
     
    +
    getClassPath() - Method in class com.sun.btrace.api.impl.BTraceTaskImpl
    +
     
    +
    getClasspath(BTraceTask) - Method in interface com.sun.btrace.spi.ClasspathProvider
    +
     
    +
    getClazz() - Method in class com.sun.btrace.runtime.Location
    +
     
    +
    getClazz() - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    getClientJarPath() - Method in class com.sun.btrace.api.BTraceCompiler
    +
     
    +
    getClientJarPath() - Method in class com.sun.btrace.spi.BaseBTraceCompiler
    +
     
    +
    getClientName(String) - Static method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    getClientName() - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    getCode() - Method in class com.sun.btrace.comm.InstrumentCommand
    +
     
    +
    getComponentType(Class) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    returns component type of an array Class.
    +
    +
    getComponentType(Class) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    returns component type of an array Class.
    +
    +
    getCounts() - Method in class com.sun.btrace.aggregation.HistogramData
    +
     
    +
    getData() - Method in class com.sun.btrace.aggregation.Aggregation
    +
    +
    Returns details of the aggregation in a tabular format which can be serialized across the wire and formatted for + display.
    +
    +
    getData() - Method in interface com.sun.btrace.aggregation.AggregationValue
    +
     
    +
    getData() - Method in class com.sun.btrace.comm.GridDataCommand
    +
     
    +
    getData() - Method in class com.sun.btrace.comm.NumberMapDataCommand
    +
     
    +
    getData() - Method in class com.sun.btrace.comm.StringMapDataCommand
    +
     
    +
    getDataHolderBytecode() - Method in interface com.sun.btrace.runtime.BTraceProbe
    +
     
    +
    getDataHolderBytecode() - Method in class com.sun.btrace.runtime.BTraceProbeNode
    +
     
    +
    getDataHolderBytecode() - Method in class com.sun.btrace.runtime.BTraceProbePersisted
    +
     
    +
    getDesc() - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    getDescriptor() - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    getDouble(Field) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Gets the value of a static double field.
    +
    +
    getDouble(Field, Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Gets the value of an instance double field.
    +
    +
    getDouble(Field) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of a static double field.
    +
    +
    getDouble(Field, Object) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of an instance double field.
    +
    +
    getDouble(String, Object) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of an instance double field.
    +
    +
    getDouble(String, Class) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of a static double field.
    +
    +
    getDumpClassPath() - Method in class com.sun.btrace.api.BTraceSettings
    +
     
    +
    getDumpDir() - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    getElements() - Method in class com.sun.btrace.aggregation.AggregationKey
    +
     
    +
    getElementType(int) - Static method in class com.sun.btrace.runtime.TypeUtils
    +
     
    +
    getEndTs(int) - Static method in class com.sun.btrace.instr.MethodTracker
    +
    +
    Used when timing the method execution or in adaptive sampling.
    +
    +
    getenv(String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Gets the value of the specified environment variable.
    +
    +
    getenv() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns an unmodifiable string map view of the current system environment.
    +
    +
    getenv(String) - Static method in class com.sun.btrace.BTraceUtils.Sys.Env
    +
    +
    Gets the value of the specified environment variable.
    +
    +
    getenv() - Static method in class com.sun.btrace.BTraceUtils.Sys.Env
    +
    +
    Returns an unmodifiable string map view of the current system environment.
    +
    +
    getEvent() - Method in class com.sun.btrace.comm.EventCommand
    +
     
    +
    getEvent() - Method in class com.sun.btrace.shared.EventHandler
    +
     
    +
    getExitCode() - Method in class com.sun.btrace.comm.ExitCommand
    +
     
    +
    getField() - Method in class com.sun.btrace.runtime.Location
    +
     
    +
    getFileRollMaxRolls() - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    getFileRollMilliseconds() - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    getFirst() - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    getFloat(Field) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Gets the value of a static float field.
    +
    +
    getFloat(Field, Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Gets the value of an instance float field.
    +
    +
    getFloat(Field) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of a static float field.
    +
    +
    getFloat(Field, Object) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of an instance float field.
    +
    +
    getFloat(String, Object) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of an instance float field.
    +
    +
    getFloatStatic(String, Class) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of a static float field.
    +
    +
    getFullBytecode() - Method in interface com.sun.btrace.runtime.BTraceProbe
    +
     
    +
    getFullBytecode() - Method in class com.sun.btrace.runtime.BTraceProbeNode
    +
     
    +
    getFullBytecode() - Method in class com.sun.btrace.runtime.BTraceProbePersisted
    +
     
    +
    getIndex() - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor.ArgumentProvider
    +
     
    +
    getInstance() - Static method in class com.sun.btrace.instr.RandomIntProvider
    +
     
    +
    getInstance() - Static method in class com.sun.btrace.runtime.ClassCache
    +
     
    +
    getInstance() - Static method in class com.sun.btrace.services.impl.Statsd
    +
     
    +
    getInstrClasses() - Method in class com.sun.btrace.api.BTraceTask
    +
    +
    The number of classes the task needs to instruments
    +
    +
    getInstrClasses() - Method in class com.sun.btrace.api.impl.BTraceTaskImpl
    +
     
    +
    getInstrumentationLevel() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the current instrumentation level.
    +
    +
    getInt(Field) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Gets the value of a static int field.
    +
    +
    getInt(Field, Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Gets the value of an instance int field.
    +
    +
    getInt(Field) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of a static int field.
    +
    +
    getInt(Field, Object) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of an instance int field.
    +
    +
    getInt(String, Object) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of an instance int field.
    +
    +
    getIntStatic(String, Class) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of a sttaic int field.
    +
    +
    getJavaClassName() - Method in class com.sun.btrace.runtime.ClassInfo
    +
     
    +
    getJavaFileForInput(JavaFileManager.Location, String, JavaFileObject.Kind) - Method in class com.sun.btrace.compiler.MemoryJavaFileManager
    +
     
    +
    getJavaFileForOutput(JavaFileManager.Location, String, JavaFileObject.Kind, FileObject) - Method in class com.sun.btrace.compiler.MemoryJavaFileManager
    +
     
    +
    getJavaType(String) - Static method in class com.sun.btrace.runtime.TypeUtils
    +
     
    +
    getKeyData() - Method in class com.sun.btrace.aggregation.Aggregation
    +
    +
    Returns a list of the AggregationKeys that belong to this aggregation.
    +
    +
    getLast() - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    getLevel() - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    getLine() - Method in class com.sun.btrace.runtime.Location
    +
     
    +
    getLoaderId() - Method in class com.sun.btrace.runtime.ClassInfo
    +
    +
    Associated class loader string representation as returned by cl.toString() or "<null>"
    +
    +
    getLocation() - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    getLong(Field) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Gets the value of a static long field.
    +
    +
    getLong(Field, Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Gets the value of an instance long field.
    +
    +
    getLong(Field) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of a static long field.
    +
    +
    getLong(Field, Object) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of an instance long field.
    +
    +
    getLong(String, Object) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of an instance long field.
    +
    +
    getLongStatic(String, Class) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of a static long field.
    +
    +
    getMBeanInfo() - Method in class com.sun.btrace.BTraceMBean
    +
     
    +
    getMBeanValue() - Method in interface com.sun.btrace.Profiler.MBeanValueProvider
    +
     
    +
    getMBeanValue() - Method in class com.sun.btrace.profiling.MethodInvocationProfiler
    +
     
    +
    getMemoryPoolUsage(String) - Static method in class com.sun.btrace.BTraceUtils.Sys.Memory
    +
    +
    Returns an overview of available memory pools
    + It is possible to provide a text format the overview will use
    +
    +
    getMessage() - Method in class com.sun.btrace.comm.MessageCommand
    +
     
    +
    getMethod() - Method in class com.sun.btrace.runtime.Location
    +
     
    +
    getMethod() - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    getMethod(Class) - Method in class com.sun.btrace.shared.ErrorHandler
    +
     
    +
    getMethod(Class) - Method in class com.sun.btrace.shared.EventHandler
    +
     
    +
    getMethod(Class) - Method in class com.sun.btrace.shared.ExitHandler
    +
     
    +
    getMethod(Class) - Method in class com.sun.btrace.shared.LowMemoryHandler
    +
     
    +
    getMethod(Class) - Method in class com.sun.btrace.shared.TimerHandler
    +
     
    +
    getMethodId(String) - Static method in class com.sun.btrace.util.MethodID
    +
    +
    Generates a unique method id based on the provided method tag
    +
    +
    getMethodId(String, String, String) - Static method in class com.sun.btrace.util.MethodID
    +
     
    +
    getMethodName() - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    getMethodNode() - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    getMethodNode() - Method in class com.sun.btrace.runtime.OnProbe
    +
     
    +
    getName() - Method in class com.sun.btrace.api.BTraceTask
    +
    +
    Returns the name specified in BTrace annotation
    +
    +
    getName() - Method in class com.sun.btrace.api.impl.BTraceTaskImpl
    +
     
    +
    getName() - Method in class com.sun.btrace.comm.DataCommand
    +
     
    +
    getName() - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    getName(boolean) - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    getName() - Method in class com.sun.btrace.runtime.OnProbe
    +
     
    +
    getName() - Method in class com.sun.btrace.util.templates.Template
    +
     
    +
    getNamedEvents() - Method in class com.sun.btrace.api.BTraceTask
    +
    +
    A list of named events
    +
    +
    getNamedEvents() - Method in class com.sun.btrace.api.impl.BTraceTaskImpl
    +
     
    +
    getNamespace() - Method in class com.sun.btrace.runtime.OnProbe
    +
     
    +
    getNamespace() - Method in class com.sun.btrace.runtime.ProbeDescriptor
    +
     
    +
    getNewName() - Method in class com.sun.btrace.comm.RenameCommand
    +
     
    +
    getNumClasses() - Method in class com.sun.btrace.comm.RetransformationStartNotification
    +
     
    +
    getOnMethod() - Method in class com.sun.btrace.runtime.BTraceMethodNode
    +
     
    +
    getOnMethods() - Method in class com.sun.btrace.runtime.BTraceProbeNode
    +
     
    +
    getOnMethods() - Method in class com.sun.btrace.runtime.BTraceProbePersisted
    +
     
    +
    getOnMethods() - Method in class com.sun.btrace.runtime.OnProbe
    +
     
    +
    getOutputDir() - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    getOutputFile() - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    getOwner() - Method in class com.sun.btrace.util.templates.Template
    +
     
    +
    getParams() - Method in class com.sun.btrace.comm.SetSettingsCommand
    +
     
    +
    getParentClz() - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    getPerfDouble(String) - Static method in class com.sun.btrace.BTraceRuntime
    +
    +
    Return the value of double perf.
    +
    +
    getPerfFloat(String) - Static method in class com.sun.btrace.BTraceRuntime
    +
    +
    Return the value of float perf.
    +
    +
    getPerfInt(String) - Static method in class com.sun.btrace.BTraceRuntime
    +
    +
    Return the value of integer perf.
    +
    +
    getPerfLong(String) - Static method in class com.sun.btrace.BTraceRuntime
    +
    +
    Return the value of long perf.
    +
    +
    getPerfString(String) - Static method in class com.sun.btrace.BTraceRuntime
    +
    +
    Return the value of String perf.
    +
    +
    getPid() - Method in class com.sun.btrace.api.BTraceTask
    +
     
    +
    getPid() - Method in class com.sun.btrace.api.impl.BTraceTaskImpl
    +
     
    +
    getpid() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the process id of the currently BTrace'd process.
    +
    +
    getpid() - Static method in class com.sun.btrace.BTraceUtils.Sys
    +
    +
    Returns the process id of the currently BTrace'd process.
    +
    +
    getProbeDescPath() - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    getProbes() - Method in class com.sun.btrace.runtime.ProbeDescriptor
    +
     
    +
    getReturnType() - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    getSamplerKind() - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    getSamplerMean() - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    getScript() - Method in class com.sun.btrace.api.BTraceTask
    +
    +
    Property getter
    +
    +
    getScript() - Method in class com.sun.btrace.api.impl.BTraceTaskImpl
    +
     
    +
    getSettings() - Method in interface com.sun.btrace.spi.BTraceSettingsProvider
    +
     
    +
    getSettings() - Method in class com.sun.btrace.spi.impl.BTraceSettingsProviderImpl
    +
     
    +
    getShort(Field) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Gets the value of a static short field.
    +
    +
    getShort(Field, Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Gets the value of an instance short field.
    +
    +
    getShort(Field) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of a static short field.
    +
    +
    getShort(Field, Object) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of an instance short field.
    +
    +
    getShort(String, Object) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of an instance short field.
    +
    +
    getShortStatic(String, Class) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of a static short field.
    +
    +
    getSig() - Method in class com.sun.btrace.util.templates.Template
    +
     
    +
    getSkipLabel() - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    getState() - Method in class com.sun.btrace.api.impl.BTraceTaskImpl
    +
    +
    Property getter
    +
    +
    getStatic(String, Class) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Gets the value of a static reference field.
    +
    +
    getStatic(String, String, String) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    getStatsd() - Method in class com.sun.btrace.api.BTraceSettings
    +
     
    +
    getStatsdHost() - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    getStatsdPort() - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    getStdErr(BTraceTask) - Method in interface com.sun.btrace.spi.OutputProvider
    +
     
    +
    getStdOut(BTraceTask) - Method in interface com.sun.btrace.spi.OutputProvider
    +
     
    +
    getSuperclass(Class) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the Class representing the superclass of the entity + (class, interface, primitive type or void) represented by the given + Class.
    +
    +
    getSuperclass(Class) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Returns the Class representing the superclass of the entity + (class, interface, primitive type or void) represented by the given + Class.
    +
    +
    getSuperClz() - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    getSupertypes(boolean) - Method in class com.sun.btrace.runtime.ClassInfo
    +
    +
    Retrieves supertypes (including interfaces)
    +
    +
    getTagMap() - Method in class com.sun.btrace.util.templates.Template
    +
     
    +
    getTags() - Method in class com.sun.btrace.util.templates.Template
    +
     
    +
    getTargetDescriptor() - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    getTargetDescriptor() - Method in class com.sun.btrace.runtime.OnProbe
    +
     
    +
    getTargetName() - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    getTargetName() - Method in class com.sun.btrace.runtime.OnProbe
    +
     
    +
    getTaskPort(BTraceTask) - Method in class com.sun.btrace.spi.impl.PortLocatorImpl
    +
     
    +
    getTaskPort(BTraceTask) - Method in interface com.sun.btrace.spi.PortLocator
    +
     
    +
    getTemplate(String, String, String) - Static method in class com.sun.btrace.util.templates.BTraceTemplates
    +
     
    +
    getTime() - Method in class com.sun.btrace.comm.MessageCommand
    +
     
    +
    getToolsJarPath() - Method in class com.sun.btrace.api.BTraceCompiler
    +
     
    +
    getToolsJarPath() - Method in class com.sun.btrace.spi.BaseBTraceCompiler
    +
     
    +
    getTotalGcTime() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the total amount of time spent in GarbageCollection up to this point + since the application was started.
    +
    +
    getTotalGcTime() - Static method in class com.sun.btrace.BTraceUtils.Sys.Memory
    +
    +
    Returns the total amount of time spent in GarbageCollection up to this point + since the application was started.
    +
    +
    getType() - Method in class com.sun.btrace.comm.Command
    +
     
    +
    getType() - Method in class com.sun.btrace.runtime.Location
    +
     
    +
    getType() - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    getValue() - Method in interface com.sun.btrace.aggregation.AggregationValue
    +
     
    +
    getValue() - Method in class com.sun.btrace.comm.NumberDataCommand
    +
     
    +
    getValue() - Method in class com.sun.btrace.runtime.Level
    +
     
    +
    getValue() - Method in class com.sun.btrace.runtime.Location
    +
     
    +
    getValueForKey(AggregationKey) - Method in class com.sun.btrace.aggregation.Aggregation
    +
    +
    Returns a value for the given key if the key has a value associated with it.
    +
    +
    getValues() - Method in class com.sun.btrace.aggregation.HistogramData
    +
     
    +
    getWhere() - Method in class com.sun.btrace.runtime.Location
    +
     
    +
    GLOBAL - Static variable in class com.sun.btrace.SharedSettings
    +
     
    +
    graph(String, Object...) - Static method in class com.sun.btrace.DOTWriter
    +
     
    +
    GRID_DATA - Static variable in class com.sun.btrace.comm.Command
    +
     
    +
    GridDataCommand - Class in com.sun.btrace.comm
    +
    +
    A data command that holds tabular data.
    +
    +
    GridDataCommand() - Constructor for class com.sun.btrace.comm.GridDataCommand
    +
    +
    Used when deserializing a GridDataCommand instance.
    + The instance is then initialized by calling the GridDataCommand.read(java.io.ObjectInput) method
    +
    +
    GridDataCommand(String, List<Object[]>) - Constructor for class com.sun.btrace.comm.GridDataCommand
    +
    +
    Creates a new instance of GridDataCommand with implicit format
    +
    +
    GridDataCommand(String, List<Object[]>, String) - Constructor for class com.sun.btrace.comm.GridDataCommand
    +
    +
    Creates a new instance of GridDataCommand with explicit format
    +
    +
    gt(int) - Static method in class com.sun.btrace.util.Interval
    +
     
    +
    + + + +

    H

    +
    +
    handleEvent(EventCommand) - Method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    handleException(Throwable) - Static method in class com.sun.btrace.BTraceRuntime
    +
    +
    Handles exception from BTrace probe actions.
    +
    +
    handleExit(int) - Method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    hasAnonymousEvents() - Method in class com.sun.btrace.api.BTraceTask
    +
    +
    A flag indicating that the task has some anonymous events assigned
    +
    +
    hasAnonymousEvents() - Method in class com.sun.btrace.api.impl.BTraceTaskImpl
    +
     
    +
    hasCycle() - Method in class com.sun.btrace.runtime.CallGraph
    +
     
    +
    hasEvents() - Method in class com.sun.btrace.api.BTraceTask
    +
    +
    Flag property getter
    +
    +
    hasEvents() - Method in class com.sun.btrace.api.impl.BTraceTaskImpl
    +
     
    +
    hash(Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a hash code value for the object.
    +
    +
    hashCode() - Method in class com.sun.btrace.aggregation.AggregationKey
    +
     
    +
    hashCode() - Method in class com.sun.btrace.api.impl.BTraceTaskImpl
    +
     
    +
    hashCode() - Method in class com.sun.btrace.ArgsMap
    +
     
    +
    hashCode() - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    hashCode() - Method in class com.sun.btrace.Profiler.Record
    +
     
    +
    hashCode() - Method in class com.sun.btrace.runtime.CallGraph.Edge
    +
     
    +
    hashCode() - Method in class com.sun.btrace.runtime.CallGraph.Node
    +
     
    +
    hashCode() - Method in class com.sun.btrace.runtime.ClassInfo
    +
     
    +
    hashCode() - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor.ValidationResult
    +
     
    +
    hashCode() - Method in class com.sun.btrace.util.Interval
    +
     
    +
    hashCode() - Method in class com.sun.btrace.util.templates.Template
    +
     
    +
    hasMatch() - Method in class com.sun.btrace.runtime.Instrumentor
    +
     
    +
    heapUsage() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns heap memory usage
    +
    +
    heapUsage() - Static method in class com.sun.btrace.BTraceUtils.Sys.Memory
    +
    +
    Returns heap memory usage
    +
    +
    histo(String, long) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Adds a value to the named histogram.
    +
    +
    histo(String, long, double) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Adds a value to the named histogram.
    +
    +
    histo(String, long, String) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Adds a value to the named histogram.
    +
    +
    histo(String, long, double, String) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Adds a value to the named histogram.
    +
    +
    HistogramData - Class in com.sun.btrace.aggregation
    +
    +
    A wire data structure describing histogram data.
    +
    +
    HistogramData(long[], long[]) - Constructor for class com.sun.btrace.aggregation.HistogramData
    +
     
    +
    hit(int) - Static method in class com.sun.btrace.instr.MethodTracker
    +
    +
    Records the invocation of a certain method and indicates whether + it should be traced or not (sampling).
    +
    +
    hitAdaptive(int) - Static method in class com.sun.btrace.instr.MethodTracker
    +
    +
    Records the invocation of a certain method and indicates whether + it should be traced or not (sampling).
    +
    +
    hitTimed(int) - Static method in class com.sun.btrace.instr.MethodTracker
    +
    +
    Records the invocation of a certain method alongside the timestamp + and indicates whether it should be traced or not (sampling).
    +
    +
    hitTimedAdaptive(int) - Static method in class com.sun.btrace.instr.MethodTracker
    +
    +
    Records the invocation of a certain method alongside the timestamp + and indicates whether it should be traced or not (sampling).
    +
    +
    holdsLock(Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns true if and only if the current thread holds the + monitor lock on the specified object.
    +
    +
    holdsLock(Object) - Static method in class com.sun.btrace.BTraceUtils.Threads
    +
    +
    Returns true if and only if the current thread holds the + monitor lock on the specified object.
    +
    +
    + + + +

    I

    +
    +
    identityHashCode(Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the same hash code for the given object as + would be returned by the default method hashCode(), + whether or not the given object's class overrides + hashCode().
    +
    +
    identityStr(Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns identity string of the form class-name@identity-hash
    +
    +
    includeClasses(Class...) - Method in class com.sun.btrace.DOTWriter
    +
     
    +
    includeClassNames(Pattern) - Method in class com.sun.btrace.DOTWriter
    +
     
    +
    includeDirs - Variable in class com.sun.btrace.compiler.Compiler
    +
     
    +
    includeObjects(Object...) - Method in class com.sun.btrace.DOTWriter
    +
     
    +
    increment(String) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Increase the given counter by 1
    +
    +
    increment(String, String) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Increase the given counter by 1
    +
    +
    increment(String, double) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Increase the given counter by 1
    +
    +
    increment(String, double, String) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Increase the given counter by 1
    +
    +
    incrementAndGet(AtomicInteger) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Atomically increments by one the current value of given AtomicInteger.
    +
    +
    incrementAndGet(AtomicLong) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Atomically increments by one the current value.
    +
    +
    incrementAndGet(AtomicInteger) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Atomically increments by one the current value of given AtomicInteger.
    +
    +
    incrementAndGet(AtomicLong) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Atomically increments by one the current value.
    +
    +
    indexOf(String, String) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    indexOf(String, String) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
     
    +
    info(String) - Static method in class com.sun.btrace.DebugSupport
    +
     
    +
    init(PerfReader) - Static method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    init(MemoryUsage) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the amount of memory in bytes that the Java virtual + machine initially requests from the operating system for + memory management.
    +
    +
    init(MemoryUsage) - Static method in class com.sun.btrace.BTraceUtils.Sys.Memory
    +
    +
    Returns the amount of memory in bytes that the Java virtual + machine initially requests from the operating system for + memory management.
    +
    +
    init(ProcessingEnvironment) - Method in class com.sun.btrace.compiler.Verifier
    +
     
    +
    initUnsafe() - Static method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    Injected - Annotation Type in com.sun.btrace.annotations
    +
    +
    Annotates a field as an injected service.
    +
    +
    INJECTED_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    insert(MethodVisitor) - Method in class com.sun.btrace.util.templates.Template
    +
     
    +
    insert(MethodVisitor, String...) - Method in class com.sun.btrace.util.templates.Template
    +
     
    +
    insert(MethodVisitor, Set<String>) - Method in class com.sun.btrace.util.templates.Template
    +
     
    +
    insertFrameAppendStack(Label, Type...) - Method in class com.sun.btrace.runtime.BTraceMethodVisitor
    +
     
    +
    insertFrameAppendStack(Label, Type...) - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    insertFrameAppendStack(Label, Type...) - Method in interface com.sun.btrace.runtime.MethodInstrumentorHelper
    +
     
    +
    insertFrameReplaceStack(Label, Type...) - Method in class com.sun.btrace.runtime.BTraceMethodVisitor
    +
     
    +
    insertFrameReplaceStack(Label, Type...) - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    insertFrameReplaceStack(Label, Type...) - Method in interface com.sun.btrace.runtime.MethodInstrumentorHelper
    +
     
    +
    insertFrameSameStack(Label) - Method in class com.sun.btrace.runtime.BTraceMethodVisitor
    +
     
    +
    insertFrameSameStack(Label) - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    insertFrameSameStack(Label) - Method in interface com.sun.btrace.runtime.MethodInstrumentorHelper
    +
     
    +
    instanceOf(Object, String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Checks whether the provided object is an instance of the named class.
    +
    +
    INSTRUMENT - Static variable in class com.sun.btrace.comm.Command
    +
     
    +
    InstrumentCommand - Class in com.sun.btrace.comm
    +
     
    +
    InstrumentCommand(byte[], ArgsMap, DebugSupport) - Constructor for class com.sun.btrace.comm.InstrumentCommand
    +
     
    +
    InstrumentCommand(byte[], String[], DebugSupport) - Constructor for class com.sun.btrace.comm.InstrumentCommand
    +
     
    +
    InstrumentCommand(byte[], Map<String, String>, DebugSupport) - Constructor for class com.sun.btrace.comm.InstrumentCommand
    +
     
    +
    InstrumentCommand() - Constructor for class com.sun.btrace.comm.InstrumentCommand
    +
     
    +
    InstrumentingClassVisitor - Class in com.sun.btrace.runtime
    +
     
    +
    InstrumentingClassVisitor(int) - Constructor for class com.sun.btrace.runtime.InstrumentingClassVisitor
    +
     
    +
    InstrumentingClassVisitor(int, ClassVisitor) - Constructor for class com.sun.btrace.runtime.InstrumentingClassVisitor
    +
     
    +
    InstrumentingMethodVisitor - Class in com.sun.btrace.runtime
    +
    +
    A method visitor providing support for introducing new local variables in bytecode + recomputing stackmap frames as necessary.
    +
    +
    InstrumentingMethodVisitor(int, String, String, String, MethodVisitor) - Constructor for class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    Instrumentor - Class in com.sun.btrace.runtime
    +
    +
    This instruments a probed class with BTrace probe + action class.
    +
    +
    InstrumentUtils - Class in com.sun.btrace.runtime
    +
     
    +
    InstrumentUtils() - Constructor for class com.sun.btrace.runtime.InstrumentUtils
    +
     
    +
    INT_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    INT_VALUE - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    INT_VALUE_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    INTEGER_BOXED_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    INTEGER_BOXED_INTERNAL - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    Interval - Class in com.sun.btrace.util
    +
     
    +
    Interval(int, int) - Constructor for class com.sun.btrace.util.Interval
    +
     
    +
    INVALID - Static variable in class com.sun.btrace.runtime.instr.MethodInstrumentor.ValidationResult
    +
     
    +
    invert(Collection<Interval>) - Static method in class com.sun.btrace.util.Interval
    +
     
    +
    invocations - Variable in class com.sun.btrace.Profiler.Record
    +
     
    +
    invoke(String, Object[], String[]) - Method in class com.sun.btrace.BTraceMBean
    +
     
    +
    invoke(Class, Object...) - Method in class com.sun.btrace.shared.LowMemoryHandler
    +
     
    +
    invokeInterface(String, String, String) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    invokeSpecial(String, String, String) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    invokeStatic(String, String, String) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    invokeVirtual(String, String, String) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    isAll() - Method in class com.sun.btrace.util.Interval
    +
     
    +
    isAny() - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor.ValidationResult
    +
     
    +
    isAnyType(Type) - Static method in class com.sun.btrace.runtime.TypeUtils
    +
     
    +
    isAnyTypeArray(Type) - Static method in class com.sun.btrace.runtime.TypeUtils
    +
     
    +
    isArray(Class) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Determines if the given Class object represents an array class.
    +
    +
    isArray(Class) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Determines if the given Class object represents an array class.
    +
    +
    isArray(Type) - Static method in class com.sun.btrace.runtime.TypeUtils
    +
     
    +
    isAssignable(Type, Type, ClassLoader, boolean) - Static method in class com.sun.btrace.runtime.InstrumentUtils
    +
     
    +
    isAssignable(Type[], Type[], ClassLoader, boolean) - Static method in class com.sun.btrace.runtime.InstrumentUtils
    +
     
    +
    isAssignableFrom(Class<?>, Class<?>) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Determines if the class or interface represented by the first + Class object is either the same as, or is a superclass or + superinterface of, the class or interface represented by the second + Class parameter.
    +
    +
    isAssignableFrom(Class<?>, Class<?>) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Determines if the class or interface represented by the first + Class object is either the same as, or is a superclass or + superinterface of, the class or interface represented by the second + Class parameter.
    +
    +
    isBcpRequired() - Method in class com.sun.btrace.runtime.BTraceMethodNode
    +
     
    +
    isBootClassPathSupported() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Tests if the Java virtual machine supports the boot class path + mechanism used by the bootstrap class loader to search for class + files.
    +
    +
    isBootClassPathSupported() - Static method in class com.sun.btrace.BTraceUtils.Sys.VM
    +
    +
    Tests if the Java virtual machine supports the boot class path + mechanism used by the bootstrap class loader to search for class + files.
    +
    +
    isBTraceHandler() - Method in class com.sun.btrace.runtime.BTraceMethodNode
    +
     
    +
    isCalled() - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    isCandidate(Class) - Method in class com.sun.btrace.runtime.ClassFilter
    +
     
    +
    isClassAnnotationMatcher() - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    isClassRegexMatcher() - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    isClassRenamed() - Method in interface com.sun.btrace.runtime.BTraceProbe
    +
     
    +
    isClassRenamed() - Method in class com.sun.btrace.runtime.BTraceProbeNode
    +
     
    +
    isClassRenamed() - Method in class com.sun.btrace.runtime.BTraceProbePersisted
    +
     
    +
    isClassRenamed() - Method in class com.sun.btrace.runtime.Verifier
    +
     
    +
    isConstructor() - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    isDebug() - Method in class com.sun.btrace.DebugSupport
    +
     
    +
    isDebug() - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    isDebugMode() - Method in class com.sun.btrace.api.BTraceSettings
    +
     
    +
    isDumpClasses() - Method in class com.sun.btrace.api.BTraceSettings
    +
     
    +
    isDumpClasses() - Method in class com.sun.btrace.DebugSupport
    +
     
    +
    isDumpClasses() - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    isEmpty() - Method in class com.sun.btrace.ArgsMap
    +
     
    +
    isEmpty() - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    isEmpty(Collection<E>) - Static method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    isEmpty(Map<K, V>) - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    isEmpty(Collection<E>) - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    isEmpty(Map<K, V>) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    isEmpty(Collection<E>) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    isExactTypeMatch() - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    isInfinite(double) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns true if the specified number is infinitely + large in magnitude, false otherwise.
    +
    +
    isInfinite(float) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns true if the specified number is infinitely + large in magnitude, false otherwise.
    +
    +
    isInfinite(double) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns true if the specified number is infinitely + large in magnitude, false otherwise.
    +
    +
    isInfinite(float) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns true if the specified number is infinitely + large in magnitude, false otherwise.
    +
    +
    isInstance(Class, Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Determines if the specified Object is assignment-compatible + with the object represented by the specified Class.
    +
    +
    isInstance(Class, Object) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Determines if the specified Object is assignment-compatible + with the object represented by the specified Class.
    +
    +
    isInterface(Class) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Determines if the specified Class object represents an + interface type.
    +
    +
    isInterface(Class) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Determines if the specified Class object represents an + interface type.
    +
    +
    isInterface() - Method in class com.sun.btrace.runtime.ClassInfo
    +
     
    +
    isInteruppted() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Tests whether this thread has been interrupted.
    +
    +
    isInteruppted() - Static method in class com.sun.btrace.BTraceUtils.Threads
    +
    +
    Tests whether this thread has been interrupted.
    +
    +
    isMBean(Class) - Static method in class com.sun.btrace.BTraceMBean
    +
     
    +
    isMethodAnnotationMatcher() - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    isMethodRegexMatcher() - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    isNameMatching(String) - Method in class com.sun.btrace.runtime.ClassFilter
    +
     
    +
    isNaN(double) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns true if the specified number is a + Not-a-Number (NaN) value, false otherwise.
    +
    +
    isNaN(float) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns true if the specified number is a + Not-a-Number (NaN) value, false otherwise.
    +
    +
    isNaN(double) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns true if the specified number is a + Not-a-Number (NaN) value, false otherwise.
    +
    +
    isNaN(float) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns true if the specified number is a + Not-a-Number (NaN) value, false otherwise.
    +
    +
    isNone() - Method in class com.sun.btrace.util.Interval
    +
     
    +
    isObject(Type) - Static method in class com.sun.btrace.runtime.TypeUtils
    +
     
    +
    isObjectOrAnyType(Type) - Static method in class com.sun.btrace.runtime.TypeUtils
    +
     
    +
    isPrimitive(Class) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns whether the given Class represent primitive type or not.
    +
    +
    isPrimitive(Class) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Returns whether the given Class represent primitive type or not.
    +
    +
    isPrimitive(String) - Static method in class com.sun.btrace.runtime.TypeUtils
    +
     
    +
    isPrimitive(Type) - Static method in class com.sun.btrace.runtime.TypeUtils
    +
     
    +
    isRetransformStartup() - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    isSampled() - Method in class com.sun.btrace.runtime.BTraceMethodNode
    +
     
    +
    isSensitiveClass(String) - Static method in class com.sun.btrace.runtime.ClassFilter
    +
     
    +
    isStatic() - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    isStatic - Variable in class com.sun.btrace.runtime.instr.SynchronizedInstrumentor
    +
     
    +
    isStaticAccess - Variable in class com.sun.btrace.runtime.instr.FieldAccessInstrumentor
    +
     
    +
    isString(Type) - Static method in class com.sun.btrace.runtime.TypeUtils
    +
     
    +
    isSubtypeMatcher() - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    isSubTypeOf(Class, String) - Static method in class com.sun.btrace.runtime.ClassFilter
    +
     
    +
    isSubTypeOf(String, ClassLoader, String...) - Static method in class com.sun.btrace.runtime.ClassFilter
    +
    +
    Return whether given Class typeA is subtype of any of the + given type names.
    +
    +
    isSyncMethod - Variable in class com.sun.btrace.runtime.instr.SynchronizedInstrumentor
    +
     
    +
    isThrowable(Type) - Static method in class com.sun.btrace.runtime.TypeUtils
    +
     
    +
    isTrackRetransforms() - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    isTransforming() - Method in interface com.sun.btrace.runtime.BTraceProbe
    +
     
    +
    isTransforming() - Method in class com.sun.btrace.runtime.BTraceProbeNode
    +
     
    +
    isTransforming() - Method in class com.sun.btrace.runtime.BTraceProbePersisted
    +
     
    +
    isTrusted() - Method in class com.sun.btrace.api.BTraceTask
    +
     
    +
    isTrusted() - Method in class com.sun.btrace.api.impl.BTraceTaskImpl
    +
     
    +
    isTrusted() - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    isUnsafe() - Method in class com.sun.btrace.api.BTraceTask
    +
    +
    Deprecated. + +
    +
    +
    isUnsafe() - Method in class com.sun.btrace.SharedSettings
    +
    +
    Deprecated.
    +
    +
    isValid() - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor.ValidationResult
    +
     
    +
    isVerified() - Method in interface com.sun.btrace.runtime.BTraceProbe
    +
     
    +
    isVerified() - Method in class com.sun.btrace.runtime.BTraceProbeNode
    +
     
    +
    isVerified() - Method in class com.sun.btrace.runtime.BTraceProbePersisted
    +
     
    +
    isVoid(Type) - Static method in class com.sun.btrace.runtime.TypeUtils
    +
     
    +
    iterator() - Method in class com.sun.btrace.ArgsMap
    +
     
    +
    iterator() - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    + + + +

    J

    +
    +
    JAVA_LANG_THREAD_LOCAL - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    JAVA_LANG_THREAD_LOCAL_GET - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    JAVA_LANG_THREAD_LOCAL_GET_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    JAVA_LANG_THREAD_LOCAL_SET - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    JAVA_LANG_THREAD_LOCAL_SET_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    jstack() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints the java stack trace of the current thread.
    +
    +
    jstack(int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints the java stack trace of the current thread.
    +
    +
    jstack(Throwable) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints the stack trace of the given exception object.
    +
    +
    jstack(Throwable, int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints the stack trace of the given exception object.
    +
    +
    jstack() - Static method in class com.sun.btrace.BTraceUtils.Threads
    +
    +
    Prints the java stack trace of the current thread.
    +
    +
    jstack(int) - Static method in class com.sun.btrace.BTraceUtils.Threads
    +
    +
    Prints the java stack trace of the current thread.
    +
    +
    jstack(Throwable) - Static method in class com.sun.btrace.BTraceUtils.Threads
    +
    +
    Prints the stack trace of the given exception object.
    +
    +
    jstack(Throwable, int) - Static method in class com.sun.btrace.BTraceUtils.Threads
    +
    +
    Prints the stack trace of the given exception object.
    +
    +
    jstackAll() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints Java stack traces of all the Java threads.
    +
    +
    jstackAll(int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints Java stack traces of all the Java threads.
    +
    +
    jstackAll() - Static method in class com.sun.btrace.BTraceUtils.Threads
    +
    +
    Prints Java stack traces of all the Java threads.
    +
    +
    jstackAll(int) - Static method in class com.sun.btrace.BTraceUtils.Threads
    +
    +
    Prints Java stack traces of all the Java threads.
    +
    +
    jstackAllStr() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the stack traces of all Java threads as a String.
    +
    +
    jstackAllStr(int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns atmost given number of frames in stack traces + of all threads as a String.
    +
    +
    jstackAllStr() - Static method in class com.sun.btrace.BTraceUtils.Threads
    +
    +
    Returns the stack traces of all Java threads as a String.
    +
    +
    jstackAllStr(int) - Static method in class com.sun.btrace.BTraceUtils.Threads
    +
    +
    Returns atmost given number of frames in stack traces + of all threads as a String.
    +
    +
    jstackStr() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the stack trace of current thread as a String.
    +
    +
    jstackStr(int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the stack trace of the current thread as a String + but includes atmost the given number of frames.
    +
    +
    jstackStr(Throwable) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the stack trace of given exception object as a String.
    +
    +
    jstackStr(Throwable, int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns stack trace of given exception object as a String.
    +
    +
    jstackStr() - Static method in class com.sun.btrace.BTraceUtils.Threads
    +
    +
    Returns the stack trace of current thread as a String.
    +
    +
    jstackStr(int) - Static method in class com.sun.btrace.BTraceUtils.Threads
    +
    +
    Returns the stack trace of the current thread as a String + but includes atmost the given number of frames.
    +
    +
    jstackStr(Throwable) - Static method in class com.sun.btrace.BTraceUtils.Threads
    +
    +
    Returns the stack trace of given exception object as a String.
    +
    +
    jstackStr(Throwable, int) - Static method in class com.sun.btrace.BTraceUtils.Threads
    +
    +
    Returns stack trace of given exception object as a String.
    +
    +
    jump(int, Label) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    + + + +

    K

    +
    +
    Kind - Enum in com.sun.btrace.annotations
    +
    +
    This enum is specified in the Location + annotation to specify probe point kind.
    +
    +
    KIND_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    + + + +

    L

    +
    +
    label(Label) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    LAST_COMMAND - Static variable in class com.sun.btrace.comm.Command
    +
     
    +
    lastIndexOf(String, String) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    lastIndexOf(String, String) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
     
    +
    lazySet(AtomicInteger, int) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Eventually sets to the given value to the given AtomicInteger.
    +
    +
    lazySet(AtomicLong, long) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Eventually sets to the given value to the given AtomicLong.
    +
    +
    lazySet(AtomicInteger, int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Eventually sets to the given value to the given AtomicInteger.
    +
    +
    lazySet(AtomicLong, long) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Eventually sets to the given value to the given AtomicLong.
    +
    +
    ldc(Object) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    le(int) - Static method in class com.sun.btrace.util.Interval
    +
     
    +
    leave() - Static method in class com.sun.btrace.BTraceRuntime
    +
    +
    Leave method is called by every probed method just + before the probe actions end (and actual probed + method continues).
    +
    +
    length(Appendable) - Static method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    length(String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the length of the given string.
    +
    +
    length(String) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    Returns the length of the given string.
    +
    +
    length(Appendable) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    Checks the length of an appendable buffer created by BTraceUtils.Strings.newStringBuilder()
    +
    +
    length - Variable in class com.sun.btrace.util.LongMap
    +
     
    +
    Level - Annotation Type in com.sun.btrace.annotations
    +
    +
    Allows specifying a probe handler instrumentation level matching expression.
    +
    +
    Level - Class in com.sun.btrace.runtime
    +
     
    +
    Level() - Constructor for class com.sun.btrace.runtime.Level
    +
     
    +
    LEVEL_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    levelCheck(OnMethod, String) - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    levelCheckAfter(OnMethod, String) - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    levelCheckBefore(OnMethod, String) - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    levelCheckVar - Variable in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    libraryPath() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the Java library path.
    +
    +
    libraryPath() - Static method in class com.sun.btrace.BTraceUtils.Sys.VM
    +
    +
    Returns the Java library path.
    +
    +
    LineNumberInstrumentor - Class in com.sun.btrace.runtime.instr
    +
    +
    This visitor helps in inserting code whenever a source + line is reached.
    +
    +
    LineNumberInstrumentor(ClassLoader, MethodVisitor, MethodInstrumentorHelper, String, String, int, String, String) - Constructor for class com.sun.btrace.runtime.instr.LineNumberInstrumentor
    +
     
    +
    loadArguments(MethodInstrumentor.ArgumentProvider...) - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    loadArguments(MethodInstrumentor.ValidationResult, Type[], boolean, MethodInstrumentor.ArgumentProvider...) - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    loader(Class) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the class loader for the given class.
    +
    +
    loadField(Type, String, Type) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    loadLocal(Type, int) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    loadNull() - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    loadStaticField(Type, String, Type) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    loadThis() - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    localVarArg(int, Type, int) - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    localVarArg(int, Type, int, boolean) - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    Location - Annotation Type in com.sun.btrace.annotations
    +
    +
    This annotation specifies a particular "location" within a + traced/probed java method for BTrace probe specifications.
    +
    +
    Location - Class in com.sun.btrace.runtime
    +
    +
    This class is used to store data of the annotation + com.sun.btrace.annotations.Location.
    +
    +
    Location() - Constructor for class com.sun.btrace.runtime.Location
    +
     
    +
    LOCATION_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    locationTypeMatches(Location, Type, Type) - Method in class com.sun.btrace.runtime.instr.ArrayAccessInstrumentor
    +
     
    +
    log(double) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the natural logarithm (base e) of a double + value.
    +
    +
    log(double) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns the natural logarithm (base e) of a double + value.
    +
    +
    log10(double) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the base 10 logarithm of a double value.
    +
    +
    log10(double) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns the base 10 logarithm of a double value.
    +
    +
    LONG_BOXED_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    LONG_BOXED_INTERNAL - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    LONG_VALUE - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    LONG_VALUE_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    LongMap<T> - Class in com.sun.btrace.util
    +
    +
    AVL tree based map implementation for long values as keys
    +
    +
    LongMap() - Constructor for class com.sun.btrace.util.LongMap
    +
     
    +
    LowMemoryHandler - Class in com.sun.btrace.shared
    +
     
    +
    LowMemoryHandler(String, String, long, String, boolean) - Constructor for class com.sun.btrace.shared.LowMemoryHandler
    +
     
    +
    lt(int) - Static method in class com.sun.btrace.util.Interval
    +
     
    +
    + + + +

    M

    +
    +
    Main - Class in com.sun.btrace.agent
    +
    +
    This is the main class for BTrace java.lang.instrument agent.
    +
    +
    Main() - Constructor for class com.sun.btrace.agent.Main
    +
     
    +
    Main - Class in com.sun.btrace.client
    +
    +
    This is the main class for a simple command line + BTrace client.
    +
    +
    Main() - Constructor for class com.sun.btrace.client.Main
    +
     
    +
    main(String[]) - Static method in class com.sun.btrace.client.Main
    +
     
    +
    main(String[]) - Static method in class com.sun.btrace.client.ProbeDump
    +
     
    +
    main(String[]) - Static method in class com.sun.btrace.compiler.Compiler
    +
     
    +
    main(String[]) - Static method in class com.sun.btrace.compiler.PCPP
    +
     
    +
    mark(int) - Method in class com.sun.btrace.compiler.ConcatenatingReader
    +
     
    +
    markSupported() - Method in class com.sun.btrace.compiler.ConcatenatingReader
    +
     
    +
    matches(Pattern, String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Matches the given (precompiled) regular expression and attempts + to match the given input against it.
    +
    +
    matches(String, String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Compiles the given regular expression and attempts to match the given + input against it.
    +
    +
    matches(Pattern, String) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    Matches the given (precompiled) regular expression and attempts + to match the given input against it.
    +
    +
    matches(String, String) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    Compiles the given regular expression and attempts to match the given + input against it.
    +
    +
    max(MemoryUsage) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the maximum amount of memory in bytes that can be used + for memory management.
    +
    +
    max(MemoryUsage) - Static method in class com.sun.btrace.BTraceUtils.Sys.Memory
    +
    +
    Returns the maximum amount of memory in bytes that can be used + for memory management.
    +
    +
    maxMemory() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the maximum amount of memory that the Java virtual machine will + attempt to use.
    +
    +
    maxMemory() - Static method in class com.sun.btrace.BTraceUtils.Sys.Memory
    +
    +
    Returns the maximum amount of memory that the Java virtual machine will + attempt to use.
    +
    +
    MEAN_DEFAULT - Static variable in annotation type com.sun.btrace.annotations.Sampled
    +
     
    +
    Memory() - Constructor for class com.sun.btrace.BTraceUtils.Sys.Memory
    +
     
    +
    MemoryJavaFileManager - Class in com.sun.btrace.compiler
    +
    +
    JavaFileManager that keeps compiled .class bytes in memory.
    +
    +
    MemoryJavaFileManager(JavaFileManager, List<String>) - Constructor for class com.sun.btrace.compiler.MemoryJavaFileManager
    +
     
    +
    merge(ArgsMap...) - Static method in class com.sun.btrace.ArgsMap
    +
     
    +
    MESSAGE - Static variable in class com.sun.btrace.comm.Command
    +
     
    +
    MessageCommand - Class in com.sun.btrace.comm
    +
     
    +
    MessageCommand(long, String) - Constructor for class com.sun.btrace.comm.MessageCommand
    +
     
    +
    MessageCommand(String) - Constructor for class com.sun.btrace.comm.MessageCommand
    +
     
    +
    MessageCommand() - Constructor for class com.sun.btrace.comm.MessageCommand
    +
     
    +
    MessageDispatcher() - Constructor for class com.sun.btrace.api.BTraceTask.MessageDispatcher
    +
     
    +
    Messages - Class in com.sun.btrace.util
    +
     
    +
    method(String) - Static method in class com.sun.btrace.runtime.CallGraph
    +
     
    +
    method - Variable in class com.sun.btrace.shared.ErrorHandler
    +
     
    +
    method - Variable in class com.sun.btrace.shared.EventHandler
    +
     
    +
    method - Variable in class com.sun.btrace.shared.ExitHandler
    +
     
    +
    method - Variable in class com.sun.btrace.shared.LowMemoryHandler
    +
     
    +
    method - Variable in class com.sun.btrace.shared.TimerHandler
    +
     
    +
    MethodCallInstrumentor - Class in com.sun.btrace.runtime.instr
    +
    +
    This visitor helps in inserting code whenever a method call + is done.
    +
    +
    MethodCallInstrumentor(ClassLoader, MethodVisitor, MethodInstrumentorHelper, String, String, int, String, String) - Constructor for class com.sun.btrace.runtime.instr.MethodCallInstrumentor
    +
     
    +
    MethodEntryExitInstrumentor - Class in com.sun.btrace.runtime.instr
    +
    +
    Instruments method entry and exit points.
    +
    +
    MethodEntryExitInstrumentor(ClassLoader, MethodVisitor, MethodInstrumentorHelper, String, String, int, String, String) - Constructor for class com.sun.btrace.runtime.instr.MethodEntryExitInstrumentor
    +
     
    +
    MethodEntryInstrumentor - Class in com.sun.btrace.runtime.instr
    +
    +
    This visitor helps in inserting code whenever a method + is entered.
    +
    +
    MethodEntryInstrumentor(ClassLoader, MethodVisitor, MethodInstrumentorHelper, String, String, int, String, String) - Constructor for class com.sun.btrace.runtime.instr.MethodEntryInstrumentor
    +
     
    +
    methodHelper() - Method in class com.sun.btrace.runtime.InstrumentingClassVisitor
    +
     
    +
    methodHelper() - Method in interface com.sun.btrace.runtime.MethodInstrumentorHelper.Accessor
    +
     
    +
    methodId(String, String) - Static method in class com.sun.btrace.runtime.CallGraph
    +
     
    +
    MethodID - Class in com.sun.btrace.util
    +
    +
    A factory class for shared method ids
    +
    +
    MethodID() - Constructor for class com.sun.btrace.util.MethodID
    +
     
    +
    MethodInstrumentor - Class in com.sun.btrace.runtime.instr
    +
    +
    Base class for all out method instrumenting classes.
    +
    +
    MethodInstrumentor(ClassLoader, MethodVisitor, MethodInstrumentorHelper, String, String, int, String, String) - Constructor for class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    MethodInstrumentor.AnyTypeArgProvider - Class in com.sun.btrace.runtime.instr
    +
     
    +
    MethodInstrumentor.ArgumentProvider - Class in com.sun.btrace.runtime.instr
    +
     
    +
    MethodInstrumentor.ValidationResult - Class in com.sun.btrace.runtime.instr
    +
     
    +
    MethodInstrumentorHelper - Interface in com.sun.btrace.runtime
    +
     
    +
    MethodInstrumentorHelper.Accessor - Interface in com.sun.btrace.runtime
    +
     
    +
    MethodInvocationProfiler - Class in com.sun.btrace.profiling
    +
    +
    Implementation of Profiler
    +
    +
    MethodInvocationProfiler(int) - Constructor for class com.sun.btrace.profiling.MethodInvocationProfiler
    +
     
    +
    MethodReturnInstrumentor - Class in com.sun.btrace.runtime.instr
    +
    +
    This visitor helps in inserting code whenever a method + call returns.
    +
    +
    MethodReturnInstrumentor(ClassLoader, MethodVisitor, MethodInstrumentorHelper, String, String, int, String, String) - Constructor for class com.sun.btrace.runtime.instr.MethodReturnInstrumentor
    +
     
    +
    MethodSerializer - Class in com.sun.btrace.shared
    +
     
    +
    MethodSerializer() - Constructor for class com.sun.btrace.shared.MethodSerializer
    +
     
    +
    MethodTracker - Class in com.sun.btrace.instr
    +
    +
    Provides a centralized place to track the fundamental metrics for + method execution.
    +
    +
    MethodTracker() - Constructor for class com.sun.btrace.instr.MethodTracker
    +
     
    +
    MethodTrackingExpander - Class in com.sun.btrace.util.templates.impl
    +
    +
    This expander takes care of macros related to all the sampling and timing functionality
    +
    +
    MethodTrackingExpander(int, MethodInstrumentorHelper) - Constructor for class com.sun.btrace.util.templates.impl.MethodTrackingExpander
    +
     
    +
    millis() - Static method in class com.sun.btrace.BTraceUtils.Time
    +
    +
    Returns the current time in milliseconds.
    +
    +
    + + + +

    N

    +
    +
    name(Thread) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the name of the given thread.
    +
    +
    name(Class) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the name of the given Class object.
    +
    +
    name(Field) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the name of the Field object.
    +
    +
    name(Class) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Returns the name of the given Class object.
    +
    +
    name(Field) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Returns the name of the Field object.
    +
    +
    name(Thread) - Static method in class com.sun.btrace.BTraceUtils.Threads
    +
    +
    Returns the name of the given thread.
    +
    +
    name - Variable in class com.sun.btrace.comm.DataCommand
    +
     
    +
    nanos() - Static method in class com.sun.btrace.BTraceUtils.Time
    +
    +
    Returns the current value of the most precise available system + timer, in nanoseconds.
    +
    +
    newAggregation(AggregationFunction) - Static method in class com.sun.btrace.BTraceUtils.Aggregations
    +
    +
    Creates a new aggregation based on the given aggregation function type.
    +
    +
    newAggregation(AggregationFunction) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Creates a new aggregation based on the given aggregation function type.
    +
    +
    newAggregationKey(Object) - Static method in class com.sun.btrace.BTraceUtils.Aggregations
    +
    +
    Creates a grouping aggregation key with the provided value.
    +
    +
    newAggregationKey(Object, Object) - Static method in class com.sun.btrace.BTraceUtils.Aggregations
    +
    +
    Creates a composite grouping aggregation key with the provided values.
    +
    +
    newAggregationKey(Object, Object, Object) - Static method in class com.sun.btrace.BTraceUtils.Aggregations
    +
    +
    Creates a composite grouping aggregation key with the provided values.
    +
    +
    newAggregationKey(Object, Object, Object, Object) - Static method in class com.sun.btrace.BTraceUtils.Aggregations
    +
    +
    Creates a composite grouping aggregation key with the provided values.
    +
    +
    newAggregationKey(Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Creates a grouping aggregation key with the provided value.
    +
    +
    newAggregationKey(Object, Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Creates a composite grouping aggregation key with the provided values.
    +
    +
    newAggregationKey(Object, Object, Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Creates a composite grouping aggregation key with the provided values.
    +
    +
    newAggregationKey(Object, Object, Object, Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Creates a composite grouping aggregation key with the provided values.
    +
    +
    newArray(Type) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    newAtomicInteger(int) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Creates a new AtomicInteger with the given initial value.
    +
    +
    newAtomicInteger(int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Creates a new AtomicInteger with the given initial value.
    +
    +
    newAtomicLong(long) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Creates a new AtomicLong with the given initial value.
    +
    +
    newAtomicLong(long) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Creates a new AtomicLong with the given initial value.
    +
    +
    newClassWriter() - Static method in class com.sun.btrace.runtime.InstrumentUtils
    +
     
    +
    newClassWriter(boolean) - Static method in class com.sun.btrace.runtime.InstrumentUtils
    +
     
    +
    newCompiler(BTraceTask) - Method in interface com.sun.btrace.spi.BTraceCompilerFactory
    +
     
    +
    newCompiler(BTraceTask) - Method in class com.sun.btrace.spi.impl.BTraceCompilerFactoryImpl
    +
     
    +
    newDeque() - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    newDeque() - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    newHashMap() - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    newHashMap() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Operating on maps
    +
    +
    newInstance() - Static method in class com.sun.btrace.api.BTraceEngine
    +
     
    +
    newInstance(Type) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    newPerfCounter(String, String, Object) - Static method in class com.sun.btrace.BTraceRuntime
    +
    +
    Utility to create a new jvmstat perf counter.
    +
    +
    newPerfCounter(Object, String, String) - Static method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    newProfiler() - Static method in class com.sun.btrace.BTraceUtils.Profiling
    +
    +
    Creates a new Profiler instance
    +
    +
    newProfiler(int) - Static method in class com.sun.btrace.BTraceUtils.Profiling
    +
    +
    Creates a new Profiler instance with the specified + expected count of the distinct methods to be recorded.
    +
    +
    newStringBuilder(boolean) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    Safely creates a new instance of an appendable string buffer
    +
    +
    newStringBuilder() - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    Safely creates a new instance of an appendable string buffer
    + The buffer will not be thread safe.
    +
    +
    newThreadLocal(Object) - Static method in class com.sun.btrace.BTraceRuntime
    +
    +
    Utility to create a new ThreadLocal object.
    +
    +
    newValue() - Method in enum com.sun.btrace.aggregation.AggregationFunction
    +
     
    +
    newVar(Type) - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    newVar(Type) - Method in interface com.sun.btrace.runtime.MethodInstrumentorHelper
    +
     
    +
    newWeakMap() - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    newWeakMap() - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    nextInt(int) - Method in class com.sun.btrace.instr.random.SharedRandomIntProvider
    +
     
    +
    nextInt(int) - Method in class com.sun.btrace.instr.random.ThreadLocalRandomIntProvider
    +
     
    +
    nextInt(int) - Method in class com.sun.btrace.instr.RandomIntProvider
    +
     
    +
    Node(String) - Constructor for class com.sun.btrace.runtime.CallGraph.Node
    +
     
    +
    none() - Static method in class com.sun.btrace.util.Interval
    +
     
    +
    nonHeapUsage() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns non-heap memory usage
    +
    +
    nonHeapUsage() - Static method in class com.sun.btrace.BTraceUtils.Sys.Memory
    +
    +
    Returns non-heap memory usage
    +
    +
    notifyTransform(String) - Method in interface com.sun.btrace.runtime.BTraceProbe
    +
     
    +
    notifyTransform(String) - Method in class com.sun.btrace.runtime.BTraceProbeNode
    +
     
    +
    notifyTransform(String) - Method in class com.sun.btrace.runtime.BTraceProbePersisted
    +
     
    +
    NULL_TYPE - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    NUMBER - Static variable in class com.sun.btrace.comm.Command
    +
     
    +
    NUMBER_INTERNAL - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    NUMBER_MAP - Static variable in class com.sun.btrace.comm.Command
    +
     
    +
    NumberDataCommand - Class in com.sun.btrace.comm
    +
    +
    A simple data command that has one number value.
    +
    +
    NumberDataCommand() - Constructor for class com.sun.btrace.comm.NumberDataCommand
    +
     
    +
    NumberDataCommand(String, Number) - Constructor for class com.sun.btrace.comm.NumberDataCommand
    +
     
    +
    NumberMapDataCommand - Class in com.sun.btrace.comm
    +
    +
    A data command that hold data of type Map<String, Number>.
    +
    +
    NumberMapDataCommand() - Constructor for class com.sun.btrace.comm.NumberMapDataCommand
    +
     
    +
    NumberMapDataCommand(String, Map<String, ? extends Number>) - Constructor for class com.sun.btrace.comm.NumberMapDataCommand
    +
     
    +
    Numbers() - Constructor for class com.sun.btrace.BTraceUtils.Numbers
    +
     
    +
    + + + +

    O

    +
    +
    OBJECT_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    OBJECT_INTERNAL - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    OBJECT_TYPE - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    ObjectAllocInstrumentor - Class in com.sun.btrace.runtime.instr
    +
    +
    This visitor helps in inserting code whenever an object + is allocated.
    +
    +
    ObjectAllocInstrumentor(ClassLoader, MethodVisitor, MethodInstrumentorHelper, String, String, int, String, String) - Constructor for class com.sun.btrace.runtime.instr.ObjectAllocInstrumentor
    +
     
    +
    ObjectAllocInstrumentor(ClassLoader, MethodVisitor, MethodInstrumentorHelper, String, String, int, String, String, boolean) - Constructor for class com.sun.btrace.runtime.instr.ObjectAllocInstrumentor
    +
     
    +
    objectArrayType - Static variable in class com.sun.btrace.runtime.TypeUtils
    +
     
    +
    objectLimit(int) - Method in class com.sun.btrace.DOTWriter
    +
     
    +
    objectOrArrayType(String) - Static method in class com.sun.btrace.runtime.TypeUtils
    +
     
    +
    offer(V) - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    offerFirst(V) - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    offerLast(V) - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    OkayCommand - Class in com.sun.btrace.comm
    +
     
    +
    OkayCommand() - Constructor for class com.sun.btrace.comm.OkayCommand
    +
     
    +
    onAfterArrayLoad(int) - Method in class com.sun.btrace.runtime.instr.ArrayAccessInstrumentor
    +
     
    +
    onAfterArrayNew(String, int) - Method in class com.sun.btrace.runtime.instr.ArrayAllocInstrumentor
    +
     
    +
    onAfterArrayStore(int) - Method in class com.sun.btrace.runtime.instr.ArrayAccessInstrumentor
    +
     
    +
    onAfterCallMethod(int, String, String, String) - Method in class com.sun.btrace.runtime.instr.MethodCallInstrumentor
    +
     
    +
    onAfterGetField(int, String, String, String) - Method in class com.sun.btrace.runtime.instr.FieldAccessInstrumentor
    +
     
    +
    onAfterLine(int) - Method in class com.sun.btrace.runtime.instr.LineNumberInstrumentor
    +
     
    +
    onAfterPutField(int, String, String, String) - Method in class com.sun.btrace.runtime.instr.FieldAccessInstrumentor
    +
     
    +
    onAfterSyncEntry() - Method in class com.sun.btrace.runtime.instr.SynchronizedInstrumentor
    +
     
    +
    onAfterSyncExit() - Method in class com.sun.btrace.runtime.instr.SynchronizedInstrumentor
    +
     
    +
    onAfterTypeCheck(int, String) - Method in class com.sun.btrace.runtime.instr.TypeCheckInstrumentor
    +
     
    +
    onBeforeArrayLoad(int) - Method in class com.sun.btrace.runtime.instr.ArrayAccessInstrumentor
    +
     
    +
    onBeforeArrayNew(String, int) - Method in class com.sun.btrace.runtime.instr.ArrayAllocInstrumentor
    +
     
    +
    onBeforeArrayStore(int) - Method in class com.sun.btrace.runtime.instr.ArrayAccessInstrumentor
    +
     
    +
    onBeforeCallMethod(int, String, String, String) - Method in class com.sun.btrace.runtime.instr.MethodCallInstrumentor
    +
     
    +
    onBeforeGetField(int, String, String, String) - Method in class com.sun.btrace.runtime.instr.FieldAccessInstrumentor
    +
     
    +
    onBeforeLine(int) - Method in class com.sun.btrace.runtime.instr.LineNumberInstrumentor
    +
     
    +
    onBeforePutField(int, String, String, String) - Method in class com.sun.btrace.runtime.instr.FieldAccessInstrumentor
    +
     
    +
    onBeforeSyncEntry() - Method in class com.sun.btrace.runtime.instr.SynchronizedInstrumentor
    +
     
    +
    onBeforeSyncExit() - Method in class com.sun.btrace.runtime.instr.SynchronizedInstrumentor
    +
     
    +
    onBeforeTypeCheck(int, String) - Method in class com.sun.btrace.runtime.instr.TypeCheckInstrumentor
    +
     
    +
    onCatch(String) - Method in class com.sun.btrace.runtime.instr.CatchInstrumentor
    +
     
    +
    onClassInstrumented(String) - Method in class com.sun.btrace.api.BTraceTask.MessageDispatcher
    +
     
    +
    onCommand(Command) - Method in interface com.sun.btrace.CommandListener
    +
     
    +
    OnError - Annotation Type in com.sun.btrace.annotations
    +
    +
    BTrace method annotated by this annotation is called when + any exception is thrown by any of the BTrace action methods.
    +
    +
    onError(Throwable) - Method in class com.sun.btrace.api.BTraceTask.MessageDispatcher
    +
     
    +
    ONERROR_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    onErrorReturn() - Method in class com.sun.btrace.runtime.instr.ErrorReturnInstrumentor
    +
     
    +
    onErrorReturn() - Method in class com.sun.btrace.runtime.instr.SynchronizedInstrumentor
    +
     
    +
    OnEvent - Annotation Type in com.sun.btrace.annotations
    +
    +
    BTrace methods annotated by this annotation are called when + BTrace client sends "event" command.
    +
    +
    ONEVENT_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    OnExit - Annotation Type in com.sun.btrace.annotations
    +
    +
    BTrace method annotated by this annotation is called when + BTrace "exit(int)" built-in function is called by some + other BTrace action method.
    +
    +
    ONEXIT_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    onGrid(String, List<Object[]>) - Method in class com.sun.btrace.api.BTraceTask.MessageDispatcher
    +
     
    +
    OnLowMemory - Annotation Type in com.sun.btrace.annotations
    +
    +
    BTrace methods annotated by this annotation are called when + the traced JVM's specified memory pool exceeds specified + threshold size.
    +
    +
    ONLOWMEMORY_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    OnMethod - Annotation Type in com.sun.btrace.annotations
    +
    +
    This annotation specifies a BTrace probe point by specifying + a java class (or classes), a method (or methods in it) and + a specific location within it.
    +
    +
    OnMethod - Class in com.sun.btrace.runtime
    +
    +
    This class is used to store data of the annotation + com.sun.btrace.annotations.OnMethod.
    +
    +
    OnMethod() - Constructor for class com.sun.btrace.runtime.OnMethod
    +
     
    +
    OnMethod(DebugSupport) - Constructor for class com.sun.btrace.runtime.OnMethod
    +
     
    +
    OnMethod(BTraceMethodNode, DebugSupport) - Constructor for class com.sun.btrace.runtime.OnMethod
    +
     
    +
    ONMETHOD_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    onMethodEntry() - Method in class com.sun.btrace.runtime.instr.ErrorReturnInstrumentor
    +
     
    +
    onMethodEntry() - Method in class com.sun.btrace.runtime.instr.MethodEntryInstrumentor
    +
     
    +
    onMethodEntry() - Method in class com.sun.btrace.runtime.instr.SynchronizedInstrumentor
    +
     
    +
    onMethodReturn(int) - Method in class com.sun.btrace.runtime.instr.ErrorReturnInstrumentor
    +
     
    +
    onMethodReturn(int) - Method in class com.sun.btrace.runtime.instr.MethodEntryExitInstrumentor
    +
     
    +
    onMethodReturn(int) - Method in class com.sun.btrace.runtime.instr.MethodReturnInstrumentor
    +
     
    +
    onMethodReturn(int) - Method in class com.sun.btrace.runtime.instr.SynchronizedInstrumentor
    +
     
    +
    onmethods() - Method in interface com.sun.btrace.runtime.BTraceProbe
    +
     
    +
    onmethods() - Method in class com.sun.btrace.runtime.BTraceProbeNode
    +
     
    +
    onmethods() - Method in class com.sun.btrace.runtime.BTraceProbePersisted
    +
     
    +
    onNumberMap(String, Map<String, ? extends Number>) - Method in class com.sun.btrace.api.BTraceTask.MessageDispatcher
    +
     
    +
    onNumberMessage(String, Number) - Method in class com.sun.btrace.api.BTraceTask.MessageDispatcher
    +
     
    +
    onPrintMessage(String) - Method in class com.sun.btrace.api.BTraceTask.MessageDispatcher
    +
     
    +
    OnProbe - Annotation Type in com.sun.btrace.annotations
    +
    +
    This annotation is used to specify a BTrace + probe point in an abstract fashion instead of + specifying the class and the method names.
    +
    +
    OnProbe - Class in com.sun.btrace.runtime
    +
    +
    This class is used to store data of the annotation + com.sun.btrace.annotations.OnProbe.
    +
    +
    OnProbe(BTraceMethodNode) - Constructor for class com.sun.btrace.runtime.OnProbe
    +
     
    +
    OnProbe() - Constructor for class com.sun.btrace.runtime.OnProbe
    +
     
    +
    ONPROBE_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    onprobes() - Method in interface com.sun.btrace.runtime.BTraceProbe
    +
     
    +
    onprobes() - Method in class com.sun.btrace.runtime.BTraceProbeNode
    +
     
    +
    onprobes() - Method in class com.sun.btrace.runtime.BTraceProbePersisted
    +
     
    +
    onStack - Variable in class com.sun.btrace.Profiler.Record
    +
     
    +
    onStringMap(String, Map<String, String>) - Method in class com.sun.btrace.api.BTraceTask.MessageDispatcher
    +
     
    +
    onTaskStart(BTraceTask) - Method in class com.sun.btrace.api.impl.BTraceTaskImpl
    +
     
    +
    onTaskStop(BTraceTask) - Method in class com.sun.btrace.api.impl.BTraceTaskImpl
    +
     
    +
    onThrow() - Method in class com.sun.btrace.runtime.instr.ThrowInstrumentor
    +
     
    +
    OnTimer - Annotation Type in com.sun.btrace.annotations
    +
    +
    BTrace methods annotated by this annotation are called when + a timer reaches the specified period value.
    +
    +
    ONTIMER_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    OUTPUT_FILE_KEY - Static variable in class com.sun.btrace.SharedSettings
    +
     
    +
    OutputProvider - Interface in com.sun.btrace.spi
    +
     
    +
    + + + +

    P

    +
    +
    parent - Variable in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    parentLoader(ClassLoader) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the parent class loader of the given loader.
    +
    +
    parseBoolean(String) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Parses the string argument as a boolean.
    +
    +
    parseBoolean(String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Parses the string argument as a boolean.
    +
    +
    parseByte(String) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Parses the string argument as a signed decimal + byte.
    +
    +
    parseByte(String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Parses the string argument as a signed decimal + byte.
    +
    +
    parseDouble(String) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns a new double initialized to the value + represented by the specified String, as performed + by the valueOf methcod of class + Double.
    +
    +
    parseDouble(String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a new double initialized to the value + represented by the specified String, as performed + by the valueOf methcod of class + Double.
    +
    +
    parseFloat(String) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns a new float initialized to the value + represented by the specified String, as performed + by the valueOf method of class Float.
    +
    +
    parseFloat(String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a new float initialized to the value + represented by the specified String, as performed + by the valueOf method of class Float.
    +
    +
    parseInt(String, int) - Static method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    parseInt(String) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Parses the string argument as a signed decimal integer.
    +
    +
    parseInt(String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Parses the string argument as a signed decimal integer.
    +
    +
    parseLong(String, long) - Static method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    parseLong(String) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Parses the string argument as a signed decimal + long.
    +
    +
    parseLong(String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Parses the string argument as a signed decimal + long.
    +
    +
    parseShort(String) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Parses the string argument as a signed decimal + short.
    +
    +
    parseShort(String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Parses the string argument as a signed decimal + short.
    +
    +
    pattern(String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    This is synonym for "regexp".
    +
    +
    pattern(String, int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    This is synonym for "regexp".
    +
    +
    pattern(String) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    This is synonym for "regexp".
    +
    +
    pattern(String, int) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    This is synonym for "regexp".
    +
    +
    PCPP - Class in com.sun.btrace.compiler
    +
    +
    A minimal pseudo-C-preprocessor derived from PCPP of the GlueGen project.
    +
    +
    PCPP(List) - Constructor for class com.sun.btrace.compiler.PCPP
    +
     
    +
    PCPP(List, Writer) - Constructor for class com.sun.btrace.compiler.PCPP
    +
     
    +
    peakThreadCount() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the peak live thread count since the Java virtual machine + started or peak was reset.
    +
    +
    peakThreadCount() - Static method in class com.sun.btrace.BTraceUtils.Sys.VM
    +
    +
    Returns the peak live thread count since the Java virtual machine + started or peak was reset.
    +
    +
    peek() - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    peek(Deque<V>) - Static method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    peek(Deque<V>) - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    peek(Deque<V>) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    peekFirst() - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    peekFirst(Deque<V>) - Static method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    peekFirst(Deque<V>) - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    peekFirst(Deque<V>) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    peekLast() - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    peekLast(Deque<V>) - Static method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    peekLast(Deque<V>) - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    peekLast(Deque<V>) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    perfInt(String) - Static method in class com.sun.btrace.BTraceUtils.Counters
    +
    +
    accessing jvmstat (perf) int counter
    +
    +
    perfInt(String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    accessing jvmstat (perf) int counter
    +
    +
    perfInt(String) - Method in interface com.sun.btrace.PerfReader
    +
     
    +
    perfLong(String) - Static method in class com.sun.btrace.BTraceUtils.Counters
    +
    +
    accessing jvmstat (perf) long counter
    +
    +
    perfLong(String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    accessing jvmstat (perf) long counter
    +
    +
    perfLong(String) - Method in interface com.sun.btrace.PerfReader
    +
     
    +
    PerfReader - Interface in com.sun.btrace
    +
    +
    This interface hides jvmstat classes from the + caller.
    +
    +
    perfString(String) - Static method in class com.sun.btrace.BTraceUtils.Counters
    +
    +
    accessing jvmstat (perf) String counter
    +
    +
    perfString(String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    accessing jvmstat (perf) String counter
    +
    +
    perfString(String) - Method in interface com.sun.btrace.PerfReader
    +
     
    +
    period - Variable in class com.sun.btrace.shared.TimerHandler
    +
     
    +
    periodArg - Variable in class com.sun.btrace.shared.TimerHandler
    +
     
    +
    poll() - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    poll(Deque<V>) - Static method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    poll(Deque<V>) - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    poll(Deque<V>) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    pollFirst() - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    pollLast() - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    pool - Variable in class com.sun.btrace.shared.LowMemoryHandler
    +
     
    +
    pop() - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    pop() - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    PORT_PROPERTY - Static variable in interface com.sun.btrace.spi.PortLocator
    +
     
    +
    PortLocator - Interface in com.sun.btrace.spi
    +
     
    +
    PortLocatorImpl - Class in com.sun.btrace.spi.impl
    +
     
    +
    PortLocatorImpl() - Constructor for class com.sun.btrace.spi.impl.PortLocatorImpl
    +
     
    +
    Postprocessor - Class in com.sun.btrace.compiler
    +
     
    +
    Postprocessor(ClassVisitor) - Constructor for class com.sun.btrace.compiler.Postprocessor
    +
     
    +
    PrefixMap - Class in com.sun.btrace.util
    +
    +
    Simplified trie-based prefix map
    +
    +
    PrefixMap() - Constructor for class com.sun.btrace.util.PrefixMap
    +
     
    +
    premain(String, Instrumentation) - Static method in class com.sun.btrace.agent.Main
    +
     
    +
    print(PrintWriter) - Method in class com.sun.btrace.aggregation.HistogramData
    +
     
    +
    print(Object) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    print(boolean) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints a boolean value.
    +
    +
    print(char) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints a character.
    +
    +
    print(int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints an integer.
    +
    +
    print(long) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints a long integer.
    +
    +
    print(float) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints a floating-point number.
    +
    +
    print(double) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints a double-precision floating-point number.
    +
    +
    print(PrintWriter) - Method in class com.sun.btrace.comm.ErrorCommand
    +
     
    +
    print(PrintWriter) - Method in class com.sun.btrace.comm.GridDataCommand
    +
     
    +
    print(PrintWriter) - Method in class com.sun.btrace.comm.MessageCommand
    +
     
    +
    print(PrintWriter) - Method in class com.sun.btrace.comm.NumberDataCommand
    +
     
    +
    print(PrintWriter) - Method in class com.sun.btrace.comm.NumberMapDataCommand
    +
     
    +
    print(PrintWriter) - Method in interface com.sun.btrace.comm.PrintableCommand
    +
    +
    Print the command internal info
    +
    +
    print(PrintWriter) - Method in class com.sun.btrace.comm.RetransformClassNotification
    +
     
    +
    print(PrintWriter) - Method in class com.sun.btrace.comm.StringMapDataCommand
    +
     
    +
    print(String) - Method in class com.sun.btrace.services.impl.Printer
    +
     
    +
    PrintableCommand - Interface in com.sun.btrace.comm
    +
    +
    Marks any command which is able to print its internal info into + the provided PrintWriter
    +
    +
    printAggregation(String, Aggregation) - Static method in class com.sun.btrace.BTraceUtils.Aggregations
    +
     
    +
    printAggregation(String, Aggregation, String) - Static method in class com.sun.btrace.BTraceUtils.Aggregations
    +
     
    +
    printAggregation(String, String, Collection<Aggregation>) - Static method in class com.sun.btrace.BTraceUtils.Aggregations
    +
     
    +
    printAggregation(String, Aggregation) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints the aggregation.
    +
    +
    printAggregation(String, Aggregation, String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints aggregation using the provided format
    +
    +
    printArray(Object[]) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
    +
    +
    printArray(int[]) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
    +
    +
    printArray(long[]) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
    +
    +
    printArray(float[]) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
    +
    +
    printArray(double[]) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
    +
    +
    printArray(boolean[]) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
    +
    +
    printArray(char[]) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
    +
    +
    printArray(byte[]) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
    +
    +
    printArray(short[]) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints the elements of the given array as comma + separated line bounded by '[' and ']'.
    +
    +
    printEnv() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints all system environment values.
    +
    +
    printEnv() - Static method in class com.sun.btrace.BTraceUtils.Sys.Env
    +
    +
    Prints all system environment values.
    +
    +
    Printer - Class in com.sun.btrace.services.impl
    +
    +
    A very rudimentary printer service.
    +
    +
    Printer(BTraceRuntime) - Constructor for class com.sun.btrace.services.impl.Printer
    +
     
    +
    printFields(Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Print all instance fields of an object as name-value + pairs.
    +
    +
    printFields(Object, boolean) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Print all instance fields of an object as name-value + pairs.
    +
    +
    printFields(Object) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Print all instance fields of an object as name-value + pairs.
    +
    +
    printFields(Object, boolean) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Print all instance fields of an object as name-value + pairs.
    +
    +
    println(Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints the given object and then prints a newline
    +
    +
    println(boolean) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints a boolean and then terminate the line.
    +
    +
    println(char) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints a character and then terminate the line.
    +
    +
    println(int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints an integer and then terminate the line.
    +
    +
    println(long) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints a long and then terminate the line.
    +
    +
    println(float) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints a float and then terminate the line.
    +
    +
    println(double) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints a double and then terminate the line.
    +
    +
    println() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Terminates the current line by writing the line separator string.
    +
    +
    println(String) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    println(String) - Method in class com.sun.btrace.services.impl.Printer
    +
     
    +
    println() - Method in class com.sun.btrace.services.impl.Printer
    +
     
    +
    printMap(Map) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints the given Map.
    +
    +
    printNumber(String, Number) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints a number.
    +
    +
    printNumberMap(String, Map<String, ? extends Number>) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints the given Map.
    +
    +
    printObject() - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    printProperties() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints all Sys properties.
    +
    +
    printProperties() - Static method in class com.sun.btrace.BTraceUtils.Sys.Env
    +
    +
    Prints all Sys properties.
    +
    +
    printSnapshot(String, Profiler) - Static method in class com.sun.btrace.BTraceUtils.Profiling
    +
     
    +
    printSnapshot(String, Profiler, String) - Static method in class com.sun.btrace.BTraceUtils.Profiling
    +
     
    +
    printStaticFields(Class) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Print all static fields of the class as name-value + pairs.
    +
    +
    printStaticFields(Class, boolean) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Print all static fields of the class as name-value + pairs.
    +
    +
    printStaticFields(Class) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Print all static fields of the class as name-value + pairs.
    +
    +
    printStaticFields(Class, boolean) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Print all static fields of the class as name-value + pairs.
    +
    +
    printStringMap(String, Map<String, String>) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints the given Map.
    +
    +
    printVmArguments() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Prints VM input arguments list.
    +
    +
    printVmArguments() - Static method in class com.sun.btrace.BTraceUtils.Sys.VM
    +
    +
    Prints VM input arguments list.
    +
    +
    probe(String, String) - Static method in class com.sun.btrace.BTraceUtils.D
    +
    +
    BTrace to DTrace communication chennal.
    +
    +
    probe(String, String, int) - Static method in class com.sun.btrace.BTraceUtils.D
    +
    +
    BTrace to DTrace communication chennal.
    +
    +
    probe(String, String, int, int) - Static method in class com.sun.btrace.BTraceUtils.D
    +
    +
    BTrace to DTrace communication channel.
    +
    +
    PROBE_DESC_PATH_KEY - Static variable in class com.sun.btrace.SharedSettings
    +
     
    +
    probeClass() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Deprecated. +
    Since 1.1. Use ProbeClassName and Self annotations instead
    +
    +
    +
    ProbeClassName - Annotation Type in com.sun.btrace.annotations
    +
    +
    It is used to mark a probe method argument as the receiver of the probe target class name
    + Applicable only for OnMethod annotation
    +
    +
    ProbeDescriptor - Class in com.sun.btrace.runtime
    +
     
    +
    ProbeDescriptor() - Constructor for class com.sun.btrace.runtime.ProbeDescriptor
    +
     
    +
    ProbeDump - Class in com.sun.btrace.client
    +
     
    +
    ProbeDump() - Constructor for class com.sun.btrace.client.ProbeDump
    +
     
    +
    probeLine() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the currently probed source line number (if available).
    +
    +
    probeMethod() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Deprecated. +
    Since 1.1. Use ProbeMethodName annotation instead
    +
    +
    +
    ProbeMethodName - Annotation Type in com.sun.btrace.annotations
    +
    +
    It is used to mark a probe method argument as the receiver of the probe target class name
    + Applicable only for OnMethod annotation
    +
    +
    process(Set<? extends TypeElement>, RoundEnvironment) - Method in class com.sun.btrace.compiler.Verifier
    +
     
    +
    processCPUTime() - Static method in class com.sun.btrace.BTraceUtils.Sys.VM
    +
    +
    Returns the CPU time used by the process on which the Java virtual machine is running in nanoseconds.
    +
    +
    Profiler - Class in com.sun.btrace
    +
    +
    Profiler is a highly specialized aggregation-like data collector optimized + for high-speed collection of the application execution call tree data.
    +
    +
    Profiler() - Constructor for class com.sun.btrace.Profiler
    +
    +
    Creates a new Profiler instance
    +
    +
    Profiler.MBeanValueProvider - Interface in com.sun.btrace
    +
    +
    Helper interface to make accessing a Profiler as an MBean + type safe.
    +
    +
    Profiler.Record - Class in com.sun.btrace
    +
    +
    Record represents an atomic unit in the application execution call tree
    +
    +
    Profiler.Snapshot - Class in com.sun.btrace
    +
    +
    Snapshot is an immutable image of the current profiling data collected + by the Profiler +

    + It is created by calling Profiler.snapshot() method
    +
    +
    Profiling() - Constructor for class com.sun.btrace.BTraceUtils.Profiling
    +
     
    +
    properties() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns all Sys properties.
    +
    +
    properties() - Static method in class com.sun.btrace.BTraceUtils.Sys.Env
    +
    +
    Returns all Sys properties.
    +
    +
    Property - Annotation Type in com.sun.btrace.annotations
    +
    +
    BTrace fields with this annotation are exposed as attributes of + the dynamic JMX bean that wraps the BTrace class.
    +
    +
    property(String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Gets the system property indicated by the specified key.
    +
    +
    property(String) - Static method in class com.sun.btrace.BTraceUtils.Sys.Env
    +
    +
    Gets the system property indicated by the specified key.
    +
    +
    provide() - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor.ArgumentProvider
    +
     
    +
    push(V) - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    push(Deque<V>, V) - Static method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    push(Deque<V>, V) - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    push(Deque<V>, V) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    push(int) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    put(String, String) - Method in class com.sun.btrace.ArgsMap
    +
     
    +
    put(Map<K, V>, K, V) - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    put(Map<K, V>, K, V) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    put(long, T) - Method in class com.sun.btrace.util.LongMap
    +
     
    +
    putAll(Map<K, V>, Map<K, V>) - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    putPerfDouble(double, String) - Static method in class com.sun.btrace.BTraceRuntime
    +
    +
    write the value of double perf.
    +
    +
    putPerfFloat(float, String) - Static method in class com.sun.btrace.BTraceRuntime
    +
    +
    Write the value of float perf.
    +
    +
    putPerfInt(int, String) - Static method in class com.sun.btrace.BTraceRuntime
    +
    +
    Write the value of integer perf.
    +
    +
    putPerfLong(long, String) - Static method in class com.sun.btrace.BTraceRuntime
    +
    +
    Write the value of float perf.
    +
    +
    putPerfString(String, String) - Static method in class com.sun.btrace.BTraceRuntime
    +
    +
    Write the value of float perf.
    +
    +
    putStatic(String, String, String) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    + + + +

    R

    +
    +
    random() - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns a double value with a positive sign, greater + than or equal to 0.0 and less than 1.0.
    +
    +
    random() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a double value with a positive sign, greater + than or equal to 0.0 and less than 1.0.
    +
    +
    RandomIntProvider - Class in com.sun.btrace.instr
    +
     
    +
    RandomIntProvider() - Constructor for class com.sun.btrace.instr.RandomIntProvider
    +
     
    +
    read(ObjectInput) - Method in class com.sun.btrace.comm.Command
    +
     
    +
    read(ObjectInput) - Method in class com.sun.btrace.comm.ErrorCommand
    +
     
    +
    read(ObjectInput) - Method in class com.sun.btrace.comm.EventCommand
    +
     
    +
    read(ObjectInput) - Method in class com.sun.btrace.comm.ExitCommand
    +
     
    +
    read(ObjectInput) - Method in class com.sun.btrace.comm.GridDataCommand
    +
     
    +
    read(ObjectInput) - Method in class com.sun.btrace.comm.InstrumentCommand
    +
     
    +
    read(ObjectInput) - Method in class com.sun.btrace.comm.MessageCommand
    +
     
    +
    read(ObjectInput) - Method in class com.sun.btrace.comm.NumberDataCommand
    +
     
    +
    read(ObjectInput) - Method in class com.sun.btrace.comm.NumberMapDataCommand
    +
     
    +
    read(ObjectInput) - Method in class com.sun.btrace.comm.OkayCommand
    +
     
    +
    read(ObjectInput) - Method in class com.sun.btrace.comm.RenameCommand
    +
     
    +
    read(ObjectInput) - Method in class com.sun.btrace.comm.RetransformationStartNotification
    +
     
    +
    read(ObjectInput) - Method in class com.sun.btrace.comm.RetransformClassNotification
    +
     
    +
    read(ObjectInput) - Method in class com.sun.btrace.comm.SetSettingsCommand
    +
     
    +
    read(ObjectInput) - Method in class com.sun.btrace.comm.StringMapDataCommand
    +
     
    +
    read(ObjectInput) - Static method in class com.sun.btrace.comm.WireIO
    +
     
    +
    read() - Method in class com.sun.btrace.compiler.ConcatenatingReader
    +
     
    +
    read(char[], int, int) - Method in class com.sun.btrace.compiler.ConcatenatingReader
    +
     
    +
    read(DataInputStream) - Method in class com.sun.btrace.runtime.BTraceProbePersisted
    +
     
    +
    ready() - Method in class com.sun.btrace.compiler.ConcatenatingReader
    +
     
    +
    Record(String) - Constructor for class com.sun.btrace.Profiler.Record
    +
     
    +
    recordEntry(Profiler, String) - Static method in class com.sun.btrace.BTraceUtils.Profiling
    +
    +
    Records the entry to a particular code block
    +
    +
    recordEntry(String) - Method in class com.sun.btrace.Profiler
    +
    +
    Records the event of entering an execution unit (eg.
    +
    +
    recordEntry(String) - Method in class com.sun.btrace.profiling.MethodInvocationProfiler
    +
     
    +
    recordExit(Profiler, String, long) - Static method in class com.sun.btrace.BTraceUtils.Profiling
    +
    +
    Records the exit out of a particular code block
    +
    +
    recordExit(String, long) - Method in class com.sun.btrace.Profiler
    +
    +
    Records the event of exiting an execution unit (eg.
    +
    +
    recordExit(String, long) - Method in class com.sun.btrace.profiling.MethodInvocationProfiler
    +
     
    +
    recordTemplate(Template) - Method in class com.sun.btrace.util.templates.BaseTemplateExpander
    +
     
    +
    recordTemplate(Template) - Method in class com.sun.btrace.util.templates.impl.MethodTrackingExpander
    +
     
    +
    References() - Constructor for class com.sun.btrace.BTraceUtils.References
    +
     
    +
    referring - Variable in class com.sun.btrace.Profiler.Record
    +
     
    +
    Reflective() - Constructor for class com.sun.btrace.BTraceUtils.Reflective
    +
     
    +
    REGEX_SPECIFIER - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    regexp(String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Compiles the given regular expression into a pattern.
    +
    +
    regexp(String, int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Compiles the given regular expression into a pattern with the given + flags.
    +
    +
    regexp(String) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    Compiles the given regular expression into a pattern.
    +
    +
    regexp(String, int) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    Compiles the given regular expression into a pattern with the given + flags.
    +
    +
    register(BTraceRuntime, BTraceTransformer) - Method in interface com.sun.btrace.runtime.BTraceProbe
    +
     
    +
    register(BTraceRuntime, BTraceTransformer) - Method in class com.sun.btrace.runtime.BTraceProbeNode
    +
     
    +
    register(BTraceRuntime, BTraceTransformer) - Method in class com.sun.btrace.runtime.BTraceProbePersisted
    +
     
    +
    register(BTraceProbe) - Method in class com.sun.btrace.runtime.BTraceTransformer
    +
     
    +
    registerCounter(int, int) - Static method in class com.sun.btrace.instr.MethodTracker
    +
    +
    Creates a supporting structures for a new method id
    +
    +
    registerMBean(Class) - Static method in class com.sun.btrace.BTraceMBean
    +
     
    +
    registerTemplates(Template...) - Static method in class com.sun.btrace.util.templates.BTraceTemplates
    +
     
    +
    remove(Object) - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    remove() - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    remove(Map<K, V>, K) - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    remove(Map<K, V>, K) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    remove(long) - Method in class com.sun.btrace.util.LongMap
    +
     
    +
    removeAll(Collection<?>) - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    removeFirst() - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    removeFirst(Deque<V>) - Static method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    removeFirst(Deque<V>) - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    removeFirst(Deque<V>) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    removeFirstOccurrence(Object) - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    removeIncoming(CallGraph.Edge) - Method in class com.sun.btrace.runtime.CallGraph.Node
    +
     
    +
    removeLast() - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    removeLast(Deque<V>) - Static method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    removeLast(Deque<V>) - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    removeLast(Deque<V>) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    removeLastOccurrence(Object) - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    removeMessageDispatcher(BTraceTask.MessageDispatcher) - Method in class com.sun.btrace.api.BTraceTask
    +
     
    +
    removeMessageDispatcher(BTraceTask.MessageDispatcher) - Method in class com.sun.btrace.api.impl.BTraceTaskImpl
    +
    +
    Dispatcher management
    +
    +
    removeOutgoing(CallGraph.Edge) - Method in class com.sun.btrace.runtime.CallGraph.Node
    +
     
    +
    removeStateListener(BTraceTask.StateListener) - Method in class com.sun.btrace.api.BTraceTask
    +
    +
    Listener management
    +
    +
    removeStateListener(BTraceTask.StateListener) - Method in class com.sun.btrace.api.impl.BTraceTaskImpl
    +
    +
    Listener management
    +
    +
    RENAME - Static variable in class com.sun.btrace.comm.Command
    +
     
    +
    RenameCommand - Class in com.sun.btrace.comm
    +
     
    +
    RenameCommand(String) - Constructor for class com.sun.btrace.comm.RenameCommand
    +
     
    +
    RenameCommand() - Constructor for class com.sun.btrace.comm.RenameCommand
    +
     
    +
    reportError(String) - Static method in class com.sun.btrace.runtime.Verifier
    +
     
    +
    reportError(String, String) - Static method in class com.sun.btrace.runtime.Verifier
    +
     
    +
    reset(Profiler) - Static method in class com.sun.btrace.BTraceUtils.Profiling
    +
     
    +
    reset() - Method in class com.sun.btrace.compiler.ConcatenatingReader
    +
     
    +
    reset() - Method in class com.sun.btrace.Profiler
    +
    +
    Resets all the collected data
    +
    +
    reset() - Method in class com.sun.btrace.profiling.MethodInvocationProfiler
    +
     
    +
    RESET - Static variable in class com.sun.btrace.util.templates.impl.MethodTrackingExpander
    +
    +
    Will reset the expander state - useful for multiple return points.
    +
    +
    resetState() - Method in class com.sun.btrace.util.templates.impl.MethodTrackingExpander
    +
     
    +
    resetState() - Method in interface com.sun.btrace.util.templates.TemplateExpander
    +
    +
    Called upon code points invalidating the current expander status
    +
    +
    restoreStack(int[], boolean) - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    restoreStack(int[], Type[], boolean) - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    retainAll(Collection<?>) - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    retransform(String, Class<?>) - Static method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    RETRANSFORM_CLASS - Static variable in class com.sun.btrace.comm.Command
    +
     
    +
    RETRANSFORMATION_START - Static variable in class com.sun.btrace.comm.Command
    +
     
    +
    RetransformationStartNotification - Class in com.sun.btrace.comm
    +
    +
    This command is sent out when the BTrace engine calls + Instrumentation.retransformClasses(Class[]) method.
    +
    +
    RetransformationStartNotification() - Constructor for class com.sun.btrace.comm.RetransformationStartNotification
    +
     
    +
    RetransformationStartNotification(int) - Constructor for class com.sun.btrace.comm.RetransformationStartNotification
    +
     
    +
    RetransformClassNotification - Class in com.sun.btrace.comm
    +
    +
    This command is sent out as a notification that a class + is going to be transformed
    +
    +
    RetransformClassNotification(String) - Constructor for class com.sun.btrace.comm.RetransformClassNotification
    +
     
    +
    RetransformClassNotification() - Constructor for class com.sun.btrace.comm.RetransformClassNotification
    +
     
    +
    Return - Annotation Type in com.sun.btrace.annotations
    +
    +
    Marks a method parameter as the one that should contain the return value
    +
    +
    RETURN_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    returnValue() - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    rt - Variable in class com.sun.btrace.services.spi.RuntimeService
    +
     
    +
    run(Reader, String) - Method in class com.sun.btrace.compiler.PCPP
    +
     
    +
    runFinalization() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Runs the finalization methods of any objects pending finalization.
    +
    +
    runFinalization() - Static method in class com.sun.btrace.BTraceUtils.Sys.Memory
    +
    +
    Runs the finalization methods of any objects pending finalization.
    +
    +
    runtime(Class<S>) - Static method in class com.sun.btrace.services.api.Service
    +
    +
    Creates a BTrace runtime aware service
    +
    +
    RuntimeService - Class in com.sun.btrace.services.spi
    +
     
    +
    RuntimeService(BTraceRuntime) - Constructor for class com.sun.btrace.services.spi.RuntimeService
    +
     
    +
    + + + +

    S

    +
    +
    safeStr(Object) - Static method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    Sampled - Annotation Type in com.sun.btrace.annotations
    +
    +
    Marks an OnMethod handler as a sampled one.
    +
    +
    Sampled.Sampler - Enum in com.sun.btrace.annotations
    +
    +
    Specifies the sampler kind + + None - no sampling + Const - keeps the average number of events between samples + Adaptive - increases or decreases the average number of events between samples to lower overhead +
    +
    +
    SAMPLED_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    SAMPLER_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    Self - Annotation Type in com.sun.btrace.annotations
    +
    +
    Marks a method parameter as the one that should contain *this* instance
    +
    +
    SELF_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    selfArg(int, Type) - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    selfTime - Variable in class com.sun.btrace.Profiler.Record
    +
     
    +
    selfTimeMax - Variable in class com.sun.btrace.Profiler.Record
    +
     
    +
    selfTimeMin - Variable in class com.sun.btrace.Profiler.Record
    +
     
    +
    send(Command) - Method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    sendEvent(String) - Method in class com.sun.btrace.api.BTraceTask
    +
    +
    Sends a named event to the script server side
    +
    +
    sendEvent() - Method in class com.sun.btrace.api.BTraceTask
    +
    +
    Sends an anonymous event to the script server side
    +
    +
    sendEvent(String) - Method in class com.sun.btrace.api.impl.BTraceTaskImpl
    +
     
    +
    sendEvent() - Method in class com.sun.btrace.api.impl.BTraceTaskImpl
    +
     
    +
    sendEvent() - Method in class com.sun.btrace.client.Client
    +
    +
    Sends an EventCommand to the traced JVM.
    +
    +
    sendEvent(String) - Method in class com.sun.btrace.client.Client
    +
    +
    Sends an EventCommand to the traced JVM.
    +
    +
    sendExit() - Method in class com.sun.btrace.client.Client
    +
    +
    Sends ExitCommand to the traced JVM.
    +
    +
    sendExit(int) - Method in class com.sun.btrace.client.Client
    +
    +
    Sends ExitCommand to the traced JVM.
    +
    +
    serialize(Serializable, String) - Static method in class com.sun.btrace.BTraceUtils.Export
    +
    +
    Serialize a given object into the given file.
    +
    +
    serialize(Serializable, String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Serialize a given object into the given file.
    +
    +
    serialize(AnnotationNode, StringBuilder) - Static method in class com.sun.btrace.compiler.AnnotationSerializer
    +
     
    +
    serialize(MethodNode) - Static method in class com.sun.btrace.shared.MethodSerializer
    +
     
    +
    SERVICE - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    Service - Class in com.sun.btrace.services.api
    +
    +
    A service factory to be used to get access to the services locally + inside one particular method.
    +
    +
    Service() - Constructor for class com.sun.btrace.services.api.Service
    +
     
    +
    ServiceType - Enum in com.sun.btrace.annotations
    +
    +
    Service type enumeration
    +
    +
    set(AtomicInteger, int) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Sets to the given value to the given AtomicInteger.
    +
    +
    set(AtomicLong, long) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Sets to the given value.
    +
    +
    set(AtomicInteger, int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Sets to the given value to the given AtomicInteger.
    +
    +
    set(AtomicLong, long) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Sets to the given value.
    +
    +
    SET_PARAMS - Static variable in class com.sun.btrace.comm.Command
    +
     
    +
    setAttribute(Attribute) - Method in class com.sun.btrace.BTraceMBean
    +
     
    +
    setAttributes(AttributeList) - Method in class com.sun.btrace.BTraceMBean
    +
     
    +
    setCalled() - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    setClazz(String) - Method in class com.sun.btrace.runtime.Location
    +
     
    +
    setClazz(String) - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    setClientName(String) - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    setDebug(boolean) - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    setDumpDir(String) - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    setExactTypeMatch(boolean) - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    setField(String) - Method in class com.sun.btrace.runtime.Location
    +
     
    +
    setFileRollMaxRolls(int) - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    setFileRollMilliseconds(int) - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    setInstrumentationLevel(int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Sets the current instrumentation level.
    +
    +
    setLevel(Level) - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    setLine(int) - Method in class com.sun.btrace.runtime.Location
    +
     
    +
    setLocation(Location) - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    setMethod(String) - Method in class com.sun.btrace.runtime.Location
    +
     
    +
    setMethod(String) - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    setName(String) - Method in class com.sun.btrace.runtime.OnProbe
    +
     
    +
    setNamespace(String) - Method in class com.sun.btrace.runtime.OnProbe
    +
     
    +
    setNamespace(String) - Method in class com.sun.btrace.runtime.ProbeDescriptor
    +
     
    +
    setOnMethods(Collection<OnMethod>) - Method in class com.sun.btrace.runtime.OnProbe
    +
     
    +
    setOutputDir(String) - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    setOutputFile(String) - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    setProbeDescPath(String) - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    setProbes(Collection<OnProbe>) - Method in class com.sun.btrace.runtime.ProbeDescriptor
    +
     
    +
    setRetransformStartup(boolean) - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    setSamplerKind(Sampled.Sampler) - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    setSamplerMean(int) - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    setScript(String) - Method in class com.sun.btrace.api.BTraceTask
    +
    +
    Property setter
    +
    +
    setScript(String) - Method in class com.sun.btrace.api.impl.BTraceTaskImpl
    +
     
    +
    SetSettingsCommand - Class in com.sun.btrace.comm
    +
    +
    This command is used to remotely set custom settings + (trusted mode, debug, etc.)
    +
    +
    SetSettingsCommand(Map<String, ?>) - Constructor for class com.sun.btrace.comm.SetSettingsCommand
    +
     
    +
    SetSettingsCommand() - Constructor for class com.sun.btrace.comm.SetSettingsCommand
    +
     
    +
    setSkipLabel(Label) - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    setStatsdHost(String) - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    setStatsdPort(int) - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    setTargetDescriptor(String) - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    setTargetDescriptor(String) - Method in class com.sun.btrace.runtime.OnProbe
    +
     
    +
    setTargetName(String) - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    setTargetName(String) - Method in class com.sun.btrace.runtime.OnProbe
    +
     
    +
    setTrackRetransforms(boolean) - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    setTrusted(boolean) - Method in class com.sun.btrace.SharedSettings
    +
     
    +
    setType(String) - Method in class com.sun.btrace.runtime.Location
    +
     
    +
    setType(String) - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    setValue(Kind) - Method in class com.sun.btrace.runtime.Location
    +
     
    +
    setWhere(Where) - Method in class com.sun.btrace.runtime.Location
    +
     
    +
    SharedRandomIntProvider - Class in com.sun.btrace.instr.random
    +
     
    +
    SharedRandomIntProvider() - Constructor for class com.sun.btrace.instr.random.SharedRandomIntProvider
    +
     
    +
    SharedSettings - Class in com.sun.btrace
    +
     
    +
    SharedSettings() - Constructor for class com.sun.btrace.SharedSettings
    +
     
    +
    SHORT_BOXED_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    SHORT_BOXED_INTERNAL - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    SHORT_VALUE - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    SHORT_VALUE_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    shutdownCmdLine() - Method in class com.sun.btrace.BTraceRuntime
    +
     
    +
    simple(Class<S>) - Static method in class com.sun.btrace.services.api.Service
    +
    +
    Creates a simple service via the default 0-argument constructor
    +
    +
    simple(String, Class<S>) - Static method in class com.sun.btrace.services.api.Service
    +
    +
    Creates a simple service via the provided factory method
    +
    +
    SimpleService - Class in com.sun.btrace.services.spi
    +
     
    +
    SimpleService() - Constructor for class com.sun.btrace.services.spi.SimpleService
    +
     
    +
    size() - Method in class com.sun.btrace.ArgsMap
    +
     
    +
    size() - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    size(Map<K, V>) - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    size(Collection<E>) - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    size(Map<K, V>) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    size(Collection<E>) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    sizeof(Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns an implementation-specific approximation of the amount of storage consumed by + the specified object.
    +
    +
    skip(long) - Method in class com.sun.btrace.compiler.ConcatenatingReader
    +
     
    +
    snapshot(Profiler) - Static method in class com.sun.btrace.BTraceUtils.Profiling
    +
    +
    Creates a new snapshot of the profiling metrics collected sofar
    +
    +
    snapshot() - Method in class com.sun.btrace.Profiler
    +
    +
    Creates an immutable snapshot of the collected profiling data
    +
    +
    snapshot(boolean) - Method in class com.sun.btrace.Profiler
    +
    +
    Creates an immutable snapshot of the collected profiling data.
    + Makes it possible to reset the profiler after creating the snapshot, eventually
    +
    +
    Snapshot(Profiler.Record[], long, long) - Constructor for class com.sun.btrace.Profiler.Snapshot
    +
     
    +
    snapshot(boolean) - Method in class com.sun.btrace.profiling.MethodInvocationProfiler
    +
     
    +
    snapshotAndReset(Profiler) - Static method in class com.sun.btrace.BTraceUtils.Profiling
    +
     
    +
    softRef(Object) - Static method in class com.sun.btrace.BTraceUtils.References
    +
    +
    Creates and returns a soft reference to the given object.
    +
    +
    softRef(Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Creates and returns a soft reference to the given object.
    +
    +
    speculate(int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Sets current speculative buffer id.
    +
    +
    speculate(int) - Static method in class com.sun.btrace.BTraceUtils.Speculation
    +
    +
    Sets current speculative buffer id.
    +
    +
    speculation() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns an identifier for a new speculative buffer.
    +
    +
    Speculation() - Constructor for class com.sun.btrace.BTraceUtils.Speculation
    +
     
    +
    speculation() - Static method in class com.sun.btrace.BTraceUtils.Speculation
    +
    +
    Returns an identifier for a new speculative buffer.
    +
    +
    start() - Method in class com.sun.btrace.api.BTraceTask
    +
    +
    Starts the injected code
    +
    +
    start() - Method in class com.sun.btrace.api.impl.BTraceTaskImpl
    +
    +
    Starts the injected code using the attached BTraceEngine
    +
    +
    start() - Static method in class com.sun.btrace.BTraceRuntime
    +
    +
    start method is called by every BTrace (preprocesed) class + just at the end of it's class initializer.
    +
    +
    START_TIME - Variable in class com.sun.btrace.Profiler
    +
    +
    This property exposes the time of creating this particular Profiler instance.
    +
    +
    started(TaskEvent) - Method in class com.sun.btrace.compiler.Verifier
    +
     
    +
    startsWith(String, String) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    startsWith(String, String) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
     
    +
    stateChanged(BTraceTask.State) - Method in interface com.sun.btrace.api.BTraceTask.StateListener
    +
    +
    Called upon state change
    +
    +
    Statsd - Class in com.sun.btrace.services.impl
    +
    +
    A simple way to submit statsd metrics.
    +
    +
    Statsd.AlertType - Enum in com.sun.btrace.services.impl
    +
     
    +
    Statsd.Priority - Enum in com.sun.btrace.services.impl
    +
     
    +
    STATSD_HOST_KEY - Static variable in class com.sun.btrace.SharedSettings
    +
     
    +
    STATSD_PORT_KEY - Static variable in class com.sun.btrace.SharedSettings
    +
     
    +
    stop() - Method in class com.sun.btrace.api.BTraceTask
    +
    +
    Stops the injected code
    +
    +
    stop() - Method in class com.sun.btrace.api.impl.BTraceTaskImpl
    +
    +
    Stops the injected code running on the attached BTraceEngine
    +
    +
    storeAsNew() - Method in class com.sun.btrace.runtime.BTraceMethodVisitor
    +
     
    +
    storeAsNew() - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    storeAsNew() - Method in interface com.sun.btrace.runtime.MethodInstrumentorHelper
    +
     
    +
    storeField(Type, String, Type) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    storeLocal(Type, int) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    storeNewLocal(Type) - Method in class com.sun.btrace.runtime.BTraceMethodVisitor
    +
     
    +
    storeStaticField(Type, String, Type) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    str(Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a string representation of the object.
    +
    +
    str(boolean) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a String object representing the specified + boolean.
    +
    +
    str(char) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a String object representing the + specified char.
    +
    +
    str(int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a String object representing the + specified integer.
    +
    +
    str(long) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a String object representing the specified + long.
    +
    +
    str(float) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a string representation of the float + argument.
    +
    +
    str(double) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a string representation of the double + argument.
    +
    +
    str(boolean) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    Returns a String object representing the specified + boolean.
    +
    +
    str(char) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    Returns a String object representing the + specified char.
    +
    +
    str(int) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    Returns a String object representing the + specified integer.
    +
    +
    str(long) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    Returns a String object representing the specified + long.
    +
    +
    str(Object) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    Returns a string representation of the object.
    +
    +
    str(float) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    Returns a string representation of the float + argument.
    +
    +
    str(double) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    Returns a string representation of the double + argument.
    +
    +
    strcat(String, String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    This is synonym to "concat".
    +
    +
    strcat(String, String) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    This is synonym to "concat".
    +
    +
    strcmp(String, String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    This is synonym to "compareTo" method.
    +
    +
    strcmp(String, String) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    This is synonym to "compareTo" method.
    +
    +
    stricmp(String, String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    This is synonym to "compareToIgnoreCase".
    +
    +
    stricmp(String, String) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    This is synonym to "compareToIgnoreCase".
    +
    +
    STRING_BUILDER_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    STRING_BUILDER_INTERNAL - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    STRING_BUILDER_TYPE - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    STRING_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    STRING_INTERNAL - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    STRING_MAP - Static variable in class com.sun.btrace.comm.Command
    +
     
    +
    STRING_TYPE - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    stringLimit(int) - Method in class com.sun.btrace.DOTWriter
    +
     
    +
    StringMapDataCommand - Class in com.sun.btrace.comm
    +
    +
    A data command that hold data of type Map<String, String>.
    +
    +
    StringMapDataCommand() - Constructor for class com.sun.btrace.comm.StringMapDataCommand
    +
     
    +
    StringMapDataCommand(String, Map<String, String>) - Constructor for class com.sun.btrace.comm.StringMapDataCommand
    +
     
    +
    Strings() - Constructor for class com.sun.btrace.BTraceUtils.Strings
    +
     
    +
    strlen(String) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    This is synonym for "length".
    +
    +
    strlen(String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    This is synonym for "length".
    +
    +
    strstr(String, String) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    Find String within String
    +
    +
    strstr(String, String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Find String within String
    +
    +
    sub(Type) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    submit(String, byte[], String[], CommandListener) - Method in class com.sun.btrace.client.Client
    +
    +
    Submits the compiled BTrace .class to the VM + attached and passes given command line arguments.
    +
    +
    submit(byte[], String[], CommandListener) - Method in class com.sun.btrace.client.Client
    +
    +
    Submits the compiled BTrace .class to the VM + attached and passes given command line arguments.
    +
    +
    substr(String, int, int) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    Substring
    +
    +
    substr(String, int) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
     
    +
    substr(String, int, int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Substring
    +
    +
    substr(String, int) - Static method in class com.sun.btrace.BTraceUtils
    +
     
    +
    SUCCESS - Static variable in class com.sun.btrace.comm.Command
    +
     
    +
    swap() - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    SynchronizedInstrumentor - Class in com.sun.btrace.runtime.instr
    +
    +
    This visitor helps in inserting code whenever a synchronized + method or block is about to be entered/exited.
    +
    +
    SynchronizedInstrumentor(ClassLoader, MethodVisitor, MethodInstrumentorHelper, String, String, int, String, String) - Constructor for class com.sun.btrace.runtime.instr.SynchronizedInstrumentor
    +
     
    +
    Sys() - Constructor for class com.sun.btrace.BTraceUtils.Sys
    +
     
    +
    systemLoadAverage() - Static method in class com.sun.btrace.BTraceUtils.Sys.VM
    +
    +
    Returns the system load average for the last minute
    +
    +
    + + + +

    T

    +
    +
    TargetInstance - Annotation Type in com.sun.btrace.annotations
    +
    +
    It is used to mark a probe method argument as the receiver of called instance + with Location value of Kind.CALL, Kind.FIELD_GET + or Kind.FIELD_SET.
    +
    +
    TARGETINSTANCE_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    TARGETMETHOD_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    TargetMethodOrField - Annotation Type in com.sun.btrace.annotations
    +
    +
    It is used to mark a probe method argument as the receiver of called method name + in Location = Kind.CALL
    +
    +
    template(String) - Method in class com.sun.btrace.ArgsMap
    +
     
    +
    Template - Class in com.sun.btrace.util.templates
    +
    +
    A template descriptor
    +
    +
    Template(String, String) - Constructor for class com.sun.btrace.util.templates.Template
    +
     
    +
    Template(String, String, String...) - Constructor for class com.sun.btrace.util.templates.Template
    +
     
    +
    TemplateExpander - Interface in com.sun.btrace.util.templates
    +
    +
    An interface to be implemented by the template expanders
    +
    +
    TemplateExpander.Consumer<T> - Interface in com.sun.btrace.util.templates
    +
    +
    A knockoff of the java.util.function.Consumer interface for pre-8 usage
    +
    +
    TemplateExpander.Result - Enum in com.sun.btrace.util.templates
    +
    +
    The result of expansion + + EXPANDED = expander has claimed and expanded the template + CLAIMED = expander has claimed the template but didn't expand it + IGNORED = expander has not claimed the template +
    +
    +
    TemplateExpanderVisitor - Class in com.sun.btrace.util.templates
    +
    +
    An ASM visitor providing customized template expansion
    +
    +
    TemplateExpanderVisitor(MethodVisitor, MethodInstrumentorHelper, String, String, String) - Constructor for class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    TEST_SAMPLE - Static variable in class com.sun.btrace.util.templates.impl.MethodTrackingExpander
    +
    +
    Will generate the branching logic (if sampling) and/or retrieve the timestamp + for the end of execution.
    +
    +
    THREAD_LOCAL_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    THREAD_LOCAL_INTERNAL - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    THREAD_LOCAL_TYPE - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    threadCount() - Static method in class com.sun.btrace.BTraceUtils.Sys.VM
    +
    +
    Returns the current number of live threads including both + daemon and non-daemon threads.
    +
    +
    threadCount() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the current number of live threads including both + daemon and non-daemon threads.
    +
    +
    threadId(Thread) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the identifier of the given Thread.
    +
    +
    threadId(Thread) - Static method in class com.sun.btrace.BTraceUtils.Threads
    +
    +
    Returns the identifier of the given Thread.
    +
    +
    ThreadLocalRandomIntProvider - Class in com.sun.btrace.instr.random
    +
     
    +
    ThreadLocalRandomIntProvider() - Constructor for class com.sun.btrace.instr.random.ThreadLocalRandomIntProvider
    +
     
    +
    Threads() - Constructor for class com.sun.btrace.BTraceUtils.Threads
    +
     
    +
    threadState(Thread) - Static method in class com.sun.btrace.BTraceUtils.Threads
    +
    +
    Returns the state of the given thread.
    +
    +
    threadState(Thread) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the state of the given thread.
    +
    +
    threshold - Variable in class com.sun.btrace.shared.LowMemoryHandler
    +
     
    +
    thresholdProperty - Variable in class com.sun.btrace.shared.LowMemoryHandler
    +
     
    +
    THROWABLE_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    THROWABLE_INTERNAL - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    THROWABLE_TYPE - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    ThrowInstrumentor - Class in com.sun.btrace.runtime.instr
    +
    +
    This visitor helps in inserting code whenever an + exception is about to be thrown.
    +
    +
    ThrowInstrumentor(ClassLoader, MethodVisitor, MethodInstrumentorHelper, String, String, int, String, String) - Constructor for class com.sun.btrace.runtime.instr.ThrowInstrumentor
    +
     
    +
    Time() - Constructor for class com.sun.btrace.BTraceUtils.Time
    +
     
    +
    time(String, long) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Records the timing information for the specified metric.
    +
    +
    time(String, long, double) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Records the timing information for the specified metric.
    +
    +
    time(String, long, String) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Records the timing information for the specified metric.
    +
    +
    time(String, long, double, String) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    Records the timing information for the specified metric.
    +
    +
    timeInterval - Variable in class com.sun.btrace.Profiler.Snapshot
    +
     
    +
    timeMillis() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the current time in milliseconds.
    +
    +
    timeNanos() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the current value of the most precise available system + timer, in nanoseconds.
    +
    +
    TimerHandler - Class in com.sun.btrace.shared
    +
     
    +
    TimerHandler(String, long, String) - Constructor for class com.sun.btrace.shared.TimerHandler
    +
     
    +
    timestamp(String) - Static method in class com.sun.btrace.BTraceUtils.Time
    +
    +
    Generates a string timestamp (current date&time)
    +
    +
    timestamp() - Static method in class com.sun.btrace.BTraceUtils.Time
    +
    +
    Generates a string timestamp (current date&time) in the default system format
    +
    +
    timestamp(String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Generates a string getTimestamp (current date&time)
    +
    +
    timestamp() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Generates a string getTimestamp (current date&time) in the default system format
    +
    +
    timeStamp - Variable in class com.sun.btrace.Profiler.Snapshot
    +
     
    +
    TLS - Annotation Type in com.sun.btrace.annotations
    +
    +
    Annotation for thread-local BTrace fields.
    +
    +
    toArray(T[]) - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    toArray() - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    toArray(Collection<E>) - Static method in class com.sun.btrace.BTraceUtils.Collections
    +
     
    +
    toHexString(int) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    Returns a string representation of the integer argument as an + unsigned integer in base 16.
    +
    +
    toHexString(long) - Static method in class com.sun.btrace.BTraceUtils.Strings
    +
    +
    Returns a string representation of the long + argument as an unsigned integer in base 16.
    +
    +
    toHexString(int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a string representation of the integer argument as an + unsigned integer in base 16.
    +
    +
    toHexString(long) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns a string representation of the long + argument as an unsigned integer in base 16.
    +
    +
    TOP_TYPE - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    toString() - Method in class com.sun.btrace.ArgsMap
    +
     
    +
    toString() - Method in class com.sun.btrace.BTraceDeque
    +
     
    +
    toString() - Method in class com.sun.btrace.Profiler.Record
    +
     
    +
    toString() - Method in class com.sun.btrace.runtime.BTraceMethodNode
    +
     
    +
    toString() - Method in class com.sun.btrace.runtime.BTraceProbeNode
    +
     
    +
    toString() - Method in class com.sun.btrace.runtime.BTraceProbeSupport
    +
     
    +
    toString() - Method in class com.sun.btrace.runtime.CallGraph.Node
    +
     
    +
    toString() - Method in class com.sun.btrace.runtime.ClassInfo
    +
     
    +
    toString() - Method in class com.sun.btrace.runtime.Location
    +
     
    +
    toString() - Method in class com.sun.btrace.runtime.OnMethod
    +
     
    +
    toString() - Method in class com.sun.btrace.util.Interval
    +
     
    +
    toString() - Method in class com.sun.btrace.util.templates.Template
    +
     
    +
    total - Variable in class com.sun.btrace.Profiler.Snapshot
    +
     
    +
    totalMemory() - Static method in class com.sun.btrace.BTraceUtils.Sys.Memory
    +
    +
    Returns the total amount of memory in the Java virtual machine.
    +
    +
    totalMemory() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the total amount of memory in the Java virtual machine.
    +
    +
    totalStartedThreadCount() - Static method in class com.sun.btrace.BTraceUtils.Sys.VM
    +
    +
    Returns the total number of threads created and also started + since the Java virtual machine started.
    +
    +
    totalStartedThreadCount() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the total number of threads created and also started + since the Java virtual machine started.
    +
    +
    toXML(Object) - Static method in class com.sun.btrace.BTraceUtils.Export
    +
    +
    Creates an XML document to persist the tree of the all + transitively reachable objects from given "root" object.
    +
    +
    toXML(Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Creates an XML document to persist the tree of the all + transitively reachable objects from given "root" object.
    +
    +
    TRACK_RETRANSFORM - Static variable in class com.sun.btrace.client.Main
    +
     
    +
    TRACK_RETRANSFORMS_KEY - Static variable in class com.sun.btrace.SharedSettings
    +
     
    +
    trackUsage - Variable in class com.sun.btrace.shared.LowMemoryHandler
    +
     
    +
    transform(ClassLoader, String, Class<?>, ProtectionDomain, byte[]) - Method in class com.sun.btrace.runtime.BTraceTransformer
    +
     
    +
    truncate(int) - Method in class com.sun.btrace.aggregation.Aggregation
    +
    +
    Reduces the size of the aggregation to the absolute value of count.
    +
    +
    truncateAggregation(Aggregation, int) - Static method in class com.sun.btrace.BTraceUtils.Aggregations
    +
    +
    Removes all aggregated values from the aggregation except for the largest or smallest + abs(count) elements.
    +
    +
    truncateAggregation(Aggregation, int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Removes all aggregated values from the aggregation except for the largest or smallest + abs(count) elements.
    +
    +
    TRUSTED_KEY - Static variable in class com.sun.btrace.SharedSettings
    +
     
    +
    type(Field) - Static method in class com.sun.btrace.BTraceUtils.Reflective
    +
    +
    Returns the type of the Field object.
    +
    +
    type(Field) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the type of the Field object.
    +
    +
    type - Variable in class com.sun.btrace.comm.Command
    +
     
    +
    TypeCheckInstrumentor - Class in com.sun.btrace.runtime.instr
    +
    +
    This class helps in inserting code whenever a type check + (instanceof or checkcast) is done.
    +
    +
    TypeCheckInstrumentor(ClassLoader, MethodVisitor, MethodInstrumentorHelper, String, String, int, String, String) - Constructor for class com.sun.btrace.runtime.instr.TypeCheckInstrumentor
    +
     
    +
    TypeUtils - Class in com.sun.btrace.runtime
    +
     
    +
    + + + +

    U

    +
    +
    unbox(Boolean) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns the value of the given Boolean object as a boolean + primitive.
    +
    +
    unbox(Character) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns the value of the given Character object as a char + primitive.
    +
    +
    unbox(Byte) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns the value of the specified Byte as a byte.
    +
    +
    unbox(Short) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns the short value represented by Short.
    +
    +
    unbox(Integer) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns the value of represented by Integer.
    +
    +
    unbox(Long) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns the long value represented by the specified Long.
    +
    +
    unbox(Float) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns the float value represented by the specified Float.
    +
    +
    unbox(Double) - Static method in class com.sun.btrace.BTraceUtils.Numbers
    +
    +
    Returns the double value represented by the specified Double.
    +
    +
    unbox(Boolean) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the value of the given Boolean object as a boolean + primitive.
    +
    +
    unbox(Character) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the value of the given Character object as a char + primitive.
    +
    +
    unbox(Byte) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the value of the specified Byte as a byte.
    +
    +
    unbox(Short) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the short value represented by Short.
    +
    +
    unbox(Integer) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the value of represented by Integer.
    +
    +
    unbox(Long) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the long value represented by the specified Long.
    +
    +
    unbox(Float) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the float value represented by the specified Float.
    +
    +
    unbox(Double) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the double value represented by the specified Double.
    +
    +
    unbox(Type) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    unbox(String) - Method in class com.sun.btrace.runtime.Assembler
    +
     
    +
    union(Collection<Interval>) - Static method in class com.sun.btrace.util.Interval
    +
     
    +
    unique(String, String, String) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    StatsD supports counting unique occurrences of events between flushes.
    +
    +
    unique(String, String) - Method in class com.sun.btrace.services.impl.Statsd
    +
    +
    StatsD supports counting unique occurrences of events between flushes.
    +
    +
    unregister() - Method in interface com.sun.btrace.runtime.BTraceProbe
    +
     
    +
    unregister() - Method in class com.sun.btrace.runtime.BTraceProbeNode
    +
     
    +
    unregister() - Method in class com.sun.btrace.runtime.BTraceProbePersisted
    +
     
    +
    unregister(BTraceProbe) - Method in class com.sun.btrace.runtime.BTraceTransformer
    +
     
    +
    UNSAFE_KEY - Static variable in class com.sun.btrace.SharedSettings
    +
    +
    Deprecated.
    +
    +
    updateEndTs(int) - Static method in class com.sun.btrace.instr.MethodTracker
    +
    +
    Used in adaptive sampling.
    +
    +
    used(MemoryUsage) - Static method in class com.sun.btrace.BTraceUtils.Sys.Memory
    +
    +
    Returns the amount of used memory in bytes.
    +
    +
    used(MemoryUsage) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the amount of used memory in bytes.
    +
    +
    + + + +

    V

    +
    +
    validateArguments(OnMethod, Type[], Type[]) - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    ValidationResult(boolean, int[]) - Constructor for class com.sun.btrace.runtime.instr.MethodInstrumentor.ValidationResult
    +
     
    +
    ValidationResult(boolean) - Constructor for class com.sun.btrace.runtime.instr.MethodInstrumentor.ValidationResult
    +
     
    +
    valueOf(String) - Static method in enum com.sun.btrace.aggregation.AggregationFunction
    +
    +
    Returns the enum constant of this type with the specified name.
    +
    +
    valueOf(String) - Static method in enum com.sun.btrace.annotations.Kind
    +
    +
    Returns the enum constant of this type with the specified name.
    +
    +
    valueOf(String) - Static method in enum com.sun.btrace.annotations.Sampled.Sampler
    +
    +
    Returns the enum constant of this type with the specified name.
    +
    +
    valueOf(String) - Static method in enum com.sun.btrace.annotations.ServiceType
    +
    +
    Returns the enum constant of this type with the specified name.
    +
    +
    valueOf(String) - Static method in enum com.sun.btrace.annotations.Where
    +
    +
    Returns the enum constant of this type with the specified name.
    +
    +
    valueOf(String) - Static method in enum com.sun.btrace.api.BTraceTask.State
    +
    +
    Returns the enum constant of this type with the specified name.
    +
    +
    valueOf(String) - Static method in enum com.sun.btrace.services.impl.Statsd.AlertType
    +
    +
    Returns the enum constant of this type with the specified name.
    +
    +
    valueOf(String) - Static method in enum com.sun.btrace.services.impl.Statsd.Priority
    +
    +
    Returns the enum constant of this type with the specified name.
    +
    +
    valueOf(String) - Static method in enum com.sun.btrace.util.templates.TemplateExpander.Result
    +
    +
    Returns the enum constant of this type with the specified name.
    +
    +
    values() - Static method in enum com.sun.btrace.aggregation.AggregationFunction
    +
    +
    Returns an array containing the constants of this enum type, in +the order they are declared.
    +
    +
    values() - Static method in enum com.sun.btrace.annotations.Kind
    +
    +
    Returns an array containing the constants of this enum type, in +the order they are declared.
    +
    +
    values() - Static method in enum com.sun.btrace.annotations.Sampled.Sampler
    +
    +
    Returns an array containing the constants of this enum type, in +the order they are declared.
    +
    +
    values() - Static method in enum com.sun.btrace.annotations.ServiceType
    +
    +
    Returns an array containing the constants of this enum type, in +the order they are declared.
    +
    +
    values() - Static method in enum com.sun.btrace.annotations.Where
    +
    +
    Returns an array containing the constants of this enum type, in +the order they are declared.
    +
    +
    values() - Static method in enum com.sun.btrace.api.BTraceTask.State
    +
    +
    Returns an array containing the constants of this enum type, in +the order they are declared.
    +
    +
    values() - Static method in enum com.sun.btrace.services.impl.Statsd.AlertType
    +
    +
    Returns an array containing the constants of this enum type, in +the order they are declared.
    +
    +
    values() - Static method in enum com.sun.btrace.services.impl.Statsd.Priority
    +
    +
    Returns an array containing the constants of this enum type, in +the order they are declared.
    +
    +
    values() - Method in class com.sun.btrace.util.LongMap
    +
     
    +
    values() - Static method in enum com.sun.btrace.util.templates.TemplateExpander.Result
    +
    +
    Returns an array containing the constants of this enum type, in +the order they are declared.
    +
    +
    Verifier - Class in com.sun.btrace.compiler
    +
    +
    An annotation processor that validates a BTrace program.
    +
    +
    Verifier() - Constructor for class com.sun.btrace.compiler.Verifier
    +
     
    +
    Verifier - Class in com.sun.btrace.runtime
    +
    +
    This class verifies that a BTrace program is safe + and well-formed.
    +
    +
    Verifier(BTraceProbeNode, boolean) - Constructor for class com.sun.btrace.runtime.Verifier
    +
     
    +
    Verifier(BTraceProbeNode) - Constructor for class com.sun.btrace.runtime.Verifier
    +
     
    +
    VerifierException - Exception in com.sun.btrace
    +
    +
    Instance of this exception type is thrown by BTrace + Verifier when an input .class is not a valid BTrace program.
    +
    +
    VerifierException(String) - Constructor for exception com.sun.btrace.VerifierException
    +
     
    +
    VerifierException(Throwable) - Constructor for exception com.sun.btrace.VerifierException
    +
     
    +
    VerifierVisitor - Class in com.sun.btrace.compiler
    +
    +
    This class tree visitor validates a BTrace program's ClassTree.
    +
    +
    VerifierVisitor(Verifier, Element) - Constructor for class com.sun.btrace.compiler.VerifierVisitor
    +
     
    +
    visit(int, int, String, String, String, String[]) - Method in class com.sun.btrace.compiler.Postprocessor
    +
     
    +
    visit(int, int, String, String, String, String[]) - Method in class com.sun.btrace.runtime.BTraceProbeNode
    +
     
    +
    visit(int, int, String, String, String, String[]) - Method in class com.sun.btrace.runtime.InstrumentingClassVisitor
    +
     
    +
    visit(int, int, String, String, String, String[]) - Method in class com.sun.btrace.runtime.Instrumentor
    +
     
    +
    visit(int, int, String, String, String, String[]) - Method in class com.sun.btrace.runtime.Verifier
    +
     
    +
    visitAnnotation(String, boolean) - Method in class com.sun.btrace.runtime.BTraceMethodNode
    +
     
    +
    visitAnnotation(String, boolean) - Method in class com.sun.btrace.runtime.Verifier
    +
     
    +
    visitAnnotation(String, boolean) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitAnnotationDefault() - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitAssert(AssertTree, Void) - Method in class com.sun.btrace.compiler.VerifierVisitor
    +
     
    +
    visitAssignment(AssignmentTree, Void) - Method in class com.sun.btrace.compiler.VerifierVisitor
    +
     
    +
    visitAttribute(Attribute) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitCatch(CatchTree, Void) - Method in class com.sun.btrace.compiler.VerifierVisitor
    +
     
    +
    visitClass(ClassTree, Void) - Method in class com.sun.btrace.compiler.VerifierVisitor
    +
     
    +
    visitCode() - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    visitCode() - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitCompoundAssignment(CompoundAssignmentTree, Void) - Method in class com.sun.btrace.compiler.VerifierVisitor
    +
     
    +
    visitDoWhileLoop(DoWhileLoopTree, Void) - Method in class com.sun.btrace.compiler.VerifierVisitor
    +
     
    +
    visitEnd() - Method in class com.sun.btrace.compiler.Postprocessor
    +
     
    +
    visitEnd() - Method in class com.sun.btrace.runtime.BTraceMethodNode
    +
     
    +
    visitEnd() - Method in class com.sun.btrace.runtime.Instrumentor
    +
     
    +
    visitEnd() - Method in class com.sun.btrace.runtime.Verifier
    +
     
    +
    visitEnd() - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitEnhancedForLoop(EnhancedForLoopTree, Void) - Method in class com.sun.btrace.compiler.VerifierVisitor
    +
     
    +
    visitField(int, String, String, String, Object) - Method in class com.sun.btrace.compiler.Postprocessor
    +
     
    +
    visitField(int, String, String, String, Object) - Method in class com.sun.btrace.runtime.BTraceProbeNode
    +
     
    +
    visitField(int, String, String, String, Object) - Method in class com.sun.btrace.runtime.Verifier
    +
     
    +
    visitFieldInsn(int, String, String, String) - Method in class com.sun.btrace.runtime.BTraceMethodNode
    +
     
    +
    visitFieldInsn(int, String, String, String) - Method in class com.sun.btrace.runtime.instr.FieldAccessInstrumentor
    +
     
    +
    visitFieldInsn(int, String, String, String) - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    visitFieldInsn(int, String, String, String) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitForLoop(ForLoopTree, Void) - Method in class com.sun.btrace.compiler.VerifierVisitor
    +
     
    +
    visitFrame(int, int, Object[], int, Object[]) - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    visitIincInsn(int, int) - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    visitIincInsn(int, int) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitInnerClass(String, String, String, int) - Method in class com.sun.btrace.runtime.Verifier
    +
     
    +
    visitInsn(int) - Method in class com.sun.btrace.runtime.instr.ArrayAccessInstrumentor
    +
     
    +
    visitInsn(int) - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    visitInsn(int) - Method in class com.sun.btrace.runtime.instr.MethodReturnInstrumentor
    +
     
    +
    visitInsn(int) - Method in class com.sun.btrace.runtime.instr.SynchronizedInstrumentor
    +
     
    +
    visitInsn(int) - Method in class com.sun.btrace.runtime.instr.ThrowInstrumentor
    +
     
    +
    visitInsn(int) - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    visitInsn(int) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitInsnAnnotation(int, TypePath, String, boolean) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitIntInsn(int, int) - Method in class com.sun.btrace.runtime.instr.ArrayAllocInstrumentor
    +
     
    +
    visitIntInsn(int, int) - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    visitIntInsn(int, int) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitInvokeDynamicInsn(String, String, Handle, Object...) - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    visitInvokeDynamicInsn(String, String, Handle, Object...) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitJumpInsn(int, Label) - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    visitJumpInsn(int, Label) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitLabel(Label) - Method in class com.sun.btrace.runtime.instr.CatchInstrumentor
    +
     
    +
    visitLabel(Label) - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    visitLabel(Label) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitLdcInsn(Object) - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    visitLdcInsn(Object) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitLineNumber(int, Label) - Method in class com.sun.btrace.runtime.instr.LineNumberInstrumentor
    +
     
    +
    visitLineNumber(int, Label) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitLocalVariable(String, String, String, Label, Label, int) - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    visitLocalVariable(String, String, String, Label, Label, int) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitLocalVariableAnnotation(int, TypePath, Label[], Label[], int[], String, boolean) - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    visitLocalVariableAnnotation(int, TypePath, Label[], Label[], int[], String, boolean) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitLookupSwitchInsn(Label, int[], Label[]) - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    visitLookupSwitchInsn(Label, int[], Label[]) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitMaxs(int, int) - Method in class com.sun.btrace.runtime.instr.ErrorReturnInstrumentor
    +
     
    +
    visitMaxs(int, int) - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    visitMaxs(int, int) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitMemberSelect(MemberSelectTree, Void) - Method in class com.sun.btrace.compiler.VerifierVisitor
    +
     
    +
    visitMethod(int, String, String, String, String[]) - Method in class com.sun.btrace.compiler.Postprocessor
    +
     
    +
    visitMethod(MethodTree, Void) - Method in class com.sun.btrace.compiler.VerifierVisitor
    +
     
    +
    visitMethod(int, String, String, String, String[]) - Method in class com.sun.btrace.runtime.BTraceProbeNode
    +
     
    +
    visitMethod(int, String, String, String, String[]) - Method in class com.sun.btrace.runtime.InstrumentingClassVisitor
    +
     
    +
    visitMethod(int, String, String, String, String[]) - Method in class com.sun.btrace.runtime.Instrumentor
    +
     
    +
    visitMethod(int, String, String, String, String[]) - Method in class com.sun.btrace.runtime.Verifier
    +
     
    +
    visitMethodInsn(int, String, String, String, boolean) - Method in class com.sun.btrace.runtime.BTraceMethodNode
    +
     
    +
    visitMethodInsn(int, String, String, String, boolean) - Method in class com.sun.btrace.runtime.instr.MethodCallInstrumentor
    +
     
    +
    visitMethodInsn(int, String, String, String, boolean) - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    visitMethodInsn(int, String, String, String, boolean) - Method in class com.sun.btrace.runtime.instr.ObjectAllocInstrumentor
    +
     
    +
    visitMethodInsn(int, String, String, String, boolean) - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    visitMethodInsn(int, String, String, String, boolean) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitMethodInvocation(MethodInvocationTree, Void) - Method in class com.sun.btrace.compiler.VerifierVisitor
    +
     
    +
    visitMethodPrologue() - Method in class com.sun.btrace.runtime.instr.ErrorReturnInstrumentor
    +
     
    +
    visitMethodPrologue() - Method in class com.sun.btrace.runtime.instr.MethodEntryInstrumentor
    +
     
    +
    visitMethodPrologue() - Method in class com.sun.btrace.runtime.instr.MethodInstrumentor
    +
     
    +
    visitMultiANewArrayInsn(String, int) - Method in class com.sun.btrace.runtime.instr.ArrayAllocInstrumentor
    +
     
    +
    visitMultiANewArrayInsn(String, int) - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    visitMultiANewArrayInsn(String, int) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitNewArray(NewArrayTree, Void) - Method in class com.sun.btrace.compiler.VerifierVisitor
    +
     
    +
    visitNewClass(NewClassTree, Void) - Method in class com.sun.btrace.compiler.VerifierVisitor
    +
     
    +
    visitOther(Tree, Void) - Method in class com.sun.btrace.compiler.VerifierVisitor
    +
     
    +
    visitOuterClass(String, String, String) - Method in class com.sun.btrace.runtime.Verifier
    +
     
    +
    visitParameter(String, int) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitParameterAnnotation(int, String, boolean) - Method in class com.sun.btrace.runtime.BTraceMethodNode
    +
     
    +
    visitParameterAnnotation(int, String, boolean) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitReturn(ReturnTree, Void) - Method in class com.sun.btrace.compiler.VerifierVisitor
    +
     
    +
    visitSynchronized(SynchronizedTree, Void) - Method in class com.sun.btrace.compiler.VerifierVisitor
    +
     
    +
    visitTableSwitchInsn(int, int, Label, Label...) - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    visitTableSwitchInsn(int, int, Label, Label...) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitThrow(ThrowTree, Void) - Method in class com.sun.btrace.compiler.VerifierVisitor
    +
     
    +
    visitTry(TryTree, Void) - Method in class com.sun.btrace.compiler.VerifierVisitor
    +
     
    +
    visitTryCatchAnnotation(int, TypePath, String, boolean) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitTryCatchBlock(Label, Label, Label, String) - Method in class com.sun.btrace.runtime.instr.CatchInstrumentor
    +
     
    +
    visitTryCatchBlock(Label, Label, Label, String) - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    visitTryCatchBlock(Label, Label, Label, String) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitTypeAnnotation(int, TypePath, String, boolean) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitTypeInsn(int, String) - Method in class com.sun.btrace.runtime.instr.ArrayAllocInstrumentor
    +
     
    +
    visitTypeInsn(int, String) - Method in class com.sun.btrace.runtime.instr.ObjectAllocInstrumentor
    +
     
    +
    visitTypeInsn(int, String) - Method in class com.sun.btrace.runtime.instr.TypeCheckInstrumentor
    +
     
    +
    visitTypeInsn(int, String) - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    visitTypeInsn(int, String) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitVariable(VariableTree, Void) - Method in class com.sun.btrace.compiler.VerifierVisitor
    +
     
    +
    visitVarInsn(int, int) - Method in class com.sun.btrace.runtime.InstrumentingMethodVisitor
    +
     
    +
    visitVarInsn(int, int) - Method in class com.sun.btrace.util.templates.TemplateExpanderVisitor
    +
     
    +
    visitWhileLoop(WhileLoopTree, Void) - Method in class com.sun.btrace.compiler.VerifierVisitor
    +
     
    +
    VM() - Constructor for class com.sun.btrace.BTraceUtils.Sys.VM
    +
     
    +
    vmArguments() - Static method in class com.sun.btrace.BTraceUtils.Sys.VM
    +
    +
    Returns the input arguments passed to the Java virtual machine + which does not include the arguments to the main method.
    +
    +
    vmArguments() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the input arguments passed to the Java virtual machine + which does not include the arguments to the main method.
    +
    +
    vmStartTime() - Static method in class com.sun.btrace.BTraceUtils.Sys.VM
    +
    +
    Returns the start time of the Java virtual machine in milliseconds.
    +
    +
    vmStartTime() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the start time of the Java virtual machine in milliseconds.
    +
    +
    vmUptime() - Static method in class com.sun.btrace.BTraceUtils.Sys.VM
    +
    +
    Returns the uptime of the Java virtual machine in milliseconds.
    +
    +
    vmUptime() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the uptime of the Java virtual machine in milliseconds.
    +
    +
    vmVersion() - Static method in class com.sun.btrace.BTraceUtils.Sys.VM
    +
    +
    Returns the Java virtual machine implementation version.
    +
    +
    vmVersion() - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Returns the Java virtual machine implementation version.
    +
    +
    VOID - Static variable in interface com.sun.btrace.AnyType
    +
     
    +
    VOID_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    VOIDREF_TYPE - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    + + + +

    W

    +
    +
    wallTime - Variable in class com.sun.btrace.Profiler.Record
    +
     
    +
    wallTimeMax - Variable in class com.sun.btrace.Profiler.Record
    +
     
    +
    wallTimeMin - Variable in class com.sun.btrace.Profiler.Record
    +
     
    +
    warning(String) - Static method in class com.sun.btrace.DebugSupport
    +
     
    +
    warning(Throwable) - Static method in class com.sun.btrace.DebugSupport
    +
     
    +
    weakCompareAndSet(AtomicInteger, int, int) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Atomically sets the value to the given updated value + if the current value == the expected value.
    +
    +
    weakCompareAndSet(AtomicLong, long, long) - Static method in class com.sun.btrace.BTraceUtils.Atomic
    +
    +
    Atomically sets the value to the given updated value + if the current value == the expected value.
    +
    +
    weakCompareAndSet(AtomicInteger, int, int) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Atomically sets the value to the given updated value + if the current value == the expected value.
    +
    +
    weakCompareAndSet(AtomicLong, long, long) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Atomically sets the value to the given updated value + if the current value == the expected value.
    +
    +
    weakRef(Object) - Static method in class com.sun.btrace.BTraceUtils.References
    +
    +
    Creates and returns a weak reference to the given object.
    +
    +
    weakRef(Object) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Creates and returns a weak reference to the given object.
    +
    +
    Where - Enum in com.sun.btrace.annotations
    +
    +
    This enum is specified in the Location + annotation to specify whether a probe point + is after or before specific point of interest.
    +
    +
    WHERE_DESC - Static variable in class com.sun.btrace.runtime.Constants
    +
     
    +
    willInstrument(Class) - Method in interface com.sun.btrace.runtime.BTraceProbe
    +
     
    +
    willInstrument(Class) - Method in class com.sun.btrace.runtime.BTraceProbeNode
    +
     
    +
    willInstrument(Class) - Method in class com.sun.btrace.runtime.BTraceProbePersisted
    +
     
    +
    WireIO - Class in com.sun.btrace.comm
    +
     
    +
    write(ObjectOutput) - Method in class com.sun.btrace.comm.Command
    +
     
    +
    write(ObjectOutput) - Method in class com.sun.btrace.comm.ErrorCommand
    +
     
    +
    write(ObjectOutput) - Method in class com.sun.btrace.comm.EventCommand
    +
     
    +
    write(ObjectOutput) - Method in class com.sun.btrace.comm.ExitCommand
    +
     
    +
    write(ObjectOutput) - Method in class com.sun.btrace.comm.GridDataCommand
    +
     
    +
    write(ObjectOutput) - Method in class com.sun.btrace.comm.InstrumentCommand
    +
     
    +
    write(ObjectOutput) - Method in class com.sun.btrace.comm.MessageCommand
    +
     
    +
    write(ObjectOutput) - Method in class com.sun.btrace.comm.NumberDataCommand
    +
     
    +
    write(ObjectOutput) - Method in class com.sun.btrace.comm.NumberMapDataCommand
    +
     
    +
    write(ObjectOutput) - Method in class com.sun.btrace.comm.OkayCommand
    +
     
    +
    write(ObjectOutput) - Method in class com.sun.btrace.comm.RenameCommand
    +
     
    +
    write(ObjectOutput) - Method in class com.sun.btrace.comm.RetransformationStartNotification
    +
     
    +
    write(ObjectOutput) - Method in class com.sun.btrace.comm.RetransformClassNotification
    +
     
    +
    write(ObjectOutput) - Method in class com.sun.btrace.comm.SetSettingsCommand
    +
     
    +
    write(ObjectOutput) - Method in class com.sun.btrace.comm.StringMapDataCommand
    +
     
    +
    write(ObjectOutput, Command) - Static method in class com.sun.btrace.comm.WireIO
    +
     
    +
    write(DataOutputStream) - Method in class com.sun.btrace.runtime.BTraceProbePersisted
    +
     
    +
    writeDOT(Object, String) - Static method in class com.sun.btrace.BTraceUtils.Export
    +
    +
    Writes a .dot document to persist the tree of the all the + transitively reachable objects from the given "root" object.
    +
    +
    writeDOT(Object, String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Writes a .dot document to persist the tree of the all the + transitively reachable objects from the given "root" object.
    +
    +
    writeXML(Object, String) - Static method in class com.sun.btrace.BTraceUtils.Export
    +
    +
    Writes an XML document to persist the tree of the all the + transitively reachable objects from the given "root" object.
    +
    +
    writeXML(Object, String) - Static method in class com.sun.btrace.BTraceUtils
    +
    +
    Writes an XML document to persist the tree of the all the + transitively reachable objects from the given "root" object.
    +
    +
    +$ A B C D E F G H I J K L M N O P R S T U V W 
    + +
    + + + + + + + +
    + + + + diff --git a/misc/btrace/javadoc/index.html b/misc/btrace/javadoc/index.html new file mode 100644 index 00000000..6a77bf0c --- /dev/null +++ b/misc/btrace/javadoc/index.html @@ -0,0 +1,75 @@ + + + + + +btrace 1.3.11 API + + + + + + + + + +<noscript> +<div>JavaScript is disabled on your browser.</div> +</noscript> +<h2>Frame Alert</h2> +<p>This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. Link to <a href="overview-summary.html">Non-frame version</a>.</p> + + + diff --git a/misc/btrace/javadoc/overview-frame.html b/misc/btrace/javadoc/overview-frame.html new file mode 100644 index 00000000..6054327d --- /dev/null +++ b/misc/btrace/javadoc/overview-frame.html @@ -0,0 +1,43 @@ + + + + + +Overview List (btrace 1.3.11 API) + + + + + + + +

     

    + + diff --git a/misc/btrace/javadoc/overview-summary.html b/misc/btrace/javadoc/overview-summary.html new file mode 100644 index 00000000..ce3e208a --- /dev/null +++ b/misc/btrace/javadoc/overview-summary.html @@ -0,0 +1,226 @@ + + + + + +Overview (btrace 1.3.11 API) + + + + + + + + +
    + + + + + + + +
    + + +
    +

    btrace 1.3.11 API

    +
    + + +
    + + + + + + + +
    + + + + diff --git a/misc/btrace/javadoc/overview-tree.html b/misc/btrace/javadoc/overview-tree.html new file mode 100644 index 00000000..236b5556 --- /dev/null +++ b/misc/btrace/javadoc/overview-tree.html @@ -0,0 +1,479 @@ + + + + + +Class Hierarchy (btrace 1.3.11 API) + + + + + + + + +
    + + + + + + + +
    + + + +
    +

    Class Hierarchy

    + +

    Interface Hierarchy

    + +

    Annotation Type Hierarchy

    +
      +
    • com.sun.btrace.annotations.BTrace (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.DTrace (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.DTraceRef (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.Duration (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.Export (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.Injected (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.Level (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.Location (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.OnError (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.OnEvent (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.OnExit (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.OnLowMemory (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.OnMethod (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.OnProbe (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.OnTimer (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.ProbeClassName (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.ProbeMethodName (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.Property (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.Return (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.Sampled (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.Self (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.TargetInstance (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.TargetMethodOrField (implements java.lang.annotation.Annotation)
    • +
    • com.sun.btrace.annotations.TLS (implements java.lang.annotation.Annotation)
    • +
    +

    Enum Hierarchy

    + +
    + +
    + + + + + + + +
    + + + + diff --git a/misc/btrace/javadoc/package-list b/misc/btrace/javadoc/package-list new file mode 100644 index 00000000..34fbe454 --- /dev/null +++ b/misc/btrace/javadoc/package-list @@ -0,0 +1,23 @@ +com.sun.btrace +com.sun.btrace.agent +com.sun.btrace.aggregation +com.sun.btrace.annotations +com.sun.btrace.api +com.sun.btrace.api.impl +com.sun.btrace.client +com.sun.btrace.comm +com.sun.btrace.compiler +com.sun.btrace.instr +com.sun.btrace.instr.random +com.sun.btrace.profiling +com.sun.btrace.runtime +com.sun.btrace.runtime.instr +com.sun.btrace.services.api +com.sun.btrace.services.impl +com.sun.btrace.services.spi +com.sun.btrace.shared +com.sun.btrace.spi +com.sun.btrace.spi.impl +com.sun.btrace.util +com.sun.btrace.util.templates +com.sun.btrace.util.templates.impl diff --git a/misc/btrace/javadoc/script.js b/misc/btrace/javadoc/script.js new file mode 100644 index 00000000..b3463569 --- /dev/null +++ b/misc/btrace/javadoc/script.js @@ -0,0 +1,30 @@ +function show(type) +{ + count = 0; + for (var key in methods) { + var row = document.getElementById(key); + if ((methods[key] & type) != 0) { + row.style.display = ''; + row.className = (count++ % 2) ? rowColor : altColor; + } + else + row.style.display = 'none'; + } + updateTabs(type); +} + +function updateTabs(type) +{ + for (var value in tabs) { + var sNode = document.getElementById(tabs[value][0]); + var spanNode = sNode.firstChild; + if (value == type) { + sNode.className = activeTableTab; + spanNode.innerHTML = tabs[value][1]; + } + else { + sNode.className = tableTab; + spanNode.innerHTML = "" + tabs[value][1] + ""; + } + } +} diff --git a/misc/btrace/javadoc/serialized-form.html b/misc/btrace/javadoc/serialized-form.html new file mode 100644 index 00000000..1f028cad --- /dev/null +++ b/misc/btrace/javadoc/serialized-form.html @@ -0,0 +1,430 @@ + + + + + +Serialized Form (btrace 1.3.11 API) + + + + + + + + + + + +
    +

    Serialized Form

    +
    +
    + +
    + + + + + + diff --git a/misc/btrace/javadoc/stylesheet.css b/misc/btrace/javadoc/stylesheet.css new file mode 100644 index 00000000..98055b22 --- /dev/null +++ b/misc/btrace/javadoc/stylesheet.css @@ -0,0 +1,574 @@ +/* Javadoc style sheet */ +/* +Overall document style +*/ + +@import url('resources/fonts/dejavu.css'); + +body { + background-color:#ffffff; + color:#353833; + font-family:'DejaVu Sans', Arial, Helvetica, sans-serif; + font-size:14px; + margin:0; +} +a:link, a:visited { + text-decoration:none; + color:#4A6782; +} +a:hover, a:focus { + text-decoration:none; + color:#bb7a2a; +} +a:active { + text-decoration:none; + color:#4A6782; +} +a[name] { + color:#353833; +} +a[name]:hover { + text-decoration:none; + color:#353833; +} +pre { + font-family:'DejaVu Sans Mono', monospace; + font-size:14px; +} +h1 { + font-size:20px; +} +h2 { + font-size:18px; +} +h3 { + font-size:16px; + font-style:italic; +} +h4 { + font-size:13px; +} +h5 { + font-size:12px; +} +h6 { + font-size:11px; +} +ul { + list-style-type:disc; +} +code, tt { + font-family:'DejaVu Sans Mono', monospace; + font-size:14px; + padding-top:4px; + margin-top:8px; + line-height:1.4em; +} +dt code { + font-family:'DejaVu Sans Mono', monospace; + font-size:14px; + padding-top:4px; +} +table tr td dt code { + font-family:'DejaVu Sans Mono', monospace; + font-size:14px; + vertical-align:top; + padding-top:4px; +} +sup { + font-size:8px; +} +/* +Document title and Copyright styles +*/ +.clear { + clear:both; + height:0px; + overflow:hidden; +} +.aboutLanguage { + float:right; + padding:0px 21px; + font-size:11px; + z-index:200; + margin-top:-9px; +} +.legalCopy { + margin-left:.5em; +} +.bar a, .bar a:link, .bar a:visited, .bar a:active { + color:#FFFFFF; + text-decoration:none; +} +.bar a:hover, .bar a:focus { + color:#bb7a2a; +} +.tab { + background-color:#0066FF; + color:#ffffff; + padding:8px; + width:5em; + font-weight:bold; +} +/* +Navigation bar styles +*/ +.bar { + background-color:#4D7A97; + color:#FFFFFF; + padding:.8em .5em .4em .8em; + height:auto;/*height:1.8em;*/ + font-size:11px; + margin:0; +} +.topNav { + background-color:#4D7A97; + color:#FFFFFF; + float:left; + padding:0; + width:100%; + clear:right; + height:2.8em; + padding-top:10px; + overflow:hidden; + font-size:12px; +} +.bottomNav { + margin-top:10px; + background-color:#4D7A97; + color:#FFFFFF; + float:left; + padding:0; + width:100%; + clear:right; + height:2.8em; + padding-top:10px; + overflow:hidden; + font-size:12px; +} +.subNav { + background-color:#dee3e9; + float:left; + width:100%; + overflow:hidden; + font-size:12px; +} +.subNav div { + clear:left; + float:left; + padding:0 0 5px 6px; + text-transform:uppercase; +} +ul.navList, ul.subNavList { + float:left; + margin:0 25px 0 0; + padding:0; +} +ul.navList li{ + list-style:none; + float:left; + padding: 5px 6px; + text-transform:uppercase; +} +ul.subNavList li{ + list-style:none; + float:left; +} +.topNav a:link, .topNav a:active, .topNav a:visited, .bottomNav a:link, .bottomNav a:active, .bottomNav a:visited { + color:#FFFFFF; + text-decoration:none; + text-transform:uppercase; +} +.topNav a:hover, .bottomNav a:hover { + text-decoration:none; + color:#bb7a2a; + text-transform:uppercase; +} +.navBarCell1Rev { + background-color:#F8981D; + color:#253441; + margin: auto 5px; +} +.skipNav { + position:absolute; + top:auto; + left:-9999px; + overflow:hidden; +} +/* +Page header and footer styles +*/ +.header, .footer { + clear:both; + margin:0 20px; + padding:5px 0 0 0; +} +.indexHeader { + margin:10px; + position:relative; +} +.indexHeader span{ + margin-right:15px; +} +.indexHeader h1 { + font-size:13px; +} +.title { + color:#2c4557; + margin:10px 0; +} +.subTitle { + margin:5px 0 0 0; +} +.header ul { + margin:0 0 15px 0; + padding:0; +} +.footer ul { + margin:20px 0 5px 0; +} +.header ul li, .footer ul li { + list-style:none; + font-size:13px; +} +/* +Heading styles +*/ +div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 { + background-color:#dee3e9; + border:1px solid #d0d9e0; + margin:0 0 6px -8px; + padding:7px 5px; +} +ul.blockList ul.blockList ul.blockList li.blockList h3 { + background-color:#dee3e9; + border:1px solid #d0d9e0; + margin:0 0 6px -8px; + padding:7px 5px; +} +ul.blockList ul.blockList li.blockList h3 { + padding:0; + margin:15px 0; +} +ul.blockList li.blockList h2 { + padding:0px 0 20px 0; +} +/* +Page layout container styles +*/ +.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer { + clear:both; + padding:10px 20px; + position:relative; +} +.indexContainer { + margin:10px; + position:relative; + font-size:12px; +} +.indexContainer h2 { + font-size:13px; + padding:0 0 3px 0; +} +.indexContainer ul { + margin:0; + padding:0; +} +.indexContainer ul li { + list-style:none; + padding-top:2px; +} +.contentContainer .description dl dt, .contentContainer .details dl dt, .serializedFormContainer dl dt { + font-size:12px; + font-weight:bold; + margin:10px 0 0 0; + color:#4E4E4E; +} +.contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd { + margin:5px 0 10px 0px; + font-size:14px; + font-family:'DejaVu Sans Mono',monospace; +} +.serializedFormContainer dl.nameValue dt { + margin-left:1px; + font-size:1.1em; + display:inline; + font-weight:bold; +} +.serializedFormContainer dl.nameValue dd { + margin:0 0 0 1px; + font-size:1.1em; + display:inline; +} +/* +List styles +*/ +ul.horizontal li { + display:inline; + font-size:0.9em; +} +ul.inheritance { + margin:0; + padding:0; +} +ul.inheritance li { + display:inline; + list-style:none; +} +ul.inheritance li ul.inheritance { + margin-left:15px; + padding-left:15px; + padding-top:1px; +} +ul.blockList, ul.blockListLast { + margin:10px 0 10px 0; + padding:0; +} +ul.blockList li.blockList, ul.blockListLast li.blockList { + list-style:none; + margin-bottom:15px; + line-height:1.4; +} +ul.blockList ul.blockList li.blockList, ul.blockList ul.blockListLast li.blockList { + padding:0px 20px 5px 10px; + border:1px solid #ededed; + background-color:#f8f8f8; +} +ul.blockList ul.blockList ul.blockList li.blockList, ul.blockList ul.blockList ul.blockListLast li.blockList { + padding:0 0 5px 8px; + background-color:#ffffff; + border:none; +} +ul.blockList ul.blockList ul.blockList ul.blockList li.blockList { + margin-left:0; + padding-left:0; + padding-bottom:15px; + border:none; +} +ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast { + list-style:none; + border-bottom:none; + padding-bottom:0; +} +table tr td dl, table tr td dl dt, table tr td dl dd { + margin-top:0; + margin-bottom:1px; +} +/* +Table styles +*/ +.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary { + width:100%; + border-left:1px solid #EEE; + border-right:1px solid #EEE; + border-bottom:1px solid #EEE; +} +.overviewSummary, .memberSummary { + padding:0px; +} +.overviewSummary caption, .memberSummary caption, .typeSummary caption, +.useSummary caption, .constantsSummary caption, .deprecatedSummary caption { + position:relative; + text-align:left; + background-repeat:no-repeat; + color:#253441; + font-weight:bold; + clear:none; + overflow:hidden; + padding:0px; + padding-top:10px; + padding-left:1px; + margin:0px; + white-space:pre; +} +.overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link, +.useSummary caption a:link, .constantsSummary caption a:link, .deprecatedSummary caption a:link, +.overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover, +.useSummary caption a:hover, .constantsSummary caption a:hover, .deprecatedSummary caption a:hover, +.overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active, +.useSummary caption a:active, .constantsSummary caption a:active, .deprecatedSummary caption a:active, +.overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited, +.useSummary caption a:visited, .constantsSummary caption a:visited, .deprecatedSummary caption a:visited { + color:#FFFFFF; +} +.overviewSummary caption span, .memberSummary caption span, .typeSummary caption span, +.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span { + white-space:nowrap; + padding-top:5px; + padding-left:12px; + padding-right:12px; + padding-bottom:7px; + display:inline-block; + float:left; + background-color:#F8981D; + border: none; + height:16px; +} +.memberSummary caption span.activeTableTab span { + white-space:nowrap; + padding-top:5px; + padding-left:12px; + padding-right:12px; + margin-right:3px; + display:inline-block; + float:left; + background-color:#F8981D; + height:16px; +} +.memberSummary caption span.tableTab span { + white-space:nowrap; + padding-top:5px; + padding-left:12px; + padding-right:12px; + margin-right:3px; + display:inline-block; + float:left; + background-color:#4D7A97; + height:16px; +} +.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab { + padding-top:0px; + padding-left:0px; + padding-right:0px; + background-image:none; + float:none; + display:inline; +} +.overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd, +.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd { + display:none; + width:5px; + position:relative; + float:left; + background-color:#F8981D; +} +.memberSummary .activeTableTab .tabEnd { + display:none; + width:5px; + margin-right:3px; + position:relative; + float:left; + background-color:#F8981D; +} +.memberSummary .tableTab .tabEnd { + display:none; + width:5px; + margin-right:3px; + position:relative; + background-color:#4D7A97; + float:left; + +} +.overviewSummary td, .memberSummary td, .typeSummary td, +.useSummary td, .constantsSummary td, .deprecatedSummary td { + text-align:left; + padding:0px 0px 12px 10px; +} +th.colOne, th.colFirst, th.colLast, .useSummary th, .constantsSummary th, +td.colOne, td.colFirst, td.colLast, .useSummary td, .constantsSummary td{ + vertical-align:top; + padding-right:0px; + padding-top:8px; + padding-bottom:3px; +} +th.colFirst, th.colLast, th.colOne, .constantsSummary th { + background:#dee3e9; + text-align:left; + padding:8px 3px 3px 7px; +} +td.colFirst, th.colFirst { + white-space:nowrap; + font-size:13px; +} +td.colLast, th.colLast { + font-size:13px; +} +td.colOne, th.colOne { + font-size:13px; +} +.overviewSummary td.colFirst, .overviewSummary th.colFirst, +.useSummary td.colFirst, .useSummary th.colFirst, +.overviewSummary td.colOne, .overviewSummary th.colOne, +.memberSummary td.colFirst, .memberSummary th.colFirst, +.memberSummary td.colOne, .memberSummary th.colOne, +.typeSummary td.colFirst{ + width:25%; + vertical-align:top; +} +td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover { + font-weight:bold; +} +.tableSubHeadingColor { + background-color:#EEEEFF; +} +.altColor { + background-color:#FFFFFF; +} +.rowColor { + background-color:#EEEEEF; +} +/* +Content styles +*/ +.description pre { + margin-top:0; +} +.deprecatedContent { + margin:0; + padding:10px 0; +} +.docSummary { + padding:0; +} + +ul.blockList ul.blockList ul.blockList li.blockList h3 { + font-style:normal; +} + +div.block { + font-size:14px; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; +} + +td.colLast div { + padding-top:0px; +} + + +td.colLast a { + padding-bottom:3px; +} +/* +Formatting effect styles +*/ +.sourceLineNo { + color:green; + padding:0 30px 0 0; +} +h1.hidden { + visibility:hidden; + overflow:hidden; + font-size:10px; +} +.block { + display:block; + margin:3px 10px 2px 0px; + color:#474747; +} +.deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink, +.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel, +.seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink { + font-weight:bold; +} +.deprecationComment, .emphasizedPhrase, .interfaceName { + font-style:italic; +} + +div.block div.block span.deprecationComment, div.block div.block span.emphasizedPhrase, +div.block div.block span.interfaceName { + font-style:normal; +} + +div.contentContainer ul.blockList li.blockList h2{ + padding-bottom:0px; +} diff --git a/misc/btrace/usersguide.html b/misc/btrace/usersguide.html new file mode 100644 index 00000000..47cbc373 --- /dev/null +++ b/misc/btrace/usersguide.html @@ -0,0 +1,503 @@ + + + +BTrace User's Guide + + + + +

    BTrace User's Guide

    +

    +BTrace is a safe, dynamic tracing tool for Java. BTrace +works by dynamically (bytecode) instrumenting classes of a running +Java program. BTrace inserts tracing actions into the classes of a running +Java program and hotswaps the traced program classes. +

    + +

    BTrace Terminology

    + +
    +
    Probe Point
    +
    "location" or "event" at which a set of tracing statements +are executed. Probe point is "place" or "event" of interest where +we want to execute some tracing statements. +
    + +
    Trace Actions or Actions
    +
    +Trace statements that are executed whenever a probe "fires". +
    +
    Action Methods
    +
    +BTrace trace statements that are executed when a probe fires +are defined inside a static method a class. Such methods are called +"action" methods. +
    +
    + +

    BTrace Program Structure

    + +

    +A BTrace program is a plain Java class that has one or more public static void methods that +are annotated with BTrace annotations. The annotations are used to +specify traced program "locations" (also known as "probe points"). The tracing actions are +specified inside the static method bodies. These static methods are referred as "action" methods. +

    + + +

    BTrace Restrictions

    +

    +To guarantee that the tracing actions are "read-only" (i.e., the trace actions don't change the +state of the program traced) and bounded (i.e., trace actions terminate in bounded time), +a BTrace program is allowed to do only a restricted set of actions. +In particular, a BTrace class +

      +
    • can not create new objects. +
    • can not create new arrays. +
    • can not throw exceptions. +
    • can not catch exceptions. +
    • can not make arbitrary instance or static method calls - only the public static methods +of com.sun.btrace.BTraceUtils +class may be called from a BTrace program. +
    • can not assign to static or instance fields of +target program's classes and objects. But, BTrace class can assign +to it's own static fields ("trace state" can be mutated). +
    • can not have instance fields and methods. Only static +public void returning methods are allowed for a BTrace class. And all +fields have to be static. +
    • can not have outer, inner, nested or local classes. +
    • can not have synchronized blocks or synchronized methods. +
    • can not have loops (for, while, do..while) +
    • can not extend arbitrary class (super class has to be java.lang.Object) +
    • can not implement interfaces. +
    • can not contains assert statements. +
    • can not use class literals. +
    +

    + +

    A simple BTrace program

    + +
    +
    +// import all BTrace annotations
    +import com.sun.btrace.annotations.*;
    +// import statics from BTraceUtils class
    +import static com.sun.btrace.BTraceUtils.*;
    +
    +// @BTrace annotation tells that this is a BTrace program
    +@BTrace
    +public class HelloWorld {
    + 
    +    // @OnMethod annotation tells where to probe.
    +    // In this example, we are interested in entry 
    +    // into the Thread.start() method. 
    +    @OnMethod(
    +        clazz="java.lang.Thread",
    +        method="start"
    +    )
    +    public static void func() {
    +        // println is defined in BTraceUtils
    +        // you can only call the static methods of BTraceUtils
    +        println("about to start a thread!");
    +    }
    +}
    +
    +
    + +

    +The above BTrace program can be run against a running Java process. This program +will print "about to start a thread!" at the BTrace client whenever the target program +is about to start a thread by Thread.start() method. There are other +interesting probe points possible. For example, we can insert trace action at +return from a method, exception return from a method, a field get or set within method(s), +object/array creation, line number(s), throwing an exception. Please refer to the +@OnMethod and other annotations for details. +

    + +

    Steps to run BTrace

    +
      +
    1. Find the process id of the target Java process that you want to trace. +You can use jps tool to find the pid. +
    2. Write a BTrace program - you may want to start modifying one of the +samples. +
    3. Run btrace tool by the following command line: +
      +   btrace <pid> <btrace-script>
      +
      +
    + +

    BTrace Command Line

    + +BTrace is run using the command line tool btrace as shown below: + +
    +
    +    btrace [-I <include-path>] [-p <port>] [-cp <classpath>] <pid> <btrace-script> [<args>]
    +
    +
    +where +
      +
    • include-path is a set of include directories that are searched for header files. +BTrace includes a simple preprocess with support for #define, #include and conditional compilation. +It is not like a complete C/C++ preprocessor - but a useful subset. See the sample "ThreadBean.java". +If -I is not specified, BTrace skips the preprocessor invocation step. +
    • port is the port in which BTrace agent listens. This is optional argument. +
    • classpath is set of directories, jar files where BTrace searches for classes during compilation. +Default is ".". +
    • pid is the process id of the traced Java program +
    • btrace-script is the trace program. If it is a ".java", then it is compiled +before submission. Or else, it is assumed to be pre-compiled [i.e., it has to be a .class] +and submitted. +
    + +

    optional

    +
      +
    • port is the server socket port at which BTrace agent listens for clients. Default is 2020. +
    • path is the classpath used for compiling BTrace program. Default is ".". +
    • args is command line arguments passed to BTrace program. BTrace +program can access these using the built-in functions "$" and "$length". +
    + + + +

    Pre-compiling BTrace scripts

    +

    +It is possible to precompile BTrace program using btracec script. btracec +is a javac-like program that takes a BTrace program and produces a .class file. +

    +
    +    btracec [-I <include-path>] [-cp <classpath>] [-d <directory>] <one-or-more-BTrace-.java-files>
    +
    +
    +where +
      +
    • include-path is a set of include directories that are searched for header files. +BTrace includes a simple preprocess with support for #define, #include and conditional compilation. +It is not like a complete C/C++ preprocessor - but a useful subset. See the sample "ThreadBean.java". +If -I is not specified, BTrace skips the preprocessor invocation step. +
    • classpath is the classpath used for compiling BTrace program(s). Default is "." +
    • directory is the output directory where compiled .class files are stored. Default is ".". +
    +This script uses BTrace compiler class - rather than regular javac and therefore will validate +your BTrace program at compile time [so that you can avoid BTrace verify error at runtime]. +

    + + +

    Starting an application with BTrace agent

    +

    +So far, we saw how to trace a running Java program. It is also possible to start an application with BTrace agent in it. +If you want to start tracing the application from the very "beginning", you may +want to start the app with BTrace agent and specify a trace script along with it +[i.e., BTrace agent is attach-on-demand loadable as well as pre-loadable agent] +You can use the following command to start an app and specify BTrace script file. +But, you need to precompile your BTrace script for this +kind of usage. +

    +
    +
    +    java -javaagent:btrace-agent.jar=script=<pre-compiled-btrace-script> <MainClass> <AppArguments>
    +
    +
    +

    +When starting the application this way, the trace output goes to a file named <btrace-class-file-name>.btrace +in the current directory. Also, you can avoid starting server for other remote BTrace clients by specifying noServer=true +as an argument to the BTrace agent. +

    + +There is a convenient script called btracer to do the above: +
    +
    +    btracer <pre-compiled-btrace.class> <application-main-class> <application-args>
    +
    +
    + + + +

    BTrace Annotations

    + +

    Method Annotations

    +
      +
    • @com.sun.btrace.annotations.OnMethod +annotation can be used to +specify target class(es), target method(s) and "location(s)" within the method(s). +An action method annotated by this annotation is called when the matching method(s) reaches +specified the location. In OnMethod annotation, traced class name is specified by +"clazz" property and traced method is specified by "method" property. "clazz" may be +a fully qualified class name (like java.awt.Component or a regular +expression specified within two forward slashes. Refer to the samples +NewComponent.java and +Classload.java. The regular expression can match zero or more +classes in which case all matching classes are instrumented. For example /java\\.awt\\..+/ +matches all classes in java.awt package. Also, method name can be a regular expression as well - matching +zero or more methods. Refer to the sample MultiClass.java. +There is another way to abstractly specify traced class(es) and method(s). Traced classes and methods may be +specified by annotation. For example, if the "clazz" attribute is specified as @javax.jws.WebService +BTrace will instrument all classes that are annotated by the WebService annotation. Similarly, method level annotations +may be used to specify methods abstractly. Refer to the sample +WebServiceTracker.java. +It is also possible to combine regular expressions with annotations - like +@/com\\.acme\\..+/ matches any class that is annotated by any annotation that matches the given +regular expression. It is possible to match multiple classes by specifying super type. i.e., match all classes that are subtypes of +a given super type. +java.lang.Runnable matches all classes implementing java.lang.Runnable +interface. Refer to the sample SubtypeTracer.java. + +
    • @com.sun.btrace.annotations.OnTimer +annotation can be used to specify tracing +actions that have to run periodically once every N milliseconds. Time period is specified as long +"value" property of this annotation. Refer to the sample +Histogram.java + +
    • @com.sun.btrace.annotations.OnError +annotation can be used to specify +actions that are run whenever any exception is thrown by tracing actions of some other probe. +BTrace method annotated by this annotation is called when any exception is thrown by any of +the other BTrace action methods in the same BTrace class. +
    • @com.sun.btrace.annotations.OnExit +annotation can be used to specify +actions that are run when BTrace code calls "exit(int)" built-in function to finish the tracing +"session". Refer to the sample ProbeExit.java. +
    • @com.sun.btrace.annotations.OnEvent + annotation is used to associate tracing +methods with "external" events send by BTrace client. BTrace methods annotated by this annotation are called when +BTrace client sends an "event". Client may send an event based on some form of user request to +send (like pressing Ctrl-C or a GUI menu). String value may used as the name of the event. +This way certain tracing actions can be executed whenever an external event "fires". As of now, +the command line BTrace client sends "events" whenever use presses Ctrl-C (SIGINT). On SIGINT, +a console menu is shown to send an event or exit the client [which is the default for SIGINT]. +Refer to the sample +HistoOnEvent.java + +
    • @com.sun.btrace.annotations.OnLowMemory +annotation can be used to trace memory threshold exceed event. +See sample MemAlerter.java + +
    • @com.sun.btrace.annotations.OnProbe +annotation can be used to specify to avoid using implementation internal classes +in BTrace scripts. @OnProbe probe specifications are mapped to one or more @OnMethod +specifications by the BTrace VM agent. Currently, this mapping is done using a XML probe descriptor +file [accessed by the BTrace agent]. Refer to the sample SocketTracker1.java +and associated probe descriptor file java.net.socket.xml. +When running this sample, this xml file needs to be copied in the directory where +the target JVM runs (or fix probeDescPath option in btracer.bat to point to whereever +the .xml file is). +
    +

    Argument Annotations

    + +

    Field Annotations

    +
      +
    • @com.sun.btrace.annotations.Export annotation can be used with BTrace fields +(static fields) to specify that the field has to be mapped to a jvmstat counter. Using this, a BTrace +program can expose tracing counters to external jvmstat clients (such as jstat). Refer to the sample + +ThreadCounter.java + +
    • @com.sun.btrace.annotations.Property annotation +can be used to flag a specific (static) field as a MBean attribute. If a BTrace class has atleast one static field with +@Property attribute, then a MBean is created and registered with platform MBean server. JMX clients such as VisualVM, jconsole can be +used to view such BTrace MBeans. After attaching BTrace to the target program, you can attach VisualVM or jconsole to the same +program and view the newly created BTrace MBean. With VisualVM and jconsole, you can use MBeans tab to view the BTrace domain and +check out it's attributes. Refer to the samples ThreadCounterBean and +HistogramBean.java. + +
    • @com.sun.btrace.annotations.TLS annotation can be used with BTrace fields (static +fields) to specify that the field is a thread local field. Each Java thread gets a separate "copy" of +the field. These thread local fields may be used by BTrace programs to identify whether we reached multiple +probe actions from the same thread or not. Refer to the samples +OnThrow.java and +WebServiceTracker.java +
    + +

    Class Annotations

    + + +

    DTrace Integration

    +

    +Solaris DTrace is a dynamic, safe tracing system for Solaris programs - both kernel and user land programs. Because of the obvious parallels b/w DTrace and +BTrace, it is natural to expect integration b/w BTrace and DTrace. There are +two ways in which BTrace is integrated with DTrace. +

    +
      +
    • BTrace program can raise a DTrace probe - by calling dtraceProbe -- see BTraceUtils javadoc referred above. +For this feature to work, you need to be running on Solaris 10 or beyond. For other platforms (Solaris 9 or below +or any other OS), dtraceProbe() will be a no-op. +
    • BTrace program can associate a D-script with it-- by @DTrace annotation +(if the D-script is a simple one liner) or by @DTraceRef if the D-script is +longer and hence stored outside of the BTrace program. See DTrace integration +samples in the BTrace samples section below. This feature works using the DTrace Java API. +For this DTrace feature to work (o.e., being able to run associated D-script), +you need to be running on Solaris 11 build 35 or beyond. You may want to check whether you have +/usr/share/lib/java/dtrace.jar on your machine or not. @DTrace and @DTraceRef annotations are ignored on other +platforms (Solaris 10 or below or any other OS). +
    + + +

    BTrace Samples

    + +

    +BTrace samples +

    + +

    +One lines about samples: +

      +
    • AWTEventTracer.java - +demonstates tracing of AWT events by instrumenting EventQueue.dispatchEvent() +method. Can filter events by instanceof check. This sample filters and prints +only focus events. +
    • AllLines.java - +demonstates line number based BTrace probes. It is possible to probe +into any class (or classes) and line number(s). When the specified +line number(s) of specified class(es) is reached, the BTrace probe +fires and the corresponding action is executed. +
    • ArgArray.java - +prints all input arguments in every readXXX method of every class +in java.io package. Demonstrates argument array access and multiple +class/method matching in probe specifications. +
    • Classload.java - prints stack trace +on every successful classload (defineClass returns) by any userdefined +class loader. +
    • CommandArg.java - demonstrates +BTrace command line argument access. +
    • Deadlock.java - demonstrates +@OnTimer probe and deadlock() built-in function. +
    • DTraceInline.java - demonstrates +@DTrace annotation to associate a simple one-line D-script with the BTrace +program. +
    • DTraceRefDemo.java - demonstrates @DTraceRef annotation to associate a D-script file with the BTrace +program. This sample associates classload.dwith itself. +
    • FileTracker.java - +prints file open for read/write by probing into File{Input/Output}Stream +constructor entry points. +
    • FinalizeTracker.java +- demonstrates that we can print all fields of an object and access +(private) fields (read-only) as well. This is useful in debugging +/ troubleshooting scenarios. This sample prints info on close() +/finalize() methods of java.io.FileInputStream class. +
    • Histogram.java - demonstates +usage of BTrace maps for collecting histogram (of javax.swing.JComponent +objects created by an app - histogram by subclass name and count). +
    • HistogramBean.java - demonstates +JMX integration. This sample exposes a Map as MBean attribute using @Property +annotation. +
    • HistoOnEvent.java - +demonstrates getting trace output based on client side event. After +starting the script by BTrace client, press Ctrl-C to get menu to +send event or exit. On sending event, histogram is printed. This way +client can "pull" trace output whenever needed rather than BTrace +agent pushing the trace output always or based on timer. + +
    • JdbcQueries.java - demonstrates +BTrace aggregation facility. This facility is similar to +DTrace aggregation facility. + +
    • JInfo.java - demonstrates +printVmArguments(), printProperties() and +printEnv() built-in functions. +
    • JMap.java - demonstrates +dumpHeap() built-in function to dump (hprof binary format) +heap dump of the target application. +
    • JStack.java - demonstrates +jstackAll() built-in function to print stack traces of +all the threads. +
    • LogTracer.java - +demonstrates trapping into an instance method (Logger.log) and +printing private field value (of LogRecord object) by field() +and objectValue() built-in functions. +
    • MemAlerter.java - +demonstrates tracing low memory event by @OnLowMememory annotation. +
    • Memory.java - prints +memory stat once every 4 seconds by a timer probe. Demonstrates +memory stat built-in functions. +
    • MultiClass.java +- demonstrates inserting trace code into multiple methods of +multiple classes using regular expressions for clazz +and method fields of @OnMethod annotation. +
    • NewComponent.java +- tracks every java.awt.Component creation and increments +a counter and prints the counter based on a timer. +
    • OnThrow.java - +prints exception stack trace every time any exception instance is +created. In most scenarios, exceptions are thrown immediately after +creation. So, it we get stack trace of throw points. +
    • ProbeExit.java - +demonstrates @OnExit probe and exit(int) +built-in function. +
    • Sizeof.java +- demonstates "sizeof" built-in function that can be used to +get (approx.) size of a given Java object. It is possible to get +size-wise histogram etc. using this built-in. +
    • SocketTracker.java +- prints every server socker creation/bind and client socket accepts. +
    • SocketTracker1.java +- similar to SocketTracker.java sample, except that this sample uses +@OnProbe probes to avoid using Sun specific socket channel implementation +classes in BTrace program. Instead @OnProbe probes are mapped to @OnMethod probes +by BTrace agent. +
    • SysProp.java - +demonstrates that it is okay to probe into System classes (like +java.lang.System) and call BTrace built-in functions in the action +method. + +
    • SubtypeTracer.java - +demonstrates that it is possible to match all subtypes of a given supertype. + +
    • ThreadCounter.java +- demonstrates use of jvmstat counters from BTrace programs. + +
    • ThreadCounterBean.java +- demonstrates exposing the BTrace program as a JMX bean with one +attribute (using @Property annotation). + +
    • ThreadBean.java +- demonstrates the use of preprocessor of BTrace [and JMX integratio]. + +
    • ThreadStart.java +- demonstrates raising DTrace probes from BTrace programs. See also +jthread.d - the associated D-script. +This sample raises a DTrace USDT probe whenever the traced program enters +java.lang.Thread.start() method. The BTrace program passes JavaThread's +name to DTrace. +
    • Timers.java - demonstrates +multiple timer probes (@OnTimer) in a BTrace program. +
    • URLTracker.java - +prints URL every time URL.openConnection returns +successfully. This program uses jurls.d +D-script as well (to show histogram of URLs opened via DTrace). +
    • WebServiceTracker.java +- demonstates tracing classes and methods by specifying class and +method level annotations rather than class and method names. +
    +

    + + diff --git a/page/2/index.html b/page/2/index.html new file mode 100644 index 00000000..ab48fcb8 --- /dev/null +++ b/page/2/index.html @@ -0,0 +1,942 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + +
    + + + + + +
    +

    + + +

    + + +
    + + + + +
    + + +

    本文整理软件开发、项目管理、软件工程相关的书籍。

    + +
    + + 阅读全文 » + +
    + + + +
    + + + + +
    +
    +
    +
    + + + + + + + +
    + + + + + +
    +

    + + +

    + + +
    + + + + +
    + + +

    本文整理一些经典的数据库教材以及MySQL相关书籍。

    + +
    + + 阅读全文 » + +
    + + + +
    + + + + +
    +
    +
    +
    + + + + + + + +
    + + + + + +
    +

    + + +

    + + +
    + + + + +
    + + +

    本文整理编程语言与编译器相关的经典书籍。

    + +
    + + 阅读全文 » + +
    + + + +
    + + + + +
    +
    +
    +
    + + + + + + + +
    + + + + + +
    +

    + + +

    + + +
    + + + + +
    + + +

    本文整理一些学习Java需要翻阅或必须的官方文档资料。

    + +
    + + 阅读全文 » + +
    + + + +
    + + + + +
    +
    +
    +
    + + + + + + + +
    + + + + + +
    +

    + + +

    + + +
    + + + + +
    + + +

    https://en.wikipedia.org/wiki/Template:Java_(software_platform)
    +http://c2.com/cgi/wiki?JavaIdioms
    +http://c2.com/cgi/wiki?JavaDesignFlaws Java语言设计缺陷

    +
      +
    1. 2011-06 Java Books Reading Order http://stackoverflow.com/q/6341593
    2. +
    3. 2009-03 Java书籍Top 10 http://coolshell.cn/articles/14.html
    4. +
    5. 2012-03 JVM程序员的阅读清单 http://blog.jobbole.com/15342/
    6. +
    + +
    + + 阅读全文 » + +
    + + + +
    + + + + +
    +
    +
    +
    + + + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/placeholder b/placeholder deleted file mode 100644 index e69de29b..00000000 diff --git a/search.xml b/search.xml new file mode 100644 index 00000000..f3d1a490 --- /dev/null +++ b/search.xml @@ -0,0 +1,4826 @@ + + + + 数据库书籍资料整理 + /2016/11/database-books/ + 本文整理一些经典的数据库教材以及MySQL相关书籍。

    + +

    http://en.wikipedia.org/wiki/Database
    +http://en.wikipedia.org/wiki/Template:Databases
    +http://en.wikipedia.org/wiki/Template:SQL

    +

    Ask HN: Help me find a good databases textbook https://news.ycombinator.com/item?id=377669
    +Database Internals - Where to Begin? http://stackoverflow.com/q/770273
    +Ask HN: good book or resources to get my SQL skills to the next level https://news.ycombinator.com/item?id=1370721
    +Ask HN: Is there a K&R for SQL? https://news.ycombinator.com/item?id=5087439
    +Tips for getting started with SQL? http://stackoverflow.com/q/110124

    +

    教材原理类书籍

    +
      +
    1. 1986-2010,Silberschatz,《数据库系统概念》(Database System Concepts, 1st 1986, 6th 2010),home豆瓣:对数据库理论、概念有很清晰地介绍
    2. +
    3. 1996、1999、2002,Ramakrishnan & Gehrke,《数据库管理系统:原理与设计 Cow Book》(Database Management Systems, 3rd 2002),home豆瓣:第1作者2006年-2012年为Yahoo首席科学家,2012年跳槽到微软,该书为伯克利CS186、MIT、CMU教材
    4. +
    5. 2006、2010,Elmasri & Navathe,《数据库系统基础》(Fundamentals of Database Systems, 6th 2010),图灵2007,第6版豆瓣
    6. +
    7. 2005,Hellerstein & Stonebraker,"Readings in Database Systems", 3th 1998, 4th 2005,MITpresshome:被称为“Red Book”,经典论文收录集,第1作者是Berkeley Database Group的leader,第2作者是Ingres之父,Hellerstein的博士导师之一
    8. +
    9. 1975-2003,C. J. Date
      +,《数据库系统导论》(An Introduction to Database Systems, 2nd 1977, 8th
      +2003),豆瓣:作者曾在IBM工作,该书是最早的数据库教材
    10. +
    11. 1999、2008,Garcia-Molina & Ullman & Widom,《数据库系统全书 DSCB》(Database Systems: The Complete Book, 2nd 2008),home豆瓣:内容偏向介绍数据库的底层实现原理,三位作者来自Stanford,并且均获得Codd奖,获奖年份依次为1999年、2006年、2007年
    12. +
    13. 1992,Jim Gray,《事务处理:概念与技术》(Transaction Processing: Concepts and Techniques, amazon):介绍事务经典之作,不过略微过时。作者1998年图灵奖,1993年第2届Codd奖得主
    14. +
    15. 1997、2009,Bernstein & Newcomer,《事务处理原理》(Principles of Transaction Processing, 2nd 2009),豆瓣:目前最新、全面的书籍。作者来自Microsoft研究院,1994年第3届Codd奖得主
    16. +
    17. 1999、2011,M. Tamer Ozsu,《分布式数据库系统原理》(Principles of Distributed Database Systems, 3rd 2011),豆瓣
    18. +
    +

    SQL相关书籍

    +
      +
    1. 2010,《SQL反模式》(SQL Antipatterns),豆瓣
    2. +
    3. 2009,《SQL学习指南》(Learning SQL),豆瓣
    4. +
    5. 1999-2008,《SQL技术手册》(SQL in a Nutshell, 2nd 2004, 3rd 2008),豆瓣:根据SQL2003 ANSI标准,同时涵盖MySQL、Oracle、PostgreSQL及SQL Server
    6. +
    7. 1995-2010,Joe Celko,《SQL权威指南》(Joe Celko's SQL for Smarties: Advanced SQL Programming, 1st 1995, 4th 2010),图灵2012豆瓣:全书652页,作者曾担任ANSl SQL标准委员会成员达10年之久,参与了SQL-89和SQL-92标准的制定
    8. +
    9. 2005,Joe Celko,《SQL编程风格》(Joe Celko's SQL Programming Style, amazon,图灵2008豆瓣
    10. +
    11. 1996、2002,Joe Celko,《SQL解惑》(Joe Celko's SQL Puzzles and Answers, 2nd 2002),图灵2008
    12. +
    13. 2005,Ben Forta,《MySQL必知必会》(MySQL Crash Course),home豆瓣
    14. +
    +

    MySQL书籍

    +

    http://en.wikipedia.org/wiki/Template:MySQL
    +https://github.com/shlomi-noach/awesome-mysql
    +http://en.wikipedia.org/wiki/Database_engine
    +2014-01 Any recommended MySQL books for more advanced stuff? (self.mysql) http://redd.it/292u19
    +What resources exist for Database performance-tuning? http://stackoverflow.com/q/761204
    +2010-12 12 Best MySQL Database Books for Your Library http://www.thegeekstuff.com/2010/12/12-best-mysql-books/

    +

    MySQL管理

    +
      +
    1. 2008、2013,《深入浅出MySQL数据库:开发优化与管理维护》,豆瓣:作者来自网易DBA小组
    2. +
    3. 2005、2008,《MySQL核心技术手册》(MySQL in a Nutshell, 2nd 2008),豆瓣:作者MySQL公司知识库编辑
    4. +
    5. 1999-2013,Paul DuBois,《MySQL技术内幕》(MySQL: Developer's Library, 2nd 2003, 5th 2013),第4版2008豆瓣,第5版豆瓣:全书886页,作者是“MySQL参考手册”(MySQL Reference Manual)的主要贡献者之一,其他书“MySQL Cookbook”(豆瓣
    6. +
    7. 2002、2007、2014,Paul DuBois,《MySQL Cookbook 中文版》,3rd 2014,第2版豆瓣:全书948页
    8. +
    +

    MySQL调优

    +
      +
    1. 2011,《Effective MySQL之SQL语句最优化》(Effective MySQL Optimizing SQL Statements, amazon),豆瓣
    2. +
    3. 2009,简朝阳,《MySQL性能调优与架构设计》,豆瓣:作者目前就职于阿里巴巴
    4. +
    5. 2012,Sevta Smirnova,《MySQL排错指南》(MySQL Troubleshooting),豆瓣:Oracle公司MySQL部门bug分析支持团队的首席技术支持工程师
    6. +
    7. 2014,李海翔,《数据库查询优化器的艺术》,豆瓣:作者现任职于Oracle公司MySQL全球开发团队,从事查询优化技术的研究和MySQL查询优化器的开发工作
    8. +
    9. 2014,贺春旸,《Mysql管理之道:性能调优、高可用与监控》,豆瓣
    10. +
    11. 2004、2008、2012,Schwartz & Zaitsev & Tkachenko,《高性能MySQL:优化,备份,复制》(High Performance MySQL, 3rd 2012),home豆瓣:深入MySQL类top1书籍,第2作者和第3作者来自MySQL AB公司高性能开发组,2006年创办Percona公司
    12. +
    13. 2010,Charles Bell & Kindahl & Thalmann,《高可用MySQL:构建健壮的数据中心》(MySQL High Availability, amazon),豆瓣,第2版豆瓣:3位作者全部来自MySQL复制和备份小组,是复制、备份方面的开发人员及专家
    14. +
    +

    MySQL源码架构

    +
      +
    1. 2010、2013,姜承尧,《MySQL技术内幕:InnoDB》,第2版豆瓣:2011至今,网易杭州研究院,数据库技术组 技术经理
    2. +
    3. 2007、2012,Charles Bell,《深入理解MySQL》(Expert MySQL, 2nd 2012),图灵2009豆瓣:全书466页,MySQL源代码分析,作者是MySQL核心开发人员
    4. +
    5. 2007,Sasha Pachev,《深入理解MySQL核心技术》(Understanding MySQL Internals, amazon),豆瓣:全书246页,纯粹的MySQL源代码分析,作者是前MysQL开发团队成员
    6. +
    +]]>
    + + 计算机系统 + + + MySQL + 数据库 + 书籍 + CS + +
    + + 亚马逊网站架构演进 + /2023/11/amazon-architecture-evolution/ + SOA 与微服务 +

    Amazon,1994 年创立,早期网站是单服务、单数据库的单体架构的系统[1][2][3],全部代码由 C++ 编写,编译成单个二进制文件,整个代码仓库被命名为 Obidos。Obidos 是底层是一个 Web 页面渲染引擎,是一个框架,业务逻辑基于这个框架开发,Obidos 渲染引擎和业务逻辑共同组成整个代码仓库。随着时间的推移,Obidos 变得越来越复杂,编译 Obidos 整个代码库耗时 12 小时,开发调试效率低下[2:1]。另外,全部业务逻辑在单个二进制文件中,导致紧耦合,新功能特性无法快速发布上线。1995 年,Amazon 网站的技术架构,如下图所示[3:1]

    + +Amazon 网站技术架构(1995) +

    到 2000 年,为了应对流量增长,解决网站的可扩展性问题,开始拆分 Obidos,向可扩展的 SOA 架构演进。拆分出的服务有,用户服务(customer service)、订单服务(order service)、商品服务(item service)等,并且每个服务都拥有各自独立的数据库。2005 年 1 月,Amazon 网站开始从 Obidos 引擎迁移到 Gurupa 引擎。Gurupa 是一个 Web 页面渲染引擎,同时也是一个 SOA 框架,Gurupa 被用于集成背后的数百个服务,使用 Perl 的 Mason 模板将各个服务响应的数据渲染成 Web 页面。到 2006 年完成了到 Gurupa 的全部迁移[4]

    +

    Amazon 网站技术架构演进过程,如下图所示[2:2]

    +Amazon 网站技术架构演进 +

    需要注意的是,图中认为从 2006 年开始 Amazon 网站架构从 SOA 演进为微服务,但是事实上,“微服务”这个术语诞生的时间是 2012 年。2006 年的架构实现与之前的 SOA 架构实现的不同点是,开始更细粒度的服务拆分。

    +

    本质上来看,微服务架构是一种特殊的 SOA 架构,在“微服务”术语诞生之前,亚马逊的 SOA 架构实现被认为是“SOA done right”(正确实现的 SOA)[5]。Netflix 的 SOA 架构实现也在“微服务”术语诞生之前,Netflix 认为自己实现架构的是“fine-grained SOA”(细粒度的 SOA)[6]。James Lewis 和 Martin Fowler 等人是“微服务”概念的早期提倡者,他们将亚马逊和 Netflix 的 SOA 架构实现归类为微服务的经典案例[7]。所以,SOA 和微服务的关系可以简单理解为,微服务是“fine-grained SOA”或“SOA done right”。

    +

    根据 Martin Fowler 的解释[8],SOA 与微服务的关系,如下图所示:

    +SOA 与微服务的关系 +

    在 SOA 架构的具体实践上,根据前亚马逊工程师 Steve Yegge 的 2011 年的文章[9][10],在 2002 年左右,亚马逊创始人兼 CEO Jeff Bezos 向全公司发布了一道指令(这个指令被外界称为“API Mandate”),具体内容如下:

    +
    +
      +
    1. 从今天起,所有的团队都要以服务接口的方式提供数据和各种功能。
    2. +
    3. 团队之间必须通过接口来通信。
    4. +
    5. 不允许任何其他形式的互操作:不允许直接链接,不允许直接读其他团队的数据,不允许共享内存,不允许任何形式的后门。唯一许可的通信方式就是通过网络调用服务。
    6. +
    7. 至于具体的技术则不做规定。HTTP、Corba、Pubsub、自定义协议都可以。贝索斯不关心这个。
    8. +
    9. 所有的服务接口,必须从一开始就要以可以公开为设计导向,没有例外。这就是说,团队必须在设计的时候就计划好,接口要可以对外面的开发人员开放。没有讨价还价的余地。
    10. +
    11. 不听话的人会被炒鱿鱼。
    12. +
    +
    +

    技术栈演进

    +

    Amazon 网站的技术栈演进过程[2:3][4:1][11]

    +
      +
    • 1995 ~ 2000:单体架构,Unix(Sun)、Obidos、Oracle、C++ +
        +
      • Obidos 是亚马逊内部 Web 动态页面渲染引擎,编程语言是 C++。
      • +
      +
    • +
    • 2000 ~ 2006:SOA 架构,Linux、Obidos、Oracle、C++ +
        +
      • 2000 年,将 Sun/Unix 服务器替换为 HP/Linux 服务器[12]
      • +
      • 2000 年,开始拆分应用服务,向 SOA 架构演进。
      • +
      • 2005 年初,开始将 Obidos 框架替换为 Gurupa 框架,Gurupa 是 Web 页面渲染引擎,同时也是 SOA 框架。Web 动态页面的编程语言从 C++ 替换为 Perl/Mason,同时应用服务开始被更细粒度的拆分。
      • +
      +
    • +
    • 2006 年开始:微服务架构,Linux、Gurupa、Oracle、Perl & Java & C++ +
        +
      • 2019.10,彻底去掉 Oracle 数据库,迁移到 Amazon RDS 和 NoSQL[13]
      • +
      +
    • +
    +

    当前 Amazon 网站的主要技术栈:

    +
      +
    • 应用服务[4:2][11:1]: +
        +
      • 展示层:Perl/Mason[14]
      • +
      • 业务逻辑层:Java(主要)、C++ 等
      • +
      • RPC框架:Gurupa 框架(自研闭源) +
          +
        • 2006 年更早之前使用 Obidos 框架
        • +
        +
      • +
      • 消息队列MQAmazon SQS
      • +
      +
    • +
    • 数据存储[13:1]: +
        +
      • 关系数据库:Amazon RDS for PostgreSQL[15]、Amazon Aurora (PostgreSQL) +
          +
        • 2019 年 10 月彻底去掉 Oracle 数据库,迁移到 Amazon RDS 和 NoSQL。
        • +
        +
      • +
      • 键值存储Amazon DynamoDB
      • +
      • 缓存:Amazon ElastiCache for Redis[16]
      • +
      • Blob文件存储Amazon S3
      • +
      +
    • +
    +

    AWS 的诞生

    +

    Amazon 网站架构演进的过程,伴随着 AWS 云服务的诞生,促使 AWS 云服务诞生的因素主要有[17][18]

    +
      +
    • 技术价值:Amazon 网站在向可扩展架构演进的过程中,其基础设施团队开始善于运营像计算、存储和数据库这样的基础设施,团队已经变得能非常熟练地运营可靠的、可扩展的、具有成本效益的数据中心,这些专业能力推动了亚马逊电商平台的发展。将维护可靠、可扩展的基础设施专业能力通过服务的方式对外交付,能有效节省第三方企业或初创公司的成本,当时亚马逊预计基础设施的成本可能会从 70% 降低至 30% 或更低[19]
    • +
    • 原始动机:Amazon 网站的流量有很强的季节性,每年 11 月和 12 月(尤其是在感恩节和圣诞节前后)流量都会飙升。为了应对购物季,不得不扩容,增加服务器资源。在购物季结束后,服务器资源被大量闲置。零售电商的利润很薄,却要面对数据中心基础设施不断扩展所带来的成本压力。所以,很多人(包括部分亚马逊员工)[20][21]认为推出 AWS 产品的一个重要原因是为了出租 SOA 网站在销售淡季时的过剩服务器容量。不过,出租过剩容量的故事是一个神话,因为不可能在每年购物季时把开发商从服务器里踢出去,而且实际上在推出 EC2 云服务后的 2 个月内,AWS 就已经烧掉了过剩的 Amazon 网站容量[19:1]
    • +
    • 商业理念Jeff Bezos,将亚马逊定位为一家技术公司,而不仅仅是一家在线零售商,所以在亚马逊的核心业务之外进行很多投资尝试,AWS 产品就是其中之一[17:1]
    • +
    +

    于是,在 2003 年亚马逊团队内部逐渐开始形成销售基础设施服务的设想。2003 年 9 月[22]Andy Jassy 写了 6 页纸的关于 AWS 的愿景文档(vision document)并提交给管理团队,愿景文档中提议了设想的 AWS 业务,并概述了 AWS 提供的初始的基础设施服务集,首批提供的服务包括存储、计算和数据库等。同年,Jassy 组建了由 57 人组成的 AWS 团队,AWS 团队的 CEO 由 Jassy 担任(Jassy 担任 AWS CEO 一直到 2021 年,2021 年 7 月开始任职亚马逊 CEO)。三年之后,2006 年 3 月 AWS 对外发布 S3 云存储,8 月对外发布 EC2 弹性云计算服务器,S3 和 EC2 是行业内最早的云服务产品。S3 发布的刚开始几个月,并没有引起太大的关注。EC2 发布后,大量开发商开始飞速涌入。在没有其他类似云服务产品最初几年,几乎每一家创业公司都在亚马逊的服务器上构建自己的系统。能吸引大量开发商的原因主要是,按需使用和收费的商业模式,以及亚马逊故意压力利润的价格策略[17:2]

    +

    迁移到 AWS

    +

    2011 年 11 月,Amazon 网站全部都迁移到了 AWS 云服务器上[23]。迁移到 AWS 上最大的动机是能利用 AWS 云服务器的弹性伸缩能力,从而节省成本。如果没有弹性伸缩能力,在淡季时,总体上服务器资源容量的利用率是 61%,无法有效利用的容量是 39%,到购物季的 11 月,无法有效利用的容量高到 76%。引入弹性伸缩技术后,可以按网站的实际流量负载情况,供应恰当的容量,避免资源浪费。Amazon 网站在淡季和购物季时的静态伸缩与弹性伸缩,如下图所示[23:1][24]

    +Amazon 网站的典型的周流量分布 +Amazon 网站的静态伸缩 +Amazon 网站的弹性伸缩 +

    参考资料

    +
    +
    +
      +
    1. 2006-05 ACM Queue Interview: A Conversation with Amazon CTO Werner Vogels https://queue.acm.org/detail.cfm?id=1142065 ↩︎

      +
    2. +
    3. 2021-02 Amazon’s architecture evolution and AWS strategy (AWS re:Invent 2020) https://www.youtube.com/watch?v=HtWKZSLLYTE ↩︎ ↩︎ ↩︎ ↩︎

      +
    4. +
    5. 2022-11 Reliable scalability: How Amazon scales in the cloud (AWS re:Invent 2022) https://www.youtube.com/watch?v=_AhfV5LZmvo ↩︎ ↩︎

      +
    6. +
    7. 2011-04 Charlie Cheever: How did Google, Amazon, and the like initially develop and code their websites, databases, etc.? https://qr.ae/pKKyB0 ↩︎ ↩︎ ↩︎

      +
    8. +
    9. 2007-06 SOA done right: the Amazon strategy https://www.zdnet.com/article/soa-done-right-the-amazon-strategy/ ↩︎

      +
    10. +
    11. 2011-05 How the cloud helps Netflix (interview Adrian Cockcroft) http://radar.oreilly.com/2011/05/netflix-cloud.html ↩︎

      +
    12. +
    13. 2014-03 James Lewis & Martin Fowler: Microservices https://martinfowler.com/articles/microservices.html ↩︎

      +
    14. +
    15. 2014-11 Microservices • Martin Fowler • GOTO 2014 https://youtu.be/wgdBVIX9ifA?t=880 ↩︎

      +
    16. +
    17. 2011-10 Steve's Google Platform rant https://gist.github.com/chitchcock/1281611 ↩︎

      +
    18. +
    19. 2016-09 亚马逊如何变成 SOA(面向服务的架构)?(摘录自Steve Yegg的《程序员的呐喊》) https://www.ruanyifeng.com/blog/2016/09/how_amazon_take_soa.html ↩︎

      +
    20. +
    21. What programming languages are used at Amazon? https://qr.ae/pKFwnw ↩︎ ↩︎

      +
    22. +
    23. 2001-10 How Linux saved Amazon millions https://web.archive.org/web/0/http://news.com.com/2100-1001-275155.html ↩︎

      +
    24. +
    25. 2019-10 Migration Complete – Amazon’s Consumer Business Just Turned off its Final Oracle Database https://aws.Amazon/blogs/aws/migration-complete-amazons-consumer-business-just-turned-off-its-final-oracle-database/?nc1=h_ls ↩︎ ↩︎

      +
    26. +
    27. 2016-04 Is Amazon still using Perl Mason to render its content? https://qr.ae/pKFwFm ↩︎

      +
    28. +
    29. Amazon RDS for PostgreSQL customers https://aws.Amazon/rds/postgresql/customers/?nc1=h_ls ↩︎

      +
    30. +
    31. Amazon ElastiCache for Redis customers https://aws.Amazon/elasticache/redis/customers/?nc1=h_ls ↩︎

      +
    32. +
    33. 一网打尽:贝佐斯与亚马逊时代,Brad Stone,2013,豆瓣:第7章 一家技术公司,而非零售商 ↩︎ ↩︎ ↩︎

      +
    34. +
    35. 2016-07 AWS CEO Andy Jassy: How AWS came to be https://techcrunch.com/2016/07/02/andy-jassys-brief-history-of-the-genesis-of-aws/ ↩︎

      +
    36. +
    37. 2011-01 Amazon CTO Werner Vogels: How and why did Amazon get into the cloud computing business? https://qr.ae/pKscWd ↩︎ ↩︎

      +
    38. +
    39. 2016-07 前亚马逊员工在 Reddit 上对文章“How AWS came to be”的评论 https://www.reddit.com/r/programming/comments/4qxthq/comment/d4wrnk7/ ↩︎

      +
    40. +
    41. 2021-01 前亚马逊员工 Dan Rose:全球最大云厂商AWS是如何诞生的? https://mp.weixin.qq.com/s/C7Mqeh1hyT6k5BQOzpWL9w ↩︎

      +
    42. +
    43. 2013-11 Andy Jassy's Book Review of "The Everything Store" https://www.Amazon/review/R1Q4CQQV1ALSN0/ ↩︎

      +
    44. +
    45. 2011-07 2011 AWS Tour Australia, Closing Keynote: How Amazon migrated to AWS, by Jon Jenkins https://www.slideshare.net/AmazonWebServices/2011-aws-tour-australia-closing-keynote-how-amazoncom-migrated-to-aws-by-jon-jenkins ↩︎ ↩︎

      +
    46. +
    47. 2017-03 AWS: Elasticity and Management https://www.slideshare.net/AmazonWebServices/elasticity-and-management ↩︎

      +
    48. +
    +
    +]]>
    + + 架构 + + + 架构 + 可扩展性 + 技术栈 + 微服务 + SOA + +
    + + Elastic Stack 日志分析平台搭建笔记 + /2019/01/elastic-stack/ + Elastic Stack(旧称 ELK Stack)是最受欢迎的开源日志平台 [ ref ]。Elastic Stack 由 Elasticsearch、Logstash、Kibana 和 Beats 四个组件组成:

    +
      +
    • Beats,是轻量型采集器的平台,从边缘机器向 Logstash 和 Elasticsearch 发送数据。
    • +
    • Logstash,集中、转换和存储数据,是动态数据收集管道,拥有可扩展的插件生态系统,能够与 Elasticsearch 产生强大的协同作用。
    • +
    • Elasticsearch,搜索、分析和存储您的数据,是基于 JSON 的分布式搜索和分析引擎,专为实现水平扩展、高可靠性和管理便捷性而设计。
    • +
    • Kibana,实现数据可视化,导览 Elastic Stack。能够以图表的形式呈现数据,并且具有可扩展的用户界面,供您全方位配置和管理 Elastic Stack。
    • +
    + +

    Elastic Stack 是逐步发展而来的,一开始只有 Elasticsearch,专注做搜索引擎,2013 年 1 月 Kibana 及其作者 Rashid Khan 加入 Elasticsearch 公司,同年 8 月 Logstash 及作者 Jordan Sissel 也加入,原本的非官方的 ELK Stack,正式成为官方用语。2015 年 3 月,旧金山举行的第 1 届 Elastic{ON} 大会上,Elasticsearch 公司改名为 Elastic。两个月后,Packetbeat 项目也加入 Elastic,Packetbeat 和 Filebeat(之前叫做 Logstash-forwarder,由 Logstash 作者 Jordan Sissel 开发)项目被整合改造为 Beats。加上 Beats 以后,官方不知道如何将 “B” 和 E-L-K 组合在一起(用过 ELKB 或 BELK),ELK Stack 于是改名为 Elastic Stack,并在 2016 年 10 月正式发布 Elastic Stack 5.0 [ ref1, ref2, ref3 ]。

    +

    使用 Logstash

    +

    Logstash(home, github)最初是来自 Dreamhost 运维工程师 Jordan Sissel 的开源项目,是管理事件和日志的工具,能够用于采集数据,转换数据,然后将数据发送到您最喜欢的“存储库”中(比如 Elasticsearch)。Logstash 使用 JRuby 开发,2011 年 5 月发布 1.0 版本。2013 年 8 月 Jordan Sissel 带着 Logstash 加入 Elasticsearch 公司,Logstash 成为 Elastic Stack 一员。

    +

    在 Ubuntu 下安装启动 Logstash 可以使用下面命令:

    +
    $ sudo apt-get install logstash                # 安装 logstash
    $ sudo systemctl start logstash.service # 系统服务方式启动 logstash
    $ /usr/share/logstash/bin/logstash --version # 查看 logstash 版本
    logstash 6.5.4
    $ sudo vim /etc/logstash/logstash.yml # 查看默认 logstash.yml
    $ sudo vim /etc/logstash/logstash-sample.conf # 查看示例 logstash-sample.conf
    +

    安装完成后,二进制文件在 /usr/share/logstash/bin 目录下,配置文件位于 /etc/logstash 目录,日志输出位于 /var/log/logstash 目录,其他详细的目录位置的分布情况,可以阅读官方文档

    +

    最简单的示例

    +

    Logstash 管道(pipeline)由 inputfilteroutput 三个元素组成,其中 inputoutput 必须设置,而 filter 可选。input 插件从数据源中消费数据,filter 插件按指定方式修改数据,output 插件将数据写入特定目标中 [ doc ]。

    +Logstash 管道 +

    现在来试试 Logstash 下 Hello Wolrd 级别的示例,运行下面命令:

    +
    $ sudo /usr/share/logstash/bin/logstash -e 'input { stdin { } } output { stdout {} }'
    +

    -e 选项能够使 Logstash 直接在命令行中设置管道配置。示例中 input 插件为 stdin (标准输入),output 插件是 stdout (标准输出)。若在控制台输入 hello world,相应的控制台将输出:

    +
    {
    "@version" => "1",
    "host" => "ubuntu109",
    "@timestamp" => 2019-01-12T05:52:56.291Z,
    "message" => "hello world"
    }
    +

    值得注意的是,输出内容编码格式默认为 rubydebug,使用 Ruby 的 "awesome_print" 库打印。另外,响应输出 @timestamp 字段的值为 2019-01-12T05:52:56.291Z,这是 ISO 8601 时间格式,时区是 0(zero),和北京时间相差 8 个小时。

    +

    输出内容编码格式,可以通过 codec 指令指定。除了默认的 rubydebug 外,官方还支持其他 20 多种编码格式,参见 doc。若把编码格式改为 json,即 stdout { codec => json },输出结果将变成:

    +
    {"message":"hello world","@version":"1","@timestamp":"2019-01-12T05:52:56.291Z","host":"ubuntu109"}
    +

    管道配置也可以保存到文件中,以 *.conf 作为文件后缀,比如保存为 test-stdin-stdout.conf

    +
    input {
    stdin { }
    }
    output {
    stdout { }
    }
    +

    启动 logstash 时,-f 选项用于指定管道配置文件的路径:

    +
    $ sudo /usr/share/logstash/bin/logstash -f ~/test-stdin-stdout.conf
    +

    默认情况下,在启动 logstash 后,若再修改管道配置文件,新的修改需要重启 logstash 才能加载生效。在开发调试时,不太方便。解决这个问题,可以使用 -r 命令行选项。开启这个选项后,只要确定配置文件已经发生变更,便会自动重新加载配置文件。

    +

    file 输入插件

    +

    上文日志是控制台输入的,但真实情况日志在日志文件中,要想使用 Logstash 读取日志文件,官方提供了 file 输入插件。管道配置文件示例 test-file-stdout.conf,如下:

    +
    input {
    file {
    path => ["/home/yulewei/test.log"]
    sincedb_path => "/dev/null"
    start_position => "beginning"
    }
    }
    filter {
    }
    output {
    stdout {
    codec => rubydebug
    }
    }
    +

    启动 Logstash:

    +
    $ sudo /usr/share/logstash/bin/logstash -r -f ~/test-file-stdout.conf
    +

    配置文件中的 path 指令用于指定日志文件的路径。start_position 指令设置 Logstash 启动时读取日志文件的位置,可以设置为 beginning 或者 end,默认是 end,即文件末尾。

    +

    为了跟踪每个输入文件中已处理了哪些数据,Logstash 文件输入插件会使用名为 sincedb 的文件来记录现有位置。由于我们的配置用于开发,所以我们希望能够重复读取文件,并进而希望禁用 sincedb 文件。在 Linux 系统上,将 sincedb_path 指令设置为 “/dev/null” 即可禁用。若没有禁用,默认保存的 sincedb 文件将在 /usr/share/logstash/data/plugins/inputs/file/ 目录下。

    +

    grok 过滤插件

    +

    上文的例子,做的核心事情就是把日志行转换到 message 字段,并附加某些元数据,如 @timestamp。如果要想解析自己的日志,把非结构化日志转换结构换日志,有两个过滤器特别常用:dissect 会根据分界符来解析日志,而 grok 则会根据正则表达式匹配来运行。

    +

    如果数据结构定义非常完善,dissect 过滤插件的运行效果非常好,而且运行速度非常快捷高效。同时,其也更加容易上手,对于不熟悉正则表达式的用户而言,更是如此。通常而言,grok 的功能更加强大,而且可以处理各种各样的数据。然而,正则表达式匹配会耗费更多资源,而且速度也会慢一些,如果未能正确进行优化的话,尤为如此。

    +

    现在先来看下 grok 过滤插件。grok 模式的基本语法是 %{SYNTAX:SEMANTIC}SYNTAX 是用于匹配数据的模式(或正则表达式)名称,SEMANTIC 是标识符或字段名称。Logstash 提供了超过 120 种默认的 grok 模式,全部预定义的模式可以在 github 上找到。典型的预定义模式(非完整列表)[ github ]:

    +
      +
    • WORD - 匹配单个词汇的模式
    • +
    • NUMBER - 匹配整数或浮点数(正值或负值均可)的模式
    • +
    • POSINT - 匹配正整数的模式
    • +
    • EMAILADDRESS - 邮箱地址
    • +
    • IP - 匹配 IPv4 或 IPv6 IP 地址的模式
    • +
    • URI - URI 地址
    • +
    • TIMESTAMP_ISO8601 - ISO8601 格式的时间
    • +
    • NOTSPACE - 匹配非空格的任何内容的格式
    • +
    • SPACE - 匹配任何数量的连续空格的模式
    • +
    • DATA - 匹配任何数据类型的限定数量的模式
    • +
    • GREEDYDATA - 匹配剩余所有数据的格式
    • +
    +

    比如,3.44 可以使用 NUMBER 模式进行匹配,192.168.2.104 可以使用 IP 模式。%{NUMBER:num} %{IP:client} 模式,将会用 NUMBER 模式把 3.44 识别为 num 字段,用 IP 模式把 192.168.2.104 识别为 client 字段。默认情况识别获得的字段值是字符串类型,grok 插件支持把类型转换为 intfloat。要想把 3.44 转换为浮点数,可以使用 %{NUMBER:num:float}

    +

    假设有如下日志内容:

    +
    Will, yulewei@gmail.com, 42, 1024, 3.14
    +

    grok 匹配表达式可以写成这样:

    +
    %{WORD:name}, %{EMAILADDRESS:email}, %{NUMBER:num1}, %{NUMBER:num2:int}, %{NUMBER:pi:float}
    +

    即,在这一行日志中依次提取出,nameemailnum1num2pi 字段。完整的 filter 过滤器配置的写法:

    +
    filter {
    grok {
    match => { "message" => "%{WORD:name}, %{EMAILADDRESS:email}, %{NUMBER:num1}, %{NUMBER:num2:int}, %{NUMBER:pi:float}" }
    }
    }
    +

    启动 logstash:

    +
    $ sudo /usr/share/logstash/bin/logstash -r -f ~/test-file-grok-stdout.conf
    +

    控制台将输出:

    +
    {
    "@version" => "1",
    "message" => "Will, yulewei@gmail.com, 42, 1024, 3.14",
    "num1" => "42",
    "pi" => 3.14,
    "@timestamp" => 2019-01-12T08:12:49.581Z,
    "path" => "/home/yulewei/test-grok.log",
    "host" => "ubuntu109",
    "email" => "yulewei@gmail.com",
    "name" => "Will",
    "num2" => 1024
    }
    +

    Logstash 提供了超过 120 种默认的 grok 模式,基本上满足大多数使用场景。若没有符合要求的预定义的模式,可以使用 Oniguruma 语法指定正则表达式:

    +
    (?<field_name>the pattern here)
    +

    上文中的 %{WORD:name}%{EMAILADDRESS:email},等价的正则表达式的写法如下 [ ref1, ref2 ]:

    +
    (?<name>\w+)
    (?<email>[a-zA-Z][a-zA-Z0-9_.+-=:]+@[0-9A-Za-z][0-9A-Za-z-]{0,62}\.[0-9A-Za-z][0-9A-Za-z-]{0,62})
    +

    调试 grok 匹配表达式容易出错,官方提供可视化的 Grok Debugger 工具,提高调试效率。

    +Grok Debugger +

    解析 http 服务器日志

    +

    现在来看下,真实的日志解析案例,使用 grok 过滤插件解析 http 服务器日志。通用日志格式(Common Log Format),是 http 服务器的标准的日志格式。对通用日志格式扩展,加上额外的 referer 和 user-agent 字段,称为组合日志格式(Combined Log Format)。两种日志格式包含的字段如下:

    +
    # 通用日志格式
    %remote-host %ident %authuser %timestamp "%request" %status %bytes
    # 组合日志格式
    %remote-host %ident %authuser %timestamp "%request" %status %bytes "%referer" "%user-agent"
    +

    ApacheNginx 服务器默认的日志格式,采用的就是通用日志格式或者组合日志格式。解析这两种日志格式,Logstash 提供预定义模式 COMMONAPACHELOGCOMBINEDAPACHELOG

    +

    典型的 nginx 日志例子:

    +
    192.168.2.104 - - [13/Jan/2019:02:01:15 +0800] "GET /images/avatar.png HTTP/1.1" 200 266975 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:64.0) Gecko/20100101 Firefox/64.0"
    +

    管道配置文件示例 test-file-grokhttp-stdout.conf,如下:

    +
    input {
    file {
    path => ["/var/log/nginx/access.log"]
    sincedb_path => "/dev/null"
    start_position => "beginning"
    }
    }
    filter {
    grok {
    match => { "message" => "%{COMBINEDAPACHELOG}" }
    remove_field => ["message"]
    }
    }
    output {
    stdout { }
    }
    +

    示例中使用了 grok 的预定义模式 COMBINEDAPACHELOG。另外,remove_field 指令用于把输出事件中某字段删除,示例中是 message 字段。

    +

    启动 logstash:

    +
    $ sudo /usr/share/logstash/bin/logstash -r -f ~/test-file-grokhttp-stdout.conf
    +

    解析获得的结构化数据,如下:

    +
    {
    "auth" => "-",
    "host" => "ubuntu109",
    "verb" => "GET",
    "clientip" => "192.168.2.104",
    "@version" => "1",
    "httpversion" => "1.1",
    "@timestamp" => 2019-01-13T13:35:52.983Z,
    "bytes" => "266975",
    "timestamp" => "13/Jan/2019:02:01:15 +0800",
    "request" => "/images/avatar.png",
    "response" => "200",
    "referrer" => "\"-\"",
    "path" => "/var/log/nginx/access.log",
    "agent" => "\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:64.0) Gecko/20100101 Firefox/64.0\"",
    "ident" => "-"
    }
    +

    dissect 过滤插件

    +

    和 grok 过滤插件使用正则表达式提取字段不同,dissect 过滤插件使用分界符切割来提取字段。由于没有使用正则表达式,运行速度相对 grok 快很多。使用 dissect 过滤插件时,需要指明提取字段的顺序,还要指明这些字段之间的分界符。过滤插件会对数据进行单次传输,并匹配模式中的分界符。同时,过滤插件还会将分界符之间的数据分配至指定字段。过滤插件不会对所提取数据的格式进行验证。

    +

    现在看下示例,test-dissect.log 文件内容如下:

    +
    Will, yulewei@gmail.com, 42, 1024, 3.14
    +

    dissect 匹配规则可以写成这样:

    +
    %{name}, %{email}, %{num1}, %{num2}, %{num3}
    +

    完整的配置文件,test-file-dissect-stdout.conf

    +
    input {
    file {
    path => ["/home/yulewei/test-dissect.log"]
    sincedb_path => "/dev/null"
    start_position => "beginning"
    }
    }
    filter {
    dissect {
    mapping => {
    "message" => "%{name}, %{email}, %{num1}, %{num2}, %{num3}"
    }
    convert_datatype => {
    "num2" => "int"
    "num3" => "float"
    }
    }
    }
    output {
    stdout { }
    }
    +

    和 grok 插件一样,默认提取的字段是字符串类型。配置文件中的 convert_datatype 指令用于将类型转为 intfloat

    +

    启动 logstash:

    +
    $ sudo /usr/share/logstash/bin/logstash -r -f ~/test-file-dissect-stdout.conf
    +

    输出结果:

    +
    {
    "host" => "ubuntu109",
    "num1" => "42",
    "message" => "Will, yulewei@gmail.com, 42, 1024, 3.14",
    "@version" => "1",
    "name" => "Will",
    "num2" => 1024,
    "@timestamp" => 2019-01-13T13:32:10.900Z,
    "path" => "/home/yulewei/test-dissect.log",
    "email" => "yulewei@gmail.com",
    "num3" => 3.14
    }
    +

    输出到 Elasticsearch

    +

    上文举的例子全部都是,输出控制台,使用 stdout 输出插件,没有实用价值。Elastic Stack 的核心其实是 Elasticsearch,使用Elasticsearch 搜索和分析日志。想要将数据发送到 Elasticsearch,可以使用 elasticsearch 输出插件。

    +

    安装 Elasticsearch

    +

    如果没有安装 Elasticsearch,参考官方文档按步骤安装。唯一要注意的是,在执行 apt install 命令前,必须先添加 elastic 的软件源地址,否则无法正常启动。核心命令如下:

    +
    $ sudo apt-get install elasticsearch           # 安装 elasticsearch
    $ sudo systemctl start elasticsearch.service # 系统服务方式启动 elasticsearch
    $ curl http://localhost:9200/ # 用 rest 接口查看 elasticsearch
    {
    "name" : "1t9JXt5",
    "cluster_name" : "elasticsearch",
    "cluster_uuid" : "yQgVsvupSqGCGQbwqnanIg",
    "version" : {
    "number" : "6.5.4",
    "build_flavor" : "default",
    "build_type" : "deb",
    "build_hash" : "d2ef93d",
    "build_date" : "2018-12-17T21:17:40.758843Z",
    "build_snapshot" : false,
    "lucene_version" : "7.5.0",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
    },
    "tagline" : "You Know, for Search"
    }
    +

    默认情况下 elasticsearch 服务器绑定的 ip 地址是回环地址 127.0.0.1,若想绑定特定 ip 地址,可以修改 /etc/elasticsearch/elasticsearch.yml 配置文件中的 network.host 选项:

    +
    network.host: 192.168.2.109
    +

    修改完成并重启后,elasticsearch 服务器访问地址从 http://localhost:9200/ 变成 http://192.168.2.109:9200/

    +

    输出到 Elasticsearch

    +

    现在来看下 elasticsearch 输出插件。示例,test-file-elasticsearch.conf

    +
    input {
    file {
    path => ["/home/yulewei/test.log"]
    sincedb_path => "/dev/null"
    start_position => "beginning"
    }
    }
    output {
    elasticsearch {
    hosts => ["http://192.168.2.109:9200"]
    index => "logstash-%{+YYYY.MM.dd}"
    }
    }
    +

    示例的 elasticsearch 输出插件使用了 hostsindex 指令。hosts 指令,用于指定 elasticsearch 服务器的地址。而 index 指令,用于指定 elasticsearch 索引的名称模式,该指令默认值为 logstash-%{+YYYY.MM.dd}。在字符串内部的 %{...},是 Logstash 字符串插值语法,官方称之为 sprintf format [ doc ]。+YYYY.MM.dd,用于指定 @timestamp 的格式化的格式。logstash-%{+YYYY.MM.dd},格式化后最终生成的值可能将是 logstash-2019.01.13

    +

    启动 logstash:

    +
    $ sudo /usr/share/logstash/bin/logstash -r -f ~/test-file-elasticsearch.conf
    +

    查看在 elasticsearch 上新创建的 logstash-* 索引以及从 logstash 同步过来的日志数据:

    +
    $ curl http://192.168.2.109:9200/_cat/indices
    yellow open logstash-2019.01.13 tFjc5xL_QYeNw4oqe4odeg 5 1 3 0 15.5kb 15.5kb
    $ curl 'http://192.168.2.109:9200/logstash-*/_search?pretty' -H 'Content-Type: application/json' -d'{"size": 1}'
    {
    "took" : 0,
    "timed_out" : false,
    "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
    },
    "hits" : {
    "total" : 3,
    "max_score" : 1.0,
    "hits" : [
    {
    "_index" : "logstash-2019.01.13",
    "_type" : "doc",
    "_id" : "RUHNRWgBLIBntI4FV8Rf",
    "_score" : 1.0,
    "_source" : {
    "path" : "/home/yulewei/test.log",
    "@timestamp" : "2019-01-13T06:01:51.303Z",
    "@version" : "1",
    "host" : "ubuntu109",
    "message" : "hello world"
    }
    }
    ]
    }
    }
    +

    可以看到,新的索引名为 logstash-2019.01.13。同步过来的日志记录全部有 5 条,第 1 条日志的 message 内容是 hello world

    +

    使用 Kibana

    +

    Kibana,能够对 Elasticsearch 中的数据进行可视化,是 Elastic Stack 的窗口。在 Ubuntu 下安装 Kibana 可以使用下面命令:

    +
    $ sudo apt-get install kibana          # 安装 kibana,当前最新版为 6.5.4
    $ sudo systemctl start kibana.service # 系统服务方式启动 kibana
    +

    默认配置下,kibana 服务访问地址是 http://localhost:5601/,连接的 elasticsearch 地址是 http://localhost:9200,这两个配置分别由 server.hostelasticsearch.url 控制 [ doc ]。上文尝试过把 elasticsearch 服务 ip 地址绑定到 192.168.2.109。现在来试下绑定 ip 地址到 kibana,编辑配置文件 /etc/kibana/kibana.yml,修改为:

    +
    server.host: "192.168.2.109"
    elasticsearch.url: "http://192.168.2.109:9200"
    +

    使用 sudo systemctl restart kibana.service 重启后,kibana 服务访问地址变成 http://192.168.2.109:5601/

    +

    elasticsearch 服务器上存在索引 logstash-2019.01.13,要想把这个索引导入到 kibana,参考官方教程即可。点击 Management 菜单,然后创建索引模式(index pattern)。索引模式可以直接为 logstash-2019.01.13,这样匹配单个索引。若要匹配多个时间的 logstash 索引,可以使用通配符 *,比如 logstash-*。如果要匹配全部 2019 年 01 月的索引,可以写成 logstash-2019.01*。完成索引模式定义后,便可以在 Discover 菜单下查看索引,如图:

    +Kibana +

    使用 Filebeat

    +

    Filebeat,轻量型日志采集器 [ home ]。其前身是由 Logstash 作者 Jordan Sissel 开发的 Logstash Forwarder。Logstash Forwarder 项目因为和收购过来的 Packetbeat 项目功能相近,并且都是 Go 语言开发,就一起被整合改造为 Beats [ ref ]。

    +

    我们知道,Logstash 使用 JRuby 开发,运行依赖 JVM,会消耗较多的系统资源。为了减少系统资源(CPU、内存和网络)的使用,Logstash Forwarder 改用 Go 语言开发。另外,在功能上也做了精简,只做单一的数据传输,不像 Logstash 有数据过滤能力。Logstash 类似于功能多样的“瑞士军刀”,能提供从多个数据源加载数据的功能,使用各种强大的插件来处理日志,并提供将多个来源的输出数据进行存储的功能。简而言之,Logstash 提供数据 ETL(数据的提取、变换和加载)的功能;而 Beats 是轻量级的数据传输工具,能将数据传输到 Logstash 或 Elasticsearch 中,其间没有对数据进行任何转换 [ Gupta2017 ]。Filebeat 和 Logstash 的关系如下图所示 [ logz.io ]:

    +Filebeat 和 Logstash 的关系 +

    安装 filebeat 很简单,参考官方文档即可,核心命令如下:

    +
    $ sudo apt-get install filebeat           # 安装 filebeat
    $ filebeat version # 查看 filebeat 版本
    filebeat version 6.5.4 (amd64), libbeat 6.5.4 [bd8922f1c7e93d12b07e0b3f7d349e17107f7826 built 2018-12-17 20:22:29 +0000 UTC]
    $ sudo systemctl start filebeat.service # 系统服务方式启动 filebeat
    +

    输出到 Elasticsearch

    +

    修改 filebeat 配置文件 /etc/filebeat/filebeat.yml,示例如下:

    +
    filebeat.inputs:
    - type: log
    paths:
    - /home/yulewei/test.log

    output.elasticsearch:
    hosts: ["192.168.2.109:9200"]
    +

    filebeat.inputs 选项用于配置日志的输入方式。子选项 type 支持 logstdinredisudptcp 等,示例中使用了 log,表明从日志文件输入。

    +

    output 选项用于配置日志的输出方式,配置支持 elasticsearch、logstash、kafka、redis、file、console 等,一次只能选择配置其中某一个。示例配置了 output.elasticsearch.hosts,指定日志输出目标 elasticsearch 的主机地址。output.elasticsearch.index 可以用来指定索引 index 名称模式,默认是 filebeat-%{[beat.version]}-%{+yyyy.MM.dd}(比如 filebeat-6.5.4-2019.01.12)[ doc ]。

    +

    完成 filebeat.yml 修改后,重启 filebeat,将可以看到,在 elasticsearch 上新创建的 filebeat-* 索引:

    +
    $ curl http://192.168.2.109:9200/_cat/indices
    yellow open filebeat-6.5.4-2019.01.12 B4JbQDnZQuK5XvsQ77uedA 3 1 11043 0 1.7mb 1.7mb
    +

    输出到 Logstash

    +

    上文的示例直接把 Filebeat 采集的日志传输到 Elasticsearch,日志数据并没有被解析或者转换。若想解析和转换日志,需要在Filebeat 和 Elasticsearch 中间引入 Logstash。现在看下把日志输出到 Logstash 的示例配置文件,filebeat.yml 示例:

    +
    filebeat.inputs:
    - type: log
    paths:
    - /home/yulewei/test.log

    output.logstash:
    hosts: ["localhost:5044"]
    +

    filebeat.inputs 和上文的示例一样。不同的是,把 output.elasticsearch.hosts 改成了 output.logstash.hosts,指定日志输出目标 Logstash 的主机地址。5044 这个端口是 Logstash 用于监听 Filebeat 的端口。

    +

    现在来看下 Logstash 的管道配置文件,示例 test-beats-stdout.conf

    +
    input {
    beats {
    port => 5044
    }
    }
    output {
    stdout {
    codec => rubydebug
    }
    }
    +

    示例中,使用了 beats 输入插件,配置的端口就 filebeat.yml 中指定的 5044。输出插件为 stdout,即把 Logstash 采集到日志输出到控制台。

    +

    重启 filebeat 和 logstash:

    +
    $ cat test.log                              # 查看日志文件内容
    hello world
    $ sudo systemctl restart filebeat.service # 重启 filebeat
    $ sudo /usr/share/logstash/bin/logstash -r -f ~/test-beats-stdout.conf
    +

    控制台输出:

    +
    {
    "tags" => [
    [0] "beats_input_codec_plain_applied"
    ],
    "source" => "/home/yulewei/test.log",
    "input" => {
    "type" => "log"
    },
    "message" => "hello world",
    "@timestamp" => 2019-01-12T13:32:05.131Z,
    "@version" => "1",
    "prospector" => {
    "type" => "log"
    },
    "beat" => {
    "hostname" => "ubuntu109",
    "version" => "6.5.4",
    "name" => "ubuntu109"
    },
    "offset" => 0,
    "host" => {
    "os" => {
    "version" => "16.04.4 LTS (Xenial Xerus)",
    "platform" => "ubuntu",
    "codename" => "xenial",
    "family" => "debian"
    },
    "architecture" => "x86_64",
    "id" => "29b1bf39547d4ca9ae26c3b7656ff9e3",
    "containerized" => false,
    "name" => "ubuntu109"
    }
    }
    +

    集成 Filebeat, Logstash, Elasticsearch, Kibana

    +

    真实场景下,日志文件可能分布在多台服务器上,同一台服务器上也可能分布着不同来源类型的日志。现在我们来尝试下,使用 Filebeat 把两个日志文件各自采集到两个不同的 Elasticsearch 索引中,并用 Kibana 可视化。有两个日志文件 test-beats1.logtest-beats2.log,内容如下:

    +
    $ cat test-beats1.log
    hello world1
    hello world1
    $ cat test-beats2.log
    hello world2
    +

    filebeat.yml 配置示例:

    +
    filebeat.inputs:
    - type: log
    paths:
    - /home/yulewei/test-beats1.log
    fields:
    log_type: test1
    - type: log
    paths:
    - /home/yulewei/test-beats2.log
    fields:
    log_type: test2

    output.logstash:
    hosts: ["localhost:5044"]
    +

    示例配置文件使用了 filebeat.inputs.fields 选项,fields 选项用于在日志事件输出中添加字段。添加的字段名可以任意指定,示例中名为 log_type。因为现在在 filebeat 配置中同时导入两个日志文件,输出到同一个 logstash 中。使用这个额外字段是为了区分日志是来自 test-beats1.log 还是 test-beats2.log。示例中,第 1 个日志事件输出的 log_type 字段值配置为 test1, 第 2 个日志配置为 test2

    +

    管道配置文件示例,test-beats-elasticsearch.conf

    +
    input {
    beats {
    port => 5044
    }
    }
    output {
    elasticsearch {
    hosts => ["http://192.168.2.109:9200"]
    index => "filebeat-%{[fields][log_type]}-%{+YYYY.MM.dd}"
    }
    stdout {
    codec => rubydebug
    }
    }
    +

    输出插件同时使用了 elasticsearchstdout。配置文件中的 elasticsearch 输出插件的 index 指令被设置为 filebeat-%{[fields][log_type]}-%{+YYYY.MM.dd}[fields][log_type] 引用的是在 filebeat.ymlfilebeat.inputs.fields 选项添加的 log_type 字段(关于在配置文件引用字段的语法,可以参考官方文档)。根据 log_type 字段不同,把日志将输出到不同的索引中。因为 filebeat.yml 配置文件中设置的 log_type 字段是 test1 或者 test2,所以最终生成的索引名是 filebeat-test1-* 或者 filebeat-test1-*filebeat-test1-* 索引中全部日志数据来自 test-beats1.log 日志文件,filebeat-test2-* 索引数据来自 test-beats2.log

    +

    启动 filebeat 和 logstash:

    +
    $ sudo systemctl restart filebeat.service
    $ sudo /usr/share/logstash/bin/logstash -r -f ~/test-beats-elasticsearch.conf
    +

    控制台输出:

    +
    ...
    {
    "@version" => "1",
    "host" => {
    "name" => "ubuntu109"
    },
    "message" => "hello world2",
    "prospector" => {
    "type" => "log"
    },
    "fields" => {
    "log_type" => "test2"
    },
    "offset" => 0,
    "tags" => [
    [0] "beats_input_codec_plain_applied"
    ],
    "beat" => {
    "name" => "ubuntu109",
    "version" => "6.5.4",
    "hostname" => "ubuntu109"
    },
    "@timestamp" => 2019-01-13T09:32:11.845Z,
    "source" => "/home/yulewei/test-beats2.log",
    "input" => {
    "type" => "log"
    }
    }
    ...
    +

    查看在 elasticsearch 上新创建的 filebeat-test1-*filebeat-test1-* 索引:

    +
    $ curl http://192.168.2.109:9200/_cat/indices/filebeat-*
    yellow open filebeat-test1-2019.01.13 NLVfFJl5TQ-7I1r9KoVLaQ 5 1 5 0 31.8kb 31.8kb
    yellow open filebeat-test2-2019.01.13 NnsBp3P9Q3-mLc8chE-Tiw 5 1 3 0 24.1kb 24.1kb
    +

    在 kibana 上查看收集的日志:

    +Kibana +

    整体架构上,如下图所示 [ doc ]:

    +Deploying Logstash +
    +

    附注:本文中提到的配置文件,可以在 github 上访问得到,elastic-stack-conf

    +

    参考资料

    + +]]>
    + + 架构 + + + 架构 + ELK + Elastic + 日志 + +
    + + InnoDB 的并发控制:锁与 MVCC + /2023/07/innodb-locking/ + 目前主流数据库事务的并发控制实现,如 MySQL InnoDB、PostgreSQL、Oracle,都使用两阶段封锁 2PLMVCC 技术,但具体实现细节上存在差异。InnoDB 是在以封锁技术为主体的情况下,用 MVCC 技术辅助实现读-写、写-读操作的并发。PostgreSQL 的并发控制技术是以 MVCC 技术为主,封锁技术为辅。本文主要关注 InnoDB 事务的并发控制实现。

    + + +

    背景知识

    +

    并发控制,是数据库系统的 ACID 特性中的隔离性(Isolation)的保障。所谓隔离性,就是事务的执行不应受到其他并发执行事务的干扰,事务的执行看上去应与其他事务是隔离的。被隔离的执行,等价于事务的某种串行执行,或者说,它等价于一个没有并发的执行。保证串行性可能只允许极小的并发度,采用较弱隔离性,能带来更高的并发度,是并发事务的正确性和性能之间的妥协。

    +

    早期各大数据库厂商实现并发控制时多采用基于封锁的并发控制技术,所以在基于封锁的技术背景下,才在 ANSI SQL-92 标准中提出了四种隔离级别:未提交读(Read Uncommitted)、己提交读(Read Committed)、可重复读(Repeatable Read)、可串行化(Serializable)(附注:为了书写简便本文将各个隔离级别依次缩写为 RU、RC、RR、SER)。ANSI SQL-92 标准的四种隔离级别,是根据三种读异常现象(phenomena)定义的,隔离级别和异常现象的关系如下:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    隔离级别P1 脏读P2 不可重复读P4 幻读
    Read Uncommitted可能可能可能
    Read Committed避免可能可能
    Repeatable Read避免避免可能
    Serializable避免避免避免
    +

    ANSI SQL-92 标准文档对三种读异常现象的定义原文如下 [ref]:

    +
    +

    The isolation level specifies the kind of phenomena that can occur during the execution of concurrent SQL-transactions. The following phenomena are possible:
    +1) P1 ("Dirty read"): SQL-transaction T1 modifies a row. SQL-transaction T2 then reads that row before T1 performs a COMMIT. If T1 then performs a ROLLBACK, T2 will have read a row that was never committed and that may thus be considered to have never existed.
    +2) P2 ("Non-repeatable read"): SQL-transaction T1 reads a row. SQL-transaction T2 then modifies or deletes that row and performs a COMMIT. If T1 then attempts to reread the row, it may receive the modified value or discover that the row has been deleted.
    +3) P3 ("Phantom"): SQL-transaction T1 reads the set of rows N that satisfy some . SQL-transaction T2 then executes SQL-statements that generate one or more rows that satisfy the used by SQL-transaction T1. If SQL-transaction T1 then repeats the initial read with the same , it obtains a different collection of rows.

    +
    +

    除了脏读、不可重复读和幻读这 3 种读数据异常外,还有写数据异常,即脏写和丢失更新。各个异常的含义如下:

    +
      +
    • P0 脏写(Dirty Write):事务 T1 写某数据项,并且未提交或回滚,事务 T2 也写该数据项,然后事务 T1 或事务 T2 回滚,回滚导致另外一个事务的修改被连带回滚。脏写异常会导致事务无法回滚,原子性无法得到保障,所以全部隔离级别下都应该避免。脏写也可以叫回滚丢失。
    • +
    • P1 脏读(Dirty Read):读到了其他事务还未提交的数据。
    • +
    • P2 不可重复读(Non-Repeatable):事务 T1 读取某数据项,事务 T2 修改 update 或删除 delete 该数据项,事务 T1 再次读取该数据项,结果不同。
    • +
    • P3 幻读(Phantom):事务 T1 读取满足某条件的数据项集合,事务 T2 生成新的满足该条件的数据项,事务 T2 再次读取满足该条件的数据项集合,结果不同。
    • +
    • P4 丢失更新(Lost Update):事务 T1 读取某数据项,事务 T2 更新该数据项并提交,事务 T1 忽略事务 T2 的更新,直接基于最初的读取数据项做更新并提交,导致事务 T2 的更新丢失。丢失更新也可以叫覆盖丢失。
    • +
    +

    各个异常的读写操作序列的简化符号表示如下 [Berenson 1995]:

    +
    P0: w1[x]...w2[x]...(c1 or a1)                 事务 T2 脏写
    A1: w1[x]...r2[x]...(a1 and c2 in any order) 事务 T2 脏读,r2[x] 为脏读
    A2: r1[x]...w2[x]...c2...r1[x]...c1 事务 T1 不可重复读,两次 r1[x] 结果不同
    A3: r1[P]...w2[y in P]...c2...r1[P]...c1 事务 T1 幻读,两次 r1[P] 结果不同
    P4: r1[x]...w2[x]...w1[x]...c1 事务 T2 更新丢失,c1 导致 w2[x] 丢失
    +

    其中 w1[x] 表示事务 T1 写入记录 x,r1[x] 表示事务 T1 读取记录 x,c1 表示事务 T1 提交,a1 表示事务 T1 回滚,r1[P] 表示事务 T1 按照谓词 P 的条件读取若干条记录,w1[y in P] 表示事务 T1 写入记录 y 满足谓词 P 的条件。

    +

    Berenson 的论文评判了 ANSI SQL-92 标准的异常定义。ANSI SQL-92 标准的异常的定义存在歧义,可以严格解释,也可以宽松解释,A1、A2 和 A3 的符号表示为严格解释,按严格解释,某些特殊的异常无法囊括,所以推荐宽松解释。按照标准的定义,容易引起误解的是,在排除 P1 脏读、P2 不可重复、P3 幻读这三种读异常后就会得到可串行化隔离级别,但是事实并非如此。标准没有定义 P0 脏写和 P4 更新丢失异常。另外,基于 MVCC 技术实现的快照隔离(Snapshot Isolation),能避免标准定义的 P1 脏读、P2 不可重复、P3 幻读,并且避免 P0 脏写和 P4 更新丢失,但还存在写偏序(Write Skew)异常。

    +

    不可重复读和幻读的区别:

    +
      +
    • 不可重复读对于事务 T2 的写操作是更新或删除操作,而幻读对于事务 T2 的写操作是插入(插入的新数据满足条件)或更新(使不满足条件的数据在更新后满足条件)操作。
    • +
    • 对于幻读现象中事务 T2 的操作,如果操作是对现有数据的更新或删除操作,则表明这样的操作等同于不可重复读,即是在多个行数据上进行更新或删除,即在多个行数据上批量化重演了不可重复读现象
    • +
    • 不可重复读和幻象最大的区别就是前者只需要“锁住”(考虑)已经读过的数据,而幻读需要对“还不存在的数据“做出预防。不可重复读现象中事务 T2 着眼于对现有数据进行操作;而幻读现象中事务 T2 着眼于对新增(或不在锁定范围内已经存在的数据上做更新后而得的数据满足了谓词条件)数据
    • +
    +

    异常由并发冲突引起,对应关系如下:

    +
      +
    • 写写冲突:P0 脏写、P4 丢失更新
    • +
    • 写读冲突:P1 脏读
    • +
    • 读写冲突:P2 不可重复读、P3 幻读
    • +
    +

    早期各大数据库厂商实现并发控制时多采用基于封锁的并发控制技术,所以在基于封锁的技术背景下,才在ANSI SQL 标准中提出了四种隔离级别。基于锁的并发控制技术的加锁方式与隔离级别的关系表 [Berenson 1995]:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    隔离级别写锁数据项的读锁谓词的读锁
    Read Uncommitted长写锁无锁要求无锁要求
    Read Commited长写锁短读锁短谓词锁
    Repeatable Read长写锁长读锁短谓词锁
    Serializable长写锁长读锁长谓词锁
    +

    说明:

    +
      +
    • 短锁(short duration lock),当前正在执行的语句持有锁,语句执行完毕锁被释放。长锁(long duration lock),当锁被持有后,直到事务提交之后才被释放。
    • +
    • RU 隔离级别,阻止 P0,长写锁
    • +
    • RC 隔离级别,阻止 P0、P1,长写锁 + 短读锁 + 短谓词锁
    • +
    • RR 隔离级别,阻止 P0、P1、P4、P2,长写锁 + 长写锁 + 短谓词锁
    • +
    • SER 隔离级别,阻止 P0、P1、P4、P2、P3,长写锁 + 长写锁 + 长谓词锁
    • +
    +

    基于锁的并发控制下,隔离级别和异常现象的关系:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    隔离级别P0 脏写P1 脏读P4 丢失更新P2 不可重复读P4 幻读
    Read Uncommitted避免可能可能可能可能
    Read Committed避免避免可能可能可能
    Repeatable Read避免避免避免避免可能
    Serializable避免避免避免避免避免
    +

    各个隔离级别在基于锁的并发控制技术下的具体的实现说明(参考自腾讯李海翔的《数据库事务处理的艺术》第 2 章):

    +基于锁的并发控制 +

    基于锁的并发控制,读-读操作可以并发执行,但读-写、写-读、写-写操作无法并发执行,阻塞等待。MVCC 结合封锁技术,使得读-写、写-读操作互不阻塞,即只有写-写操作不能并发,并发度被提高到 75%,这就是 MVCC 被广为使用的原因。

    +

    InnoDB 的并发控制以封锁技术为主,MVCC 技术为辅助。让我们先看下 InnoDB 的封锁技术。

    +

    共享锁与排他锁

    +

    InnoDB 存储引擎实现两种标准的行级锁模式,共享锁(读锁)和排他锁(写锁)[doc]:

    +
      +
    • 共享锁(shared lock,S):允许事务读一行数据。
    • +
    • 排他锁(exclusive Lock,X):允许事务删除或更新一行数据。
    • +
    +

    如果事务 T1 持有行 r 上的共享锁(S),则来自某个不同事务 T2 的对行 r 上的锁的请求将按如下方式处理:

    +
      +
    • T2 对 S 锁的请求可以立即被授予。因此,T1 和 T2 持有 r 上的锁。
    • +
    • T2 对 X 锁的请求不能立即被授予。
    • +
    +

    如果事务 T1 持有行 r 上的排他锁(X),则某个不同事务 T2 对 r 上任一类型的锁的请求无法立即被授予。相反,事务 T2 必须等待事务 T1 释放其对行 r 的锁定。

    +

    共享锁和排他锁的兼容性:

    + + + + + + + + + + + + + + + + + + + + +
    待申请 \ 已持有共享锁 S排他锁 X
    共享锁 S兼容冲突
    排他锁 X冲突冲突
    +

    区分共享锁(读锁)和排它锁(写锁)后,读锁与读锁的并发可被允许进行,并发能力得以提高。

    +

    对于 updatedeleteinsert 语句,InnoDB 会自动给涉及数据集加排他锁(X);对于普通 select 语句,InnoDB 不会加任何锁(SERIALIZABLE隔离级别下除外);事务可以通过以下语句显式给查询 select 显式加共享锁或排他锁:

    +
      +
    • 共享锁(S):select ... for share
    • +
    • 排他锁(X):select ... for update
    • +
    +

    现在让我们来试验下共享锁和排他锁。创建 tbl 表,并添加表数据:

    +
    create table tbl 
    (a int, b int, c int, d int, primary key(a), unique key(b), key(c));
    insert into tbl values
    (10, 10, 10, 10), (20, 20, 20, 20), (30, 30, 30, 30),
    (40, 40, 40, 40), (50, 50, 50, 50), (60, 60, 60, 60),
    (70, 70, 70, 70), (80, 80, 80, 80), (90, 90, 90, 90),
    (100, 100, 100, 100);
    +

    InnoDB 的排它锁示例,如下:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    事务1事务2
    mysql> begin;mysql> begin;
    -- 在 a = 10 的索引记录上添加排他锁
    mysql> select * from tbl where a = 10 for update;
    -- 阻塞,获取 a = 10 的排他锁超时
    mysql> update tbl set b = 42 where a = 10;
    ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
    -- 阻塞,获取 a = 10 的排他锁超时
    mysql> update tbl set b = 42 where a >= 10;
    -- 阻塞,获取 a = 10 的排他锁超时
    mysql> delete from tbl where a = 10;
    -- 阻塞,获取 a = 10 的排他锁超时
    mysql> select * from tbl where a = 10 for update;
    -- 更新成功,可以获得其他记录的排他锁
    mysql> update tbl set b = 42 where a = 20;
    mysql> commit;
    -- 更新成功,在事务 1 释放锁后,其他事务可以获取排他锁
    mysql> update tbl set b = 42 where a = 10;
    +

    InnoDB的共享锁示例,如下:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    事务1事务2
    mysql> begin;mysql> begin;
    -- 在 a = 10 的索引记录上添加共享锁
    mysql> select * from tbl where a = 10 for share;
    -- 获取 a = 10 的共享锁成功
    mysql> select * from tbl where a = 10 for share;
    -- 阻塞,获取 a = 10 的排他锁超时
    mysql> update tbl set b = 42 where a = 10;
    mysql> commit;
    -- 更新成功,在事务 1 释放锁后,其他事务可以获取排他锁
    mysql> update tbl set b = 42 where a = 10;
    +

    多粒度与意向锁

    +

    InnoDB 存储引擎支持多粒度锁定(multiple granularity locking),这种锁定允许事务在行级上的锁和表级上的锁同时存在。为了支持在不同粒度上进行加锁操作,InnoDB 存储引擎支持一种额外的锁方式,称之为意向锁(Intention Lock)。意向锁是将锁定的对象分为多个层次,意向锁意味着事务希望在更细粒度上进行加锁。

    +

    若将上锁的对象看成一棵树,那么对最下层的对象上锁,也就是对最细粒度的对象进行上锁,那么首先需要对粗粒度的对象上锁。如果需要对页上的记录 r 进行上 X 锁,那么分别需要对数据库 A、表、页上意向锁 IX,最后对记录 r 上 X 锁。若其中任何一个部分导致等待,那么该操作需要等待粗粒度锁的完成。

    +

    在一个对象加锁之前,该对象的全部祖先节点均加上了意向锁。希望给某个记录加锁的事务必须遍历从根到记录的路径。在遍历树的过程中,该事务给各节点加上意向锁。

    +粒度层次图 +

    举例来说,假设在表 1 的记录 r 上持有 X 锁,表 1 上必定持有 IX 锁。如果其他事务想在表 1 上加 S 表锁或 X 表锁,但与已有 IX 锁不兼容,所以该事务需要等待。再举例,假设表 1 持有 S 锁,如果其他事务想在表 1 的记录 r 上加 X 锁,需要先获得表 1 的 IX 锁,但与已有 S 锁不兼容,所以该事务需要等待。有了意向锁之后,就能快速判断行锁和表锁之间是否兼容。

    +

    InnoDB 存储引擎支持意向锁设计比较简练,其意向锁即为表级别的锁,两种意向锁 [doc]:

    +
      +
    • 意向共享锁(IS):事务打算给数据行加行共享锁(S),事务在给一个数据行加共享锁(S)前必须先取得该表的 IS 锁。
    • +
    • 意向排他锁(IX):事务打算给数据行加行排他锁(X),事务在给一个数据行加排他锁(X)前必须先取得该表的 IX 锁。
    • +
    +

    IS、IX、S、X 锁的兼容性:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    待申请 \ 已持有ISIXSX
    IS兼容兼容兼容冲突
    IX兼容兼容冲突冲突
    S兼容冲突兼容冲突
    X冲突冲突冲突冲突
    +

    兼容关系:各种意向锁(IS、IX)之间全部兼容,意向共享锁 IS 和共享锁 S 兼容,共享锁 S 和共享锁 S 兼容,其他冲突。

    +

    SQL 语句可以分为数据定义语言(DDL)、数据控制语言(DCL)、数据查询语言(DQL)、数据操纵语言(DML)四种类型的语句,前两种语句,涉及的对象在数据之上,所以加锁的范围,通常是表级,对应表级锁。后两种语句操作的对象是数据,加锁的范围,通常是数据级,这就对应行级锁。

    +

    三种行锁:记录锁、间隙锁和 next-key 锁

    +

    InnoDB 行锁分为 3 种类型 [doc]:

    +
      +
    • 记录锁(record lock):对索引记录项加锁。
    • +
    • 间隙锁(gap lock):间隙锁,对索引记录项之间的“间隙”、笫一条记录前的“间隙”或最后一条记录后的“间隙“加锁。锁定一个范围,但不包含索引记录本身。
    • +
    • next-key 锁(next-key Lock):前两种锁的组合,记录锁 + 间隙锁,锁定一个范围,并且锁定索引记录本身。(中文世界有时将 next-key lock 翻译为“临键锁”)
    • +
    +

    如果索引上包含 10, 20, 30, 40, 50 这些记录,那么可能的 next-key 锁的锁区间(interval),如下:

    +
    (-无穷, 10]     即,间隙锁 (-无穷, 10) + 记录锁 10。区间为,左开右闭区间
    (10, 20] 即,间隙锁 (10, 20) + 记录锁 20
    (20, 30] 即,间隙锁 (20, 30) + 记录锁 30
    (30, 40] 即,间隙锁 (30, 40) + 记录锁 40
    (40, 50] 即,间隙锁 (40, 50) + 记录锁 50
    (50, +无穷] 即,间隙锁 (50, +无穷)
    +

    最后一个锁区间 (50, +无穷],对应的是上界伪记录(supremum pseudo-record),不是真实存在的记录。这个锁区间用于防止在最大值 50 之后插入记录。

    +

    记录锁总是会去锁住索引记录,如果 InnoDB 存储引擎表在建立的时候没有设置任何一个索引,那么这时 InnoDB 存储引擎会使用隐式的主键来进行锁定。

    +

    MySQL 默认的事务隔离级别是可重复读(REPEATABLE-READ),如果把事务隔离级别改成已提交读(READ-COMMITTED),间隙锁会被禁用。禁用间隙锁后,幻读异常会出现,因为其他事务可以在间隙中插入新行。InnoDB 的间隙锁,就是为了解决幻读异常而引入的。关于幻读异常,参见官方文档 doc

    +

    RR 隔离级别下,InnoDB 的锁通常使用 next-key 锁。但是,在唯一索引(和主键索引)上的等值查询next-key 锁退化为记录锁,间隙锁并不需要,即仅锁住索引本身,而不是范围。如果在唯一索引(和主键索引)上做范围查询,间隙锁依然需要。官方文档描述如下 [doc]:

    +
    +

    Gap locking is not needed for statements that lock rows using a unique index to search for a unique row. (This does not include the case that the search condition includes only some columns of a multiple-column unique index; in that case, gap locking does occur.)

    +
    +

    间隙锁是“纯抑制性的”,间隙锁唯一的作用就是为了防止其他事务的插入到间隙中。间隙锁和间隙锁之间是互不冲突的,所以间隙共享 S 锁和间隙排他 X 锁没有任何区别。

    +

    另外,还有一种锁叫插入意向锁(insert intention lock),基于间隙锁,专门用于 insert 操作。在执行 insert 操作时,需要先申请获取插入意向锁,也就是说,需要先检查当前插入位置上的下一条记录上是否持有间隙锁,如果被间隙锁锁住,则锁冲突,插入被阻塞。多个事务做 insert 操作,被相同的间隙锁阻塞,如果插入的值各不相同,这些事务的 insert 操作之间不阻塞。

    +

    所以,间隙锁与插入意向锁的兼容关系是,已持有的间隙锁与待申请的插入意向锁冲突,而插入意向锁之间兼容,在一个间隙锁锁上可以有多个意向锁等待。

    +

    IS、IX、X、S 锁和记录锁、间隙锁、next-key 锁的关系:

    +
      +
    • IS、IX、S、X 是锁模式(lock mode)(源码层面上对应 lock_mode 枚举)。
    • +
    • 记录锁、间隙锁、next-key 锁、插入意向锁是行锁类型(record lock type)。
    • +
    • 每一种行锁类型,都包含 IS、IX、S、X 锁模式,如共享的记录锁、排他的记录锁、共享的间隙录锁、排他的间隙锁等。
    • +
    +

    锁监控:data_locks 和 data_lock_waits 表

    +

    MySQL 8.0 之前,information_schema 库提供 innodb_trxinnodb_locksinnodb_lock_waits 三张表,用来监控事务和诊断潜在的锁问题,具体介绍可以参见官方 5.7 文档 doc

    +
      +
    • innodb_trx:当前事务表
    • +
    • innodb_locks:锁等待中的锁信息表
    • +
    • innodb_lock_waits:锁等待中的事务表
    • +
    +

    在 MySQL 8.0 之前,要想获得当前已持有的锁信息,需要开启参数 innodb_status_output_locks 并且执行命令 show engine innodb status,具体介绍可以参见官方文档“15.17 InnoDB Monitors”,doc

    +

    MySQL 8.0 开始,innodb_locks 表和 innodb_lock_waits 表,被 performance_schema 库的 data_locks 表和 data_lock_waits 表替代。其中值得注意的不同点是,新的 data_locks 表,同时包含了已持有的锁和请求中的锁的信息,这样查看当前已持有的锁信息更加方便。相关 SQL 示例:

    +
    -- 查询全部锁信息
    select * from performance_schema.data_locks \G
    -- 查询全部记录锁的锁信息
    select * from performance_schema.data_locks where LOCK_TYPE = 'RECORD' \G
    -- 查询等待中的锁信息
    select * from performance_schema.data_locks where LOCK_STATUS = 'WAITING' \G
    -- 查询锁等待中的事务
    select * from performance_schema.data_lock_waits \G
    -- 使用 sys 库的 innodb_lock_waits 视图
    -- 查询锁等待中的事务
    select * from sys.innodb_lock_waits \G
    +

    命令 show engine innodb status 的输出和 data_locks 表的对应关系,可以参考文章 link

    +

    行锁加锁案例分析

    +

    RR 隔离级别

    +

    本文的全部案例采用的 MySQL 版本为 8.0.30。MySQL 的默认事务隔离级别是 REPEATABLE-READ(可重复读),事务隔离级别可以通过系统变量 transaction_isolation 控制。

    +
    -- 事务隔离级别,默认为可重复读(Repeatable Read)
    mysql> select @@global.transaction_isolation, @@transaction_isolation;
    +--------------------------------+-------------------------+
    | @@global.transaction_isolation | @@transaction_isolation |
    +--------------------------------+-------------------------+
    | REPEATABLE-READ | REPEATABLE-READ |
    +--------------------------------+-------------------------+
    1 row in set (0.00 sec)
    +

    tbl 表的数据如下:

    +
    mysql> select * from tbl;
    +-----+------+------+------+
    | a | b | c | d |
    +-----+------+------+------+
    | 10 | 10 | 10 | 10 |
    | 20 | 20 | 20 | 20 |
    | 30 | 30 | 30 | 30 |
    | 40 | 40 | 40 | 40 |
    | 50 | 50 | 50 | 50 |
    | 60 | 60 | 60 | 60 |
    | 70 | 70 | 70 | 70 |
    | 80 | 80 | 80 | 80 |
    | 90 | 90 | 90 | 90 |
    | 100 | 100 | 100 | 100 |
    +-----+------+------+------+
    10 rows in set (0.00 sec)
    +

    (a1) 主键索引上的等值查询

    +

    SQL 语句:

    +
    select * from tbl where a = 10 for update;
    +

    data_locks 表中的行锁数据:

    +
    mysql> select * from performance_schema.data_locks where LOCK_TYPE = 'RECORD' \G
    *************************** 1. row ***************************
    ENGINE: INNODB
    ENGINE_LOCK_ID: 4816436360:185:4:3:140408965390368
    ENGINE_TRANSACTION_ID: 56664
    THREAD_ID: 367
    EVENT_ID: 22
    OBJECT_SCHEMA: testdb
    OBJECT_NAME: tbl
    PARTITION_NAME: NULL
    SUBPARTITION_NAME: NULL
    INDEX_NAME: PRIMARY
    OBJECT_INSTANCE_BEGIN: 140408965390368
    LOCK_TYPE: RECORD
    LOCK_MODE: X,REC_NOT_GAP
    LOCK_STATUS: GRANTED
    LOCK_DATA: 10
    +

    加锁情况:

    +
      +
    • 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    • +
    +

    其他 SQL 语句的加锁情况(通过查 data_locks 表确认):

    +
    -- 在 a = 10 的索引记录上添加共享记录锁(S,REC_NOT_GAP)
    select * from tbl where a = 10 for share;

    -- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    update tbl set b = 42 where a = 10;

    -- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    delete from tbl where a = 10;
    +

    加锁与锁冲突 SQL 演示:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    事务1事务2
    mysql> begin;mysql> begin;
    -- 在 a = 10 的索引记录上添加排他记录锁
    mysql> select * from tbl where a = 10 for update;
    -- 阻塞,因为 a = 10 上存在排他记录锁
    mysql> select * from tbl where a = 10 for update;
    -- 阻塞,因为 a = 10 上存在排他记录锁
    mysql> insert into tbl (a) values (10);
    -- 插入成功
    mysql> insert into tbl (a) values (9);
    -- 插入成功
    mysql> insert into tbl (a) values (11);
    mysql> rollback;mysql> rollback;
    +

    (a2) 唯一索引上的等值查询

    +

    SQL 语句的加锁情况(通过查 data_locks 表确认):

    +
    -- 在 b = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    select * from tbl where b = 10 for update;

    -- 在 b = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 覆盖索引,但系统会认为接下来要更新数据,因此会顺便给主键索引上满足条件的行加上行锁
    select a from tbl where b = 10 for update;

    -- 在 b = 10 的索引记录上添加共享记录锁(S,REC_NOT_GAP)
    -- 在 a = 10 的索引记录上添加共享记录锁(S,REC_NOT_GAP)
    select * from tbl where b = 10 for share;

    -- 在 b = 10 的索引记录上添加共享记录锁(S,REC_NOT_GAP)
    -- 覆盖索引,所以只在字段 b 上加锁
    select a from tbl where b = 10 for share;

    -- 在 b = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    update tbl set b = 42 where b = 10;

    -- 在 b = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    delete from tbl where b = 10;
    +

    上面的全部 SQL,除了走覆盖索引的 select for share 外,其他的加锁范围都相同。

    +

    (a3) 非唯一索引上的等值查询

    +

    SQL 语句的加锁情况(通过查 data_locks 表确认):

    +
    -- 在 c = 10 的索引记录上添加排他 next-key 锁,区间为 (-无穷, 10](X)
    -- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 c = 20 的索引记录上添加排他间隙锁,区间为 (10, 20)(X,GAP)
    select * from tbl where c = 10 for update;

    -- 在 c = 10 的索引记录上添加共享 next-key 锁,区间为 (-无穷, 10](S)
    -- 在 a = 10 的索引记录上添加共享记录锁(S,REC_NOT_GAP)
    -- 在 c = 20 的索引记录上添加共享间隙锁,区间为 (10, 20)(S,GAP)
    select * from tbl where c = 10 for share;

    -- 在 c = 10 的索引记录上添加共享 next-key 锁,区间为 (-无穷, 10](S)
    -- 在 c = 20 的索引记录上添加共享间隙锁,区间为 (10, 20)(S,GAP)
    -- 覆盖索引,所以只在字段 c 上加锁
    select a from tbl where c = 10 for share;

    -- 在 c = 10 的索引记录上添加排他 next-key 锁,区间为 (-无穷, 10](X)
    -- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 c = 20 的索引记录上添加排他间隙锁,区间为 (10, 20)(X,GAP)
    update tbl set c = 42 where c = 10;

    -- 在 c = 10 的索引记录上添加排他 next-key 锁,区间为 (-无穷, 10](X)
    -- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 c = 20 的索引记录上添加排他间隙锁,区间为 (10, 20)(X,GAP)
    delete from tbl where c = 10;
    +

    上面的全部 SQL,除了走覆盖索引的 select for share 外,其他的加锁范围都相同。

    +

    加锁与锁冲突 SQL 演示:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    事务1事务2
    mysql> begin;mysql> begin;
    -- 在 c = 10 的索引记录上添加排他 next-key 锁,区间为 (-无穷, 10]
    -- 在 a = 10 的索引记录上添加排他记录锁
    -- 在 c = 20 的索引记录上添加排他间隙锁,区间为 (10, 20)
    mysql> select * from tbl where c = 10 for update;
    -- 阻塞,因为 c = 10 上存在排他 next-key 锁
    mysql> select * from tbl where c = 10 for update;
    -- 阻塞,因为 a = 10 上存在排他记录锁
    mysql> select * from tbl where a = 10 for update;
    -- 阻塞,因为 c = 10 上存在排他 next-key 锁,区间为 (-无穷, 10]
    mysql> insert into tbl (a, c) values (1, 9);
    -- 阻塞,因为 c = 10 上存在排他 next-key 锁,区间为 (-无穷, 10]
    mysql> insert into tbl (a, c) values (1, 10);
    -- 阻塞,因为 c = (10, 20) 区间存在间隙锁
    mysql> insert into tbl (a, c) values (1, 11);
    -- 插入成功
    mysql> insert into tbl (a, c) values (1, 21);
    mysql> rollback;mysql> rollback;
    +

    (a4) 无索引的等值查询

    +

    SQL 语句的加锁情况(通过查 data_locks 表确认):

    +
    -- 在 a 主键的全部索引记录上添加排他 next-key 锁
    select * from tbl where d = 10 for update;
    +

    因为字段 d 上没有索引,这个 SQL 语句,只能在聚簇索引上全表扫描。加锁情况,在 a 主键的全部索引记录上添加排他 next-key 锁。表 tbl 共 10 条记录,全部的持有的 next-key 锁的锁区间,如下:

    +
    (-无穷, 10]
    (10, 20]
    (20, 30]
    (30, 40]
    (40, 50]
    (50, 60]
    (60, 70]
    (70, 80]
    (80, 90]
    (90, 100]
    (100, +无穷]
    +

    (a5) 值不存在的等值查询

    +

    SQL 语句的加锁情况(通过查 data_locks 表确认):

    +
    ---- 主键索引上的值不存在的等值查询
    -- 在 a = 100 的索引记录上添加排他间隙锁,区间为 (90, 100)(X,GAP)
    select * from tbl where a = 95 for update;
    -- 在 a 的索引记录上添加排他 next-key 锁,区间为 (100, +无穷](X)
    select * from tbl where a = 105 for update;

    ---- 唯一索引上的值不存在的等值查询
    -- 在 b = 100 的索引记录上添加间隙锁,区间为 (90, 100)(X,GAP)
    select * from tbl where b = 95 for update;
    -- 在 b 的索引记录上添加排他 next-key 锁,区间为 (100, +无穷](X)
    select * from tbl where b = 105 for update;

    ---- 非唯一索引上的值不存在的等值查询
    -- 在 c = 100 的索引记录上添加间隙锁,区间为 (90, 100)
    select * from tbl where c = 95 for update;
    -- 在 c 的索引记录上添加排他 next-key 锁,区间为 (100, +无穷](X)
    select * from tbl where c = 105 for update;
    +

    (b1) 主键索引上的范围查询

    +

    SQL 语句的加锁情况(通过查 data_locks 表确认):

    +
    -- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 a = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)
    -- 在 a 的索引记录上添加排他 next-key 锁,区间为 (100, +无穷](X)
    select * from tbl where a >= 90 for update;

    -- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 a 的索引记录上添加排他 next-key 锁,区间为 (100, +无穷](X)
    select * from tbl where a >= 100 for update;

    -- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 a = 100 的索引记录上添加排他间隙锁,区间为 (90, 100)(X,GAP)
    -- 附注:与主键上的等值查询 `a = 90` 的加锁范围的区别是额外加了区间为 (90, 100) 间隙锁
    select * from tbl where a >= 90 and a < 91 for update;

    -- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 a = 100 的索引记录上添加排他间隙锁,区间为 (90, 100)(X,GAP)
    -- 附注:与相同查询条件的 `select for update`,加锁范围相同
    update tbl set d = 42 where a >= 90 and a < 91;

    -- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 a = 100 的索引记录上添加排他间隙锁,区间为 (90, 100)(X,GAP)
    -- 附注:与相同查询条件的 `select for update` 的 SQL,加锁范围相同
    delete from tbl where a >= 90 and a < 91;
    +

    (b2) 唯一索引上的范围查询

    +

    SQL 语句的加锁情况(通过查 data_locks 表确认):

    +
    -- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
    -- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)
    -- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 b 的索引记录上添加排他 next-key 锁,区间为 (100, +无穷](X)
    select * from tbl where b >= 90 for update;

    -- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
    -- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)(不必要的记录锁)
    select * from tbl where b >= 90 and b < 91 for update;

    -- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
    -- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)(不必要的记录锁)
    -- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)(不必要的记录锁)
    update tbl set d = 42 where b >= 90 and b < 91;

    -- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
    -- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)(不必要的记录锁)
    -- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)(不必要的记录锁)
    delete from tbl where b >= 90 and b < 91;
    +

    加锁与锁冲突 SQL 演示:

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    事务1事务2
    mysql> begin;mysql> begin;
    -- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90]
    -- 在 a = 90 的索引记录上添加排他记录锁
    -- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100]
    mysql> select * from tbl where b >= 90 and b < 91 for update;
    -- 阻塞,因为 b = 90 上存在排他 next-key 锁
    mysql> select * from tbl where b = 90 for update;
    -- 阻塞,因为 b = 100 上存在排他 next-key 锁(不必要的记录锁)
    mysql> select * from tbl where b = 100 for update;
    -- 阻塞,因为 a = 90 上存在排他记录锁
    mysql> select * from tbl where a = 90 for update;
    mysql> rollback;mysql> rollback;
    +

    (b3) 非唯一索引上的范围查询

    +

    SQL 语句的加锁情况(通过查 data_locks 表确认):

    +
    -- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
    -- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)
    -- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 b 的索引记录上添加排他 next-key 锁,区间为 (100, +无穷](X)
    select * from tbl where c >= 90 for update;

    -- 在 c = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
    -- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 c = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)(不必要的记录锁)
    select * from tbl where c >= 90 and c < 91 for update;

    -- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
    -- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)(不必要的记录锁)
    -- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)(不必要的记录锁)
    update tbl set d = 42 where c >= 90 and c < 91;

    -- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
    -- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)(不必要的记录锁)
    -- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)(不必要的记录锁)
    delete from tbl where c >= 90 and c < 91;
    +

    对比,唯一索引上的范围查询的加锁情况,容易得出结论,唯一索引和普通索引上的范围查询的加锁规则相同

    +

    RC 隔离级别

    +

    把事务隔离级别修改为已提交读(Read Committed):

    +
    -- 事务隔离级别,修改为已提交读(Read Committed)
    mysql> set @@transaction_isolation = 'READ-COMMITTED';
    +

    (a1) 主键索引上的等值查询

    +

    SQL 语句的加锁情况(通过查 data_locks 表确认):

    +
    -- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    select * from tbl where a = 10 for update;

    -- 在 a = 10 的索引记录上添加共享记录锁(S,REC_NOT_GAP)
    select * from tbl where a = 10 for share;

    -- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    update tbl set b = 42 where a = 10;

    -- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    delete from tbl where a = 10;
    +

    结论:因为主键索引上的等值查询不涉及间隙锁,所以 RR 和 RC 隔离级别下的加锁规则相同。

    +

    (a2) 唯一索引上的等值查询

    +

    同样的,因为唯一索引上的等值查询不涉及间隙锁,所以 RR 和 RC 隔离级别下的加锁规则相同。

    +

    (a3) 非唯一索引上的等值查询

    +
    -- 在 c = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    select * from tbl where c = 10 for update;

    -- 在 c = 10 的索引记录上添加排他记录锁(S,REC_NOT_GAP)
    -- 在 a = 10 的索引记录上添加排他记录锁(S,REC_NOT_GAP)
    select * from tbl where c = 10 for share;

    -- 在 c = 10 的索引记录上添加排他记录锁(S,REC_NOT_GAP)
    -- 覆盖索引,所以只在字段 b 上加锁
    select a from tbl where c = 10 for share;

    -- 在 c = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    update tbl set c = 42 where c = 10;

    -- 在 c = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    delete from tbl where c = 10;
    +

    (a4) 无索引的等值查询

    +
    -- 在 a = 10 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    select * from tbl where d = 10 for update;
    +

    (a5) 值不存在的等值查询

    +
    ---- 主键索引上的值不存在的等值查询
    -- 无锁
    select * from tbl where a = 95 for update;
    -- 无锁
    select * from tbl where a = 105 for update;

    ---- 唯一索引上的值不存在的等值查询
    -- 无锁
    select * from tbl where b = 95 for update;
    -- 无锁
    select * from tbl where b = 105 for update;

    ---- 非唯一索引上的值不存在的等值查询
    -- 无锁
    select * from tbl where c = 95 for update;
    -- 无锁
    select * from tbl where c = 105 for update;
    +

    (b1) 主键索引上的范围查询

    +
    -- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    select * from tbl where a >= 90 for update;

    -- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    select * from tbl where a >= 90 and a < 91 for update;

    -- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    update tbl set d = 42 where a >= 90 and a < 91;

    -- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    delete from tbl where a >= 90 and a < 91;
    +

    (b2) 唯一索引上的范围查询

    +
    -- 在 b = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 b = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 a = 100 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    select * from tbl where b >= 90 for update;

    -- 在 b = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    select * from tbl where b >= 90 and b < 91 for update;

    -- 在 b = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    update tbl set d = 42 where b >= 90 and b < 91;

    -- 在 b = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    delete from tbl where b >= 90 and b < 91;
    +

    (b3) 非唯一索引上的范围查询

    +

    加锁情况,和 RC 隔离级别的唯一索引上的范围查询完全相同。

    +

    行锁加锁规则总结

    +

    RC 隔离级别时的加锁规则:

    +
      +
    • 间隙锁被禁用,只有记录锁,没有间隙锁和 next-key 锁。
    • +
    • 对全部满足查询条件的索引记录加记录锁。如果查询条件满足覆盖索引,就只对辅助索引加记录锁。如果需要回表,对辅助索引记录和聚簇索引记录引同时加锁。
    • +
    • 如果不存在满足查询条件的索引记录,就不加锁。
    • +
    +

    RR 隔离级别时的加锁规则:

    +
      +
    • 加锁的基本单位是 next-key 锁。
    • +
    • 对全部满足查询条件的索引记录加 next-key 锁。如果查询条件满足覆盖索引,就只对辅助索引加记录锁。如果需要回表,对辅助索引记录和聚簇索引记录引同时加锁。
    • +
    • 范围查询时,或值不存在的等值查询时,在从右扫描到的最后的不满足查询条件的记录上加间隙锁。如果索引的最大记录值,满足查询条件,则在上界伪记录(supremum pseudo-record)上加 next-key 锁(相当于间隙锁)。
    • +
    • 等值查询时,在主键索引和唯一索引上加锁,next-key 锁退化为记录锁。
    • +
    +

    范围查询时的不必要加锁 bug

    +

    注意,RR 隔离级别时,在主键索引上的范围查询时,确实是按上文的规则加间隙锁。但实际验证发现,在辅助索引(包括唯一索引和普通索引)上的范围查询时,在最后的不满足查询条件的记录上实际加的是 next-key 锁。这样加锁的问题是,会在不满足查询条件的记录上记录锁,这个记录锁其实是不必要的,是一个 bug。

    +

    其实,这个不必要的记录锁 bug,在 MySQL 8.0.18 之前,主键索引的场景下也存在,MySQL 8.0.18 修复了,但只修复了主键索引的场景,辅助索引的场景未修复。修复对应 bug 为“Bug #29508068 UNNECESSARY NEXT-KEY LOCK TAKEN”,修复提交记录见 github

    +

    在 MySQL 8.0.19 版本上,有人再次提了 bug,“Bug #98639 Redundant row-level locking for secondary index”。不过 MySQL 官方认为“Not a Bug”。然后,提 bug 的人,也只好妥协认为这个是“performance issue”。

    +

    对比下面这 3 个 SQL 的加锁情况,可以发现后 2 个 SQL 存在不必要的加锁问题。

    +
    -- 主键索引上的范围查询
    -- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 a = 100 的索引记录上添加排他间隙锁,区间为 (90, 100)(X,GAP)
    select * from tbl where a >= 90 and a < 91 for update;

    -- 唯一索引上的范围查询
    -- 在 b = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
    -- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 b = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)(不必要的记录锁)
    select * from tbl where b >= 90 and b < 91 for update;

    -- 非唯一索引上的范围查询
    -- 在 c = 90 的索引记录上添加排他 next-key 锁,区间为 (80, 90](X)
    -- 在 a = 90 的索引记录上添加排他记录锁(X,REC_NOT_GAP)
    -- 在 c = 100 的索引记录上添加排他 next-key 锁,区间为 (90, 100](X)(不必要的记录锁)
    select * from tbl where c >= 90 and c < 91 for update;
    +

    隔离级别的实现

    +

    上文提到,PostgreSQL 的并发控制技术是以 MVCC 技术为主,封锁技术为辅。先看下 PostgreSQL 对隔离级别的实现 [doc]:

    +
      +
    • PostgreSQL 支持 SQL 标准的 4 种隔离级别,默认的隔离级别是 RC。但 PostgreSQL 内部只实现 3 种隔离级别 RC、RR 和 SER。若选择 RU 隔离,实际上是 RC。
    • +
    • PostgreSQL 的 RR 隔离级别,底层是基于 MVCC 技术实现的快照隔离(SI,Snapshot Isolation)。快照隔离下,能避免 SQL-92 定义的三种异常,脏读、不可重复读和幻读异常,但是可能会出现写偏序(Write Skew)异常。
    • +
    • PostgreSQL 的 SER 隔离,底层是可串行化的快照隔离(SSI,Serializable Snapshot Isolation)。
    • +
    +

    InnoDB 的并发控制以封锁技术为主,MVCC 技术辅助,各个隔离级别的具体实现是:

    +
      +
    • RC 隔离级别:快照读 + 写长锁 +
        +
      • 快照读,能避免脏读
      • +
      +
    • +
    • RR 隔离级别:快照读 + 写长锁 + 间隙锁(没有实现真正的快照隔离 SI) +
        +
      • 快照读,能一定程度避免不可重复读和幻读异常,但因为 InnoDB 的刷新快照的特殊实现,不能完全避免
      • +
      • 间隙锁,能避免幻读异常,只有锁定读时才会申请获取间隙锁
      • +
      +
    • +
    • 可串行化隔离级别:读长锁 + 写长锁 + 间隙锁 +
        +
      • 完全基于锁实现串行化,并发度很低,性能不好
      • +
      +
    • +
    +

    InnoDB 实现的 MVCC 技术,能让事务以快照读的方式执行查询。快照读snapshot read),或者叫一致性非锁定读(consistent nonlocking read),或者一致性读(consistent read),即使用多版本技术实现的读取数据在某个时间点的快照的查询。在 RR 和 RC 隔离级别下,一致性读是普通的 select 语句的默认模式。快照读避免加锁,从而提高并发度。在 RR 和 RC 隔离级别下快照读的区别:

    +
      +
    • RR 隔离级别时,事务中的所有一致性读都会读取该事务中第一次此类读取建立的快照。
    • +
    • RC 隔离级别时,事务中的每个一致性读都会设置并读取其自己的最新快照,快照是最新已提交的数据。
    • +
    +

    如果事务在查询数据后,要对该数据做修改操作,快照读无法提供足够的保护,因为其他事务可以对这些数据做修改操作。为了提供额外的保护,InnoDB 提供锁定读locking read),即同时执行锁定操作的 select 语句,锁持有直到事务结束。锁定读分两种:

    +
      +
    • select ... for share 是加共享锁的查询数据
    • +
    • select ... for update 是加排他锁的查询数据
    • +
    +

    RR 隔离级别下的不可重复读和幻读异常

    +

    上文提到,“快照读,能一定程度避免不可重复读和幻读异常,但因为 InnoDB 的刷新快照的特殊实现,不能完全避免”。现在来看下 RR 隔离级别下的不可重复读异常的示例:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    事务1事务2
    mysql> begin;mysql> begin;
    -- 返回值为 10,快照读
    mysql> select b from tbl where a = 10;
    -- 把 b 值修改为 0
    mysql> update tbl set b = 0 where a = 10;
    mysql> commit;
    -- 返回值为 10,没有出现不可重复读异常
    mysql> select b from tbl where a = 10;
    -- update 会读取 a = 10 的已提交的最新值
    -- 同时 a = 10 记录的快照会被刷新
    mysql> update tbl set b = b + 1 where a = 10;
    -- 返回值为 1,出现不可重复读异常
    mysql> select b from tbl where a = 10;
    +

    这个问题在 MySQL 的 Bug 系统中可以找到,参见:Bug #57973、Bug #63870 等。官方认为,这不是 Bug,InnoDB 就是按这种方式设计。Bug #57973 下 MySQL 工程师 Kevin Lewis 对这个问题的解答 [ref]:

    +
    +

    [16 Aug 2013 19:23] Kevin Lewis
    +Rejecting this bug because InnoDB is working as designed for the following reason;
    +...
    +But when InnoDB Repeatable Read transactions modify the database, it is possible to get phantom reads added into the static view of the database, just as the ANSI description allows. Moreover, InnoDB relaxes the ANSI description for Repeatable Read isolation in that it will also allow non-repeatable reads during an UPDATE or DELETE. Specifically, it will write to newly committed records within its read view. And because of gap locking, it will actually wait on other transactions that have pending records that may become committed within its read view. So not only is an UPDATE or DELETE affected by pending or newly committed records that satisfy the predicate, but also 'SELECT … LOCK IN SHARE MODE' and 'SELECT … FOR UPDATE'.
    +This WRITE COMMITTED implementation of REPEATABLE READ is not typical of any other database that I am aware of. But it has some real advantages over a standard 'Snapshot' isolation. When an update conflict would occur in other database engines that implement a snapshot isolation for Repeatable Read, an error message would typically say that you need to restart your transaction in order to see the current data. So the normal activity would be to restart the entire transaction and do the same changes over again. But InnoDB allows you to just keep going with the current transaction by waiting on other records which might join your view of the data and including them on the fly when the UPDATE or DELETE is done. This WRITE COMMITTED implementation combined with implicit record and gap locking actually adds a serializable component to Repeatable Read isolation.

    +
    +

    就是说,InnoDB 实现的 RR 隔离级别,放松了 SQL 标准对 RR 隔离级别的要求。事务 T1 在快照读后,如果其他事务 T2 修改了快照对应的记录并提交,之后事务 T1 执行涉及快照的 DML 语句(update、delete、insert)或锁定读,会触发快照刷新,事务 T2 最新提交的修改会刷新进快照。最终导致事务 T1 再次执行相同条件的快照读,读取结果不同,出现不可重复读或幻读异常。简单概括就是,在快照失效后,又刷新快照,导致两次读到的快照不同。另外,如果实现上选择不刷新快照,并且事务 T1 正常执行,会出现 P4 丢失更新异常。

    +

    不可重复读异常的避免(一定程度上避免,但没有完全避免):

    +
      +
    • 如果事务重复的两次读都是快照读(普通 select 语句),并且中间没有执行涉及快照的 DML 或锁定读,这样两次读到的是相同的快照读,所以不会出现不可重复读异常。
    • +
    • 如果事务重复的两次读都是当前读(select for update/share),因为第一次加锁,其他事务无法更新该记录,所以也不会出现不可重复读异常。
    • +
    • 如果事务重复的两次读都是快照读,但是中间执行涉及快照的 DML 或锁定读,触发了快照刷新,如果快照被更新,就会出现不可重复读异常。
    • +
    +

    幻读异常的避免(一定程度上避免,但没有完全避免):

    +
      +
    • 如果事务重复的两次读都是快照读(普通 select 语句),并且中间没有执行涉及快照的 DML 或锁定读,这样两次读到的是相同的快照读,所以不会出现幻读异常。
    • +
    • 如果事务重复的两次读都是当前读(select for update/share),因为第一次当前读加间隙锁,其他事务无法插入,被阻塞,所以也不会出现幻读异常。
    • +
    • 如果事务重复的两次读都是快照读,但是中间执行涉及快照的 DML 或锁定读,触发了快照刷新,如果快照被更新,就会出现幻读异常。
    • +
    +

    上述的快照失效的场景,PostgreSQL 的处理方式是,事务会被回滚并报错提示,应用程序收到这个报错,可以尝试重试,重试的事务读到的快照是最新的,这样即避免丢失更新异常,也避免了幻读和不可重复读异常(参见官方文档 doc)。

    +

    参考资料

    +

    MySQL 8.0 Reference Manual

    + +

    其他参考资料:

    + +]]>
    + + MySQL + + + MySQL + 数据库 + InnoDB + + MVCC + +
    + + I/O 多路复用与网络服务器并发策略 + /2023/07/io-multiplexing-network-server/ + 目前主流的网络服务器,网络 I/O 相关的底层最核心的技术都是 I/O 多路复用(I/O Multiplexing),比如 Apache HTTP Server、Nginx、Redis 等。本文尝试解释各种 I/O 模型,包括解释什么是 I/O 多路复用,同时也总结 I/O 多路复用底层的系统调用 select、poll、kqueue 和 epoll 的演进和区别,并编写了使用这些函数的示例代码。另外,本文还总结了各种基于 I/O 多路复用实现的网络服务器的并发策略的三种模式,包括对 Apache HTTP Server、Nginx 和 Redis 等网络服务器的并发策略的具体案例的解析。

    + +

    I/O 模型与多路复用

    +

    类 Unix 系统下的 I/O 操作,默认是阻塞 I/O(Blocking I/O,缩写为 BIO)。比如,当一个进程发出了读操作请求,但没有可访问的数据时,该进程通常会阻塞在内核中,直到出现可以访问的数据为止。然而,进程有时要处理对多个描述符的 I/O 操作,需要在多个文件描述符上阻塞,典型的场景是终端 I/O 和网络 I/O。

    +

    例如,有一个远程登录程序,它要从键盘读入数据然后把这些数据通过套接字发送到一个远程的计算机上。这个程序还需要从和远程终端相连接的套接字上读取数据,并将数据显示于屏幕上。如果进程在读键盘数据时阻塞,它就不能读那些从远程终端发送到屏幕上的数据。这样一来,在来自远程终端的更多数据到达之前,用户就不知道该通过键盘输入些什么,于是,死锁便产生了。相反的,如果进程在读从远程终端送来的数据时阻塞,它将不能读来自键盘终端的数据。

    +

    历史上,Unix 系统通过使用多个进程让应用能同时处理多个文件描述符,这些进程间可以通过管道或者是其他的进程间通信方法进行通信。然而,如果处理上下文切换的代价比处理输入的代价更大,那么这种方法就会导致巨大的系统开销,因为它要求在进程间进行频繁的上下文切换。并且,在一个进程内实现这种应用会显得比较直观。由于上述原因,BSD 提供了三种机制,允许对描述符进行多路 I/O 访问,非阻塞式 I/O、 I/O 多路复用和信号驱动 I/O[1]

    +
      +
    • 非阻塞 I/O(Nonblocking I/O,缩写为 NIO):进程对描述符尝试 I/O 操作,如果描述符未就绪(ready),系统不把本进程投入睡眠,而是返回一个错误(EAGAINEWOULDBLOCK)。进程收到错误后,要么放弃,要么不停地轮询(polling),直至发现有描述符可以进行 I/O 操作为止。这种轮询的方法的问题在于,进程必须连续不断地运行,检查描述符是否就绪,很浪费 CPU 时间。
    • +
    • I/O 多路复用(I/O Multiplexing):让系统提供一种方法在多个感兴趣的描述符中查找哪个描述符可以进行 I/O 操作,如果没有这样的描述符,系统会让进程处于睡眠状态,直到出现这样的描述符为止。这种方法的缺点是对于每个操作,进程要完成两个系统调用,一个用来查找就绪描述符,另一个是 I/O 操作本身。非阻塞 I/O 是在用户空间轮询查找就绪描述符,而 I/O 多路复用是执行特殊的系统调用在内核空间查找就绪描述符。
    • +
    • 信号驱动 I/O(Signal-Driven I/O):当可以进行 I/O 操作时,使所有描述符发信号。进程只用等待这些信号就可以知道是否可以进行 I/O 操作。这种方法的缺点在于捕获这些信号的开销是巨大的,所以此方法对于那些涉及大量 I/O 操作的应用并不实用。
    • +
    +

    类 Unix 系统下,默认的 I/O 操作都是阻塞 I/O。有两种方法可以将描述符设置非阻塞 I/O:(1) 如果是调用 open() 获得描述符,则可以在调用时设置 O_NONBLOCK 标志;(2) 对于已经打开的一个描述符,则可调用 fcntl(),由该函数为描述符设置 O_NONBLOCK 标志。另外,对于网络套接字的描述符,如果想在获得描述符时直接指定为非阻塞 I/O,可以在调用 socket() 或 accept() 时传入 SOCK_NONBLOCK 标志,当然也可以在获得描述符后,再调用 fcntl()修改。

    +

    I/O 多路复用,最早是在 4.2BSD(1983.08)中由 select() 系统调用提供的。虽然该系统调用主要用于终端 I/O 和网络 I/O,但它对其他描述符同样是起作用的。poll() 是另外一个实现 I/O 多路复用的系统调用,和 select() 功能几乎相同。SVR3(1987)在增加 STREAMS 机制时增加了 poll() 系统调用。但在 SVR4 (1988)之前,poll() 只对 STREAMS 设备起作用。SVR4 开始支持对任意描述符起作用的 poll()select()poll() 系统调用,都是在 POSIX.1-2001 开始标准化定义,然而从可移植性角度考虑,支持 select() 的系统比支持 poll() 的系统要多,所以在应用的实现上,相比于 poll() 基于 select() 实现更多。另外 POSIX 还定义了 pselect(),它是能够处理信号阻塞并提供了更高时间分辨率的 select() 的增强版本。

    +

    在 Linux 系统下,poll() 系统调用从 2.1.23 版本(1997.01)开始提供,而 poll() 库函数由 libc 5.4.28(1997.05)开始提供。早期 Linux 内核未提供 poll() 系统调用,glibc 使用 select() 来模拟实现 poll()。另外,Linux 还提供特有的 I/O 多路复用解决方案,即 epoll,详细介绍参见下文。

    +

    为了能持续不断的监听 I/O 操作就绪事件,应用实现上需要循环调用 select()poll()。为了方便使用,封装各个不同的 I/O 多路复用函数的第三方库,通常会把这样的循环调用被抽象为事件循环(event loop),然后把 I/O 就绪事件的处理抽象成回调函数(callback)。最早的提供事件循环(event loop)抽象的典型的第三方库是 libevent 库(最早在 2002.04 发布)。

    +

    信号驱动 I/O,在描述符就绪时内核会发送 SIGIO 信号。但是信号驱动 I/O 对于 TCP 套接字近乎无用,问题在于 SIGIO 信号产生得过于频繁,并且它的出现并没有告诉我们发生了什么事件,无法区分触发信号的各种情况。在 UDP 上使用信号驱动式 I/O 没有上述问题。关于信号驱动 I/O 的详细阐述,可以参阅《UNIX网络编程 卷1》的第 25 章[2]

    +

    描述符就绪条件

    +

    select()poll() 系统调用是在多个文件描述符中查找就绪(ready)的描述符。就绪条件具体指是什么呢?select()man 文档,有如下描述(poll() 的就绪条件类似,不展开讨论):

    +
    +

    A file descriptor is considered ready if it is possible to perform a corresponding I/O operation (e.g., read(2), or a sufficiently small write(2)) without blocking.
    +...
    +A file descriptor is ready for reading if a read operation will not block; in particular, a file descriptor is also ready on end-of-file.
    +A file descriptor is ready for writing if a write operation will not block. However, even if a file descriptor indicates as writable, a large write may still block.

    +
    +

    针对网络套接字描述符的就绪条件,《UNIX网络编程 卷1》如下总结:

    +套接字描述的就绪条件小结 +

    表中的“有数据可读”含义是,该套接字接收缓冲区中的数据字节数大于等于套接字接收缓冲区低水位标记的当前大小。对这样的套接字执行读操作不会阻塞并将返回一个大于 0 的值(也就是返回准备好读入的数据)。接收低水位标记,可以通过调用 setsockopt() 的 SO_RCVLOWAT 选项来设置,默认值为 1。

    +

    表中的“有可用于写的空间”含义是,该套接字发送缓冲区中的可用空间字节数大于等于套接字发送缓冲区低水位标记的当前大小,并且或者该套接字已连接,或者该套接字不需要连接(如UDP套接字)。发送低水位标记,可以通过调用 setsockopt() 的 SO_SNDLOWAT 选项来设置,默认值为 1024。

    +

    表中的“关闭连接的读一半”和“关闭连接的写一半”含义是,套接字的 TCP 连接接收了关闭 FIN,此时会收到读就绪事件和写就绪事件。对这样的套接字做读操作将不阻塞并返回 0(也就是返回 EOF);对这样的套接字做写操作将产生 SIGPIPE 信号(Broken pipe: write to pipe with no readers)。

    +

    I/O 模型的比较

    +

    上文阐述的就是 Unix 系统的 4 种 I/O 模型,阻塞 I/O、非阻塞 I/O、I/O 多路复用和信号驱动式 I/O。另外,还有一种 I/O 模型是,异步 I/O(Asynchronous I/O,缩写为 AIO)。异步 I/O,由 POSIX 规范定义,工作机制是,告知内核启动某个操作,并让内核在整个操作(包括将数据从内核复制到我们自己的缓冲区)完成后通知进程。这种模型与信号驱动模型的主要区别在于:信号驱动 I/O 是由内核通知我们何时可以启动一个 I/O 操作,而异步 I/O 模型是由内核通知我们 I/O 操作何时完成。POSIX 定义的异步 I/O 的函数为,aio_write()aio_read() 等。

    +

    关于 POSIX 异步 IO,Linux 的 aio 的 man 文档,有如下说明:

    +
    +

    The current Linux POSIX AIO implementation is provided in user space by glibc. This has a number of limitations, most notably that maintaining multiple threads to perform I/O operations is expensive and scales poorly. Work has been in progress for some time on a kernel state-machine-based implementation of asynchronous I/O (see io_submit(2), io_setup(2), io_cancel(2), io_destroy(2), io_getevents(2)), but this implementation hasn't yet matured to the point where the POSIX AIO implementation can be completely reimplemented using the kernel system calls.

    +
    +

    本质上,Linux 下的 POSIX AIO 是在用户空间下用线程模拟实现的 AIO,并非真正的 AIO,性能很差,所以很少被使用。

    +

    Linux 内核实现的 AIO 是 io_submitio_setupio_getevents 等系统调用,也被成为“Linux Native AIO”,或者缩写为 KAIO(kernel AIO),从 Linux 2.5 开始支持(2001.11),这些系统调用对应的库函数由 libaio 库提供。但是 Linux Native AIO 几乎不可用,只适合以 O_DIRECT 方式做直接 IO(无缓存的 I/O)。如果真的实现了异步 AIO,io_submit 系统调用不应该阻塞,但是对缓存 I/O、网络访问、管道等,io_submit 会发生阻塞,整个操作将在 io_submit 系统调用期间执行,并且通过调用 io_getevents,I/O 操作完成结果可以立即访问,这样也就破坏了异步 I/O 的目的[3]

    +

    最新的内核实现的 AIO 是 io_uring,已经被 Linux 5.1(2019.05)采纳。很多开源项目,比如 libeventlibuvNginxRedis 等,都有打算支持或甚至已经支持 io_uring。io_uring 的杂类资料整理,可以参考“Awesome io_uring”[4]。本文主要关注 I/O 多路复用,io_uring 不再展开讨论。

    +

    《UNIX网络编程 卷1》对这 5 种 I/O 模型做了对比[2:1]

    +5 种 I/O 模型的比较 +

    可以看出,前 4 种模型的主要区别在于第一阶段(等待描述符就绪),因为它们的第二阶段是一样的:在数据从内核复制到调用者的缓冲区期间,进程阻塞于 recvfrom 调用。相反,异步 I/O 模型在这两个阶段都要处理,从而不同于其他 4 种模型。

    +

    各个 I/O 模型,用户空间的应用与内核空间的交互过程如下图所示(信号驱动 I/O 实际场景较少使用,所以忽略)[5]

    + + + + + + + + + + + + + +
    阻塞式 I/O非阻塞式 I/O
    非阻塞式 I/O + I/O 多路复用异步 I/O
    +

    通常对“I/O 多路复用”术语的理解,其实就是特指,由 select() 、poll() 或类似的系统调用实现的在多个文件描述符中查找就绪状态描述符的技术。不过,根据 McKusick 书籍的描述[1:1]I/O 多路复用也可以泛指为,单个进程同时处理多个文件描述符的技术,与之相对立的技术是早期的由多个进程同时处理多个描述符的解决方案。广义理解的话,I/O 多路复用包括非阻塞 I/O、狭义的 I/O 多路复用、信号驱动式 I/O、异步 IO 等技术

    +

    单独的“多路复用(multiplexing)”术语,维基百科的解释是,一个通信和计算机网络领域的专业术语,多路复用通常表示在一个信道上传输多路信号或数据流的过程和技术。

    +

    阻塞、非阻塞与同步、异步的区别

    +

    在概念上,阻塞 I/O 和非阻塞 I/O,是根据系统是否会阻塞进程的执行而区分的:

    +
      +
    • 阻塞 I/O,在执行 I/O 操作后,如果 I/O 操作的描述符未就绪,系统会让进程进入睡眠状态,直到描述符就绪为止。
    • +
    • 非阻塞 I/O,在执行 I/O 操作后,不会阻塞当前进程,可以继续执行其他的任务。
    • +
    +

    另外,POSIX 定义了同步 I/O(Synchronous I/O)和异步 I/O(Asynchronous I/O)两个术语[2:2]

    +
      +
    • 同步 I/O 操作,导致请求进程阻塞,直到 I/O 操作完成
    • +
    • 异步 I/O 操作,不导致请求进程阻塞。
    • +
    +
    +

    A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes.
    +An asynchronous I/O operation does not cause the requesting process to be blocked.

    +
    +

    按照这个定义,阻塞 I/O、非阻塞 I/O、I/O 多路复用和信号驱动 I/O 都是同步 I/O,因为其中真正的 I/O 操作将阻塞进程(第二阶段,将数据从内核复制到用户空间的缓冲区阶段)。只有异步 I/O 模型与 POSIX 定义的异步 I/O 相匹配。

    +

    不过,对于 I/O 多路复用是属于同步 I/O 还是异步 I/O 存在争议,不同视角下存在不同的理解。I/O 多路复用,单看等待 I/O 就绪阶段,其实是异步的。所以很多时候,I/O 多路复用,虽然没有实现真正的 POSIX 定义的异步 I/O,但也被归类为异步 I/O。比如,Jones 的文章[5:1]将 I/O 多路复用归类为阻塞的异步 I/O,将 POSIX AIO 归类为非阻塞的异步 I/O。类似的,封装各个不同的 I/O 多路复用函数的 libevent 库的官方文档[6]自称是“Asynchronous I/O”。Node.js 底层是基于 I/O 多路复用封装的 libuv 库,libuv 库也自称是“Asynchronous I/O”。另外,如果跳出 I/O 视角,从整体应用的执行流程角度看,基于 I/O 多路复用实现的应用,相对于在多个描述符列表上主轮询流程,在单个描述符上 I/O 事件的应用处理流程相对独立,可以认为是异步的。Node.js 文档对“异步”的解释如下[7]

    +
    +

    Asynchronous means that things can happen independently of the main program flow.

    +
    +

    严格意义上,典型的 I/O 多路复用的应用是单进程单线程执行的,本质上都是串行执行的,是假异步。

    +

    服务器并发策略与 C10K 问题

    +

    世界上第一个 HTTP 服务器,CERN httpd,早期实现采用的 I/O 模型是阻塞 I/O,然后为了能同时处理多个客户端连接,会为每个客户端连接创建一个新的处理请求的子进程(process-per-connection),这种并发模式被称为 fork 模式,这也是传统的 Unix 服务器采用的并发模式。之后的版本,改为基于 select() 的 I/O 多路复用 + fork 模式(参见源码 HTDaemon.c)。

    +

    NCSA HTTPd,是早期的第一个流行的 HTTP 服务器,在版本 1.3 以及之前版本,也是采用阻塞 I/O + fork 模式实现,会为每个客户端连接创建一个新的子进程(参见源码 httpd.c)。之后 NCSA HTTPd 的 1.4 版本,I/O 模型改造为基于 select() 的 I/O 多路复用,进程模型改为“pre-forking”模式,但这种模式本质上还是每个客户端连接对应单个子进程(process-per-connection),“pre-forking”的优点是在创建新客户端连接时有预先创建的子进程直接处理请求(类似进程池),避免在创建新连接的同时执行创建子进程这样的重型操作,具体可以参见 1996.03 的官方文档的对“pre-forking”模型的性能测试[8](相关的实现源码参见 httpd.c)。

    +

    Apache HTTP Server,最早在 1995.04 对外公开发布首个版本 0.6.2,这个版本的代码基于 NCSA httpd 1.3[9]。 之后在 5 月和 6 月,Apache 也开始实现“pre-forking”特性,在版本 0.8.0 开始正式支持[9:1][10]。一直到 Apache HTTP Server 2.2,prefork 模式依然是 Unix 系统下的默认模式[11]在 Apache 的 prefork 模式下,每个客户端连接由单独的子进程处理,这样的子进程被 Apache 称为 worker 进程,worker 进程数就是同时处理的客户端连接数。因为线程相对进程更加轻量,理论上每个客户端连接对应单个线程(thread-per-connection)更有优势。所以,在 2002.04,Apache 发布 2.0 的首个 GA 版本时,新增了 worker 模式,一种多进程和多线程混合的模式。在 Apache 的 worker 模式下,每个客户端连接由单独的子线程处理,这样的子线程也就是 worker 线程,worker 线程数就是同时处理的客户端连接数。

    +

    相对单线程,多进程或多线程的问题是,占用更多内存(每个线程都需要维护自己的线程栈),以及频繁的上下文切换。所以,有些 HTTP 服务器倾向于基于 select() 实现单进程单线程的网络服务器。这种模式实现的服务器一般会把循环调用 select() 的过程抽象为事件循环(event loop),把 I/O 操作就绪事件的处理抽象成回调函数(callback),所以也被称为事件驱动服务器(event-driven server)。多核 CPU 时,为了能充分使用 CPU 多核资源,事件驱动服务器的进程数(或线程数)通常为 CPU 核数。事件驱动模式,在软件架构中被也称为 Reactor 模式。基于事件并发和基于线程的并发的比较,可以阅读 John Ousterhout 的 1995 年的经典 slides:“Why Threads Are A Bad Idea (for most purposes)”[12]

    +

    早期的典型的基于 select() 实现的单线程 HTTP 服务器的例子,是由 ACME 实验室开发并开源的 thttpd(1995.11 对外发布 1.0 版)。thttpd 服务器作者 Jef Poskanzer 在文章“Web Server Comparisons”(1998.07)[13]中对比了各个 Web 服务器。根据文章的对比,容易发现基于 select() 实现的单线程服务器,在响应性能和最大并发连接数上都占优,thttpd 支持的最大的每秒请求数 QPS 是 720,thttpd 支持的最大并发连接数是 1000+。

    +

    虽然在实验条件下表现良好,但是在真实场景下,基于 select() 实现的 HTTP 单线程服务器,性能并没有优于传统的基于 fork 模式的服务器[14]。Banga 等人经过分析后得出的主要原因是,当服务器同时处理的客户端连接数超过几千后,系统调用 select()poll() 的性能很差,不具备可伸缩性。

    +

    最早的 HTTP 1.0 协议,在服务响应完成后连接会立即关闭,连接无法保持。HTTP 底层是 TCP 协议,建立 TCP 连接需要经过三次握手的过程。如果能复用 TCP 连接,同一个 HTTP 连接上的后续的 HTTP 请求就不用重新建立 TCP 连接,也就是能在同一个 HTTP 连接上支持多次 HTTP 请求和响应,这样 HTTP 性能也就得到了提高。于是,HTTP 1.1 协议(RFC 2068,1997.01)开始持久连接(persistent connection),默认让 HTTP 连接“keep-alive”。关于 HTTP 持久连接的详细介绍,可以参考 RFC 2068 的“8.1 Persistent Connections”。

    +

    HTTP 协议支持持久连接后,也带来了另外一个问题,就是出现大量的冷链接(cold connection)。浏览器如果未主动关闭连接,停留在网页上,并且如果连接未超时,此时的连接虽然不活跃但会保持一段时间,这样的连接就是冷链接。同时,随着互联网的快速发展,访问网站的用户量不断上升,Web 服务器需要维持的链接数也不断上升,如何让服务支持更多客户端连接问题也愈发尖锐。当时 Web 服务器支持的最大并发连接数大致是 1K,于是 Dan Kegel 在 1999 年提出了 C10k 问题,如何能让服务器支持 10K 的客户端连接,字母“C”代表的是“client connection”。在文章“The C10K problem”[15]中,Dan Kegel 对 C10K 问题的描述如下:

    +
    +

    It's time for web servers to handle ten thousand clients simultaneously, don't you think? After all, the web is a big place now.

    +
    +

    另外,值得一提的是,HTTP 1.0 和 HTTP 1.1 协议存在队头阻塞问题(HOL 阻塞,head of line blocking),为了避免队头阻塞,从而使网页能更快响应,大多数浏览器会为每个域名同时开启多个 HTTP 连接,通常是 6 个并发连接[16],结果导致 Web 服务器需要维持的链接数增加数倍。在发布 HTTP 1.1 协议的十几年后的 2012 年,HTTP 2.0 的首个草稿发布,而制定 HTTP/2 协议的最大的目标之一就是解决队头阻塞问题。

    +

    select 和 poll 性能问题

    +

    当 Web 服务器需要同时处理大量客户端连接时,服务器的性能表现差,原因就出在系统调用 select()poll() 的性能上,具体的问题有如下三点[17]

    +
      +
    • 每次调用 select()poll(),内核都必须检查所有被指定的文件描述符,看它们是否处于就绪状态。随着待检查的文件描述符数量的增加,调用耗时也随之线性增加。若待检查的文件描述符数为 n,select()poll() 的时间复杂度为 O(n)。
    • +
    • 每次调用 select()poll(),程序都必须传递一个表示所有需要被检查的文件描述符的数据结构到内核,内核检查过描述符后,修改这个数据结构并返回给程序。(此外,对于 select() 来说,我们还必须在每次调用前初始化这个数据结构。)随着待检查的文件描述符数量的增加,传递给内核的数据结构大小也会随之增加。当检查大量文件描述符时,从用户空间到内核空间来回拷贝这个数据结构将占用大量的 CPU 时间。
    • +
    • select()poll() 调用完成后,程序必须检查返回的数据结构中的每个元素,以此查明哪个文件描述符处于就绪状态。
    • +
    +

    解决系统调用 select()poll() 的性能问题,让服务器能同时处理大量连接,比较典型的解决方案是,FreeBSD 4.1(2000.07 发布)开始支持的 kqueue 系统调用 ,以及 Linux 2.5.44(2002.10 发布)开始支持的 epoll 系统调用。

    +

    kqueue 和 epoll 系统调用

    +

    kqueue 相关的 API 主要涉及两个系统调用 kqueue()kevent()

    +
      +
    • kqueue():用于在内核空间创建 kqueue 数据结构
    • +
    • kevent(): +
        +
      • 当传入其中的 changelist 等参数时,用于将感兴趣的 kevent 事件对象注册到 kqueuekevent 对象上记录感兴趣文件描述符和事件类型
      • +
      • 当传入其中的 eventlist 等参数时,用于查询就绪的 kevent 事件对象列表
      • +
      +
    • +
    +

    kqueue 的实现原理[18]:调用 kqueue() 创建由内核空间维护 kqueue 实例,kqueue 实例内包含链表,链表上保存全部监听的 kevent 事件对象,kevent 对象上感兴趣的记录文件描述符和事件类型。通过 kevent() 系统调用,可以在链表上注册、删除某 kevent 对象。当设备 I/O 事件触发时,设备与 kqueue 实例关联的钩子函数(hook)会被执行,钩子函数会判断事件是否与监听的事件相符合,如果符合就把事件添加到 kqueue 实例内下链表 active list 的末尾。查询就绪事件列表时,调用 kevent(),内核只需要检查链表 active list 是否有元素,若有就把就绪事件列表拷贝到用户空间。

    +

    epoll 相关的 API 主要涉及三个系统调用 epoll_create()epoll_ctl()epoll_wait()

    +
      +
    • epoll_create():用于在内核空间创建 epoll 实例
    • +
    • epoll_ctl():用于添加感兴趣的 epoll_event 事件对象到 epoll 实例,epoll_event 对象上记录感兴趣文件描述符和事件类型
    • +
    • epoll_wait():用于查询就绪的 epoll_event 事件对象列表
    • +
    +

    epoll 的实现原理:调用 epoll_create() 创建由内核空间维护的 epoll 实例,epoll 实例内包含红黑树,红黑树上保存全部监听的 epoll_event 事件对象,epoll_event 对象上记录感兴趣的文件描述符和事件类型。通过 epoll_ctl() 系统调用,可以在红黑树上注册、删除某 epoll_event 对象。所有添加到红黑树中的事件都会与设备驱动程序建立回调关系,当 I/O 就绪事件触发时,会把事件添加到 epoll 实例内的链表 rdllist。查询就绪事件列表时,调用 epoll_wait(),内核只需要检查链表 rdllist 是否有元素,若有就把就绪事件列表拷贝到用户空间。

    +

    水平触发和边缘触发

    +

    epoll 系统调用的事件通知模式,区分水平触发(level-triggered,LT)和边缘触发(edge-triggered,ET),默认通知模式是水平触发 LT,EPOLLET 标志可以将通知模式改为边缘触发。poll()select() 所提供的通知模式是水平触发,不支持边缘触发。水平触发和边缘触发的通知模式的含义如下[17:1]

    +
      +
    • 水平触发通知模式:如果文件描述符上可以非阻塞地执行 I/O 系统调用,此时认为它已经就绪。水平触发模式下,应用程序可以不立即处理该事件,当应用程序下一次调用 epoll_wait() 时,epoll_wait() 还会再次向应用程序通告此事件,直到该事件被处理。这种模式下 epoll 相当于一个效率较高的 poll。
    • +
    • 边缘触发通知模式:如果文件描述符自上次状态检查以来有了新的 I/O 事件,此时需要触发通知。也就是说,当 epoll_wait() 检测到某 I/O 事件发生并将此事件通知应用程序后,后续的 epoll_wait() 调用将不再向应用程序通知这一事件,只通知新的 I/O 事件。边缘触发模式在很大程度上降低了同一个 epoll 事件被重复触发的次数,因此效率要比水平触发模式高。但是相对水平触发,边缘触发模式下开发难度更大。
    • +
    +

    “水平触发”和“边缘触发”术语源于电子工程领域。水平触发是只要有状态发生就触发。边缘触发是只有在状态改变的时候才会发生。条件触发关心的是事件状态,边缘触发关心的是事件本身。

    +

    采用边缘触发通知的程序通常要按照如下规则来设计:

    +
      +
    • 在接收到一个 I/O 事件通知后,程序在某个时刻应该在相应的文件描述符上尽可能多地执行 I/O(比如尽可能多地读取字节)。如果程序没这么做,那么就可能失去执行 I/O 的机会。
    • +
    • 如果尽可能多地执行 I/O,而文件描述符被设置为阻塞模式,那么最终当没有更多的 I/O 可执行时,I/O 系统调用就会阻塞。所以,每个被检查的文件描述符通常都应该设置为非阻塞模式。
    • +
    +

    另外,在边缘触发 ET 模式下,如果多个线程同时监听相同的描述符,只会有一个线程被唤醒用来处理 I/O 事件。epoll 的 man 文档对这个特性有如下描述,这个特性也避免了“惊群问题”(thundering herd problem)。

    +
    +

    If multiple threads (or processes, if child processes have inherited the epoll file descriptor across fork(2)) are blocked in epoll_wait(2) waiting on the same epoll file descriptor and a file descriptor in the interest list that is marked for edge-triggered (EPOLLET) notification becomes ready, just one of the threads (or processes) is awoken from epoll_wait(2). This provides a useful optimization for avoiding "thundering herd" wake-ups in some scenarios.

    +
    +

    因此,边缘触发通知模式其中一个适用的场景是,多核 CPU 上的多线程服务器,每个 CPU 核上运行一个线程,这些线程同时监听相同的描述符[19]

    +

    kqueue 文档没有使用水平触发和边缘触发术语。但接口效果上,默认是水平触发。开启EV_CLEAR标志可以达到类似边缘触发的效果。EV_CLEAR 标志的 man 文档描述:

    +
    +

    After the event is retrieved by the user, its state is reset.

    +
    +

    因为边缘触发通知模式效率更高,Nginx 服务器采用的就是边缘触发,参见源码 ngx_epoll_module.cngx_kqueue_module.c

    +

    select、poll、kqueue 和 epoll 的比较

    +

    selectpollkqueueepoll 系统调用的多个维度的对比总结,如下表:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    系统调用selectpollkqueueepoll
    类 Unix 系统的支持情况POSIX 标准。最早 4.2BSD 提供(1983)POSIX 标准。最早 SVR3 提供(1987)BSD 专有。最早 FreeBSD 4.1 提供 (2000.08)Linux 专有。最早 Linux 2.5.44 提供(2002.10)
    查询就绪描述符的时间复杂度O(n)O(n)O(1)O(1)
    感兴趣描述符列表传递每次 select() 都全量拷贝到内核空间每次 poll() 都全量拷贝到内核空间由内核空间维护由内核空间维护
    就绪描述符列表的返回只返回就绪描述符数量,需要检查感兴趣描述符列表来判断哪些是就绪描述符只返回就绪描述符数量,需要检查感兴趣描述符列表来判断哪些是就绪描述符返回就绪事件数量,并同时返回就绪事件列表返回就绪事件数量,并同时返回就绪事件列表
    最大描述符数被常数 FD_SETSIZE 限制(值为 1024)无限制无限制无限制
    触发通知模式水平水平水平和边缘水平和边缘
    +

    附注:查询就绪描述符的时间复杂度,selectpoll 都是 O(n),n 为感兴趣描述符的总数,因为内核实现上需要轮询全部感兴趣的描述符列表。kqueueepoll 都是 O(1),实际的查询耗时与就绪描述符总数线性有关,但真实场景下就绪描述符数量相对描述符总数很小,可以认为是常数,所以复杂度是 O(1)。

    +

    总体上,selectpoll 之间大同小异,而 kqueueepoll 之间也是大同小异。

    +

    libevent 库,对系统调用 selectpollkqueueepoll 做了性能基准测试,如下图所示(图片来源)。基准测试声明了大量连接(文件描述符),大多数连接是冷的,只有少数是活跃的。测试衡量的是,在不同的总连接数下,为 100 个活动连接提供服务所需的时间。可以看到,系统调用 selectpoll,随着文件描述符的增加,耗时也随之线性增加,2500 个文件描述符时耗时大约 20ms,5000 个文件描述符时耗时大约 40ms,10000 个文件描述符时耗时大约 80ms。而系统调用 kqueueepoll,耗时始终在 3ms ~ 5ms 之间。

    +性能基准测试:select vs poll vs kqueue vs epoll +

    echo 服务的简单示例代码

    +

    上文总结了 selectpollkqueueepoll 的接口特性和实现原理,但对具体应该如何使用这些函数没有切身感受。笔者使用 I/O 多路复用函数 select、poll、epoll 和 kqueue 以及 libevent 库,各自编写了 echo 服务的简单示例代码。所谓 echo 服务,即服务端接收到客户端的字符串输入,然后响应相同的字符串(为了方便区分响应字符串加了 > 前缀)。比如,如果客户端输入字符串 hello,服务端将响应字符串 > hello;如果客户端输入字符串 world,服务端将响应字符串 > world。完整的示例代码参见 io-multiplexing-demo

    +

    Nginx 服务器的并发策略解析

    +

    上文介绍了 NCSA HTTPd、Apache HTTP Server 和 thttpd 等 Web 服务器的并发策略。主要的并发策略有三种模式:单连接单进程模式、单连接单线程模式和单线程的事件驱动模式。

    +

    Nginx 最早是 2002 年开始开发的,2004.08 采用 BSD 协议对外开源首个版本 0.1.0,开发 Nginx 的目的是为了解决 C10k 问题[20]。2002 年,当时 FreeBSD 已经提供 kqueue 系统调用,而 Linux 的 epoll 即将正式发布,新的 kqueueepoll 系统调用让 Nginx 解决 C10k 问题成为可能。根据 w3techs 的统计,在 2013.07 Nginx 超越 Apache 成为 top 1000 网站使用最多的 Web 服务器[21]

    +

    Nginx 采用的是事件驱动架构,在单线程的进程上执行事件循环,以异步非阻塞的方式处理 I/O 操作事件,事件循环底层基于高效的 epollkqueue 实现的 I/O 多路复用[22]

    +

    Nginx 服务器,区分 Master 进程和 Worker 进程。Master 进程,用于加载配置文件、启动 Worker 进程和平滑升级等。Worker 进程,是单线程的进程,用于执行事件循环,并以非阻塞方式处理 I/O 操作,因此单个 Worker 进程就能并发处理大量连接。一个完整的请求完全由 Worker 进程来处理,而且只在一个 Worker 进程中处理。为了能充分利用多核 CPU 资源,通常生产环境配置的 Worker 进程数量等于 CPU 核心数。Nginx 的架构图如下[22:1]

    +Nginx 架构图 +

    Redis 服务器的并发策略解析

    +

    Redis 是内存数据库,处理网络请求也是采用单线程的事件驱动模式,底层基于高效的 epollkqueue 实现的 I/O 多路复用。事件循环处理的事件主要有,建立客户端新连接事件、客户端连接的缓冲区可读事件、客户端连接的缓冲区可写事件。Redis 的命令处理过程如下:

    +
      +
    • 在收到建立客户端新连接事件后,会在新建立的客户端套接字上监听可读事件,用于等待客户端发起命令请求。客户端连接可能会一直保持,处理之后的多个客户端命令请求。
    • +
    • 如果监听到客户端连接的缓冲区可读事件,也就是收到客户端的命令请求,服务器会读取命令、解析命令,然后执行命令,最后把命令响应结果输出到内存缓冲区。值得注意的是,命令响应结果输出到内存缓冲区,但并未输出客户端连接的缓冲区。
    • +
    • 在等到开启新的事件循环时,Redis 会在等待接收新的 I/O 事件之前,统一将全部内存缓冲区的命令响应结果输出到各个客户端。当命令响应结果数据量非常大时,无法一次性将所有数据都发送给某客户端,这时就会监听该客户端缓冲区可写事件。
    • +
    • 如果监听到客户端连接的缓冲区可写事件,Redis 就会发送剩余部分的数据给客户端。
    • +
    +

    上述的命令处理过程,在源码层面上涉及的核心代码都在 networking.c 中:处理客户端新连接建立的事件的回调函数是 acceptTcpHandler,处理客户端命令请求事件的回调函数 readQueryFromClient,命令响应结果输出到各个客户端对应的函数是 handleClientsWithPendingWrites,处理客户端的可写事件的回调函数是 sendReplyToClient。更详细的实现原理解析,本文不再展开,可以自行深入阅读相关源代码或书籍资料。

    +

    Redis 与 Nginx 在并发策略上有不同的选择,Nginx 有多个 Worker 进程,每个 Worker 进程都运行自己的事件循环,而 Redis 整体上只有一个事件循环,采用的是单线程架构。这样的架构设计带来的问题就是 Redis 无法多核 CPU 并发。针对无法多核 CPU 并发问题,Redis 官方 FAQ 的推荐的解决方案是[23]:在多核 CPU 的单台机器上启动多个 Redis 实例。Redis 作者 antirez,解释了选择单线程而不选择多线程的原因,主要是:在 Redis 的数据结构上实现并发控制太复杂,多线程编程降低开发速度并且导致 bug 修复困难[24][25]。采用单线程的原因,概况成一句话就是[25:1]

    +
    +

    There is less to gain, and a lot of complexity to add.

    +
    +

    不过,随着 Redis 版本的演进,部分逻辑已经改成了多线程实现,Redis 新增的多线程特性有三处,Redis 2.4 新增的异步磁盘 IO、Redis 4.0 新增的“Lazy Freeing”和 Redis 6.0 新增的“Threaded I/O”。但整体设计上,还是可以认为 Redis 主要使用单线程设计,依然是单线程的事件循环,并以单线程的方式执行命令(绝大多数命令,“Lazy Freeing”相关的命令除外)[26][27]

    +

    参考资料

    +
    +
    +
      +
    1. FreeBSD操作系统设计与实现,McKusick,2004:6.4.5 描述符上的多路I/O操作 ↩︎ ↩︎

      +
    2. +
    3. Unix网络编程 卷1:套接字联网API,Stevens,第3版2003 ↩︎ ↩︎ ↩︎

      +
    4. +
    5. 2014-04 AIO User Guide: A description of how to use AIO https://web.archive.org/web/0/http://code.google.com/p/kernel/wiki/AIOUserGuide ↩︎

      +
    6. +
    7. Awesome io_uring https://github.com/espoal/awesome-iouring ↩︎

      +
    8. +
    9. 2006-08 M. Jones: Boost application performance using asynchronous I/O https://developer.ibm.com/articles/l-async/ ↩︎ ↩︎

      +
    10. +
    11. Learning Libevent: A tiny introduction to asynchronous IO https://libevent.org/libevent-book/01_intro.html ↩︎

      +
    12. +
    13. Node.js: JavaScript Asynchronous Programming and Callbacks https://nodejs.dev/en/learn/javascript-asynchronous-programming-and-callbacks/ ↩︎

      +
    14. +
    15. 1995-04 NCSA httpd: Performance of Several HTTP Demons on an HP 735 Workstation https://web.archive.org/web/0/http://www.ncsa.uiuc.edu/InformationServers/Performance/V1.4/report.html ↩︎

      +
    16. +
    17. About the Apache HTTP Server Project https://httpd.apache.org/ABOUT_APACHE.html ↩︎ ↩︎

      +
    18. +
    19. Changes with Apache (12 Jun 1995: This release included modified versions of a lot of code from the Apache 0.6.4 public release, plus an early pre-forking patch codeveloped by Robert Thau and Rob Hartill.) https://github.com/apache/httpd/blob/1.3.x/src/CHANGES#L9427 ↩︎

      +
    20. +
    21. Apache HTTP Server Version 2.2: Multi-Processing Modules (MPMs) https://httpd.apache.org/docs/2.2/en/mpm.html#defaults ↩︎

      +
    22. +
    23. 1995 John Ousterhout: Why Threads Are A Bad Idea (for most purposes) (slides) http://www.cc.gatech.edu/classes/AY2010/cs4210_fall/papers/ousterhout-threads.pdf ↩︎

      +
    24. +
    25. 1998-07 Jef Poskanzer: Web Server Comparisons(thttpd 服务器作者) http://www.acme.com/software/thttpd/benchmarks.html ↩︎

      +
    26. +
    27. 1998 Gaurav Banga, Jeffrey C. Mogul: Scalable Kernel Performance for Internet Servers Under Realistic Loads. USENIX Annual Technical Conference 1998 dblp usenix.org ↩︎

      +
    28. +
    29. 1999-05 Dan Kegel: The C10K problem(最后更新时间 2011.07) http://www.kegel.com/c10k.html ↩︎

      +
    30. +
    31. 2014-02 详解浏览器最大并发连接数 https://web.archive.org/web/0/http://www.iefans.net/liulanqi-zuida-bingfa-lianjieshu ↩︎

      +
    32. +
    33. Linux Unix系统编程手册,Kerrisk 下册:第63章 其他备选的I/O模型 ↩︎ ↩︎

      +
    34. +
    35. 2001 Jonathan Lemon: Kqueue - A Generic and Scalable Event Notification Facility. USENIX Annual Technical Conference 2001 dblp usenix.org ↩︎

      +
    36. +
    37. What is the purpose of epoll's edge triggered option? https://stackoverflow.com/a/73540436/689699 ↩︎

      +
    38. +
    39. 2012-01 Interview with Igor Sysoev, author of Apache's competitor NGINX https://web.archive.org/web/0/http://www.freesoftwaremagazine.com/articles/interview_igor_sysoev_author_apaches_competitor_nginx ↩︎

      +
    40. +
    41. 2013-07 Nginx just became the most used web server among the top 1000 websites https://w3techs.com/blog/entry/nginx_just_became_the_most_used_web_server_among_the_top_1000_websites ↩︎

      +
    42. +
    43. 2012-03 AOSA Volume 2 - nginx (Andrew Alexeev) https://aosabook.org/en/v2/nginx.html ↩︎ ↩︎

      +
    44. +
    45. Redis FAQ: How can Redis use multiple CPUs or cores? https://redis.io/docs/getting-started/faq/#how-can-redis-use-multiple-cpus-or-cores ↩︎

      +
    46. +
    47. 2010-09 antirez: An update on the Memcached/Redis benchmark http://oldblog.antirez.com/post/update-on-memcached-redis-benchmark.html ↩︎

      +
    48. +
    49. 2019-02 antirez: An update about Redis developments in 2019 http://antirez.com/news/126 ↩︎ ↩︎

      +
    50. +
    51. Redis Doc: Diagnosing latency issues: Single threaded nature of Redis https://redis.io/docs/management/optimization/latency/#single-threaded-nature-of-redis ↩︎

      +
    52. +
    53. 2019-08 林添毅:正式支持多线程!Redis 6.0与老版性能对比评测 https://mp.weixin.qq.com/s/6WQNq5dNk-GuEhZXtVCo-A ↩︎

      +
    54. +
    +
    +]]>
    + + 架构 + + + 架构 + IO + 服务器 + 网络 + 并发 + +
    + + iText处理pdf书签和标注代码乱记 + /2016/12/itext-pdf/ + 将文档1中的书签转存到文档2​:

    + +
    PdfReader reader1 = new PdfReader("in1.pdf");
    List<HashMap<String, Object>> bookmarks = SimpleBookmark.getBookmark(reader1);

    PdfReader reader2 = new PdfReader("in2.pdf");
    PdfStamper stamper = new PdfStamper(reader2, new FileOutputStream("out.pdf"));
    stamper.getWriter().setOutlines(bookmarks);
    stamper.close();
    +

    导出书签文件​:

    +
    PdfReader reader = new PdfReader("in.pdf");
    List<HashMap<String, Object>> bookmarks = SimpleBookmark.getBookmark(reader);
    SimpleBookmark.exportToXML(bookmarks, new FileWriter("out.xml"), "utf-8", false);

    导入书签到文件​:
    PdfReader reader = new PdfReader("in.pdf");
    List<HashMap<String, Object>> bookmarks = SimpleBookmark.importFromXML(new FileReader("out.xml"));
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("out.pdf"));
    stamper.getWriter().setOutlines(bookmarks);
    stamper.close();
    +

    将文档1中的标注(包括超链接)转存到文档2​:

    +
    PdfReader reader1 = new PdfReader("in1.pdf");
    PdfReader reader2 = new PdfReader("in2.pdf");
    Document document = new Document(reader2.getPageSize(3));
    PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("out.pdf"));
    document.open();

    List<HashMap<String, Object>> bookmarks = SimpleBookmark.getBookmark(reader1);
    writer.setOutlines(bookmarks);

    int num = reader1.getNumberOfPages();
    for (int i = 1; i <= num; i++) {
    PdfImportedPage page = writer.getImportedPage(reader2, i);
    PdfContentByte content = writer.getDirectContent();
    content.addTemplate(page, 0, 0);

    PdfDictionary pageDict = reader1.getPageN(i);
    PdfArray annotArray = pageDict.getAsArray(PdfName.ANNOTS);
    for (int j = 0; annotArray != null && j < annotArray.size(); ++j) {
    PdfDictionary curAnnot = annotArray.getAsDict(j);
    PdfAnnotation pdfAnnot = new PdfAnnotation(writer, null);
    pdfAnnot.putAll(curAnnot);
    writer.addAnnotation(pdfAnnot);
    }
    document.newPage();
    }

    document.close();
    reader1.close();
    reader2.close();
    +

    如果仅仅读取全部链接,只需将上述代码18行开始的for循环修改为:

    +
    for (int j = 0; annotArray != null && j < annotArray.size(); ++j) {
    PdfDictionary curAnnot = annotArray.getAsDict(j);
    if (PdfName.LINK.equals(curAnnot.getAsName(PdfName.SUBTYPE))) {
    PdfAnnotation pdfAnnot = new PdfAnnotation(writer, null);
    pdfAnnot.putAll(curAnnot);
    writer.addAnnotation(pdfAnnot);
    }
    }
    +

    参考资料:

    +
      +
    1. iText 5 examples - iText 5 actions and annotations http://developers.itextpdf.com/content/itext-5-examples
    2. +
    3. iText in Action, 2nd 2010, 7. Making documents interactive https://www.manning.com/books/itext-in-action-second-edition
    4. +
    +]]>
    + + Java + + + 工具 + 代码 + Java + +
    + + Java 8 的 Stream API 笔记 + /2016/12/java-8-stream-api/ + Java 8增加了函数式编程的能力,通过流(Stream)API来支持对集合的filter/map/reduce操作。流是Java 8中处理集合的关键抽象概念,实现声明式的集合处理方式。

    + +

    Java 8流API示例

    +

    对集合的filter、map和reduce操作,示例代码如下:

    +
    // 计算偶数个数
    List<Integer> list = Arrays.asList(3, 2, 12, 5, 6, 11, 13);
    long count = list.stream()
    .filter(x -> x % 2 == 0).count();
    System.out.println(count);

    // 筛选出偶数列表
    List<Integer> evenList = list.stream()
    .filter(x -> x % 2 == 0).collect(Collectors.toList());
    System.out.println(evenList);

    // 筛选出偶数列表, 然后全部元素加1
    List<Integer> plusList = list.stream()
    .filter(x -> x % 2 == 0)
    .map(x -> x + 1).collect(Collectors.toList());
    System.out.println(plusList);

    // 全部偶数求和
    int sum = list.stream()
    .filter(x -> x % 2 == 0)
    .mapToInt(Integer::intValue).sum();
    System.out.println(sum);

    // 全部偶数求和
    sum = list.stream()
    .filter(x -> x % 2 == 0)
    .reduce(0, (x, y) -> x + y);
    System.out.println(sum);
    +

    流与集合的区别

    +

    流(Stream)和集合(collection)有以下区别 [doc]:

    +
      +
    • 无存储(no storage)。流并不是存储元素的数据结构。流,通过计算的操作流水线来传输数据源。数据源,比如数据结构、数组、生成器函数或I/O通道。
    • +
    • 原生函数式(functional in nature)。对流进行操作会产生结果,但并不会修改数据源。比如,筛选流,是生成一个不包含被筛选掉的元素新流,而不是从原集合中删除元素。
    • +
    • 惰性读取(laziness-seeking)。很多对流的操作,比如筛选(filtering)、映射(mapping)或去重(duplicate removal),能够被惰性实现,以便于性能的优化。比如,“找出第一个由三个连续单词组成的String”,并不需要检测全部的输入字符串。流操作被划分为中间操作(用于生成流)和终止操作(用于生成值或副作用)。中间操作总是惰性的。
    • +
    • 可能是无界的(possibly unbounded)。集合的大小是必须确定的,但流并不是。像limit(n) 或 findFirst()这样的逻辑短路操作,允许在有限时间内完成对无限流的计算。
    • +
    • 可消耗的(consumable)。流的元素在流的生命周期中只能被访问一次。类似于 Iterator,要想重新访问同一个元素,必须生成新的流。
    • +
    +

    流操作与流水线

    +

    当使用Stream时,会通过三个阶段来建立一个操作流水线 [ref]。

    +
      +
    1. 创建一个Stream。
    2. +
    3. 在一个或多个步骤中,指定将初始Stream转换为另一个Stream的中间操作
    4. +
    5. 使用一个终止操作来产生一个结果。该操作会强制它之前的延迟操作立即执行。在这之后,该Stream就不会再被使用了。
    6. +
    +

    整个流操作流水线,如图所示 [ref]:

    +

    流操作流水线

    +

    Java 8的流创建、中间操作和终止操作的API汇总表,如下 [ref]

    + + + + + + + + + + + + + + + + +
    创建流中间操作终止操作

    Collection
    stream()
    parallelStream()

    Stream, IntStream, LongStream, DoubleStream
    static generate() 无序
    static of(..)
    static empty()
    static iterate(..)
    static concat(..)
    static builder()

    IntStream, LongStream
    static range(..)
    static rangeClosed(..)

    Arrays
    static stream(..)

    BufferedReader
    lines(..)

    Files
    static list(..)
    static walk(..)
    static find(..)

    JarFile
    stream()

    ZipFile
    stream()

    Pattern
    splitAsStream(..)

    SplittableRandom
    ints(..) 无序
    longs(..) 无序
    doubles(..) 无序

    Random
    ints(..)
    longs(..)
    doubles(..)

    ThreadLocalRandom
    ints()
    longs(..)
    doubles(..)

    BitSet
    stream()

    CharSequence (String)
    IntStream chars()
    IntStream codePoints()

    StreamSupport (low level)
    static doubleStream(..)
    static intStream(..)
    static longStream(..)
    static stream(..)

    BaseStream
    sequential()
    parallel()
    unordered()
    onClose(..)

    Stream
    filter(..)
    map(..)
    mapToInt(..)
    mapToLong(..)
    mapToDouble(..)
    flatMap(..)
    flatMapToInt(..)
    flatMapToLong(..)
    flatMapToDouble(..)
    distinct() 有状态
    sorted(..) 有状态
    peek(..)
    limit(..) 有状态, 逻辑短路
    skip(..) 有状态

    IntStream、LongStream和DoubleStream方法与Stream类似, 其中额外的方法如下:

    IntStream
    mapToObj(..)
    asLongStream()
    asDoubleStream()
    boxed()

    LongStream
    mapToObj(..)
    asDoubleStream()
    boxed()

    DoubleStream
    mapToObj(..)
    boxed()

    BaseStream
    iterator()
    spliterator()

    Stream
    forEach(..)
    forEachOrdered(..)
    toArray(..)
    reduce(..)
    collect(..)
    min(..)
    max(..)
    count()
    anyMatch(..) 逻辑短路
    allMatch(..) 逻辑短路
    noneMatch(..) 逻辑短路
    findFirst() 逻辑短路
    findAny() 逻辑短路*, 不确定*

    IntStream、LongStream和DoubleStream方法与Stream类似, 其中额外的方法如下:

    IntStream, LongStream, DoubleStream
    sum()
    average()
    summaryStatistics()

    +

    筛选与映射操作

    +

    筛选与映射操作,即上文所说的中间操作。相关的API如下:

    +
    Stream<T> filter(Predicate<? super T> predicate)
    <R> Stream<R> map(Function<? super T,? extends R> mapper)
    <R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)
    +

    filter(..),筛选出元素符合某个条件的新流。map(..),用于对元素作某种形式的转换。flatMap(..),用于将多个子流合并为一个新流。

    +

    其他的中间操作有,提取子流,limit(..)(提取前n个)和skip(..)(丢弃前n个);有状态的转换,distinct()(过滤重复元素)和sorted(..)(排序),以及主要用于日志调试的peek(..)

    +
    Stream<T> limit(long maxSize)
    Stream<T> skip(long n)
    Stream<T> distinct()
    Stream<T> sorted(Comparator<? super T> comparator)
    Stream<T> peek(Consumer<? super T> action)
    +

    归约操作与收集器

    +

    流有多种形式的通用的归约操作,reduce(..)collect(..),同时也有多种特化的归约形式,比如 sum()min(..)max(..)count()等。reduce(..)collect(..)的方法签名如下:

    +
    Optional<T> reduce(BinaryOperator<T> accumulator)
    T reduce(T identity, BinaryOperator<T> accumulator)
    <U> U reduce(U identity, BiFunction<U,? super T,U> accumulator,
    BinaryOperator<U> combiner)
    <R,A> R collect(Collector<? super T,A,R> collector)
    +

    sum()min(..)max(..)count()等特化的归约操作,是reduce(..)归约操作的特殊化,内部实现依赖reduce(..),相应JDK的实现源码可以作为印证。

    +

    IntStream的sum(..)的JDK现实源码为 [github]:

    +
    @Override
    public final int sum() {
    return reduce(0, Integer::sum);
    }
    +

    IntStream的min(..)的JDK现实源码为 [github]:

    +
    @Override
    public final OptionalInt min() {
    return reduce(Math::min);
    }
    +

    Stream的count()的JDK现实源码为 [github]:

    +
    @Override
    public final long count() {
    return mapToLong(e -> 1L).sum();
    }
    +

    如果不想将流归约为单个值,而只要查看集合被流操作后的结果,需要使用收集器(collector)。上文已经见到,将流收集为List:

    +
    List<Integer> evenList = list.stream()
    .filter(..).collect(Collectors.toList());
    +

    Collectors是收集器工具类,提供获取预定义收集器(实现接口Collector)的静态方法。Collectors类,除了将流收集为List,还可以是Map、Set、String,或者也能进行统计操作,如求和、计算平均值、最大值、最小值。Collectors的全部静态方法列表如下:

    +
      +
    • averaging[Double|Int|Long]
    • +
    • collectingAndThen
    • +
    • counting
    • +
    • groupingBy
    • +
    • groupingByConcurrent
    • +
    • joining
    • +
    • mapping
    • +
    • maxBy
    • +
    • minBy
    • +
    • partitioningBy
    • +
    • reducing
    • +
    • summarizing[Double|Int|Long]
    • +
    • summing[Double|Int|Long]
    • +
    • toCollection
    • +
    • toConcurrentMap
    • +
    • toList
    • +
    • toMap
    • +
    • toSet
    • +
    +]]>
    + + Java + + + Java + +
    + + Java Agent 学习笔记 + /2018/10/java-agent/ + Java 从 1.5 开始提供了 java.lang.instrumentdoc)包,该包为检测(instrument) Java 程序提供 API,比如用于监控、收集性能信息、诊断问题。通过 java.lang.instrument 实现工具被称为 Java Agent。Java Agent 可以修改类文件的字节码,通常是,在字节码方法插入额外的字节码来完成检测。关于如何使用 java.lang.instrument 包,可以参考 javadoc 的包描述(en, zh)。

    + +

    开发 Java Agent 的涉及的要点如下图所示 [ ref ]
    +Java Agent

    +

    Java Agent 支持两种方式加载,启动时加载,即在 JVM 程序启动时在命令行指定一个选项来启动代理;启动后加载,这种方式使用从 JDK 1.6 开始提供的 Attach API 来动态加载代理。

    +

    启动时加载 agent

    +

    最简单的例子

    +

    现在创建命名为 proj-demo 的 gradle 项目,目录布局如下:

    +
    $ tree proj-demo
    proj-demo
    ├── build.gradle
    └── src
    ├── main
    │   └── java
    │   └── com
    │   └── demo
    │   └── App.java
    └── test
    └── java

    7 directories, 2 files
    +

    com.demo.App 类的实现:

    +
    public class App {

    public static void main(String[] args) throws InterruptedException {
    while (true) {
    System.out.println(getGreeting());
    Thread.sleep(1000L);
    }
    }

    public static String getGreeting() {
    return "hello world";
    }
    }
    +

    运行 com.demo.App,每隔 1 秒输出 hello world

    +
    $ gradle build
    $ java -cp "target/classes/java/main" com.demo.App
    hello world
    hello world
    +

    现在创建名称为 proj-premain 的 gradle 项目,com.demo.MyPremain 类实现 premain 方法:

    +
    package com.demo;

    public class MyPremain {
    public static void premain(String agentArgs, Instrumentation inst) {
    System.out.println(agentArgs);
    }
    }
    +

    META-INF/MANIFEST.MF 文件指定 Premain-Class 属性:

    +
    jar {
    manifest {
    attributes 'Premain-Class': 'com.demo.MyPremain'
    }
    from {
    configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    }
    }
    +

    打包生成 proj-premain.jar,这个 jar 包就是 javaagent 代理。现在来试试运行 com.demo.App 时,启动这个 javaagent 代理。根据 javadoc 的描述,可以将以下选项添加到命令行来启动代理:

    +
    -javaagent:jarpath[=options] 
    +

    指定 -javaagent:"proj-premain.jar=hello agent",传入的 agentArgshello agent,再次运行 com.demo.App

    +
    $ java -javaagent:"proj-premain.jar=hello agent" -cp "target/classes/java/main" com.demo.App
    hello agent
    hello world
    hello world
    +

    可以看到,在运行 main 之前,运行了 premain 方法,即先输出 hello agent,每隔 1 秒输出 hello world

    +

    修改字节码

    +

    在实现 premain 时,除了能获取 agentArgs 参数,还能获取 Instrumentation 实例。Instrumentation 类提供 addTransformer 方法,用于注册提供的转换器 ClassFileTransformer

    +
    // 注册提供的转换器
    void addTransformer(ClassFileTransformer transformer)
    +

    ClassFileTransformer 是抽象接口,唯一需要实现的是 transform 方法。在转换器使用 addTransformer 注册之后,每次定义新类时(调用 ClassLoader.defineClass)都将调用该转换器的 transform 方法。该方法签名如下:

    +
    // 此方法的实现可以转换提供的类文件,并返回一个新的替换类文件
    byte[] transform(ClassLoader loader,
    String className,
    Class<?> classBeingRedefined,
    ProtectionDomain protectionDomain,
    byte[] classfileBuffer)
    throws IllegalClassFormatException
    +

    操作字节码可以使用 ASM、Apache BCEL、Javassist、cglib、Byte Buddy 等库。下面示例代码,使用 BCEL 库实现名为 GreetingTransformer 转换器。该转换器实现的逻辑就是,将 com.demo.App.getGreeting() 方法输出的 hello world,替换为输出 premain 方法的传入的参数 agentArgs

    +
    public class MyPremain {
    public static void premain(String agentArgs, Instrumentation inst) {
    inst.addTransformer(new GreetingTransformer(agentArgs));
    }
    }
    +
    import org.apache.bcel.*;
    import java.lang.instrument.ClassFileTransformer;
    import java.lang.instrument.Instrumentation;
    import java.security.ProtectionDomain;

    public class GreetingTransformer implements ClassFileTransformer {
    private String agentArgs;

    public GreetingTransformer(String agentArgs) {
    this.agentArgs = agentArgs;
    }

    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
    ProtectionDomain protectionDomain, byte[] classfileBuffer) {
    if (!className.equals("com/demo/App")) {
    return classfileBuffer;
    }
    try {
    JavaClass clazz = Repository.lookupClass(className);
    ClassGen cg = new ClassGen(clazz);
    ConstantPoolGen cp = cg.getConstantPool();
    for (Method method : clazz.getMethods()) {
    if (method.getName().equals("getGreeting")) {
    MethodGen mg = new MethodGen(method, cg.getClassName(), cp);
    InstructionList il = new InstructionList();
    il.append(new PUSH(cp, this.agentArgs));
    il.append(InstructionFactory.createReturn(Type.STRING));
    mg.setInstructionList(il);
    mg.setMaxStack();
    mg.setMaxLocals();
    cg.replaceMethod(method, mg.getMethod());
    }
    }
    return cg.getJavaClass().getBytes();
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    }
    return null;
    }
    }
    +

    启动后加载 agent

    +

    最早 JDK 1.5发布 java.lang.instrument 包时,agent 是必须在 JVM 启动时,通过命令行选项附着(attach)上去。但在 JVM 正常运行时,加载 agent 没有意义,只有出现问题,需要诊断才需要附着 agent。JDK 1.6 实现了 attach-on-demand(按需附着)[ JDK-4882798 ],可以使用 Attach API 动态加载 agent [ oracle blog, javadoc ]。这个 Attach API 在 tools.jar 中。JVM 启动时默认不加载这个 jar 包,需要在 classpath 中额外指定。使用 Attach API 动态加载 agent 的示例代码如下:

    +
    import com.sun.tools.attach.VirtualMachine;
    import com.sun.tools.attach.VirtualMachineDescriptor;

    public class AgentLoader {

    public static void main(String[] args) throws Exception {
    if (args.length < 2) {
    System.err.println("Usage: java -cp .:$JAVA_HOME/lib/tools.jar"
    + " com.demo.AgentLoader <pid/name> <agent> [options]");
    System.exit(0);
    }

    String jvmPid = args[0];
    String agentJar = args[1];
    String options = args.length > 2 ? args[2] : null;
    for (VirtualMachineDescriptor jvm : VirtualMachine.list()) {
    if (jvm.displayName().contains(args[0])) {
    jvmPid = jvm.id();
    break;
    }
    }

    VirtualMachine jvm = VirtualMachine.attach(jvmPid);
    jvm.loadAgent(agentJar, options);
    jvm.detach();
    }
    }
    +

    启动时加载 agent,-javaagent 传入的 jar 包需要在 MANIFEST.MF 中包含 Premain-Class 属性,此属性的值是 代理类 的名称,并且这个 代理类 要实现 premain 静态方法。启动后加载 agent 也是类似,通过 Agent-Class 属性指定 代理类代理类 要实现 agentemain 静态方法。agent 被加载后,JVM 将尝试调用 agentmain 方法。

    +

    上文提到每次定义新类(调用 ClassLoader.defineClass)时,都将调用该转换器的 transform 方法。对于已经定义加载的类,需要使用重定义类(调用 Instrumentation.redefineClass)或重转换类(调用 Instrumentation.retransformClass)。

    +
    // 注册提供的转换器。如果 canRetransform 为 true,那么重转换类时也将调用该转换器
    void addTransformer(ClassFileTransformer transformer, boolean canRetransform)
    // 使用提供的类文件重定义提供的类集。新的类文件字节,通过 ClassDefinition 传入
    void redefineClasses(ClassDefinition... definitions)
    throws ClassNotFoundException, UnmodifiableClassException
    // 重转换提供的类集。对于每个添加时 canRetransform 设为 true 的转换器,在这些转换器中调用 transform 方法
    void retransformClasses(Class<?>... classes)
    throws UnmodifiableClassException
    +

    重定义类(redefineClass)从 JDK 1.5 开始支持,而重转换类(retransformClass)是 JDK 1.6 引入。相对来说,重转换类能力更强,当存在多个转换器时,重转换将由 transform 调用链组成,而重定义类无法组成调用链。重定义类能实现的逻辑,重转换类同样能完成,所以保留重定义类方法(Instrumentation.redefineClass)可能只是为了向后兼容 [ stackoverflow ]。

    +

    实现 agentmain 的示例代码如下,其中 GreetingTransformer 转换器的类定义和上文一样。

    +
    public class MyAgentMain {

    public static void agentmain(String agentArgs, Instrumentation inst) {
    inst.addTransformer(new GreetingTransformer(agentArgs), true);
    try {
    Class clazz = Class.forName("com.demo.App");
    if (inst.isModifiableClass(clazz)) {
    inst.retransformClasses(clazz);
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }
    +

    MANIFEST.MF 文件配置:

    +
    jar {
    manifest {
    attributes 'Agent-Class': 'com.demo.MyAgentMain'
    attributes 'Can-Redefine-Classes' : true
    attributes 'Can-Retransform-Classes' : true
    }
    from {
    configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    }
    }
    +

    需要注意的是,和定义新类不同,重定义类和重转换类,可能会更改方法体、常量池和属性,但不得添加、移除、重命名字段或方法;不得更改方法签名、继承关系 [ javadoc ]。这个限制将来可能会通过 “JEP 159: Enhanced Class Redefinition” 移除 [ ref ]。

    +

    使用 Byte Buddy

    +

    Byte Buddy(home, github, javadoc),运行时的代码生成和操作库,2015 年获得 Oracle 官方 Duke's Choice award,提供高级别的创建和修改 Java 类文件的 API,使用这个库时,不需要了解字节码。另外,对 Java Agent 的开发 Byte Buddy 也有很好的支持,可以参考 Byte Buddy 作者 Rafael Winterhalter 写的介绍文章 [ ref1, ref2 ]。

    +

    上文使用 BCEL 实现的 GreetingTransformer,现在改用 Byte Buddy,会变得非常简单。实现 premain 示例代码:

    +
    public static void premain(String agentArgs, Instrumentation inst) {
    new AgentBuilder.Default()
    .type(ElementMatchers.named("com.demo.App"))
    .transform(new AgentBuilder.Transformer() {
    @Override
    public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
    TypeDescription typeDescription,
    ClassLoader classLoader,
    JavaModule module) {
    return builder.method(ElementMatchers.named("getGreeting"))
    .intercept(FixedValue.value(agentArgs));
    }
    }).installOn(inst);
    }
    +

    实现 agentmain

    +
    public static void agentmain(String agentArgs, Instrumentation inst) {
    new AgentBuilder.Default()
    .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
    .disableClassFormatChanges()
    .type(ElementMatchers.named("com.demo.App"))
    .transform(new AgentBuilder.Transformer() {
    @Override
    public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
    TypeDescription typeDescription,
    ClassLoader classLoader,
    JavaModule module) {
    return builder.method(ElementMatchers.named("getGreeting"))
    .intercept(FixedValue.value(agentArgs));
    }
    }).installOn(inst);
    }
    +

    另外,Byte Buddy 对 Attach API 作了封装,屏蔽了对 tools.jar 的加载,可以直接使用 ByteBuddyAgent 类:

    +
    ByteBuddyAgent.attach(new File(agentJar), jvmPid, options);
    +

    上文中的 AgentLoader,可以使用这个 API 简化,实现的完整示例参见 AgentLoader2

    +

    实现性能计时器

    +

    Byte Buddy 的 github 的 README 文档提供了一个性能计时拦截器的代码示例,能对某个方法的运行耗时做统计。现在我们来看下是如何实现的。假设 com.demo.App2 类如下:

    +
    public class App2 {

    public static void main(String[] args) {
    while (true) {
    System.out.println(getGreeting());
    }
    }

    public static String getGreeting() {
    try {
    Thread.sleep((long) (1000 * Math.random()));
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    return "hello world";
    }
    }
    +

    使用 Byte Buddy 实现计时拦截器的 agent,如下:

    +
    public class TimerAgent {

    public static void premain(String agentArgs, Instrumentation inst) {
    new AgentBuilder.Default()
    .type(ElementMatchers.any())
    .transform((builder, type, classLoader, module) ->
    builder.method(ElementMatchers.nameMatches(agentArgs))
    .intercept(MethodDelegation.to(TimingInterceptor.class)))
    .installOn(inst);
    }
    }
    +
    public class TimingInterceptor {

    @RuntimeType
    public static Object intercept(@Origin Method method, @SuperCall Callable<?> callable) throws Exception {
    long start = System.currentTimeMillis();
    try {
    return callable.call();
    } finally {
    System.out.println(method + " took " + (System.currentTimeMillis() - start) + "ms");
    }
    }
    }
    +

    getGreeting 方法进行性能剖析,运行结果如下:

    +
    $ java -javaagent:"proj-byte-buddy.jar=get.*" -cp "target/classes/java/main" com.demo.App2
    public static java.lang.String com.demo.App2.getGreeting() took 694ms
    hello world
    public static java.lang.String com.demo.App2.getGreeting() took 507ms
    hello world
    +

    示例代码中的 premain 参数 agentArgs 用于指定需要剖析性能的方法名,支持正则表达式。当实际参数传入 get.* 时,匹配到 getGreeting 方法。上面的示例,使用的是 Byte Buddy 的方法委托 Method Delegation API [ javadoc ]。Delegation API 实现原理就是,将被拦截的方法委托到另一个办法上,如下左图所示(图片来自 Rafael Winterhalter 的 slides)。这种写法会修改被代理类的类定义格式,只能用在启动时加载 agent,即 premain 方式代理。

    +

    若要通过 Byte Buddy 实现启动后动态加载 agent,官方提供了 Advice API [ javadoc ]。Advice API 实现原理上是,在被拦截方法内部的开始和结尾添加代码,如下右图所示。这样只更改了方法体,不更改方法签名,也没添加额外的方法,符合重定义类(redefineClass)和重转换类(retransformClass)的限制。

    +delegation vs. advice +

    现在来看下使用 Advice API 实现性能定时器的代码示例:

    +
    public class TimingAdvice {

    @Advice.OnMethodEnter
    public static long enter() {
    return System.currentTimeMillis();
    }

    @Advice.OnMethodExit
    public static void exit(@Advice.Origin Method method, @Advice.Enter long start) {
    long duration = System.currentTimeMillis() - start;
    System.out.println(method + " took " + duration + "ms");
    }
    }
    +
    public static void agentmain(String agentArgs, Instrumentation inst) {
    new AgentBuilder.Default()
    .disableClassFormatChanges()
    .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
    // .with(AgentBuilder.Listener.StreamWriting.toSystemOut())
    .type(ElementMatchers.any())
    .transform((builder, type, classLoader, module) ->
    builder.visit(Advice.to(TimingAdvice.class)
    .on(ElementMatchers.nameMatches(agentArgs))))
    .installOn(inst);
    }
    +

    若对 com.demo.App 类,动态加载这个 Advice API 实现的 agent,getGreeting() 方法将会被重定义为(真正的实现可能稍有不同,但原理一致):

    +
    public static String getGreeting() {
    long $start = System.nanoTime();
    String $result = "hello world";
    long $duration = System.nanoTime() – $start;
    System.out.println("App.getGreeting()" + " took " + $duration + "ms");
    return $result;
    }
    +

    实际应用案例

    +

    Java Agent 的实际应用案例很多,举些笔者实际工作中使用到的开源软件的应用案例。

    +

    微服务是目前流行的互联网架构,实施微服务架构其中用于观察分布式服务的 APM (应用性能管理)系统是必不可缺的一环。典型的 APM 系统,如 PinpointSkyWalking,为了减少的 Java 服务应用代码的入侵,底层实现上都采用 Java Agent 技术,在 Java 服务应用启动时加载 agent,进行字节码增强技术,实现分布式追踪、服务性能监控等特性。具体可参见 Pinpoint 文档和 SkyWalking 文档

    +

    Alibaba Java 诊断利器 Arthas,实现上使用了动态 Attach API,相关源代码参见 github。Arthas 4.0 开始支持 premain 方式启动时加载 agent,参见 issue #550

    +
    +

    **附注:**本文中提到的代码,可以在 github 上访问得到,javaagent-demo

    +

    参考资料

    + +]]>
    + + Java + + + Java + 字节码 + javaagent + byte-buddy + +
    + + Java书籍资料整理 + /2016/11/java-books/ + https://en.wikipedia.org/wiki/Template:Java_(software_platform)
    +http://c2.com/cgi/wiki?JavaIdioms
    +http://c2.com/cgi/wiki?JavaDesignFlaws Java语言设计缺陷

    +
      +
    1. 2011-06 Java Books Reading Order http://stackoverflow.com/q/6341593
    2. +
    3. 2009-03 Java书籍Top 10 http://coolshell.cn/articles/14.html
    4. +
    5. 2012-03 JVM程序员的阅读清单 http://blog.jobbole.com/15342/
    6. +
    + +
    +

    Java官方文档与书籍

    +

    http://docs.oracle.com/javase/8/
    +http://docs.oracle.com/javase/tutorial/

    +

    Java Language and Virtual Machine Specifications http://docs.oracle.com/javase/specs/

    +

    Sun官方Addison-Wesley出版的Java Series,link

    +
      +
    1. 1996-2014,Gosling, Joy, Steele, Bracha,《Java语言规范》(The Java Language Specification, 2nd 2000, 3rd 2005, Java SE 8 2014),Java 7 online,第3版豆瓣,Java 8中文豆瓣
    2. +
    3. 1996-2013,Lindholm, Yellin, Bracha, etc,《Java虚拟机规范》(The Java Virtual Machine Specification, 1st 1996, 2nd 1999, Java SE 7 2013, Java SE 8 2014),Java 7 online豆瓣
    4. +
    5. 1996-2005,Arnold, Gosling, etc,《Java程序设计语言》(The Java Programming Language, 1st 1996,2nd 1997,4th 2005),第4版豆瓣:涵盖J2SE 5.0,内容比《Java编程思想》精简,条理更清晰,覆盖面更广
    6. +
    7. 1998-2013,《Java教程》(The Java Tutorial: A Short Course on the Basics, 2nd 1998, 3rd 2001, 4th 2006, 5th 2013),第4版豆瓣:全书415页,涵盖Java 5.0和6.0,内容比《Java程序设计语言》简单,是官方在线指定文档
    8. +
    9. 1997,《Java经典问答》(The Java Faq, 1997),豆瓣
    10. +
    11. 1997.06,《Java语言编码规范》(Code Conventions for the Java Programming Language),oracle.com html, pdf
    12. +
    +
    +

    Java书籍

    +
      +
    1. 1998-2006,Bruce Eckel,《Java编程思想》(Thinking in Java, 1st 1998, 4th 2006),home豆瓣:内容有深度,但组织混乱,抓不住脉络,杂糅了Java与C++比较、设计模式等内容,2003年Jolt震撼大奖
    2. +
    3. 1996-2012,Cay S. Horstmann,《Java核心技术,2卷》(Core Java 2, 1st 1996, 8th 2007, 9th 2012),home,第10版卷1豆瓣、卷2豆瓣
    4. +
    5. 2001、2008,Joshua Bloch,《Effective Java》,2nd 2008,豆瓣:2002年Jolt震撼大奖
    6. +
    7. 2005,Joshua Bloch & Neal Gafter,《Java解惑》(Java Puzzlers: Traps, Pitfalls, and Corner Cases, amazon),home图灵2010豆瓣
    8. +
    9. Java语言精粹 Java: The Good Parts http://book.douban.com/subject/6516576/
    10. +
    11. 2006,Metsker,《Java设计模式》(Design Patterns in Java, amazon),豆瓣,修订版豆瓣
    12. +
    13. Herbert Schildt,《Java完全参考手册》(Java: The Complete Reference, 8th 2011),第8版豆瓣,第9版豆瓣:Oracle Press,全书1105页,参考手册,可读性不高,涵盖Java 7
    14. +
    15. Herbert Schildt,《Java编程入门教程》(Java: A Beginner's Guide),第6版豆瓣
    16. +
    17. 2012,Sarang,《Java 7编程高级进阶》(Java Programming, amazon),豆瓣:Oracle Press,内容条理清晰,但深度、广度不够,Java虚拟机技术总监Pampuch作序,客户端软件的首席架构师Coward技术校审
    18. +
    19. Jakarta Commons Cookbook中文版 https://book.douban.com/subject/1936665/
    20. +
    +

    https://github.com/iluwatar/java-design-patterns

    +

    Java并发编程

    +
      +
    1. 2006,Goetz, Peierls, Joshua Bloch, Doug Lea & etc,《Java并发编程实战》(Java Concurrency in Practice, amazon),豆瓣:top1书籍,Sun官方书籍,相对偏向理论的并发编程书籍见“多处理器编程的艺术,修订版2012”
    2. +
    3. 2011,Subramaniam,《Java虚拟机并发编程》(Programming Concurrency on the JVM, amazon),豆瓣:全书216页,主要讲Scala下的Akka
    4. +
    5. 1999,Doug Lea,《Java并发编程:设计原则与模式》(Concurrent Programming in Java, 2nd 1999),豆瓣:过时
    6. +
    7. 2012,[西] González,《Java 7并发编程实战手册》(Java 7 Concurrency Cookbook, amazon),豆瓣:amazon评价不高,可作辅助阅读,难度低于Goetz版
    8. +
    +

    2012-12 Review : Java 7 Concurrency Cookbook,原文:mkyong.com,译文:importnew.com

    +

    Java高级内容(Java 7 & Java 8)

    +
      +
    1. 2012,Evans & Verburg,《Java程序员修炼之道》(The Well-Grounded Java Developer, amazon),图灵2013豆瓣:全面解读Groovy、Scala在JVM上的应用
    2. +
    3. 2014,《Java 8实战》(Java 8 in Action, amazon),豆瓣
    4. +
    5. 2014,Horstmann,《写给大忙人看的Java SE 8》(Java SE 8 for the Really Impatient, amazon),豆瓣:极好的全面介绍Java 8
    6. +
    7. 2014,《Java 8函数式编程》(Java 8 Lambdas, amazon),豆瓣
    8. +
    9. 2014,Subramaniam,“Functional Programming in Java”, amazon豆瓣
    10. +
    +

    Java虚拟机与底层书籍

    +
      +
    1. 2014,Scott Oaks,《Java性能权威指南》(Java Performance: The Definitive Guide),豆瓣
    2. +
    3. 2011,Charlie Hunt, Binu John,《Java性能优化权威指南》(Java Performance, amazon),豆瓣:第1作者是Oracle JVM性能主管工程师
    4. +
    5. 2000,Bill Venners,《深入Java虚拟机》(Inside the Java Virtual Machine, 2nd 2000),豆瓣
    6. +
    7. 2011、2013,周志明,《深入理解Java虚拟机:VM高级特性与最佳实践》,豆瓣:相比较陈涛版更偏向概念和理论
    8. +
    9. 2014,陈涛,《HotSpot实战》,豆瓣:内容有大量的HotSpot源码解析
    10. +
    11. 2015,高翔龙,《Java虚拟机精讲》,豆瓣
    12. +
    13. 2014,《大规模Java平台虚拟化与调优》
    14. +
    15. Scott Oaks, Java Performance: The Definitive Guide,豆瓣
    16. +
    17. 2015,OpenJDK cookbook,amazon
    18. +
    +
    +

    偏向Java EE

    +
      +
    1. 2004,Bruce Tate,《轻快的Java》(Better, Faster, Lighter Java, O'Reilly, amazon),豆瓣:2005年Jolt震撼大奖
    2. +
    3. 2005,Bruce Tate,《超越Java:探讨程序语言的未来》(Beyond Java, O'Reilly, amazon),豆瓣
    4. +
    5. 2010,Bruce Tate,《七周七语言:理解多种编程范型》(Seven Languages in Seven Weeks, Pragmatic, amazon),豆瓣:2011年Jolt生产力大奖
    6. +
    +]]>
    + + Java + + + 书籍 + Java + +
    + + Java 外部函数接口:JNI, JNA, JNR + /2018/01/java-ffi/ + 遇到的问题 +

    前段时间开发的时候,遇到一个问题,就是如何用 Java 实现 chdir?网上搜索一番,发现了 JNR-POSIX 项目 [ stackoverflow ]。俗话说,好记性不如烂笔头。现在将涉及到的相关知识点总结成笔记。

    + +

    其实针对 Java 实现 chdir 问题,官方 20 多年前就存在对应的 bug,即 JDK-4045688 'Add chdir or equivalent notion of changing working directory'。这个 bug 在 1997.04 创建,目前的状态是 Won't Fix(不予解决),理由大致是,若实现与操作系统一样的进程级别的 chdir,将影响 JVM 上的全部线程,这样引入了可变(mutable)的全局状态,这与 Java 的安全性优先原则冲突,现在添加全局可变的进程状态,已经太迟了,对不变性(immutability)的支持才是 Java 要实现的特性。

    +

    chdir 是平台相关的操作系统接口,POSIX 下对应的 APIint chdir(const char *path);,而 Windows 下对应的 APIBOOL WINAPI SetCurrentDirectory(_In_ LPCTSTR lpPathName);,另外 Windows 下也可以使用 MSVCRT 中 APIint _chdir(const char *dirname);(MSVCRT 下内部实现其实就是调用 SetCurrentDirectory [ reactos ] )。

    +

    Java 设计理念是跨平台,"write once, run anywhere"。很平台相关的 API,虽然各个平台都有自己的类似的实现,但存在会差异。除了多数常见功能,Java 并没有对全部操作系统接口提供完整支持,比如很多 POSIX API。除了 chdir,另外一个典型的例子是,在 Java 9 以前 JDK 获取进程 id 一直没有简洁的方法 [ stackoverflow ],最新发布的 Java 9 中的 JEP 102(Process API Updates)才增强了进程 API。获取进程 id 可以使用以下方式 [ javadoc ]:

    +
    long pid = ProcessHandle.current().pid();
    +

    相比其他语言,Pyhon 和 Ruby,对操作系统相关的接口都有更多的原生支持。Pyhon 和 Ruby 实现的相关 API 基本上都带有 POSIX 风格。比如上文提到,chdirgetpid,在 Pyhon 和 Ruby 下对应的 API 为:Pyhon 的 os 模块 os.chdir(path)os.getpid();Ruby 的 Dir 类的 Dir.chdir( [ string] ) 类方法和 Process 类的 Process.pid 类属性。Python 解释器的 chdir 对应源码为 posixmodule.c#L2611,Ruby 解释器的 chdir 对应源码为 dir.c#L848win32.c#L6741

    +

    JNI 实现 getpid

    +

    Java 下要想实现本地方法调用,需要通过 JNI。关于 JNI 的介绍,可以参阅“Java核心技术,卷II:高级特性,第9版2013”的“第12章 本地方法”,或者读当年 Sun 公司 JNI 设计者 Sheng Liang(梁胜)写的“Java Native Interface: Programmer's Guide and Specification”。本文只给出实现 getpid 的一个简单示例。

    +

    首先使用 Maven 创建一个简单的脚手架:

    +
    mvn archetype:generate     \
    -DgroupId=com.test \
    -DartifactId=jni-jnr \
    -DpackageName=com.test \
    -DinteractiveMode=false
    +

    com.test 包下添加 GetPidJni 类:

    +
    package com.test;

    public class GetPidJni {
    public static native long getpid();

    static {
    System.loadLibrary("getpidjni");
    }

    public static void main(String[] args) {
    System.out.println(getpid());
    }
    }
    +

    javac 编译代码 GetPidJNI.java,然后用 javah 生成 JNI 头文件:

    +
    $ mkdir -p target/classes
    $ javac src/main/java/com/test/GetPidJni.java -d "target/classes"
    $ javah -cp "target/classes" com.test.GetPidJni
    +

    生成的 JNI 头文件 com_test_GetPidJni.h,内容如下:

    +
    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class com_test_GetPidJni */

    #ifndef _Included_com_test_GetPidJni
    #define _Included_com_test_GetPidJni
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
    * Class: com_test_GetPidJni
    * Method: getpid
    * Signature: ()J
    */
    JNIEXPORT jlong JNICALL Java_com_test_GetPidJni_getpid
    (JNIEnv *, jclass);

    #ifdef __cplusplus
    }
    #endif
    #endif
    +

    现在有了头文件声明,但还没有实现,手动敲入 com_test_GetPidJni.c

    +
    #include "com_test_GetPidJni.h"

    JNIEXPORT jlong JNICALL
    Java_com_test_GetPidJni_getpid (JNIEnv * env, jclass c) {
    return getpid();
    }
    +

    编译 com_test_GetPidJni.c,生成 libgetpidjni.dylib

    +
    $ gcc -I $JAVA_HOME/include -I $JAVA_HOME/include/darwin -dynamiclib -o libgetpidjni.dylib com_test_GetPidJni.c
    +

    生成的 libgetpidjni.dylib,就是 GetPidJni.java 代码中的 System.loadLibrary("getpidjni");,需要加载的 lib。

    +

    现在运行 GetPidJni 类,就能正确获取 pid:

    +
    $ java -Djava.library.path=`pwd` -cp "target/classes" com.test.GetPidJni
    +

    JNI 的问题是,胶水代码(黏合 Java 和 C 库的代码)需要程序员手动书写,对不熟悉 C/C++ 的同学是很大的挑战。

    +

    JNA 实现 getpid

    +

    JNA(Java Native Access, wiki, github, javadoc, mvn),提供了相对 JNI 更加简洁的调用本地方法的方式。除了 Java 代码外,不再需要额外的胶水代码。这个项目最早可以追溯到 Sun 公司 JNI 设计者 Sheng Liang 在 1999 年 JavaOne 上的分享。2006 年 11月,Todd Fast (也来自 Sun 公司) 首次将 JNA 发布到 dev.java.net 上。Todd Fast 在发布时提到,自己在这个项目上已经断断续续开发并完善了 6-7 年时间,项目刚刚在 JDK 5 上重构和重设计过,还可能有很多缺陷或缺点,希望其他人能浏览代码并参与进来。Timothy Wall 在 2007 年 2 月重启了这项目,引入了很多重要功能,添加了 Linux 和 OSX 支持(原本只在 Win32 上测试过),加强了 lib 的可用性(而非仅仅基本功能可用)[ ref ]。

    +

    看下示例代码:

    +
    import com.sun.jna.Library;
    import com.sun.jna.Native;

    public class GetPidJNA {

    public interface LibC extends Library {
    long getpid();
    }

    public static void main(String[] args) {
    LibC libc = Native.loadLibrary("c", LibC.class);
    System.out.println(libc.getpid());
    }
    }
    +

    JNR 实现 getpid

    +

    最初,JRuby 的核心开发者 Charles Nutter 在实现 Ruby 的 POSIX 集成时就使用了 JNA [ ref ]。但过了一段时候后,开始开发 JNR(Java Native Runtime, github, mvn) 替代 JNA。Charles Nutter 在介绍 JNR 的 slides 中阐述了原因:

    +
    Why Not JNA?
    - Preprocessor constants?
    - Standard API sets out of the box
    - C callbacks?
    - Performance?!?
    +

    即,(1) 预处理器的常量支持(通过 jnr-constants 解决);(2) 开箱即用的标准 API(作者实现了 jnr-posix, jnr-x86asm, jnr-enxio, jnr-unixsocket);(3) C 回调 callback 支持;(4) 性能(提升 8-10 倍)。

    +JNR 各个模块的层次结构 +

    使用 JNR-FFI(github, mvn)实现 getpid,示例代码:

    +
    import jnr.ffi.LibraryLoader;

    public class GetPidJnr {

    public interface LibC {
    long getpid();
    }

    public static void main(String[] args) {
    LibC libc = LibraryLoader.create(LibC.class).load("c");
    System.out.println(libc.getpid());
    }
    }
    +

    使用 JNR-POSIX(github, mvn)实现 chdirgetpid,示例代码:

    +
    import jnr.posix.POSIX;
    import jnr.posix.POSIXFactory;

    public class GetPidJnrPosix {

    private static POSIX posix = POSIXFactory.getPOSIX();

    public static void main(String[] args) {
    System.out.println(posix.getcwd());
    posix.chdir("..");
    System.out.println(posix.getcwd());
    System.out.println(posix.getpid());
    }
    }
    +

    JMH 性能比较

    +

    性能测试代码为 BenchmarkFFI.javagithub),测试结果如下:

    +
    # JMH version: 1.19
    # VM version: JDK 1.8.0_144, VM 25.144-b01

    Benchmark Mode Cnt Score Error Units
    BenchmarkFFI.testGetPidJna thrpt 10 8225.209 ± 206.829 ops/ms
    BenchmarkFFI.testGetPidJnaDirect thrpt 10 10257.505 ± 736.135 ops/ms
    BenchmarkFFI.testGetPidJni thrpt 10 77852.899 ± 3167.101 ops/ms
    BenchmarkFFI.testGetPidJnr thrpt 10 58261.657 ± 5187.550 ops/ms
    +

    即:JNI > JNR > JNA (Direct Mapping) > JNA (Interface Mapping)。相对 JNI 的实现性能,其他三种方式,从大到小的性能百分比依次为:74.8% (JNR), 13.2% (JnaDirect), 10.6% (JNA)。在博主电脑上测试,JNR 相比 JNA 将近快了 6-7 倍(JNR 作者 Charles Nutter 针对 getpid 的测试结果是 JNR 比 JNA 快 8-10 倍 [ twitter slides ])。

    +

    实现原理

    +

    JNA 源码简析

    +

    先来看下 JNA,JNA 官方文档 FunctionalDescription.md,对其实现原理有很好的阐述。这里将从源码角度分析实现的核心逻辑。

    +

    回顾下代码,我们现实定义了接口 LibC,然后通过 Native.loadLibrary("c", LibC.class) 获取了接口实现。这一步是怎么做到的呢?翻下源码 Native.java#L547 就知道,其实是通过**动态代理(dynamic proxy)**实现的。使用动态代理需要实现 InvocationHandler 接口,这个接口的实现在 JNA 源码中是类 com.sun.jna.Library.Handler。示例中的 LibC 接口定义的全部方法,将全部分派到 Handler 的 invoke 方法下。

    +
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
    +

    然后根据返回参数的不同,分派到 Native 类的,invokeXxx 本地方法:

    +
    /**
    * Call the native function.
    *
    * @param function Present to prevent the GC to collect the Function object
    * prematurely
    * @param fp function pointer
    * @param callFlags calling convention to be used
    * @param args Arguments to pass to the native function
    *
    * @return The value returned by the target native function
    */
    static native int invokeInt(Function function, long fp, int callFlags, Object[] args);

    static native long invokeLong(Function function, long fp, int callFlags, Object[] args);

    static native Object invokeObject(Function function, long fp, int callFlags, Object[] args);
    ...
    +

    比如,long getpid() 会被分派到 invokeLong,而 int chmod(String filename, int mode) 会被分派到 invokeInt。invokeXxx 本地方法参数:

    +
      +
    • 参数 Function function,记录了 lib 信息、函数名称、函数指针地址、调用惯例等元信息;
    • +
    • 参数 long fp,即函数指针地址,函数指针地址通过 Native#findSymbol()获得(底层是 Linux API dlsym 或 Windows API GetProcAddress )。
    • +
    • 参数 int callFlags,即调用约定,对应 cdecl 或 stdcall。
    • +
    • 参数 int callFlags,即函数入参,若无参数,args 大小为 0,若有多个参数,原本的入参被从左到右依次保存到 args 数组中。
    • +
    +

    再来看下 invokeXxx 本地方法的实现 dispatch.c#L2122invokeIntinvokeLong 实现源码类似):

    +
    /*
    * Class: com_sun_jna_Native
    * Method: invokeInt
    * Signature: (Lcom/sun/jna/Function;JI[Ljava/lang/Object;)I
    */
    JNIEXPORT jint JNICALL
    Java_com_sun_jna_Native_invokeInt(JNIEnv *env, jclass UNUSED(cls),
    jobject UNUSED(function), jlong fp, jint callconv,
    jobjectArray arr)
    {
    ffi_arg result;
    dispatch(env, L2A(fp), callconv, arr, &ffi_type_sint32, &result);
    return (jint)result;
    }
    +

    即,全部 invokeXxx 本地方法统一被分派到 dispatch 函数 dispatch.c#L439

    +
    static void
    dispatch(JNIEnv *env, void* func, jint flags, jobjectArray args,
    ffi_type *return_type, void *presult)
    +

    这个 dispatch 函数是全部逻辑的核心,实现最终的本地函数调用。

    +

    我们知道,发起函数调用,需要构造一个栈帧stack frame)。构造栈帧,涉及到参数压栈次序(参数从左到右压入还是从右到左压入)和清理栈帧(调用者清理还是被调用者清理)等实现细节问题。不同的编译器在不同的 CPU 架构下有不同的选择。构造栈帧的具体实现细节的选择,被称为调用惯例calling convention)。按照调用惯例构造整个栈帧,这个过程由编译器在编译阶段完成的。比如要想发起 sum(2, 3) 这个函数调用,编译器可能会生成如下等价汇编代码:

    +
    ; 调用者清理堆栈(caller clean-up),参数从右到左压入栈
    push 3
    push 2
    call _sum ; 将返回地址压入栈, 同时 sum 的地址装入 eip
    add esp, 8 ; 清理堆栈, 两个参数占用 8 字节
    +

    dispatch 函数是,需要调用的函数指针地址、输入参数和返回参数,全部是运行时确定。要想完成这个函数调用逻辑,就要运行时构造栈帧,生成参数压栈和清理堆栈的工作。JNA 3.0 之前,实现运行时构造栈帧的逻辑的对应代码 dispatch_i386.cdispatch_ppc.cdispatch_sparc.s,分别实现 Intel x86、PowerPC 和 Sparc 三种 CPU 架构。

    +

    运行时函数调用,这个问题其实是一个一般性的通用问题。早在 1996 年 10 月,Cygnus Solutions 的工程师 Anthony Green 等人就开发了 libffi(home, wiki, github, doc),解决的正是这个问题。目前,libffi 几乎支持全部常见的 CPU 架构。于是,从 JNA 3.0 开始,摒弃了原先手动构造栈帧的做法,把 libffi 集成进了 JNA。

    +

    直接映射(Direct Mapping)
    +https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#RegisterNatives
    +http://www.chiark.greenend.org.uk/doc/libffi-dev/html/The-Closure-API.html

    +

    JNR 源码简析

    +

    JNR 底层同样也是依赖 libffi,参见 jffi。但 JNR 相比 JNA 性能更好,做了很有优化。比较重要的点是,JNA 使用动态代理生成实现类,而 JNR 使用 ASM 字节码操作库生成直接实现类,去除了每次调用本地方法时额外的动态代理的逻辑。使用 ASM 生成实现类,对应的代码为 AsmLibraryLoader.java。其他细节,限于文档不全,本人精力有限,不再展开。

    +

    Java 9 的 getpid 实现

    +

    Java 9 以前 JDK 获取进程 id 没有简洁的方法,最新发布的 Java 9 中的 JEP 102(Process API Updates)增强了进程 API。进程 id 可以使用以下方式 [ javadoc ]

    +
    long pid = ProcessHandle.current().pid();
    +

    翻阅实现源码,可以看到对应的实现就是 JNI 调用:

    +

    jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl [ src ]

    +
    /**
    * Return the pid of the current process.
    *
    * @return the pid of the current process
    */
    private static native long getCurrentPid0();
    +

    *nix 平台下实现为:

    +

    jdk/src/java.base/unix/native/libjava/ProcessHandleImpl_unix.c [ src ]

    +
    /*
    * Class: java_lang_ProcessHandleImpl
    * Method: getCurrentPid0
    * Signature: ()J
    */
    JNIEXPORT jlong JNICALL
    Java_java_lang_ProcessHandleImpl_getCurrentPid0(JNIEnv *env, jclass clazz) {
    pid_t pid = getpid();
    return (jlong) pid;
    }
    +

    Windows 平台下实现为:

    +

    jdk/src/java.base/windows/native/libjava/ProcessHandleImpl_win.c [ src ]

    +
    /*
    * Returns the pid of the caller.
    *
    * Class: java_lang_ProcessHandleImpl
    * Method: getCurrentPid0
    * Signature: ()J
    */
    JNIEXPORT jlong JNICALL
    Java_java_lang_ProcessHandleImpl_getCurrentPid0(JNIEnv *env, jclass clazz) {
    DWORD pid = GetCurrentProcessId();
    return (jlong)pid;
    }
    +

    参考资料

    +
      +
    1. Changing the current working directory in Java? https://stackoverflow.com/q/840190
    2. +
    3. How can a Java program get its own process ID? http://stackoverflow.com/q/35842
    4. +
    5. Java核心技术,卷II:高级特性,第9版2013:第12章 本地方法,豆瓣
    6. +
    7. Java Native Interface: Programmer's Guide and Specification, Sheng Liang (wikilinkedinmsa), 1999,豆瓣:作者梁胜,中国科技大学少年班83级,并拥有耶鲁大学计算机博士学位(1990-1996),目前 Rancher Labs 创始人兼 CEO [ ref ]
    8. +
    9. 2013-07 Charles Nutter: Java Native Runtime http://www.oracle.com/technetwork/java/jvmls2013nutter-2013526.pdf
    10. +
    11. JEP 191: Foreign Function Interface http://openjdk.java.net/jeps/191 作者是Charles Nutter
    12. +
    13. 2014-03 Java 外部函数接口 http://www.infoq.com/cn/news/2014/03/java-foreign-function-interface
    14. +
    15. 2005-08 Brian Goetz:用动态代理进行修饰 https://www.ibm.com/developerworks/cn/java/j-jtp08305.html
    16. +
    +]]>
    + + Java + + + Java + JNI + JNA + JNR + FFI + Pyhon + Ruby + +
    + + Java 运行时获取方法参数名 + /2017/05/java-method-parameter/ + 本文整理 Java 运行时获取方法参数名的两种方法,Java 8 的最新的方法和 Java 8 之前的方法。

    +

    Java 8 的新特性

    +

    翻阅 Java 8 的新特性,可以看到有这么一条“JEP 118: Access to Parameter Names at Runtime”。这个特性就是为了能运行时获取参数名新加的。这个 JEP 只是功能增强的提案,并没有最终实现的 JDK 相关的 API 的介绍。查看“Enhancements to the Reflection API” 会看到如下介绍:

    + +
    +

    Enhancements in Java SE 8
    +Method Parameter Reflection: You can obtain the names of the formal parameters of any method or constructor with the method java.lang.reflect.Executable.getParameters. However, .class files do not store formal parameter names by default. To store formal parameter names in a particular .class file, and thus enable the Reflection API to retrieve formal parameter names, compile the source file with the -parameters option of the javac compiler.

    +
    + +

    javac 文档中关于 -parameters 的介绍如下 [ doc man ]:

    +
    +

    -parameters
    +Stores formal parameter names of constructors and methods in the generated class file so that the method java.lang.reflect.Executable.getParameters from the Reflection API can retrieve them.

    +
    +

    现在试验下这个特性。有如下两个文件:

    +
    package com.test;

    public class TestClass {
    public int sum(int num1, int num2) {
    return num1 + num2;
    }
    }
    +
    package com.test;
    import java.lang.reflect.Method;
    import java.lang.reflect.Parameter;

    public class Java8Main {
    public static void main(String[] args) throws NoSuchMethodException {
    Method method = TestClass.class.getDeclaredMethod("sum", int.class, int.class);
    Parameter[] parameters = method.getParameters();
    for (Parameter parameter : parameters) {
    System.out.println(parameter.getType().getName() + " " + parameter.getName());
    }
    }
    }
    +

    先试试 javac 不加 -parameters 编译,结果如下:

    +
    $ javac -d "target/classes" src/main/java/com/test/*.java
    $ java -cp "target/classes" com.test.Java8Main
    int arg0
    int arg1
    +

    加上 -parameters 后,运行结果如下:

    +
    $ javac -d "target/classes" -parameters src/main/java/com/test/*.java
    $ java -cp "target/classes" com.test.Java8Main
    int num1
    int num2
    +

    可以看到,加上 -parameters 后,正确获得了参数名。实际开发中,很少直接用命令行编译 Java 代码,项目一般都会用 maven 管理。在 maven 下,只需修改 pom 文件的 maven-compiler-plugin 插件配置即可,就是加上了 compilerArgs 节点 [ doc ],如下:

    +
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
    <source>1.8</source>
    <target>1.8</target>
    <compilerArgs>
    <arg>-parameters</arg>
    </compilerArgs>
    </configuration>
    </plugin>
    +

    实现原理

    +

    “Enhancements in Java SE 8”提到,参数名信息回存储在 class 文件中。现在试试用 javap doc man)命令反编译生成的 class 文件。反编译 class 文件:

    +
    $ javap -v -cp "target/classes" com.test.TestClass
    Classfile /Users/yulewei/IdeaProjects/hellojava/target/classes/com/test/TestClass.class
    Last modified 2017-5-2; size 305 bytes
    MD5 checksum 24b99fec7f3062f5de1c3ca4270a1d36
    Compiled from "TestClass.java"
    public class com.test.TestClass
    minor version: 0
    major version: 52
    flags: ACC_PUBLIC, ACC_SUPER
    Constant pool:
    #1 = Methodref #3.#15 // java/lang/Object."<init>":()V
    #2 = Class #16 // com/test/TestClass
    #3 = Class #17 // java/lang/Object
    #4 = Utf8 <init>
    #5 = Utf8 ()V
    #6 = Utf8 Code
    #7 = Utf8 LineNumberTable
    #8 = Utf8 sum
    #9 = Utf8 (II)I
    #10 = Utf8 MethodParameters
    #11 = Utf8 num1
    #12 = Utf8 num2
    #13 = Utf8 SourceFile
    #14 = Utf8 TestClass.java
    #15 = NameAndType #4:#5 // "<init>":()V
    #16 = Utf8 com/test/TestClass
    #17 = Utf8 java/lang/Object
    {
    public com.test.TestClass();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
    stack=1, locals=1, args_size=1
    0: aload_0
    1: invokespecial #1 // Method java/lang/Object."<init>":()V
    4: return
    LineNumberTable:
    line 3: 0

    public int sum(int, int);
    descriptor: (II)I
    flags: ACC_PUBLIC
    Code:
    stack=2, locals=3, args_size=3
    0: iload_1
    1: iload_2
    2: iadd
    3: ireturn
    LineNumberTable:
    line 6: 0
    MethodParameters:
    Name Flags
    num1
    num2
    }
    SourceFile: "TestClass.java"
    +

    在结尾的 MethodParameters 属性就是,实现运行时获取方法参数的核心。这个属性是 Java 8 的 class 文件新加的,具体介绍可以参考官方“Java 虚拟机官方”文档的介绍,“4.7.24. The MethodParameters Attribute”,doc

    +

    class 文件中的调试信息

    +

    上文介绍了 Java 8 通过新增的反射 API 运行时获取方法参数名。那么在 Java 8 之前,有没有办法呢?或者在编译时没有开启 -parameters 参数,又如何动态获取方法参数名呢?其实 class 文件中保存的调试信息就可以包含方法参数名。

    +

    javac-g 选项可以在 class 文件中生成调试信息,官方文档介绍如下 [ doc man ]:

    +
    +

    -g
    +Generates all debugging information, including local variables. By default, only line number and source file information is generated.
    +-g:none
    +Does not generate any debugging information.
    +-g:[keyword list]
    +Generates only some kinds of debugging information, specified by a comma separated list of keywords. Valid keywords are:
    +   source
    +     Source file debugging information.
    +   lines
    +     Line number debugging information.
    +   vars
    +     Local variable debugging information.

    +
    +

    可以看到默认是包含源代码信息和行号信息的。现在试验下不生成调试信息的情况:

    +
    $ javac -d "target/classes" src/main/java/com/test/*.java -g:none
    $ javap -v -cp "target/classes" com.test.TestClass
    Classfile /Users/yulewei/IdeaProjects/hellojava/target/classes/com/test/TestClass.class
    Last modified 2017-5-2; size 177 bytes
    MD5 checksum 559f5448154e4d7dd089f8155d8d0f55
    public class com.test.TestClass
    minor version: 0
    major version: 52
    flags: ACC_PUBLIC, ACC_SUPER
    Constant pool:
    #1 = Methodref #3.#9 // java/lang/Object."<init>":()V
    #2 = Class #10 // com/test/TestClass
    #3 = Class #11 // java/lang/Object
    #4 = Utf8 <init>
    #5 = Utf8 ()V
    #6 = Utf8 Code
    #7 = Utf8 sum
    #8 = Utf8 (II)I
    #9 = NameAndType #4:#5 // "<init>":()V
    #10 = Utf8 com/test/TestClass
    #11 = Utf8 java/lang/Object
    {
    public com.test.TestClass();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
    stack=1, locals=1, args_size=1
    0: aload_0
    1: invokespecial #1 // Method java/lang/Object."<init>":()V
    4: return

    public int sum(int, int);
    descriptor: (II)I
    flags: ACC_PUBLIC
    Code:
    stack=2, locals=3, args_size=3
    0: iload_1
    1: iload_2
    2: iadd
    3: ireturn
    }
    +

    对比上文的反编译结果,可以看到,输出结果中的 Compiled from "TestClass.java" 没了,Constant pool 中也不再有 LineNumberTableSourceFilecode 属性里的 LocalVariableTable 属性也没了(当然,因为编译时没加 -parameters 参数,MethodParameters 属性自然也没了)。若选择不生成这两个属性,对程序运行产生的最主要的影响就是,当抛出异常时,堆栈中将不会显示出错代码所属的文件名和出错的行号,并且在调试程序的时候,也无法按照源码行来设置断点。

    +
    $ javac -d "target/classes" src/main/java/com/test/*.java -g:vars
    $ javap -v -cp "target/classes" com.test.TestClass
    Classfile /Users/yulewei/IdeaProjects/hellojava/target/classes/com/test/TestClass.class
    Last modified 2017-5-2; size 302 bytes
    MD5 checksum d430f817e0e2cfafc9095279c67aaa72
    public class com.test.TestClass
    minor version: 0
    major version: 52
    flags: ACC_PUBLIC, ACC_SUPER
    Constant pool:
    #1 = Methodref #3.#15 // java/lang/Object."<init>":()V
    #2 = Class #16 // com/test/TestClass
    #3 = Class #17 // java/lang/Object
    #4 = Utf8 <init>
    #5 = Utf8 ()V
    #6 = Utf8 Code
    #7 = Utf8 LocalVariableTable
    #8 = Utf8 this
    #9 = Utf8 Lcom/test/TestClass;
    #10 = Utf8 sum
    #11 = Utf8 (II)I
    #12 = Utf8 num1
    #13 = Utf8 I
    #14 = Utf8 num2
    #15 = NameAndType #4:#5 // "<init>":()V
    #16 = Utf8 com/test/TestClass
    #17 = Utf8 java/lang/Object
    {
    public com.test.TestClass();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
    stack=1, locals=1, args_size=1
    0: aload_0
    1: invokespecial #1 // Method java/lang/Object."<init>":()V
    4: return
    LocalVariableTable:
    Start Length Slot Name Signature
    0 5 0 this Lcom/test/TestClass;

    public int sum(int, int);
    descriptor: (II)I
    flags: ACC_PUBLIC
    Code:
    stack=2, locals=3, args_size=3
    0: iload_1
    1: iload_2
    2: iadd
    3: ireturn
    LocalVariableTable:
    Start Length Slot Name Signature
    0 4 0 this Lcom/test/TestClass;
    0 4 1 num1 I
    0 4 2 num2 I
    }
    +

    可以看到,code 属性里的出现了 LocalVariableTable 属性,这个属性保存的就是方法参数和方法内的本地变量。在演示代码的 sum 方法中没有定义本地变量,若存在的话,也将会保存在 LocalVariableTable 中。

    +

    javap-v 选项会输出全部反编译信息,若只想看行号和本地变量信息,改用 -l 即可。输出结果如下:

    +
    $ javap -l -cp "target/classes" com.test.TestClass
    public class com.test.TestClass {
    public com.test.TestClass();
    LocalVariableTable:
    Start Length Slot Name Signature
    0 5 0 this Lcom/test/TestClass;

    public int sum(int, int);
    LocalVariableTable:
    Start Length Slot Name Signature
    0 4 0 this Lcom/test/TestClass;
    0 4 1 num1 I
    0 4 2 num2 I
    }
    +

    若要全部生成全部提示信息,编译参数需要改为 -g:source,lines,vars。一般在 IDE 下调试代码都需要调试信息,所以这三个参数默认都会开启。IDEA 下的 javac 默认参数设置,如图:

    +

    IDEA 默认的 javac 设置

    +

    若使用 maven,maven 的默认的编译插件 maven-compiler-plugin 也会默认开启这三个参数 [doc],经实际验证也包括了LocalVariableTable

    +

    同样的,gradle 默认也会包含调试信息 [ doc ]。

    +

    代码如何实现

    +

    上文中讲了 class 文件中的调试信息中 LocalVariableTable 属性里就包含方法名参数,这就是运行时获取方法参数名的方法。读取这个属性,JDK 并没有提供 API,只能借助第三方库解析 class 文件实现。

    +

    要解析 class 文件典型的工具库有 ObjectWeb 的 ASM(wikihomemvnjavadoc)、Apache 的 Commons BCEL(wikihomemvnjavadoc)、 日本教授开发的 Javassist(wikigithubmvnjavadoc)等。其中 ASM 使用最广,使用 ASM 的知名开源项目有,AspectJ, CGLIB, Clojure, Groovy, JRuby, Jython, TopLink等等 [ ref ]。当然使用 BCEL 的项目也很多 [ ref ]。ASM 相对其他库的 jar 更小,运行速度更快 [ javadoc ]。目前 asm-5.0.1.jar 文件大小 53 KB,BCEL 5.2 版本文件大小 520 KB,javassist-3.20.0-GA.jar 文件大小 751 KB。jar 包文件小,自然意味着代码量更少,提供的功能自然也少了。

    +

    BCEL

    +

    先来看看用 BCEL 获取方法参数名的写法,代码如下:

    +
    package com.test;
    import org.apache.bcel.Repository;
    import org.apache.bcel.classfile.JavaClass;
    import org.apache.bcel.classfile.LocalVariable;
    import org.apache.bcel.classfile.LocalVariableTable;
    import org.apache.bcel.classfile.Method;
    import org.apache.bcel.generic.Type;

    public class BcelMain {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
    java.lang.reflect.Method m = TestClass.class.getDeclaredMethod("sum", int.class, int.class);
    JavaClass clazz = Repository.lookupClass("com.test.TestClass");
    Method bcelMethod = clazz.getMethod(m);
    LocalVariableTable lvt = bcelMethod.getLocalVariableTable();
    for (LocalVariable lv : lvt.getLocalVariableTable()) {
    System.out.println(lv.getName() + " " + lv.getSignature() + " " + Type.getReturnType(lv.getSignature()));
    }
    }
    }
    +

    输出结果:

    +
    this  Lcom/test/TestClass;  com.test.TestClass
    num1 I int
    num2 I int
    +

    ASM

    +

    ASM 的写法如下:

    +
    package com.test;
    import org.objectweb.asm.*;

    public class AsmMain {

    public static void main(String[] args) throws Exception {
    ClassReader classReader = new ClassReader("com.test.TestClass");
    classReader.accept(new ParameterNameDiscoveringVisitor("sum", "(II)I"), 0);
    }

    private static class ParameterNameDiscoveringVisitor extends ClassVisitor {
    private final String methodName;
    private final String methodDesc;

    public ParameterNameDiscoveringVisitor(String name, String desc) {
    super(Opcodes.ASM5);
    this.methodName = name;
    this.methodDesc = desc;
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
    if (name.equals(this.methodName) && desc.equals(methodDesc))
    return new LocalVariableTableVisitor();
    return null;
    }
    }

    private static class LocalVariableTableVisitor extends MethodVisitor {

    public LocalVariableTableVisitor() {
    super(Opcodes.ASM5);
    }

    @Override
    public void visitLocalVariable(String name, String description, String signature, Label start, Label end, int index) {
    System.out.println(name + " " + description);
    }
    }
    }
    +

    Spring 框架

    +

    若使用 Spring 框架,对于运行时获取参数名,Spring 提供了内建支持,对应的实现类为 DefaultParameterNameDiscovererjavadoc)。该类先尝试用 Java 8 新的反射 API 获取方法参数名,若无法获取,则使用 ASM 库读取 class 文件的 LocalVariableTable,对应的代码分别为 StandardReflectionParameterNameDiscovererLocalVariableTableParameterNameDiscoverer

    +

    参考资料

    + +]]>
    + + Java + + + Java + 字节码 + JVM + +
    + + Java Executor 框架笔记 + /2017/03/java-executor/ + 本文整理 Java 并发框架 Executor 的用法,并对结合 JDK 相关的实现源码作简单分析。

    +

    任务与线程池

    +

    先来看下 Executor 框架的 javadoc 描述 [ ref1 ref2 ]

    + +

    接口:

    +
      +
    • Executor 是一个简单的标准化接口,用于定义类似于线程的自定义子系统,包括线程池、异步 IO 和轻量级任务框架。根据所使用的具体 Executor 类的不同,可能在新创建的线程中,现有的任务执行线程中,或者调用 execute() 的线程中执行任务,并且可能顺序或并发执行。
    • +
    • ExecutorService 提供了多个完整的异步任务执行框架。ExecutorService 管理任务的排队和安排,并允许受控制的关闭。ScheduledExecutorService 子接口及相关的接口添加了对延迟的和定期任务执行的支持。ExecutorService 提供了安排异步执行的方法,可执行由 Callable 表示的任何函数,结果类似于 Runnable。
    • +
    • Future 返回函数的结果,允许确定执行是否完成,并提供取消执行的方法。RunnableFuture 是拥有 run 方法的 Future,run 方法执行时将设置其结果。
    • +
    +

    实现:

    + +

    涉及到的类与接口的层次结构,如下图所示:

    +Executor 相关类 +任务相关类 +

    线程池

    +

    Executor,此接口提供一种将任务提交与每个任务将如何运行的机制(包括线程使用的细节、调度等)分离开来的方法。接口只定义唯一一个方法:

    +
    void execute(Runnable command)
    在未来某个时间执行给定的命令
    +

    实现 Executor 接口,就是定义某种运行任务的机制。最简单的运行任务的机制是,在调用者的线程中立即运行已提交的任务,如下:

    +
    class DirectExecutor implements Executor {
    public void execute(Runnable r) {
    r.run();
    }
    }
    +

    或者,以下实现将为每个任务生成一个新线程:

    +
    class ThreadPerTaskExecutor implements Executor {
    public void execute(Runnable r) {
    new Thread(r).start();
    }
    }
    +

    更典型的执行任务的方式是,使用线程池(Thread pool)。

    +

    JDK 下的 Executors 类提供创建线程池的静态工厂方法:

    +
      +
    1. newFixedThreadPool:固定大小线程池,创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程
    2. +
    3. newCachedThreadPool:无界线程池,创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们
    4. +
    5. newSingleThreadExecutor:单个后台线程池,创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程
    6. +
    7. newScheduledThreadPool:任务调度线程池,创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行
    8. +
    +

    这 4 个工厂方法返回的类型是 ExecutorService,该接口扩展自 Executor。ExecutorService 提供了管理终止的方法,以及可为跟踪一个或多个异步任务执行状况而生成 Future 的方法。

    +

    现在让我们来看看创建线程池的静态工厂方法,对应的实现源码 [ src ]:

    +
    public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
    }
    public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
    }
    public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
    (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()));
    }
    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
    }
    +

    可以看到 newFixedThreadPoolnewCachedThreadPoolnewSingleThreadExecutor 内部都是通过类 ThreadPoolExecutor 实现。ThreadPoolExecutor 的构造方法的 javadoc 如下:

    +
    public ThreadPoolExecutor(int corePoolSize,
    int maximumPoolSize,
    long keepAliveTime,
    TimeUnit unit,
    BlockingQueue<Runnable> workQueue)

    用给定的初始参数和默认的线程工厂及被拒绝的执行处理程序创建新的 ThreadPoolExecutor。使用 Executors 工厂方法之一比使用此通用构造方法方便得多。

    参数:
    corePoolSize - 池中所保存的线程数,包括空闲线程。
    maximumPoolSize - 池中允许的最大线程数。
    keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
    unit - keepAliveTime 参数的时间单位。
    workQueue - 执行前用于保持任务的队列。此队列仅保持由 execute 方法提交的 Runnable 任务。
    +

    ThreadPoolExecutor 的处理流程如下图所示(参考自《Java并发编程的艺术》第9章 Java中的线程池):
    +线程池的主要处理流程
    +ThreadPoolExecutor 执行示意图

    +

    基本上预定义的三个线程池已经满足常见的使用需求,若有特殊需求也可以,特殊构造 ThreadPoolExecutor 实例。此类提供 protected 的 beforeExecuteafterExecute 钩子 (hook) 方法,就是预留扩展用的。

    +

    ScheduledExecutorService 类提供的方法:

    +
    ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit)
    创建并执行在给定延迟后启用的 ScheduledFuture
    ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)
    创建并执行在给定延迟后启用的一次性操作
    ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
    创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期
    ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
    创建并执行一个在给定初始延迟后首次启用的定期操作,随后,在每一次执行终止和下一次执行开始之间都存在给定的延迟
    +

    用法就如文档所示,不展开描述。

    +

    提交任务

    +

    若直接使用线程运行任务,则典型的做法是创建 Runnable 接口实例,然后启动线程,如下:

    +
    Runnable r = ...
    Thread worker = new Thread(r);
    worker.start();
    worker.join();
    int result = getSavedValue();
    +

    Runnable 实例是没有直接的办法获取运行结果的返回值的,若要获取,需要添加额外的代码,如示例中 getSavedValue

    +

    Executor 框架下,使用 ExecutorService 的 submit 方法提交任务。

    +
    <T> Future<T> submit(Callable<T> task)
    提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future。该 Future 的 get 方法在成功完成时将会返回该任务的结果。
    +

    Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。但是 Callable 会返回结果,并且可以抛出经过检查的异常。 submit 方法也可以接受 Runnable 参数,但阅读内部实现代码的话,就可以看到,最终还是会通过 Executors 类的 callable 方法,将 Runnable 转换成 Callable [ src src ]。Runnable 是为线程设计的,Callable 是为任务设计。任务和线程概念上分离,这样线程如何运用任务,即运行任务的机制,就可以按具体情况定义了。

    +

    上文提到 ExecutorService 扩展自 Executor 接口,那么现在就看下 submit 方法实现源码 [ src ]:

    +
    public <T> Future<T> submit(Callable<T> task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<T> ftask = newTaskFor(task);
    execute(ftask);
    return ftask;
    }
    +

    可以看到内部实现其实就是调用 execute,但传入参数和返回结果包裹了 Callable 和 Future。execute 方法跟具体实现有关,对于 ThreadPoolExecutor 的实现逻辑,代码会根据线程大小,以及任务队列 workQueue 和工作线程 worker 状况,做出相应选择:[ doc src ]:

    +
      +
    • 如果运行的线程少于 corePoolSize,则 Executor 始终首选添加新的线程,而不进行排队。
    • +
    • 如果运行的线程等于或多于 corePoolSize,则 Executor 始终首选将请求加入队列,而不添加新的线程。
    • +
    • 如果无法将请求加入队列,则创建新的线程,除非创建此线程超出 maximumPoolSize,在这种情况下,任务将被拒绝。
    • +
    +

    使用 ExecutorService

    +

    ExecutorService 示例:

    +
    package concurrent;

    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.*;

    public class ExecutorMain {

    public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
    ExecutorService pool = Executors.newFixedThreadPool(10);

    List<Future<Integer>> futures = new ArrayList<>();
    futures.add(pool.submit(() -> {
    Thread.sleep(2000);
    System.out.println("return 1");
    return 1;
    }));
    futures.add(pool.submit(() -> {
    Thread.sleep(1000);
    System.out.println("return 2");
    return 2;
    }));
    futures.add(pool.submit(() -> {
    Thread.sleep(3000);
    System.out.println("return 3");
    return 3;
    }));

    for (Future<Integer> future : futures) {
    Integer result = future.get();
    System.out.println("get " + result);
    }
    pool.shutdown();
    }
    }
    +

    输出结果:

    +
    return 2
    return 1
    get 1
    get 2
    return 3
    get 3
    +

    为什么输出结果是这样呢?查文档知道,Future 的 get 方法,若已经完成,则直接返回,否则会等待计算完成,然后获取其结果。在示例代码中,任务1 需要 2 秒完成,任务2 需要 1 秒完成,任务3 需要 3 秒完成。自然,在线程池中完成次序是,任务2 - 任务1 - 任务3。main 主线程,先是获取 get 任务1 的执行结果,需要等待 2 秒,在去获取 get 任务2 的执行结果,此时该任务已经完成,直接返回,接下来是获取 get 任务3 的执行结果,任务3 耗时 3 秒,此时时间线是第 2 秒,所以需等 1 秒,才能获取 get 执行结果。

    +

    使用 ExecutorService,若想按任务完成次序获取执行结果,可以将代码中 for 循环,修改为轮询方式,就不断地在调用 get 前,先用 isDone 判断是否任务已经完成。代码如下:

    +
    while (true) {
    Iterator<Future<Integer>> iter = futures.iterator();
    if (!iter.hasNext()) break;
    while (iter.hasNext()) {
    Future<Integer> future = iter.next();
    if (future.isDone()) {
    Integer result = future.get();
    System.out.println("get " + result);
    iter.remove();
    }
    }
    }
    +

    输出结果:

    +
    return 2
    get 2
    return 1
    get 1
    return 3
    get 3
    +

    这种实现方式,虽然可行,但相当繁琐。幸运的是,JDK 还提供一种更好的方法,CompletionService

    +

    使用 CompletionService

    +

    CompletionServiceExecutorBlockingQueue 的功能融合在一起。你可以将 Callable 任务提交给它来执行,然后使用类似于队列操作的 takepoll 等方法来获得已完成的结果,而这些结果会在完成时将被封装为 Future。ExecutorCompletionService 实现了 CompletionService。ExecutorCompletionService 的实现非常简单。在构造函数中创建一个 BlockingQueue 来保存计算完成的结果。当计算完成时,调用 FutureTask 中的 done 方法。当提交某个任务时,该任务将首先包装为一个 QueueingFuture,这是 FutureTask 一个子类,然后再改写子类的 done 方法,并将结果放入 BlockingQueue 中,take 和 poll 方法委托给了 BlockingQueue,这些方法会在得出结果之前阻塞。[ Goetz 2006, 6.3.5 ]

    +

    可以看出整个实现逻辑核心在于重写 FutureTask 的 done 方法,正如这个方法的 javadoc 所述,定义该方法的目的就是如此:

    +
    protected void done()
    当此任务转换到状态 isDone(不管是正常地还是通过取消)时,调用受保护的方法。默认实现不执行任何操作。子类可以重写此方法,以调用完成回调或执行簿记
    +

    再来看下,BlockingQueue 的实现源码 [ src ],以及 submit 任务是对应的实现源码 [ src ]:

    +
    public Future<V> submit(Callable<V> task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<V> f = newTaskFor(task);
    executor.execute(new QueueingFuture(f));
    return f;
    }
    +
    private class QueueingFuture extends FutureTask<Void> {
    QueueingFuture(RunnableFuture<V> task) {
    super(task, null);
    this.task = task;
    }
    protected void done() { completionQueue.add(task); }
    private final Future<V> task;
    }
    +

    然后再看下 ExecutorCompletionService 的 take 和 poll 方法的实现源码 [ src ]:

    +
    public Future<V> take() throws InterruptedException {
    return completionQueue.take();
    }

    public Future<V> poll() {
    return completionQueue.poll();
    }
    +

    整个实现逻辑正如上面文字所述。

    +

    上文示例的 ExecutorMain,现在用 CompletionService 重现实现如下:

    +
    package concurrent;

    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.*;

    public class CompletionServiceMain {

    public static void main(String[] args) throws InterruptedException, ExecutionException {
    ExecutorService pool = Executors.newFixedThreadPool(10);
    CompletionService<Integer> service = new ExecutorCompletionService<>(pool);

    List<Future<Integer>> futures = new ArrayList<>();
    futures.add(service.submit(() -> {
    Thread.sleep(2000);
    System.out.println("return 1");
    return 1;
    }));
    futures.add(service.submit(() -> {
    Thread.sleep(1000);
    System.out.println("return 2");
    return 2;
    }));
    futures.add(service.submit(() -> {
    Thread.sleep(3000);
    System.out.println("return 3");
    return 3;
    }));

    for (int i = 0; i < futures.size(); i++) {
    Integer result = service.take().get();
    System.out.println("get " + result);
    }
    pool.shutdown();
    }
    }
    +

    运行结果,就是依次输出,任务2 - 任务1 - 任务3:

    +
    return 2
    get 2
    return 1
    get 1
    return 3
    get 3
    +

    Guava 的 ListenableFuture

    +

    CompletionService 的逻辑是,任务完成后,依次添加到完成队列中,然后让主线程主动去获取这些已经完成的任务。其实这种主线程主动模式,也可以修为被动模式,即任务完成后主动以事件回调的形式通知主线程,主动方从主线程换成了任务本身。这种方式就消除了等待任务完成的过程。可惜的是直到 Java 8 新添加的 CompletableFuture 才支持实现这种机制。在 Java 8 之前,需要借助第三方库,比如 Guava 提供的 ListenableFuture。使用 CompletableFuture 需要了解 lambda 以及函数式编程相关知识,本文暂不展开,本文只讨论 ListenableFuture。来看下 Guava 的 ListenableFuture 主要涉及到的类 [ doc ]:

    +
      +
    • ListeningExecutorService:扩展自 ExecutorService 接口,但不同的是,提交 submit 过去的任务返回的是 ListenableFuture 实例。
    • +
    • ListenableFuture:扩展自 Future 接口,唯一新增的方法是 addListener,用于添加 Future 完成后的回调监听器。
    • +
    • MoreExecutors:工具类,类似于 JDK 的 Executors,主要提供 Executor 的桥接、转换和构造的工具方法。
    • +
    • Futures:工具类,提供 Future 接口相关的静态工具方法,如静态方法 addCallback 用于添加任务执行的回调监听器,包括对任务执行成功的 onSuccess 事件和执行失败(抛出异常或被取消)的 onFailure 事件。
    • +
    • ListenableFutureTask:实现 ListenableFuture 接口的 FutureTask。
    • +
    +

    这些类如何使用呢?还是先来看下示例代码吧。

    +
    package concurrent;

    import com.google.common.util.concurrent.*;
    import java.util.concurrent.Executors;

    public class ListenableFutureMain {

    public static void main(String[] args) {
    ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));

    ListenableFuture<Integer> task = service.submit(() -> {
    Thread.sleep(2000);
    return 42;
    });
    Futures.addCallback(task, new FutureCallback<Integer>() {
    public void onSuccess(Integer result) {
    System.out.println("onSuccess " + result);
    }
    public void onFailure(Throwable t) {
    System.out.println("onFailure");
    }
    });

    service.shutdown();
    }
    }
    +

    简单解释下。MoreExecutors 工具类的 listeningDecorator 方法将 JDK 创建的 ExecutorService 装饰为 ListeningExecutorService。接下来,创建的任务,并提交 submit 到这个 ExecutorService 里。submit 方法返回 ListenableFuture 接口实例(内部实现其实就是 ListenableFutureTask 对象)。Futures 工具类的 addCallback 方法用于添加在任务执行回调的监听器。

    +

    类似于 JDK 的 CompletionService,实现 Guava 的 ListeningExecutorService 也是通过重写 FutureTask 的 done 方法完成的。FutureTask 对应的子类就是 ListenableFutureTask(事实上,Guava 版本 19 开始 ListenableFutureTask 类替换成立了 TrustedListenableFutureTask 类 [ github ],这里暂不展开分析)。实现 ListenableFutureTask 的核心代码如下 [ src ]:

    +
    private final ExecutionList executionList = new ExecutionList();

    @Override
    public void addListener(Runnable listener, Executor exec) {
    executionList.add(listener, exec);
    }

    @Override
    protected void done() {
    executionList.execute();
    }
    +

    之前查看 submit 方法实现源码时,看到该方法内部会调用 newTaskFor 方法创建 FutureTask。相应的 JDK 的 AbstractExecutorService 的 newTaskFor 也 Guava 的 AbstractListeningExecutorService 被重写为 [ src ]:

    +
    @Override protected final <T> ListenableFutureTask<T> newTaskFor(Callable<T> callable) {
    return ListenableFutureTask.create(callable);
    }
    +

    这样在线程池中运行任务的不再是 FutureTask,而变成了 ListenableFutureTask。任务完成后调用 done 方法,而 done 方法就去执行该任务关联的监听器列表,即 executionList.execute()

    +

    再来看下 Futures 工具类的 addCallback 方法的实现 [ src ]:

    +
    public static <V> void addCallback(final ListenableFuture<V> future,
    final FutureCallback<? super V> callback, Executor executor) {
    Preconditions.checkNotNull(callback);
    Runnable callbackListener = new Runnable() {
    @Override
    public void run() {
    final V value;
    try {
    // TODO(user): (Before Guava release), validate that this
    // is the thing for IE.
    value = getUninterruptibly(future);
    } catch (ExecutionException e) {
    callback.onFailure(e.getCause());
    return;
    } catch (RuntimeException e) {
    callback.onFailure(e);
    return;
    } catch (Error e) {
    callback.onFailure(e);
    return;
    }
    callback.onSuccess(value);
    }
    };
    future.addListener(callbackListener, executor);
    }
    +

    ListenableFuture API 功能的完整介绍参见 ListenableFutureExplained,本文不再展开。

    +

    Fork/Join 框架

    +

    一个大的任务可能会由多个子任务组成,比如整个任务A,由任务B 和任务C 组成,而任务B 又可以被分解为任务D 和任务E,如下图所示。任务分解组合问题,利用 ListenableFuture 的回调将子任务组合起来是一种解决办法,但还是不够优雅简洁。Java 7 引入的 Fork/Join 框架,就是以这种方式设计的。Fork/Join 框架编程的风格就是,将任务分解为多个子任务,并行执行,然后将结果组合起来,即分而治之。ExecutorService 适合解决相互独立的任务,而 Fork/Join 框架适合解决任务分解组合的情况 [ ref ]。

    +任务的分治 +

    其实整个 java.util.concurrent 包是由 JSR-166 规范引入的,Fork/Join 框架就是其中的 jsr166y。JSR-166 由 Doug Lea 主导,是主要设计和代码实现者,而 jsr166y 最初源自他发表于 2000 年的论文“A Java Fork/Join Framework”(msa pdf)。

    +

    工作窃取

    +

    Fork/Join 框架采用工作窃取(work stealing)的任务调度机制 [ ref ]:

    +
      +
    • 每一个工作线程维护自己的调度队列中的可运行任务。
    • +
    • 队列以双端队列 deque 的形式被维护,不仅支持 LIFO(last-in-first-out 后进先出)的 push 和 pop 操作,还支持 FIFO(first-in-first-out 先进先出)的 take 操作。
    • +
    • 对于一个给定的工作线程来说,任务所产生的子任务将会被放入到工作者自己的双端队列 deque 中。
    • +
    • 工作线程使用 LIFO(最早的优先)的顺序,通过弹出任务来处理队列中的任务。
    • +
    • 当一个工作线程的本地没有任务去运行的时候,它将使用 FIFO 的规则尝试随机的从别的工作线程中拿(“窃取 steal”)一个任务去运行。
    • +
    • 当一个工作线程触及了 join 操作,如果可能的话它将处理其他任务,直到目标任务被告知已经结束(通过 isDone 方法)。所有的任务都会无阻塞的完成。
    • +
    • 当一个工作线程无法再从其他线程中获取任务和失败处理的时候,它就会退出(通过 yields, sleeps, 和/或者优先级调整)并经过一段时间之后再度尝试直到所有的工作线程都被告知他们都处于空闲的状态。在这种情况下,他们都会阻塞直到其他的任务再度被上层调用。
    • +
    +work stealing +

    使用 LIFO 规则来处理每个工作线程的自己任务,窃取别的工作线程的任务却使用 FIFO 规则,这是一种被广泛使用的进行递归 fork/join 设计的一种调优手段。这种模式有以下两个优点:它通过窃取工作线程队列反方向的任务减少了竞争。同时,它利用了递归的分治算法越早的产生大任务这一特点。因此,更早期被窃取的任务有可能会提供一个更大的单元任务,从而使得窃取线程能够在将来进行递归分解。

    +

    这些规则的结果是,拥有相对细粒度的基本任务,比那些仅仅使用粗粒度划分或没有使用递归分解的任务运行更快。

    +

    使用示例

    +

    ForkJoinPool 类是用于执行 ForkJoinTask 的 ExecutorService。在构造过程中,可以在构造函数中指定线程池的大小。如果使用的是默认的无参构造函数,那么会创建大小等同于可用处理器数量的线程池。ForkJoinPool 类的典型方法:

    +
    public void execute(ForkJoinTask<?> task)
    异步,不需要等待计算结果,只是将任务提交给线程池
    public <T> T invoke(ForkJoinTask<T> task)
    同步,等待计算结束,并返回计算结果值
    public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task)
    异步,不需要等待计算结果,只是将任务提交给线程池
    +

    提交到 ForkJoinPool 中的任务由 ForkJoinTask 抽象类表示。ForkJoinTask 的实现子类有 RecursiveActionRecursiveTask,以及 Java 8 新增的 CountedCompleter。RecursiveAction 用于没有返回结果的任务,RecursiveTask 用于返回结果的任务。CountedCompleter 用于完成动作会触发另外一个动作的任务 [ javadoc ]。

    +

    计算斐波那契数(Fibonacci number)是一个经典的分而治之的问题。Doug Lea 的论文以及 RecursiveTask 的 javadoc 都以斐波那契数为例进行说明。斐波那契数定义公式为:

    +

    Fn=Fn1+Fn2F_{n}=F_{n-1}+F_{n-2} +

    +

    F0=0,F1=1F_{0}=0, F_{1}=1 +

    +

    使用 Fork/Join 框架计算斐波那契数的示例代码如下:

    +
    package concurrent;

    import java.util.concurrent.ForkJoinPool;
    import java.util.concurrent.RecursiveTask;

    public class ForkJoinMain {

    public static class Fibonacci extends RecursiveTask<Integer> {
    final int n;

    public Fibonacci(int n) {
    this.n = n;
    }

    protected Integer compute() {
    if (n <= 1)
    return n;
    Fibonacci f1 = new Fibonacci(n - 1);
    Fibonacci f2 = new Fibonacci(n - 2);
    f1.fork();
    return f2.compute() + f1.join();
    }
    }

    public static void main(String[] args) throws Exception {
    ForkJoinPool pool = new ForkJoinPool();
    Fibonacci fib = new Fibonacci(3);
    pool.invoke(fib); // 等待计算完成
    Integer result = fib.get();
    System.out.println(result);
    }
    }
    +

    这个计算过程如下图所示:

    +

    fork-join

    +

    参考资料

    +
      +
    1. Java 并发编程实战,Goetz,2006;第6章 任务执行 https://book.douban.com/subject/10484692/
    2. +
    3. Java并发编程的艺术,方腾飞,2015 https://book.douban.com/subject/26591326/
    4. +
    5. ExecutorService vs ExecutorCompletionService in Java https://dzone.com/articles/executorservice-vs
    6. +
    7. Java's Fork/Join vs ExecutorService - when to use which? https://stackoverflow.com/q/21156599
    8. +
    9. Java Fork Join框架 (三) 设计 http://ifeve.com/a-java-fork-join-framework-3-2/
    10. +
    +]]>
    + + Java + + + 并发 + Java + +
    + + Java 官方文档整理 + /2016/11/java-official-doc/ + 本文整理一些学习Java需要翻阅或必须的官方文档资料。

    + +

    Java SE文档

    +

    Java SE Technologies at a Glance http://www.oracle.com/technetwork/java/javase/tech/index.html

    +

    http://docs.oracle.com/javase/8/
    +http://docs.oracle.com/javase/8/docs/index.html Platform Overview平台概览图
    +http://docs.oracle.com/javase/8/javase-books.htm

    +

    Java Platform Overview (docs/technotes/guides)

    +
      +
    1. Java Programming Language (guides/language)
    2. +
    3. Java Virtual Machine Technology (guides/vm)
    4. +
    5. JDK Tools and Utilities (technotes/tools)
    6. +
    +

    Java SE API:

    +
      +
    1. Base Libraries (guides/#base):
    2. +
    + +
      +
    1. Integration Libraries (guides/#integration): IDL (CORBA, org.omg.*), JDBC (java.sql & javax.sql), RMI (java.rmi), RMI-IIOP (org.omg.*) JNDI (javax.naming), Scripting (javax.script)
    2. +
    3. User Interface Libraries (guides/#userinterface): Swing, Java 2D, AWT, Accessibility, Drag and Drop, Input Methods, Image I/O, Print Service, Sound
    4. +
    +

    http://docs.oracle.com/javase/8/docs/technotes/guides/scripting/

    +

    中文API文档:
    +http://download.oracle.com/technetwork/java/javase/6/docs/zh/api/
    +http://www.cjsdn.net/Doc/JDK60/

    +
    +

    Java虚拟机

    +

    https://en.wikipedia.org/wiki/Template:Java_Virtual_Machine
    +https://en.wikipedia.org/wiki/Java_performance

    +

    JDK源码
    +https://github.com/dmlloyd/openjdk
    +https://github.com/openjdk-mirror/jdk7u-jdk
    +https://github.com/openjdk-mirror/jdk7u-hotspot

    +

    虚拟机与性能
    +http://en.wikipedia.org/wiki/Template:Java_%28software_platform%29
    +http://en.wikipedia.org/wiki/Template:Java_Virtual_Machine
    +http://en.wikipedia.org/wiki/Java_performance
    +http://openjdk.java.net/groups/hotspot/

    +

    Java SE HotSpot at a Glancelink

    +
      +
    1. HotSpot Engine Architecture,link
    2. +
    3. HotSpot Thread Implementation (Solaris),link
    4. +
    5. HotSpot Garbage Collection,link
    6. +
    +
      +
    • Memory Management Whitepaper[pdf]link:最权威、最完整文档
    • +
    • Garbage Collector Ergonomics,link
    • +
    • Garbage Collection Tuning,link
    • +
    • Garbage First ("G1") Garbage Collector,link
    • +
    +
      +
    1. HotSpot Ergonomics,link
    2. +
    3. HotSpot Performance and Tuning,link
    4. +
    +
      +
    • 2007.10, Java SE 6.0 Performance White Paper,link
    • +
    • 2005.03, J2SE 5.0 Performance White Paper,link
    • +
    +
      +
    1. HotSpot Publications,link
    2. +
    +

    Troubleshooting Java SE 8,link 资料汇总

    +
      +
    1. Java Troubleshooting Guide Java SE 8,link
    2. +
    3. Troubleshooting Guide for Java SE 6 with HotSpot VM,link
    4. +
    5. Troubleshooting Guide for HotSpot VM (JDK 7),link
    6. +
    +]]>
    + + Java + + + Java + JVM + +
    + + 微服务 API 网关 Kong 实践 + /2020/05/kong-gateway/ + Kong 简介 +

    Kong 是云原生、高效、可扩展、分布式的微服务抽象层,被称为 API 网关,或者 API 中间件。Kong 在 2015 年 4 月由 Mashape 公司开源,基于 OpenResty 和 Apache Cassandra/PostgreSQL 构建,提供易于使用的 RESTful API 来操作和配置 API 系统[1][2]

    + +

    Mashape 是 API 集市,是为应用开发者与 API 提供者服务的 API 交易市场,Mashape 让发者能够方便地查找与购买 API,而 API 提供商则能轻松地销售与管理 API[3]。随着 Mashape 市场上的 API 越来越多,原先基于 Node.js 实现的 API 代理不再适用,不能处理大流量尖峰,无法快速扩容。于是,寻找处理大流量的方案,同时需要保证可靠性和安全性,成为 Mashape 亟待解决的问题。2013 年,在 CloudFlare(当时 OpenResty 背后的公司)的工程师的建议下,Mashape 开始在 OpenResty 基础上开发 Kong 项目[4]。Mashape 公司的名字,MashAPE,有人猿猩猩的含义,公司 logo 也是相应动物。类似的,Kong,对应的是,King Kong,就是电影里的金刚[4:1]。在 Mashape 开启 Kong 项目两年后,2015 年 4 月,Mashape 公司开源了 Kong[2:1]

    +

    2017 年 5月,Mashape 和 RapidAPI 合并,组成全球最大的 API 集市[5][6]。5 个月后,Mashape, Inc. 改名为 Kong Inc.,新的公司以 Kong 项目为聚焦,把全部工程师投入到 Kong 开发中,并且于此同时他们发布了 Kong 企业版[7]

    +

    Kong,作为微服务的请求的网关,能通过插件提供负载均衡、日志记录、鉴权、限流、转换以及其他等功能。相对与旧的、没有使用网关的方式,Kong 把这些通用功能中心化,让微服务更加专注于业务本身。

    +The Old way vs. The Kong Way +

    Kong 的整体架构,如下图所示[1:1]

    +
      +
    • 管理 API:通过 RESTful API 管理 Kong;能自动化集成;管理 API 能通过插件扩展
    • +
    • 插件:使用 Lua 脚本创建 Plugins;实现强力的定制化;与第三方服务集成
    • +
    • 集群和数据存储:数据存储可选择 PostgreSQL 或 Cassandra;能从单节点扩展为集群;使用内存缓存提高性能
    • +
    • OpenResty:拦截请求/响应生命周期;基于 NGINX 扩展;Lua 脚本化
    • +
    • NGINX:验证过的高性能基础组件;HTTP 和反向代理服务器;处理底层操作
    • +
    +Kong Architecture +

    Kong 安装

    +

    目前最新的 Kong 版本是 2.0.x,2.0 发布时间是 2020 年 1 月,而 1.0 发布时间是 2018 年 12 月[8][9]。笔者公司使用的 Kong 版本是 0.14.1,暂时未升级自最新版,所以下文阐述的 Kong 版本主要以 0.14.1 为准,并同时会提及其他版本的特性。

    +

    安装 Kong 很简单,参见官方文档即可。在 Ubuntu 18.04 下安装 Kong 0.14.1,可以执行下面的命令:

    +
    # kong 安装
    $ sudo apt update
    $ sudo apt install openssl libpcre3 procps perl
    $ wget -O kong-community-edition-0.14.1.trusty.all.deb https://bintray.com/kong/kong-community-edition-deb/download_file?file_path=dists/kong-community-edition-0.14.1.trusty.all.deb
    $ sudo dpkg -i kong-community-edition-0.14.1.trusty.all.deb
    $ kong version
    0.14.1
    +

    Kong 依赖数据库,Postgres 或者 Cassandra,默认依赖 Postgres(kong 1.1 开始支持无数据库声明式配置[10])。我们预先安装 Postgres:

    +
    # 安装 postgresql
    $ sudo apt install postgresql
    $ sudo service postgresql start
    $ psql --version
    psql (PostgreSQL) 10.12 (Ubuntu 10.12-0ubuntu0.18.04.1)
    +

    在 Postgres 下添加 Kong 需要的的数据库实例和用户。下面的示例,创建数据库 kong,用户名 kong,密码为 kong

    +
    $ sudo -u postgres psql
    postgres=# CREATE USER kong; CREATE DATABASE kong OWNER kong;
    postgres=# ALTER USER kong WITH PASSWORD 'kong';
    postgres=# \q
    +

    执行完成后,即可使用用户名为 kong 的用户连接 Postgres,psql -h localhost -U kong -d kong

    +

    Kong 安装完成后,默认会创建配置文件 /etc/kong/kong.conf.default,这份配置文件在 GitHub 上也能找到,被注释掉的配置项,就是默认设置。

    +

    在启动 Kong 网关服务器前,我们参考 kong.conf.default,创建自己的 kong.conf 配置文件。我们把配置文件放在 /home/yulewei/kong 目录下,同时也把这目录当作为 Kong 的 prefix 目录。修改这配置 kong.conf,文件末尾添加:

    +
    prefix = /home/yulewei/kong/
    pg_user=kong
    pg_password=kong
    pg_database = kong
    +

    使用 kong 命令,启动 Kong 网关服务器:

    +
    # 初始化或迁移数据库数据
    $ kong migrations up -c /home/yulewei/kong/kong.conf
    # 启动 kong
    $ kong start -c /home/yulewei/kong/kong.conf
    +

    Kong 默认绑定 4 个端口:

    +
      +
    • :8000 用来接收来自客户端的 HTTP 流量的请求,并转发到上游服务
    • +
    • :8443 用来接收来自客户端的 HTTPS 流量的请求,并转发到上游服务
    • +
    • :8001 用来接收访问 Admin API 的 HTTP 流量的请求
    • +
    • :8444 用来接收访问 Admin API 的 HTTPS 流量的请求
    • +
    +

    所以,可以执行下面的命令,来确认 Kong 是否正常运行:

    +
    # 确认 Kong 是否正常运行
    $ curl -i http://localhost:8000/
    $ curl -i http://localhost:8001/
    +

    Kong 底层依赖 OpenResty,启动 Kong 后,可以看到 nginx 进程:

    +
    # 查看 nginx 进程
    $ ps -ef | grep nginx
    yulewei 19090 1 0 16:05 ? 00:00:00 nginx: master process /usr/local/openresty/nginx/sbin/nginx -p /home/yulewei/kong -c nginx.conf
    yulewei 19091 19090 0 16:05 ? 00:00:00 nginx: worker process
    yulewei 19092 19090 0 16:05 ? 00:00:00 nginx: worker process
    +

    安装 Kong 0.14.1,自动安装的 OpenResty 版本是 1.13.6.2,OpenResty 捆绑的安装了 LuaJIT。

    +
    $ /usr/local/openresty/nginx/sbin/nginx -v
    nginx version: openresty/1.13.6.2

    $ /usr/local/openresty/bin/resty -V
    resty 0.21
    nginx version: openresty/1.13.6.2
    built by gcc 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.4)
    built with OpenSSL 1.0.2n 7 Dec 2017
    TLS SNI support enabled
    configure arguments: ... 省略 ...

    $ /usr/local/openresty/luajit/bin/luajit -v
    LuaJIT 2.1.0-beta3 -- Copyright (C) 2005-2017 Mike Pall. http://luajit.org/
    +

    另外,同时也安装了 LuaRocks,LuaRocks 关联的是 OpenResty 捆绑的 LuaJIT。事实上,Kong 就是一个 LuaRocks 的 rock 包,在Kong 项目的 GitHub 上可以看到 rockspec 文件。Kong 的安装,底层实现上,是通过 luarocks 命令完成的,类似这样的命令,luarocks install kong 0.14.1-0[11][12]。可以使用 luarocks show 命令查看这个 Kong 的 rcok 包:

    +
    $ luarocks show kong
    kong 0.14.1-0 - Kong is a scalable and customizable API Management Layer built on top of Nginx.

    License: MIT
    Homepage: http://getkong.org
    Installed in: /usr/local

    Modules:
    kong (/usr/local/share/lua/5.1/kong/init.lua)
    kong.api (/usr/local/share/lua/5.1/kong/api/init.lua)
    ... 省略 ...
    +

    有个小细节值得注意,通过 luarocks 看到,Kong 采用的协议是 MIT。但事实上,Kong 0.5.0 开始协议从 MIT 改成了 Apache 2.0。此处是一个小 bug,Kong 的 rockspec 文件没有及时更新,这个问题后来修复了,参见 #4125

    +

    GUI 管理工具

    +

    管理 Kong 可以直接使用 Admin API,当然也有基于 Admin API 实现 GUI 管理工具。

    +

    Kong 官方的企业版提供了 GUI 管理工具,Kong Manager(Kong EE 0.34 之前称为 Admin GUI),Kong 社区版没有提供 GUI 管理工具。

    +

    第三方的开源 GUI 工具,比较活跃的就是 Konga,值得推荐,如下图。

    +konga +

    另外,还有其他的 GUI 工具,比如 Kong Dashboard,也可以了解下。

    +

    Kong 使用

    +

    Kong 核心概念:

    +
      +
    • Service:对应位于 Kong 后方的自身的 Upstream API 或微服务。
    • +
    • Route:Kong 的入口点,定义了如何把请求发送到特定 Service 的规则。一个 Service 可以有多个Route
    • +
    • Plugin:插件提供了模块化系统,用来修改或控制 Kong。插件提供了大量功能,比如访问控制、缓存、限流、日志记录等。
    • +
    • Consumer:消费者,表示使用 API 的用户,能用来对用户进行访问控制、跟踪等。
    • +
    +

    Kong 网关的请求响应工作流,如下图所示:

    +Kong Overview +

    反向代理

    +

    Kong 的核心功能就是对现有的上游服务的 API 作反向代理。反向代理,官方的完整的文档参见[13]。现在我们来试验下 Kong 的反向代理功能,执行下面的命令:

    +
    # 添加 service
    $ curl -XPOST -H 'Content-Type: application/json' \
    -d '{"name":"example.service","url":"http://httpbin.org"}' \
    http://localhost:8001/services/

    # 在 service 上添加 route
    $ curl -XPOST -H 'Content-Type: application/json' \
    -d '{"paths":["/base64"],"strip_path":false}' \
    http://localhost:8001/services/example.service/routes
    +

    上面的第一条命令,通过调用 Kong 提供的 Admin API,让 Kong 创建了名为 example.serviceserviceservice 指向的上游服务是 http://httpbin.org。第二条命令,在 example.service 上添加 route 规则,规则是让请求路径前缀为 /base64 的请求转发到这个 service。来验证下,刚刚的 Kong 的配置:

    +
    # 验证 Kong 配置结果
    $ curl http://httpbin.org/base64/aGVsbG8ga29uZw==
    hello kong
    $ curl http://localhost:8000/base64/aGVsbG8ga29uZw==
    hello kong
    +

    上文的 Kong 配置,等价的 nginx.conf 配置文件的写法是:

    +
    server {
    listen 8000;
    location /base64 {
    proxy_pass http://httpbin.org/base64;
    }
    }
    +

    除了前缀外,route 规则的 paths 字段也支持 PCRE 正则表达式,来看下示例:

    +
    curl -XPOST -H 'Content-Type: application/json' \
    -d '{"paths":["/status/\\d+"],"strip_path":false}' \
    http://localhost:8001/services/example.service/routes
    +

    上面的命令,添加 route 规则,设置的 paths 字段值为 /status/\d+,让只有请求路径的中包含数字才能匹配。

    +
    # 验证 Kong 配置结果
    $ curl -sI http://httpbin.org/status/418 | head -n1
    HTTP/1.1 418 I'M A TEAPOT
    $ curl -sI http://localhost:8000/status/418 | head -n1
    HTTP/1.1 418 I'M A TEAPOT
    $ curl -sI http://localhost:8000/status/200 | head -n1
    HTTP/1.1 200 OK
    $ curl http://localhost:8000/status/abc
    {"message":"no route and no API found with those values"}
    +

    负载均衡

    +

    上文的反向代理指向的是单台的上游服务器,如果要指向多台上游服务器,实现负载均衡,要如何配置呢?负载均衡,Nginx 可以通过 upstream 指令实现,而类似的,Kong 通过创建 upstream 对象实现。

    +

    假设在服务器 192.168.2.100:80192.168.2.101:80 上运行着本地版的 httpbin.org 的 REST API 服务(通过 docker run -p 80:80 kennethreitz/httpbin)。执行下面的命令:

    +
    # 添加 upstream
    curl -XPOST -H 'Content-Type: application/json' \
    -d '{"name":"example.upstream"}' \
    http://localhost:8001/upstreams/

    # 在 upstream 上添加 target
    curl -XPOST -H 'Content-Type: application/json' \
    -d '{"target":"192.168.2.100:80"}' \
    http://localhost:8001/upstreams/example.upstream/targets

    # 在 upstream 上添加 target
    curl -XPOST -H 'Content-Type: application/json' \
    -d '{"target":"192.168.2.101:80"}' \
    http://localhost:8001/upstreams/example.upstream/targets

    # 添加 service
    curl -XPOST -H 'Content-Type: application/json' \
    -d '{"name":"example.service","host":"example.upstream"}' \
    http://localhost:8001/services/

    # 在 service 上添加 route
    curl -XPOST -H 'Content-Type: application/json' \
    -d '{"paths":["/base64"],"strip_path":false}' \
    http://localhost:8001/services/example.service/routes
    +

    上面的命令,先创建了 upstream 对象,虚拟主机名(virtual hostname)为 example.upstream 。然后在这个 upstream 上添加 target192.168.2.100:80192.168.2.101:80。再然后把 service 对象的 host 字段值设置为 example.upstream。这样全部发送到这个 service 的请求都会被转发到 example.upstream 这个 upstreamupstream 再执行负载均衡算法,把请求转发到最终的上游服务器。和 Nginx 一样,默认的负载均衡算法为加权轮询算法(weighted-round-robin)。

    +
    # 验证 Kong 配置结果
    $ curl http://localhost:8000/base64/aGVsbG8ga29uZw==
    hello kong
    +

    上文的 Kong 配置,等价的 nginx.conf 配置文件的写法是:

    +
    upstream example.upstream {
    server 192.168.2.100:80;
    server 192.168.2.101:80;
    }
    server {
    listen 8000;
    location /base64 {
    proxy_pass http://example.upstream/base64;
    }
    }
    +

    关于 Kong 负载均衡的更多介绍,可以阅读官方文档[14],本文不再展开。

    +

    开启插件

    +

    Kong 提供了很多插件,官方整理维护的全部插件列表,可以在官网上看到。全部插件分 8 大类:身份认证类插件(Authentication)、安全控制类插件(Security)、流量控制类插件(Traffic Control)、无服务器计算类插件(Serverless)、分析与监控类插件(Analytics & Monitoring)、协议转换类插件(Transformations)、日志记录类插件(Logging)、部署类插件(Deployment)。Kong 0.14.1 社区版默认绑定的预定义插件,全部 31 个,调用下面的 Admin API 可以查看:

    +
    # Kong 社区版全部默认绑定的插件,共 31 个
    $ curl http://localhost:8001/plugins/enabled
    {"enabled_plugins":["response-transformer","oauth2","acl","correlation-id","pre-function","jwt","cors","ip-restriction","basic-auth","key-auth","rate-limiting","request-transformer","http-log","file-log","hmac-auth","ldap-auth","datadog","tcp-log","zipkin","post-function","request-size-limiting","bot-detection","syslog","loggly","azure-functions","udp-log","response-ratelimiting","aws-lambda","statsd","prometheus","request-termination"]}
    +

    现在我们来试下 Kong 的 basic-auth 插件,用来实现 HTTP Basic 认证(RFC 7617)。执行下面的命令,在上文的 example.serviceservice 上开启 basic-auth 插件:

    +
    # 在 service 上开启 basic-auth 插件
    $ curl -XPOST --data "name=basic-auth" \
    http://localhost:8001/services/example.service/plugins
    +

    这样全部到 example.service 的请求都需要进行 Basic 认证。再次请求之前的 /base64 接口,返回状态码 401 Unauthorized

    +
    # 接口 HTTP 状态码返回 401
    $ curl -i http://localhost:8000/base64/aGVsbG8ga29uZw==
    HTTP/1.1 401 Unauthorized
    ... 省略 ...

    {"message":"Unauthorized"}
    +

    添加身份认证的凭证,添加 username/password:

    +
    # 添加 consumer
    $ curl -XPOST --data "username=Jason" \
    http://localhost:8001/consumers/
    # 在 consumer 上添加 basic-auth 插件的凭证 username/password
    $ curl -XPOST --data "username=test&password=123456" \
    http://localhost:8001/consumers/Jason/basic-auth
    +

    现在请求头上带上凭证,重新请求 /base64 接口,响应正常:

    +
    $ curl -u 'test:123456' http://localhost:8000/base64/aGVsbG8ga29uZw==
    hello kong
    +

    Kong 插件,除了绑定到 service 上外,也可以绑定在 routeconsumer 上。如果开启插件时,servicerouteconsumer 全部都不关联,就是全局范围开启插件,插件会在全部请求上运行。全局范围上开启 basic-auth 插件,命令如下:

    +
    # 全局范围上开启 basic-auth 插件
    $ curl -XPOST --data "name=basic-auth" \
    http://localhost:8001/plugins
    +

    关于 Kong 插件的更多介绍,可以阅读官方文档,本文不再展开。

    +

    Kong 插件开发

    +

    Kong 基于 OpenResty,OpenResty 通过 ngx_http_lua_module 模块实现了在 Nginx 中内嵌 Lua 脚本的能力。Kong 插件,使用 Lua 脚本实现,全部默认加载的预定义插件对应的 Lua 源码(包括上文提到的 basic-auth 插件),可以在 Kong 项目仓库的 kong/plugins 目录下看到。

    +

    除了能使用 Kong 预定义插件,我们可以根据 Kong 插件开发文档[15],开发自定义插件。

    +

    如何开发插件,文本不展开。Kong 官方提供了自定义插件的模板代码,源码参见项目 kong-plugin[16]。另外,有兴趣也可以参考笔者提供的 Kong 自定义插件示例,源码参见 kong-plugin-demo[17]

    +

    值得注意的是,Kong 使用 Lua 的 rxi/classic 模块来模拟 Lua 中的类,自定义 Kong 的插件时,实现 handler 需要继承 BasePlugin class,目前最新的文档还是采用这种写法。不过,Kong 1.2 开始,Kong 内部的预定义实现的插件,废弃了继承 BasePlugin class 的写法,参见 Pull Request #4590,“plugins handlers do not have to inherit from BasePlugin anymore #4590”。去掉对 BasePlugin class 的继承后,在开启单个插件(key-auth)的场景下,压测 Kong 性能提升 6%,开启多个插件的场景,性能提升更高。

    +

    参考资料

    +
    +
    +
      +
    1. What is Kong? https://konghq.com/about-kong/ ↩︎ ↩︎

      +
    2. +
    3. 2015-04 Mashape 开源 API 网关——Kong https://www.infoq.cn/article/2015/04/kong/ ↩︎ ↩︎

      +
    4. +
    5. 2012-07 打造大集市:API交易网站Mashape正式推出 https://www.csdn.net/article/2012-07-31/2807936 ↩︎

      +
    6. +
    7. 2015-10 How Mashape Manages Over 15,000 APIs & Microservices https://stackshare.io/kong/how-mashape-manages-over-15000-apis-and-microservices ↩︎ ↩︎

      +
    8. +
    9. 2017-05 Mashape 和 RapidAPI 合并,组成全球最大的应用编程接口(API)集市! https://www.sohu.com/a/144114294_465914 ↩︎

      +
    10. +
    11. 2017-05 The API Marketplace Joins RapidAPI https://konghq.com/blog/the-api-marketplace-joins-rapidapi/ ↩︎

      +
    12. +
    13. 2017-10 Welcome Kong Inc. A New Name, a New Product, a New Era. https://konghq.com/blog/introducing-kong-inc/ ↩︎

      +
    14. +
    15. 2018-12 Kong 1.0 GA https://konghq.com/blog/kong-1-0-ga/ ↩︎

      +
    16. +
    17. 2020-01 Kong Gateway 2.0 GA https://konghq.com/blog/kong-gateway-2-0-0-released/ ↩︎

      +
    18. +
    19. Documentation for Kong: DB-less and Declarative Configuration https://docs.konghq.com/1.1.x/db-less-and-declarative-config/ ↩︎

      +
    20. +
    21. Kong Installation: Compile Source https://docs.konghq.com/install/source/ ↩︎

      +
    22. +
    23. Build tools to package and release Kong https://github.com/Kong/kong-build-tools ↩︎

      +
    24. +
    25. Documentation for Kong: Proxy Reference https://docs.konghq.com/0.14.x/proxy/ ↩︎

      +
    26. +
    27. Documentation for Kong: Load Balancing Reference https://docs.konghq.com/0.14.x/loadbalancing/ ↩︎

      +
    28. +
    29. Documentation for Kong: Plugin Development https://docs.konghq.com/0.14.x/plugin-development/ ↩︎

      +
    30. +
    31. Kong 官方自定义插件的模板代码 https://github.com/Kong/kong-plugin ↩︎

      +
    32. +
    33. Kong 自定义插件示例 https://github.com/yulewei/kong-plugin-demo ↩︎

      +
    34. +
    +
    +]]>
    + + 架构 + + + 架构 + 微服务 + Kong + API + Nginx + OpenResty + 网关 + +
    + + 编程语言与编译器书籍资料整理 + /2016/11/lang-and-compiler-books/ + 本文整理编程语言与编译器相关的经典书籍。

    + +

    https://zh.wikipedia.org/wiki/Template:程序设计语言
    +https://en.wikipedia.org/wiki/Template:IPC
    +https://en.wikipedia.org/wiki/Programming_language#Further_reading

    +

    Language Books/Tutorials for popular languages http://stackoverflow.com/q/22873

    +

    编程语言、程序分析相关书籍:

    +
      +
    1. 1999、2005、2009,Michael L. Scott,《程序设计语言:实践之路》(Programming Language Pragmatics, 1st 1999, 3rd 2009),home,第3版豆瓣:全书800多页,内容优于Sebesta版,有16页参考文献,涵盖程序语言、编译原理、计算机体系结构等多个子学科
    2. +
    3. 1993-2012,Robert W. Sebesta,《程序设计语言概念》(Concepts of Programming Languages, 10th 2012, 11th 2015),第10版豆瓣:全书600页左右,内容编程语言发展历史概述,以及分别介绍、比较
    4. +
    5. 2002、2004,Benjamin C. Pierce,《类型和程序设计语言》(Types and Programming Languages, amazon),home豆瓣
    6. +
    7. 1993,Glynn Winskel,《程序设计语言的形式语义》(The Formal Semantics of Programming Languages, amazon),豆瓣
    8. +
    9. 2002,John Mitchell,《程序设计语言概念》(Concepts in Programming Languages),home豆瓣:作者来自Stanford,courses,内容主要讲Lisp及其他
    10. +
    11. 1996,John Mitchell,《程序设计语言理论基础》(Foundations for Programming Languages),豆瓣
    12. +
    13. 2004,“Concepts, Techniques, and Models of Computer Programming”,CTM,wikihome
    14. +
    15. 2010,Bruce Tate,《七周七语言:理解多种编程范型》(Seven Languages in Seven Weeks, Pragmatic),豆瓣:书中介绍了Ruby、Io、Prolog、Scala、Erlang、Clojure和Haskell这七种语言
    16. +
    17. 2010,Martin Fowler,《领域特定语言》(Domain-Specific Languages, amazon),homeinfoq豆瓣
    18. +
    19. 2010,《领域专用语言实战》(DSLs in Action),图灵2013豆瓣
    20. +
    21. 2013,[日]西尾泰和,《代码之髓:编程语言核心概念》,图灵2014豆瓣
    22. +
    23. 2014,Neal Ford,《函数式编程思维》,豆瓣:涉及Java、Clojure、Scala
    24. +
    +
    +

    编译器相关书籍:

    +
      +
    1. 1986、2007,Aho & Sethi & Ullman,龙书《编译原理》(Compilers: Principles, Techniques, and Tools, 1st 1986, 2nd 2006),home豆瓣:侧重理论
    2. +
    3. 1997、2002,Appel,虎书《现代编译原理》(Modern Compiler Implementation in Java/C/ML, amazon),home,C语言,图灵2006豆瓣;Java语言,豆瓣:作者TOPLAS杂志主编,介于龙书,鲸书之间,算是实践中有理论
    4. +
    5. 2004、2011,Cooper & Torczon,《编译器设计》(Engineering a Compiler,2nd 2011),豆瓣书评:两位作者均来自Rice Univ,博士导师都为Kennedy
    6. +
    7. 1997,Muchnick,鲸书《高级编译器设计与实现》(Advanced Compiler Design and Implementation, amazon),豆瓣:名气次于龙书和虎书,内容侧重编译器后端优化
    8. +
    9. 1988、1991、2009,《编译器构造》(Crafting a Compiler, 1st 1988, 3rd 2009),豆瓣:该书不是很出名,但相对“龙书”和“虎书”读性很高
    10. +
    11. 1996、2011,Richard Jones & etc,《垃圾回收算法手册》(The Garbage Collection Handbook, amazon),home,第2版豆瓣:GC最佳书籍
    12. +
    13. 2016,中村成洋,《垃圾回收的算法与实现》,豆瓣
    14. +
    15. 2001,Allen & Kennedy,《现代体系结构的优化编译器》(Optimizing Compilers for Modern Architectures, amazon),豆瓣:两位作者均来自Rice Univ,其中Kennedy在1999年获得ACM SIGPLAN成就奖,该奖项的第3届得主
    16. +
    +]]>
    + + 编程 + + + 书籍 + CS + 语言 + +
    + + Java 编译器 javac 及 Lombok 实现原理解析 + /2017/04/javac-api/ + javac 是 Java 代码的编译器[1][2],初学 Java 的时候就应该接触过。本文整理一些 javac 相关的高级用法。Lombok 库,大家平常一直在使用,但可能并不知道实现原理解析,其实 Lombok 实现上依赖的是 Java 编译器的注解处理 API(JSR-296[3],本文同时尝试解析 Lombok 的实现原理。

    + +

    先来看下 javac 命令行工具。javac 命令行工具,官方文档有完整的使用说明[4],当然也可以,运行 javac -helpman javac 查看帮助信息。下面是经典的 hello world 代码:

    +
    package com.example;
    public class Greeting {
    public static void main(String[] args) {
    System.out.println("hello world");
    }
    }
    +

    编译与运行:

    +
    $ tree   # 代码目录结构
    .
    ├── pom.xml
    └── src
    └── main
    ├── java
    │ └── com
    │ └── example
       │   └── Greeting.java
    └── resources
    $ mkdir -p target/classes # 创建 class 文件的存放目录
    $ javac -d target/classes src/main/java/com/example/Greeting.java
    $ java -cp target/classes com.example.Greeting
    hello world
    +

    除了使用命令行工具编译 Java 代码,JDK 6 增加了规范“JSR-199: Java Compiler API”和“JSR-296: Pluggable Annotation Processing API”,开始还提供相关的 Java 编译器 API。Java 编译器的实现代码和 API 的整体结构如图所示[2:1][5]

    +

    Compiler Package Overview

    +

    绿色标注的包是官方 API(Official API),即 JSR-199 和 JSR-296,黄色标注的包为Supported API,紫色标注的包代码全部在 com.sun.tools.javac.* 包下,为内部 API(Internal API)和实现类。完整的包说明如下[2:2][5:1][6]

    +
      +
    • javax.annotation.processing - 注解处理 (JSR-296)
    • +
    • javax.lang.model - 注解处理和编译器 Tree API 使用的语言模型 (JSR-296) + +
    • +
    • javax.tools - Java 编译器 API (JSR-199)
    • +
    • com.sun.source.* - 编译器的 Tree API,支持对抽象语法树做只读访问
    • +
    • com.sun.tools.javac.* - 内部 API 和实现类 +
        +
      • com.sun.tools.javac.api - javax.tools 包下的 JavaCompiler 和其他 API 的实现
      • +
      • com.sun.tools.javac.code - javax.lang.model.* 包下的 API 的实现
      • +
      • com.sun.tools.javac.comp - 编译器主要处理阶段的实现
      • +
      • com.sun.tools.javac.file - 实现访问文件系统,包括 javax.tools.StandardFileManager 的实现
      • +
      • com.sun.tools.javac.jvm - class 文件的读写,编译器的字节码生成阶段的实现
      • +
      • com.sun.tools.javac.main - 代码编译的入口实现
      • +
      • com.sun.tools.javac.model - javax.lang.model.* 包的其他实现
      • +
      • com.sun.tools.javac.parser - 读取 Java 源代码,并生成语法树
      • +
      • com.sun.tools.javac.processing - 注解处理 API 的实现
      • +
      • com.sun.tools.javac.resources - 本地化文本和版本号的资源文件
      • +
      • com.sun.tools.javac.tree - 编译器语法树相关的表示类和工具类,com.sun.source.* 包下的 API 的实现
      • +
      • com.sun.tools.javac.util - 基础工具类
      • +
      +
    • +
    +

    全部源码都位于 JDK 源码的 langtools 目录下。对外的 API,被编译到 rt.jarcom.sun.source.*com.sun.tools.javac.* 包,被编译到 tools.jar,在 JDK 下的具体位置是 $JAVA_HOME\lib\tools.jar。值得一提的是,langtools 目录,除了包含 javac 的实现外,还实现了 javadocjavah 等命令,编译后也是在 tools.jar 下。

    +

    另外,由于是内部 API 和实现类,com.sun.tools.javac.* 包下全部代码中都有标注警告:

    +
    +

    This is NOT part of any supported API. If you write code that depends on this, you do so at your own risk. This code and its internal interfaces are subject to change or deletion without notice.

    +
    +

    Java 编译器 API

    +

    首先,看下 JSR-199 引入的 Java 编译器 API(Java Compiler API)。在没有引入 JSR-199 之前,如果要通过编程方式编译 Java 代码,只能使用 com.sun.tools.javac.* 包下提供内部 API。上文提到的使用命令 javac 编译 Greeting.java 的等价写法如下:

    +
    import com.sun.tools.javac.main.Main;

    public class JavacMain {
    public static void main(String[] args) {
    Main compiler = new Main("javac");
    compiler.compile(new String[]{"src/main/com/example/Greeting.java", "-d", "target/classes"});
    }
    }
    +

    事实上,javac 命令的底层实现就是执行 com.sun.tools.javac.Main 类。执行 javac 命令,等价于执行 java -cp $JAVA_HOME/lib/tools.jar com.sun.tools.javac.Main

    +
    # 直接执行 com.sun.tools.javac.Main 类编译 Java 源代码
    java -cp $JAVA_HOME/lib/tools.jar com.sun.tools.javac.Main -d target/classes src/main/java/com/example/Greeting.java
    +

    JSR-199,提供了 Java 编译器 API,对应的是 javax.tools.* 包。阅读包的 javadoc 容易发现,API 最核心是 javax.tools.JavaCompiler 接口,该类的 javadoc 阐述了如何使用该类,可以阅读。使用 Java 编译器 API 编译 Java 源代码,示例如下:

    +
    import javax.tools.*;
    import java.io.File;
    import java.io.IOException;
    import java.util.Arrays;

    public class Jsr199Main {
    public static void main(String[] args) throws IOException {
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();

    StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);

    File file = new File("src/main/java/com/example/Greeting.java");
    Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(Arrays.asList(file));
    List<String> options = Arrays.asList("-d", "target/classes");

    compiler.getTask(null, fileManager, diagnostics, options, null, compilationUnits).call();

    fileManager.close();
    }
    }
    +

    上述两种编程方式编译 Java 代码的方式,在 javac 命令的 man[4:1] 文档的 “Programmatic Interface” 小节也有提及,有兴趣可以阅读。

    +

    在实际开发过程中,我们基本上都是使用 Maven 或 Gradle 编译 Java 代码。Maven 编译 Java 代码,依赖的是 Maven 的 maven-compiler-plugin 插件。那么 maven-compiler-plugin 插件底层实现是否使用了 javax.tools.JavaCompiler 呢?查阅官网文档后,容易发现实际情况和猜想的一样(其实也是显而易见的结论) [doc]:

    +
    +

    The Compiler Plugin is used to compile the sources of your project. Since 3.0, the default compiler is javax.tools.JavaCompiler (if you are using java 1.6) and is used to compile Java sources. If you want to force the plugin using javac, you must configure the plugin option forceJavacCompilerUse.

    +
    +

    类似的,Gradle 编译 Java 代码,底层也使用了 Java 编译器 API,可以参见源码 JdkJavaCompiler [github]。

    +

    javac 的编译过程

    +

    上文提到,JSR-269,可插拔式注解处理 API(Pluggable Annotation Processing API)。注解处理,是编译过程中的其中一个阶段。要理解注解处理,需要先了解 Java 代码的编译过程。完整的编译过程如下图所示[7]

    +

    javac-flow.png

    +

    整个过程就是:

    +
      +
    1. 源代码经过词法解析和语法解析(parse),生成抽象语法树(abstract syntax tree)。然后遍历抽象语法树,将遇到的符号填充入符号表(enter symbol table)。
    2. +
    3. 注解处理(annotation processing),所有注解处理器会被处理,若处理器生成新的代码或 class 文件,编译过程会重新开始,直到没有新的文件生成。每一次循环称为一个 round,也就是上图的回环过程。
    4. +
    5. 语义分析和字节码生成,包括标注(attribute)、数据及控制流分析(flow)、解语法糖(desugar)、字节码生成(generate)。
    6. +
    +

    把上述编译过程对应到代码中,javac 编译动作的入口是 com.sun.tools.javac.main.JavaCompiler 类,上述 3 个过程的代码逻辑集中在这个类的 compile()和 compile2()方法,如下图所示,整个编译过程主要的处理由图中标注的 8 个方法来完成[8]

    +JavaCompiler compile +

    具体来看下,词法解析和语法解析。Java 的词法和语法规则,在《Java语言规范》(The Java Language Specification)中定义。从底层实现上来看,com.sun.tools.javac.parser.Scanner 类,按照单个字符的方式读取 Java 源文件中的关键字和标示符等内容,然后将其转换为符合 Java 语法规范(JLS ch3)的 Token 序列。例如,针对语句 int y = x + 1; 的词法解析过程如下图所示[9]

    +词法解析 +

    然后,com.sun.tools.javac.parser.JavacParser 类,读取 Token 序列,将 Token 序列构造为抽象语法树 com.sun.tools.javac.tree.JCTree。语句 int y = x + 1;,生成的抽象语法树,如下图所示[9:1]

    +抽象语法树 +

    该语句对应的 JCTree.JCVariableDecl 对象,在 IDEA 的 debug 模式下查看,如下图所示:

    +IDEA debug +

    语法树中的每一个语法节点,实际上都直接或者间接地继承了 JCTree 类,并且都以静态内部类的形式定义在 JCTree 类中。Java 源文件的完整的词法解析和语法解析,由 JavacParserparseCompilationUnit 方法完成。解析完成后,方法返回 JCTree.JCCompilationUnit 类。JCTree.JCCompilationUnit 类,为某个 Java 源文件解析后的整个语法树的根节点。

    +

    上文提到,com.sun.source.* 包下暴露的 Tree API,提供对语法树只能做只读操作。com.sun.tools.javac.tree 包,是 com.sun.source.* 包下的 API 的实现。com.sun.source.tree.Tree 接口对应的实现类为 JCTreeTree 的子接口的实现类为 JCTree 的子类,并一一对应,比如,com.sun.source.tree.ClassTree 对应的实现类为 JCTree.JCClassDeclTree 接口及其子接口只暴露只读方法,而 JCTree 类及其子类,大部分的内部定义字段都是 public,可以直接读写。

    +

    主要的语法树节点 JCTree 子类,如下:

    +
      +
    • JCTree.JCStatement:声明语句的语法树节点。主要的子类包括: +
        +
      • JCTree.JCBlock:语句块(JLS 14.2
      • +
      • JCTree.JCClassDecl:类声明(JLS 8.1
      • +
      • JCTree.JCForLoopfor 语句(JLS 14.14.1
      • +
      • JCTree.JCEnhancedForLoop:增强for语句(JLS 14.14.2
      • +
      • JCTree.JCIfif 语句(JLS 14.9
      • +
      • JCTree.JCReturnreturn 语句(JLS 14.7
      • +
      • JCTree.JCVariableDecl:变量声明,比如 int x = 0 语句(JLS 14.4
      • +
      • 其他(不一一列举)
      • +
      +
    • +
    • JCTree.JCExpression:表达式的语法树节点。主要的子类包括: +
        +
      • JCAssign:赋值语句表达式,比如 x = 0 语句(JLS 15.26
      • +
      • JCIdent:标识符表达式,比如 x 标识符(JLS 3.8
      • +
      • JCBinary:二元运算符,比如 x + 1 语句(JLS 15.18
      • +
      • JCLiteral:字面量运算符表达式,比如 1 字面量(JLS 3.10
      • +
      • JCTree.JCPrimitiveTypeTree:基础类型,比如 int 等类型(JLS 4.2
      • +
      +
    • +
    • JCTree.JCMethodDecl:方法声明(JLS 8.4
    • +
    • JCTree.JCCompilationUnit:编译单元,对应单个源文件内的全部内容(JLS 7.3
    • +
    +

    全部的各个类型的树节点的类定义,可以参见 JCTreeTree 类的 javadoc 或源代码。

    +

    在构造抽象语法树后,就是符号表填充阶段。在符号表填充阶段,会扫描 JCTree 语法树,遇到类型、变量、方法定义时,会它们的信息存储到符号表中,方便后续阶段进行快速查询。符号,对应的是 com.sun.tools.javac.code.Symbol 类。而 Symbol 类,是 javax.lang.model 包下 Element 的实现类,Symbol 子类是对应 Element 子类的实现。

    +

    Element 提供 ElementKind getKind() 方法,能获取元素类型(ElementKind)。全部的 ElementKind 共 17 种:ANNOTATION_TYPE(注解)、CLASS(类)、CONSTRUCTOR(构造方法)、ENUM(枚举)、ENUM_CONSTANT(枚举值)、EXCEPTION_PARAMETER(异常参数)、FIELD(字段)、INSTANCE_INIT(实例初始化语句块)、INTERFACE(接口)、LOCAL_VARIABLE(本地变量)、METHOD(方法)、PACKAGE(包)、PARAMETER(参数)、RESOURCE_VARIABLE(资源变量)、STATIC_INIT(静态初始化语句块)、TYPE_PARAMETER(类型参数) 以及 OTHER(其他)。

    +

    全部 Element 子类以及对应的 Symbol 子类,如下:

    +
      +
    • PackageElement:表示包 package +
        +
      • 实现类:Symbol.PackageSymbol
      • +
      • 元素类型 ElementKindPACKAGE(包)
      • +
      +
    • +
    • TypeElement:表示类 class 或接口 interface 等 +
        +
      • 实现类:Symbol.ClassSymbol
      • +
      • 元素类型 ElementKindANNOTATION_TYPE(注解)、INTERFACE(接口)、ENUM(枚举)、CLASS(类)
      • +
      +
    • +
    • VariableElement:表示字段、枚举值、方法参数、本地变量、资源变量、异常参数 +
        +
      • 实现类:Symbol.VarSymbol
      • +
      • 元素类型 ElementKindEXCEPTION_PARAMETER(异常参数)、PARAMETER(参数)、ENUM_CONSTANT(枚举值)、RESOURCE_VARIABLE(资源变量)、LOCAL_VARIABLE(本地变量)、FIELD(字段)
      • +
      +
    • +
    • ExecutableElement:表示方法、构造方法、初始化语句块 +
        +
      • 实现类:Symbol.MethodSymbol
      • +
      • 元素类型 ElementKindCONSTRUCTOR(构造方法)、STATIC_INIT(静态初始化语句块)、INSTANCE_INIT(实例初始化语句块)、METHOD(方法)
      • +
      +
    • +
    • TypeParameterElement:表示参数化类型,即泛型尖括号内的类型 +
        +
      • 实现类:Symbol.TypeVariableSymbol
      • +
      • 元素类型 ElementKindTYPE_PARAMETER(类型参数)
      • +
      +
    • +
    +

    在填充符号表后,就是语义分析和代码生成,包括标注(attribute)、数据及控制流分析(flow)、解语法糖(desugar)、字节码生成(generate)阶段。

    +

    在实际开发时,比如常见的“找不到符号(cannot find symbol)”编译报错,就是在标注阶段的名称消解(name resolution)时触发的。编译报错示例代码,如下:

    +
    public class CantResolve {
    int foo = bar;
    }
    +

    编译错误的提示内容:

    +
    找不到符号
    符号: 变量 bar
    位置: 类 CantResolve
    +

    编译过程的各个阶段的更详细的阐述可以阅读书籍[8:1][10],本文不再展开。

    +

    可插拔式注解处理 API

    +

    JSR-296 定义的可插拔式注解处理 API 在 javax.annotation.processing 包下,最核心的接口是 javax.annotation.processing.Processor,通过实现这个接口来定义自己的注解处理器。

    +

    编译器工具与 Processor 实现类的交互过程是:

    +
      +
    • 如果存在没有被使用的 Processor 对象,就调用无参构造方法创建一个 Processor 实例。
    • +
    • 然后,编译器工具调用注解处理器的 init 方法,初始化注解处理器,方法参数是 ProcessingEnvironment 对象(注解处理的执行环境,从环境中获得相关工具类,比如 Elements)。
    • +
    • 之后,编译器工具调用注解处理器的 getSupportedAnnotationTypes(查询该注解处理器支持的注解集合)、getSupportedOptions(查询该注解处理器支持的参数选项集合)、getSupportedSourceVersion(查询该注解处理器支持的源代码版本)方法。
    • +
    • 最后,调用注解处理器的 process 方法。
    • +
    +

    注解处理会执行多轮(round),每轮都会调用 process 方法,调用时传入在上一轮的源代码和 class 文件中找到的该注解处理器支持的注解子集。在处理注解期间,如果任何注解处理器生成了新的源文件或 class 文件,编译器将回到解析、填充符号表、注解处理的过程,直到没有新的文件生成。

    +

    init 方法的参数 ProcessingEnvironment 对象,为注解处理的执行环境,从环境中获得相关工具类,比如,Elements 类,用于操作 Element 元素;Filer 类,用于生成新的文件;Messager 类,用于报告编译错误、告警或其他消息。另外,ProcessingEnvironment,也可以获得传递给注解处理器参数选项。

    +

    AbstractProcessor 抽象类,实现类了 Processor 接口,用于简化实际的注解处理器类的实现。该类通过读取 @SupportedAnnotationTypes@SupportedOptions@SupportedSourceVersion 注解值,来实现 Processor 接口对应的三个方法。

    +

    用命令行编译代码时,javac 编译器,会搜索可用的注解处理器。搜索路径可以通过参数选项 -processorpath 指定,如果未指定,将使用 classpath。注解处理器,可以通过 -processor 参数选项指定。若未通过 -processor 参数选项指定,注解处理器会使用 SPI 方式定位,在搜索路径查找 META-INF/services/javax.annotation.processing.Processor 文件。文件中填写的是注解处理器类名(多个的话,换行填写),编译器就会自动使用这里填写的注解处理器进行注解处理。另外,编译器 API 的 CompilationTasksetProcessors 方法也可以传入注解处理器。

    +

    如果注解处理器支持参数选项,编译时,参数选项可以用 -Akey[=value] 的方式传递[4:2]

    +

    扫描语法树

    +

    JDK 源码的 langtools 目录下,提供了示例注解处理器 CheckNamesProcessor,一个检查命名的注解处理器。CheckNamesProcessor 注解处理器,内部实现了 javax.lang.model.util 包下 ElementScanner,用来扫描 Element 元素符号,然后检查类命名、方法命名、字段命名、参数命名等是否符合命名规范,如果不符合命名规范,就打印编译器告警。

    +

    javax.lang.model.util.ElementScanner8 类用于扫描 Element 的核心方法:

    +
    public final R scan(Element e)
    +

    对语法树的扫描,com.sun.source.util 包下,提供了语法树扫描器 TreeScanner,用于扫描语法树上的树节点 Tree。类似的,com.sun.tools.javac.tree.TreeScanner,用于扫描语法树上的树节点 JCTree

    +

    com.sun.source.util.TreeScanner 类用于扫描语法树的核心方法:

    +
    public R scan(Tree node, P p)
    +

    com.sun.tools.javac.tree.TreeScanner 类用于扫描语法树的核心方法:

    +
    public void scan(JCTree tree)
    +

    需要注意的是,注解处理器的 process 方法,传递过来的是 Element 对象,需要先获得 Element 对象关联的 TreeJCTree 对象,才能扫描语法树。工具类 com.sun.source.util.Trees 提供了这样的桥接能力,该类的实现类为 com.sun.tools.javac.api.JavacTreesTrees 的相关方法:

    +
    // 通过 ProcessingEnvironment 获得 Trees 对象
    public static Trees instance(ProcessingEnvironment env)
    // 通过 Element 获得 Tree
    public abstract Tree getTree(Element element);
    +

    类似的,JavacTrees 的相关方法:

    +
    // 通过 ProcessingEnvironment 获得 JavacTrees 对象
    public static JavacTrees instance(ProcessingEnvironment env)
    // 通过 Element 获得 JCTree
    public JCTree getTree(Element element)
    +

    使用 ElementScannerTreeScanner 扫描语法树的示例注解处理器,参见 VisitProcessor

    +

    修改语法树

    +

    在语法解析时,JavacParser 类,底层实现上利用 TreeMaker 类构造的语法树各个节点。TreeMaker 类,封装了创建语法树节点的方法,部分常用的方法举例:

    +
      +
    • TreeMaker.Assign 方法:用于生成赋值语句的语法树节点 JCTree.JCAssign
    • +
    • TreeMaker.Binary 方法:用于生成二元操作符的语法树节点 JCTree.JCBinary
    • +
    • TreeMaker.Block 方法:用于生成语句块的语法树节点 JCTree.JCBlock
    • +
    • TreeMaker.VarDef 方法:用于生成变量定义的语法树节点 JCTree.JCVariableDecl
    • +
    • TreeMaker.MethodDef 方法:用于生成方法定义的语法树节点 JCTree.JCMethodDecl
    • +
    • 等等
    • +
    +

    在注解处理阶段,init 方法传入了 ProcessingEnvironment 对象,通过该对象可以获得当前上下文中的 TreeMaker 对象,然后就可以利用 TreeMaker 创建新的语法树节点。

    +

    语句 int y = x + 1;,使用 TreeMaker 构造对应的 JCTree.JCVariableDecl,示例代码如下:

    +
    Name x = ...
    Name y = names.fromString("y");
    // x + 1
    JCTree.JCBinary binary = maker.Binary(JCTree.Tag.PLUS, maker.Ident(x), maker.Literal(TypeTag.INT, 1));
    // int y = x + 1
    JCTree.JCVariableDecl decl = maker.VarDef(maker.Modifiers(0), y, maker.TypeIdent(TypeTag.INT), binary);
    +

    因为 JCTree 类及其子类的大部分的内部定义字段都是 public,可以直接读写,所以要想修改语法树,可以直接相关字段的值。比如,把 int y = x + 1 语句对应的 JCTree.JCVariableDecl 树节点改为 int y = 42,可以直接修改 JCTree.JCVariableDeclinit 字段,示例代码如下:

    +
    JCTree.JCVariableDecl decl = ...
    decl.init = maker.Literal(TypeTag.INT, 42);
    +

    修改语法树的示例代码,参见 PlusProcessor 注解处理器。该示例注解处理器,修改 @PlusOne 注解标注的方法的内部实现,改造后的方法的逻辑为,返回请求参数值加 1 后的值。比如,修改语法树前,func 方法实现如下:

    +
    @PlusOne
    public int func(int x) {
    return x * x;
    }
    +

    PlusProcessor 注解处理器修改语法树后,func 方法变成:

    +
    public int func(int x) {
    return x + 1;
    }
    +

    修改方法内部实现的核心代码如下:

    +
    private void modifyToPlusOneMethod(JCTree.JCMethodDecl methodDecl) {
    JCTree.JCVariableDecl param = methodDecl.params.head;
    // x + 1
    JCTree.JCBinary binary = maker.Binary(JCTree.Tag.PLUS, maker.Ident(param.name), maker.Literal(TypeTag.INT, 1));
    JCTree.JCReturn ret = maker.Return(binary);
    // 修改方法内部实现
    methodDecl.body.stats = List.of(ret);
    }
    +

    这个注解处理器仅仅用于示例,没有其他实际用途。实际开发中,Lombok 库被广泛使用,其底层实现就是利用注解处理器修改由 Lombok 注解(@Data@Getter@Setter 等)标注的代码的语法树,自动生成样板代码。针对 Lombok 库实现原理的解析,参见下文。

    +

    创建新文件

    +

    可插拔式注解处理 API,定义了 javax.annotation.processing.Filer 接口,这个接口提供了让注解处理器创建新文件的能力。createSourceFile 方法,用于创建新的源代码文件,createClassFile,用于创建新的 class 文件。

    +

    来看下示例代码,GreetingProcessor 注解处理器。该注解处理器功能就是基于 Filer 自动生成 Greeting 类(打印 "hello world")。核心代码片段如下:

    +
    private boolean generateGreeting(String className) throws Exception {
    byte[] bytes = Files.readAllBytes(Paths.get(this.getClass().getResource("/Greeting.tpl").toURI()));
    String greetingTemplate = new String(bytes, StandardCharsets.UTF_8);
    String greetingSourceCode = String.format(greetingTemplate, LocalDateTime.now(), className);
    JavaFileObject fileObject = filer.createSourceFile(className);
    try (PrintWriter writer = new PrintWriter(fileObject.openWriter())) {
    writer.println(greetingSourceCode);
    }
    return true;
    }
    +

    模板文件 Greeting.tpl 的内容为:

    +
    import javax.annotation.Generated;

    @Generated(value = "by GreetingProcessor", date = "%s")
    public class %s {
    public static void main(String[] args) {
    System.out.println("hello world");
    }
    }
    +

    在实际开发中,MapStruct 是流行的用于 Bean 之间映射的工具库之一,其底层实现就是基于注解处理器 API。阅读源码,容易发现 MapStruct 库内部实现的注解处理器是 org.mapstruct.ap.MappingProcessorjavadocgithub)。MappingProcessor 注解处理器生成的 Mapper 实现类,底层调用的就是 Filer 接口的 createSourceFile 方法,参见源代码 github。另外,MapStruct 库的注解处理器生成源代码文件利用了模板引擎 FreeMarker 库,可以参见 javadocgithub

    +

    另外值得一提的是,除了模板引擎,生成源代码文件也可以使用 JavaPoet 工具库,JavaPoet 库提供 Java API 来生成 .java 源文件。笔者基于 JavaPoet 库,实现了能处理类似 Lombok 的 @Builder 注解的 BuilderProcessor 注解处理器,有兴趣的话可以查阅(附注:实际的 Lombok 的 @Builder 注解实现原理是修改语法树,并不是生成新的 Builder 类文件)。

    +

    Lombok 的实现原理

    +

    依赖 JSR-269 实现的第三方工具库有很多[11],比如代码自动生成的 LombokMapStruct 和 Google Auto,代码检查的 Checker 和 Google Error Prone,编译阶段完成依赖注入的 Google Dagger 2 等。笔者在实际开发中就经常使用 Lombok 库和 MapStruct 库。MapStruct 库的实现原理,上文已经做了简单介绍。现在来看下 Lombok 的实现原理。

    +

    Lombok 提供 @NonNull@Getter, @Setter, @ToString, @EqualsAndHashCode, @Data 等注解,自动生成常见样板代码 boilerplate,解放开发效率。Lombok 支持 javac 和 ecj (Eclipse Compiler for Java)。对于 javac 编译器对应的注解处理器是 LombokProcessor,然后经过一些处理过程,每个注解都会有特定的 handler 来处理,@NonNull 对应 HandleNonNull@Getter 对应 HandleGetter@Setter 对应 HandleSetter@ToString 对应 HandleToString@EqualsAndHashCode 对应 HandleEqualsAndHashCode@Data 对应 HandleData。如果想要改造 Lombok 项目,让 Lombok 支持新的注解,其实就是添加新的 handler。关于 Lombok 原理以及如何为 Lombok 贡献代码,文档 “Documentation for lombok developers”[12],也有简单介绍,可以阅读。

    +

    阅读这些 handler 的实现,可以看到样板代码的生成依赖的就是 com.sun.tools.javac.* 包。最新版的 Lombok 源码太繁杂了,可以从早期版本入手,比如 v0.8.1 版本。

    +

    现在来看下如何实现 @Getter 注解。@Getter 注解的功能,就是自动生成类字段的 getter 方法,如果注解加到 class 上,就生成类的全部字段的 getter 方法。假设字段名叫 foo,那边生成的 getter 方法如下所示:

    +
    public int getFoo() {
    return foo;
    }
    +

    参考 Lombok v0.8.1 和 v0.9.3 的 HandleGetter 实现源码(从 v0.9.3 版本开始,@Getter 注解支持加到 class 上,之前只能加到字段上),提取出其中的核心代码,实现 @Getter 的示例代码如下:

    +
    private void handleGetter(JCTree.JCClassDecl classDecl) {
    List<JCTree> methodDecls = List.nil();
    for (JCTree tree : classDecl.defs) {
    if (tree instanceof JCTree.JCVariableDecl) {
    // 创建 getter 方法
    JCTree.JCVariableDecl fieldDecl = (JCTree.JCVariableDecl) tree;
    String methodGetterName = Utils.toGetterName(fieldDecl);
    if (!Utils.methodExists(methodGetterName, classDecl)) {
    JCTree.JCMethodDecl methodGetter = this.createGetter(fieldDecl);
    methodDecls = methodDecls.append(methodGetter);
    }
    }
    }
    classDecl.defs = classDecl.defs.appendList(methodDecls);
    }

    // 生成 getter 方法
    private JCTree.JCMethodDecl createGetter(JCTree.JCVariableDecl field) {
    JCTree.JCStatement returnStatement = maker.Return(maker.Ident(field));
    JCTree.JCBlock methodBody = maker.Block(0, List.of(returnStatement));
    Name methodName = names.fromString(Utils.toGetterName(field));
    JCTree.JCExpression methodType = (JCTree.JCExpression) field.getType();

    return maker.MethodDef(maker.Modifiers(Flags.PUBLIC), methodName, methodType,
    List.nil(), List.nil(), List.nil(), methodBody, null);
    }
    +

    容易发现,实现 @Getter 注解依赖的 JCTreeTreeMaker 等相关类,这些类在上文都已经提及并介绍,不再复述。

    +

    为了加深对 javac 内部 API 的理解,笔者参考 Lombok 的源码,实现了支持类似 Lombok 的 @Data@Getter@Setter@Slf4j 注解的注解处理器MyLombokProcessor,代码参见 GitHub。

    +

    附注:本文的示例代码的完整代码,都可以在 GitHub 的 annotation-processor-demo[13] 仓库上找到。

    +

    参考资料

    +
    +
    +
      +
    1. OpenJDK: The Java programming language Compiler Group http://openjdk.java.net/groups/compiler/ ↩︎

      +
    2. +
    3. The Java Programming Language Compiler, javac https://docs.oracle.com/javase/8/docs/technotes/guides/javac/ ↩︎ ↩︎ ↩︎

      +
    4. +
    5. 2011-05 How does lombok work? http://stackoverflow.com/q/6107197 ↩︎

      +
    6. +
    7. javac https://docs.oracle.com/javase/8/docs/technotes/tools/unix/javac.html https://www.mankier.com/1/javac ↩︎ ↩︎ ↩︎

      +
    8. +
    9. OpenJDK: Compiler Package Overview https://openjdk.org/groups/compiler/doc/package-overview/index.html ↩︎ ↩︎

      +
    10. +
    11. OpenJDK: The Hitchhiker's Guide to javac https://openjdk.org/groups/compiler/doc/hhgtjavac/index.html ↩︎

      +
    12. +
    13. OpenJDK: Compilation Overview https://openjdk.org/groups/compiler/doc/compilation-overview/index.html ↩︎

      +
    14. +
    15. 深入理解Java 7虚拟机,周志明 第2版2013:第10章 早期 (编译期) 优化 ↩︎ ↩︎

      +
    16. +
    17. 莫枢 RednaxelaFX :JVM分享——Java程序的编译、加载与执行 http://www.valleytalk.org/2011/07/28/java-程序的编译,加载-和-执行/ ↩︎ ↩︎

      +
    18. +
    19. 深入解析Java编译器:源码剖析与实例详解,马智 2019 ↩︎

      +
    20. +
    21. Awesome Java Annotation Processing https://github.com/gunnarmorling/awesome-annotation-processing ↩︎

      +
    22. +
    23. Documentation for lombok developers https://projectlombok.org/contributing/ ↩︎

      +
    24. +
    25. annotation-processor-demo https://github.com/yulewei/annotation-processor-demo ↩︎

      +
    26. +
    +
    +]]>
    + + Java + + + Java + JVM + 编译器 + javac + Lombok + +
    + + MyBatis 生成器的表注释 + /2016/12/mybatis-generator/ + MyBatis是流行的持久化框架,通过抽象底层的JDBC代码,在类对象和数据库列之间自动映射SQL的参数和结果,以SQL为映射的间接层,实现SQL映射器。MyBatis Generator (MBG) 是一个Mybatis的代码生成器,内省数据库的表,然后自动生成映射表的实体类,并生成CRUD(插入,查询,更新,删除)操作的样板代码。MyBatis,之前所在的公司在用,生成器也在用。虽然生成器大大提供了开发效率,但生成的代码可读性比较低,尤其是自动生成的实体类,如下:

    + +
    /**
    * This field was generated by MyBatis Generator. This field corresponds to the database column author.book_id
    * @mbggenerated Tue Jan 19 13:37:24 CST 2016
    */
    private Integer bookId;
    +

    这些自动生成注释,没有实质性信息,其实真正有用的是,设计表时,该字段的用途,即表字段的注释。

    +

    addRemarkComments选项

    +

    庆幸的是,MyBatis生成器在版本1.3.3中添加了,addRemarkComments选项 [github],可以在生成的实体类中附带表字段的注释。addRemarkComments官方文档的介绍 [doc]:

    +
    +

    This property is used to specify whether MBG will include table and column remarks from db table in the generated comments. The property supports these values:

    +
      +
    • false: This is the default value When the property is false or unspecified, all generated comments will not include table and column remarks from db table when the element was generated.
    • +
    • true: When the property is true, table and columns remarks from db table will be added to the generated comments.
    • +
    +

    Warning: If suppressAllComments option is true, this option will be ignored.

    +
    +

    使用方法很简单,只需将MyBatis生成器的配置文件中的commentGenerator节点修改为:

    +
    <commentGenerator>
    <property name="addRemarkComments" value="true" />
    </commentGenerator>
    +

    自定义注释生成器类

    +

    通过addRemarkComments选项生成的实体类的注释不够精简。于是笔者参考MyBatis的默认的注释生成器DefaultCommentGenerator[github],对其进行改造成如下:

    +
    package com.test.mbg;

    import java.util.Date;

    import org.apache.commons.lang3.time.DateFormatUtils;
    import org.mybatis.generator.api.IntrospectedColumn;
    import org.mybatis.generator.api.IntrospectedTable;
    import org.mybatis.generator.api.dom.java.Field;
    import org.mybatis.generator.api.dom.java.JavaElement;
    import org.mybatis.generator.api.dom.java.Method;
    import org.mybatis.generator.api.dom.java.TopLevelClass;
    import org.mybatis.generator.config.MergeConstants;
    import org.mybatis.generator.internal.DefaultCommentGenerator;
    import org.mybatis.generator.internal.util.StringUtility;

    /**
    * 官方类似的功能见,在版本1.3.3中添加的 addRemarkComments <br>
    * http://www.mybatis.org/generator/configreference/commentGenerator.html <br>
    * https://github.com/mybatis/generator/issues/23
    *
    * @see DefaultCommentGenerator#addRemarkComments
    */
    public class RemarksCommentGenerator extends DefaultCommentGenerator {

    @Override
    public void addModelClassComment(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
    topLevelClass.addJavaDocLine("/**");

    String remarks = introspectedTable.getRemarks();
    if (StringUtility.stringHasValue(remarks)) {
    String[] remarkLines = remarks.split(System.getProperty("line.separator"));
    for (String remarkLine : remarkLines) {
    topLevelClass.addJavaDocLine(" * " + remarkLine);
    }
    }

    topLevelClass.addJavaDocLine(" * ");
    StringBuilder sb = new StringBuilder();
    sb.append(" * ");
    sb.append(introspectedTable.getFullyQualifiedTable());
    topLevelClass.addJavaDocLine(sb.toString());
    topLevelClass.addJavaDocLine(" *");
    addJavadocTag(topLevelClass, false);
    topLevelClass.addJavaDocLine(" */");
    }

    public void addFieldComment(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) {
    field.addJavaDocLine("/**");

    String remarks = introspectedColumn.getRemarks();
    if (StringUtility.stringHasValue(remarks)) {
    String[] remarkLines = remarks.split(System.getProperty("line.separator"));
    for (String remarkLine : remarkLines) {
    field.addJavaDocLine(" * " + remarkLine);
    }
    }

    field.addJavaDocLine(" *");
    StringBuilder sb = new StringBuilder();
    sb.append(" * ");
    sb.append(introspectedTable.getFullyQualifiedTable());
    sb.append('.');
    sb.append(introspectedColumn.getActualColumnName());
    field.addJavaDocLine(sb.toString());
    field.addJavaDocLine(" *");
    addJavadocTag(field, false);
    field.addJavaDocLine(" */");
    }

    public void addFieldComment(Field field, IntrospectedTable introspectedTable) {
    field.addJavaDocLine("/**");
    addJavadocTag(field, false);
    field.addJavaDocLine(" */");
    }

    public void addGetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) {
    method.addJavaDocLine("/**");
    addJavadocTag(method, false);
    method.addJavaDocLine(" */");
    }

    public void addSetterComment(Method method, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) {
    method.addJavaDocLine("/**");
    addJavadocTag(method, false);
    method.addJavaDocLine(" */");
    }

    protected void addJavadocTag(JavaElement javaElement, boolean markAsDoNotDelete) {
    StringBuilder sb = new StringBuilder();
    sb.append(" * ");
    sb.append(MergeConstants.NEW_ELEMENT_TAG);
    if (markAsDoNotDelete) {
    sb.append(" do_not_delete_during_merge"); //$NON-NLS-1$
    }
    String s = getDateString();
    if (s != null) {
    sb.append(' ');
    sb.append(s);
    }
    javaElement.addJavaDocLine(sb.toString());
    }

    protected String getDateString() {
    return DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
    }
    }
    +

    MyBatis的配置文件修改为:

    +
    <commentGenerator type="com.test.mbg.RemarksCommentGenerator">
    </commentGenerator>
    +

    运行MyBatis生成器

    +

    改用自定义的RemarksCommentGenerator后,运行MyBatis插件可能会报错。需要使用Java来运行MyBatis生成器,代码如下 [doc]:

    +
    package com.test.mbg;

    import java.io.File;
    import java.util.ArrayList;
    import java.util.List;

    import org.mybatis.generator.api.MyBatisGenerator;
    import org.mybatis.generator.config.Configuration;
    import org.mybatis.generator.config.xml.ConfigurationParser;
    import org.mybatis.generator.internal.DefaultShellCallback;

    /**
    * 使用Java运行 MyBatis Generator
    * http://www.mybatis.org/generator/running/runningWithJava.html
    */
    public class MyBatisGen {

    public static void main(String[] args) throws Exception {
    String fileName = "F:/code/mybatis-generator.xml";
    File configFile = new File(fileName);
    List<String> warnings = new ArrayList<String>();
    boolean overwrite = true;
    ConfigurationParser cp = new ConfigurationParser(warnings);
    Configuration config = cp.parseConfiguration(configFile);
    DefaultShellCallback callback = new DefaultShellCallback(overwrite);
    MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
    myBatisGenerator.generate(null);
    }
    }
    +]]>
    + + Java + + + 数据库 + Java + MyBatis + +
    + + MySQL 5.7 的 JSON 类型 + /2019/06/mysql-5.7-json/ + 2015 年 8 月,MySQL 5.7.8 开始提供对 JSON 的原生支持[1][2]。MySQL 对 JSON 的支持可以说是千呼万唤始出来。2009 年开始 NoSQL 逐渐流行起来,相继出现了键值对数据库、文档数据库、列族数据库、图数据库等各类 NoSQL,解决经典关系型数据库无法解决的痛点。其中,对灵活存储半结构化数据的需求,使得类似 MongoDB 这类文档数据库涌现出来。各大主流关系型数据库也在响应趋势,开始支持半结构化数据。早在 2012 年,PostgreSQL 9.2 就已经添加了 JSON 数据类型[3]。Oracle 也在 2014 年 7 月发布 12c Release 1 后开始支持 JSON[4][5]。Facebook 在 MySQL 5.7 没发布之前,对 5.6 版本的 MySQL 添加了存储 JSON 功能,这个特性被 Facebook 命名为 DocStore (Document Database for MySQL at Facebook)[6][7]。另外,SQL 标准组织行动也很快,在 2014 年 3 月已经完成了 SQL/JSON 标准草案(SQL/JSON Proposals)[8][9][10]。完整的草案在 2016 年 12 月正式被采纳为标准,即 SQL:2016。

    + +

    浏览 SQL/JSON 标准草案可以发现,全部作者共有 9 人,这些作者来自两个公司,Oracle 和 IBM,而排前面的作者如 Jim Melton, Fred Zemke, Beda Hammerschmidt 都 Oracle 的专家(有兴趣可以看下他们的 LinkedIn)。正因为 SQL:2016 主要就是 Oracle 参与制定的,目前,Oracle 数据库对 SQL:2016 的支持也是最全的[11]

    +

    MySQL 对 JSON 的支持,设计文档主要是 WL#7909: Server side JSON functions[12],另外还有 WL#8132: JSON datatype and binary storage format[13]、WL#8249: JSON comparator[14]、WL#8607: Inline JSON path expressions in SQL[15] 等。在 MySQL 开始 WL#7909 之时,SQL/JSON 标准草案已经公开,WL#7909 中也提及了这份标准,但是如果拿 MySQL 提供 JSON 的功能与 SQL:2016 比较,可以发现 MySQL 虽然融入了部分的设计,但并没有完全参考标准,定义的 JSON 函数多数有区别。

    +

    回到正题,下面来看下 MySQL 5.7 的 JSON 的用法。

    +

    JSON 函数列表

    +

    MySQL 官方列出 JSON 相关的函数,完整列表如下[16]

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    分类函数描述
    json 创建函数json_array()创建 json 数组
    json_object()创建 json 对象
    json_quote()用双引号包裹 json 文档
    json 查询函数json_contains()判断是否包含某个 json 值
    json_contains_path()判断某个路径下是否包 json 值
    json_extract()提取 json 值
    column->pathjson_extract() 的简洁写法,5.7.9 开始支持
    column->>pathjson_unquote(json_extract()) 的简洁写法,5.7.13 开始支持
    json_keys()把 json 对象的顶层的全部键提取为 json 数组
    json_search()按给定字符串关键字搜索 json,返回匹配的路径
    json 修改函数json_append()5.7.9 废弃,改名为 json_array_append()
    json_array_append()在 josn 文档末尾添加数组元素
    json_array_insert()在 josn 数组中插入元素
    json_insert()插入值(只插入新值,不替换旧值)
    json_merge()5.7.22 废弃,与 json_merge_preserve() 同义
    json_merge_patch()合并 json 文档,重复键的值将被替换掉
    json_merge_preserve()合并 json 文档,保留重复键
    json_remove()删除 json 文档中的数据
    json_replace()替换值(只替换旧值,不插入新值)
    json_set()设置值(替换旧值,或插入新值)
    json_unquote()移除 json 值的双引号包裹
    json 属性函数json_depth()返回 json 文档的最大深度
    json_length()返回 json 文档的长度
    json_type()返回 json 值的类型
    json_valid()判断是否为合法 json 文档
    json 工具函数json_pretty()美化输出 json 文档,5.7.22 新增
    json_storage_size()返回 json 文档占用的存储空间,5.7.22 新增
    +

    官方文档对全部函数都作了充分解释并提供一定的示例代码。另外,官方博客也有极佳的相关介绍文章[17][18]。下文挑选了部分函数,演示它们的使用方法。

    +

    创建与插入 JSON

    +
    -- 创建 tbl 表,字段 data 为 json 类型
    mysql> create table tbl (data JSON);
    Query OK, 0 rows affected (0.17 sec)

    -- 插入 json 对象
    mysql> insert into tbl values ('{"id": 1, "name": "Will"}');
    Query OK, 1 row affected (0.04 sec)

    -- 插入 json 数组
    mysql> insert into tbl values ('[1, 42, 1024]');
    Query OK, 1 row affected (0.01 sec)

    -- 使用 json_object() 创建 json 对象
    mysql> insert into tbl values (json_object('id', 2, 'name', 'Joe'));
    Query OK, 1 row affected (0.02 sec)

    -- 使用 json_array() 创建 json 数组
    mysql> insert into tbl values (json_array(1, "abc", null, true, curtime()));
    Query OK, 1 row affected (0.02 sec)

    -- 查询 tbl 表数据
    mysql> select * from tbl;
    +-------------------------------------------+
    | data |
    +-------------------------------------------+
    | {"id": 1, "name": "Will"} |
    | [1, 42, 1024] |
    | {"id": 2, "name": "Andy"} |
    | [1, "abc", null, true, "20:27:41.000000"] |
    +-------------------------------------------+
    4 rows in set (0.00 sec)
    +

    上面的 SQL 示例简单验演示了创建 JSON 列以及写入并查询 JSON 数据,比较简单,就不做解释了。

    +

    查询 JSON

    +

    json_extract() 与 -> 操作符

    +

    如果要查询 JSON 文档中内容,提取 JSON 中的值,可以使用 json_extract() 函数。函数定义如下:

    +
    json_extract(json_doc, path[, path] ...)
    +

    先来看下 SQL 示例:

    +
    -- 使用 json_extract() 函数查询 json 对象
    mysql> select json_extract('{"id": 1, "name": "Will"}', '$.name');
    +-------------------------------------------------------+
    | json_extract('{"id": 1, "name": "Will"}', '$.name') |
    |-------------------------------------------------------|
    | "Will" |
    +-------------------------------------------------------+
    1 row in set (0.01 sec)
    +

    示例中的 $.name,使用的是 JSON 路径语法,用来提取 JSON 文档的内容。JSON 路径语法,源自 Stefan Goessner 的 JsonPath[19],不过 MySQL 作了简化。路径语法使用 $ 开头来表示整个 JSON 文档。如果要提取部分 JSON 文档,可以在路径后面添加选择符:

    +
      +
    • 在路径 path 后上追加对象的键名称,可以获取这个键下成员。如果加键名称后,路径表达式非法,需要对键名称用双引号包裹(比如,键名称中包含空格的情况)
    • +
    • 在路径 path 后加上追加 [N],用于选择数组的第 N 个元素。数组索引从 0 开始。如果 path 下并不是数组,path[0] 获取结果就是 path 本身。
    • +
    • 路径可以包含 *** 通配符: +
        +
      • .[*] 用于获取 JSON 对象的全部成员。
      • +
      • [*] 用于获取 JSON 数组的全部元素。
      • +
      • prefix**suffix 表示全部以 prefix 开始,以 suffix 结尾的路径。
      • +
      +
    • +
    • 如果路径在 JSON 文档中不存在数据,将返回 NULL
    • +
    +

    假设 $ 引用的是如下 JSON 数组:

    +
    [3, {"a": [5, 6], "b": 10}, [99, 100]]
    +

    $[0] 获取到的值为 3,$[1] 获取到 {"a": [5, 6], "b": 10}$[2] 获取到 [99, 100]$[3] 获取到 NULL(因为不存在第 4 个元素)。

    +

    因为 $[1]$[2] 获取的并非纯量(nonscalar),它们可以进一步使用路径访问到内嵌的值,比如:$[1].a 获取到 [5, 6]$[1].a[1] 获取到 6$[1].b 获取到 10$[2][0] 获取到 99

    +

    上文提到,如果追加键值名后,路径表达式非法,需要对键名称用双引号包裹。假设 $ 引用的是如下 JSON 对象:

    +
    {"name 1": "Will", "name 2": "Andy"}
    +

    两个键都包含空格,需要加上双引号,才能使用路径表达式访问。$."name 1" 将获取到 Will,而 $."name 2" 将获取到 Andy

    +

    现在来看下通配符的示例,假设 JSON 对象如下:

    +
    {"a": {"b": 1}, "c": {"b": 2}, "d": [3, 4, 5]}
    +

    使用 $.* 将获取到 [{"b": 1}, {"b": 2}, [3, 4, 5]]
    +使用 $.d[*] 将获取到 [3, 4, 5]
    +使用 $**.b(对应 $.a.b$.c.b)将获取到 [1, 2]

    +

    MySQL 5.7.9 开始,官方支持 json_extract(column, path) 的简洁写法,内联 JSON 路径表达式 column->path(WL#8607)。示例如下:

    +
    -- 使用内联 json 路径表达式,查询 json 对象
    mysql> select * from tbl where data -> '$.id' = 2;
    +---------------------------+
    | data |
    +---------------------------+
    | {"id": 2, "name": "Andy"} |
    +---------------------------+
    1 row in set (0.00 sec)
    +

    本质上,这种写法是语法糖,column->path 等价于 json_extract(column, path),内联 JSON 路径表达式会在语法解析阶段被转换为 json_extract() 调用。另外,column->path,存在以下限制[20]

    +

    限制

    +

    即,1. 数据源必须是表字段,2. 路径表达式必须为字符串,3. SQL 语句中最多只支持一个。

    +

    现在来试验下这个限制,如果使用内联 JSON 路径表达式查询 MySQL 变量,将会报语法错误:

    +
    mysql> set @j = '["a", "b"]';

    -- 语法错误
    mysql> select @j -> '$[0]';
    ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-> '$[0]'' at line 1
    +

    json_unquote() 与 ->> 操作符

    +

    假设数据如下:

    +
    mysql> select * from tbl;
    +-----------------------------------------------+
    | data |
    +-----------------------------------------------+
    | {"id": 1, "name": "Will"} |
    | {"id": 2, "name": "printf(\"hello world\");"} |
    +-----------------------------------------------+
    2 rows in set (0.00 sec)
    +

    来看下使用 -> 提取获得 JSON 值:

    +
    mysql> select data -> '$.id', data -> '$.name', substr(data -> '$.name', 1, 1) from tbl;
    +----------------+----------------------------+--------------------------------+
    | data -> '$.id' | data -> '$.name' | substr(data -> '$.name', 1, 1) |
    +----------------+----------------------------+--------------------------------+
    | 1 | "Will" | " |
    | 2 | "printf(\"hello world\");" | " |
    +----------------+----------------------------+--------------------------------+
    2 rows in set (0.00 sec)

    mysql> create table tmp (id int, name varchar(50));
    mysql> insert tmp select data -> '$.id', data -> '$.name' from tbl;
    mysql> select *, substr(name, 1, 1) from tmp;
    +------+----------------------------+--------------------+
    | id | name | substr(name, 1, 1) |
    +------+----------------------------+--------------------+
    | 1 | "Will" | " |
    | 2 | "printf(\"hello world\");" | " |
    +------+----------------------------+--------------------+
    2 rows in set (0.01 sec)
    +

    可以看到,对于 string 类型的 JSON 值,使用 json_extract()-> 获取的都是被双引号包裹的字符串。MySQL 提供 json_unquote() 函数,用于去掉双引号包裹。另外,MySQL 支持 column->>path 语法,通过 ->> 操作符获取纯量(scalar)。column->>path 写法等价于 json_unquote( json_extract(column, path) ) 或者 json_unquote(column -> path)。来看下 SQL 示例:

    +
    mysql> select data ->> '$.id' as id, data -> '$.name' as name,
    -> data ->> '$.name' as name, json_unquote(data -> '$.name') as name from tbl;
    +------+----------------------------+------------------------+------------------------+
    | id | name | name | name |
    +------+----------------------------+------------------------+------------------------+
    | 1 | "Will" | Will | Will |
    | 2 | "printf(\"hello world\");" | printf("hello world"); | printf("hello world"); |
    +------+----------------------------+------------------------+------------------------+
    2 rows in set (0.00 sec)
    +

    MySQL 这种区分 ->->> 的写法,怀疑是源自 Postgres。因为 Postgres 也分别提供了 ->->> 操作符,-> 也是保留双引号(get JSON object field by key),而 ->> 才能获取实际的字符串值(get JSON object field as text)[21][22]

    +

    在笔者看来,这种需要通过 json_unquote() 才能获取实际字符串值的写法完全没有必要,因为很难想到有需要保留双引号的使用场景,而就获取实际的字符串值才是多数情况。实际上,SQLite 的开发者也持有相同的想法。2015 年 10 月,SQLite 3.9 发布,开始支持 JSON 类型[23][24]。简单对比下,可以发现 SQLite 提供的 JSON 函数和 MySQL 极其相似,很多函数同名并且同语义。SQLite 也提供了 json_extract() 函数,与 MySQL 不同,SQLite 返回的是移除双引号后的字符串(the dequoted text for a JSON string value)。看下示例:

    +
    sqlite> select json_extract('{"id": 1, "name": "Will"}', '$.name');
    Will
    sqlite> select json_extract('{"code": "printf(\"hello world\");"}', '$.code');
    printf("hello world");
    +

    对于提取 JSON 文档中的纯量(scalar),SQL 标准定义了的 json_value() 函数,MySQL 没有支持,但 Oracle、MariaDB、MSSQL 都有支持。MariaDB 在兼容 MySQL 的同时也支持 SQL 标准,json_extract() 和 json_value() 在 MariaDB 下都可用。来看下 SQL 示例:

    +
    MariaDB [testdb]> select * from tbl;
    +-----------------------------------------------+
    | data |
    +-----------------------------------------------+
    | {"id": 1, "name": "Will"} |
    | {"id": 2, "name": "printf(\"hello world\");"} |
    +-----------------------------------------------+
    2 rows in set (0.00 sec)

    -- 使用 json_extract() 提取 JSON 值,string 类型的值保留双引号
    MariaDB [testdb]> select json_extract(data, '$.id'), json_extract(data, '$.name') from tbl;
    +----------------------------+------------------------------+
    | json_extract(data, '$.id') | json_extract(data, '$.name') |
    +----------------------------+------------------------------+
    | 1 | "Will" |
    | 2 | "printf(\"hello world\");" |
    +----------------------------+------------------------------+
    2 rows in set (0.00 sec)

    -- 使用 json_value() 提取 JSON 值,string 类型的值自动移除双引号
    MariaDB [testdb]> select json_value(data, '$.id'), json_value(data, '$.name') from tbl;
    +--------------------------+----------------------------+
    | json_value(data, '$.id') | json_value(data, '$.name') |
    +--------------------------+----------------------------+
    | 1 | Will |
    | 2 | printf("hello world"); |
    +--------------------------+----------------------------+
    2 rows in set (0.00 sec)
    +

    其他查询函数

    +

    除了上文的 json_extract() 函数,查询 JSON 文档相关的还有其他函数,如 json_contains()、json_contains_path()、json_keys()、json_search()。示例如下:

    +
    mysql> set @j = '{"a": 1, "b": 2, "c": {"d": 4}}';
    Query OK, 0 rows affected (0.00 sec)

    -- 使用 json_contains() 函数判断是否存在某 JSON 值
    mysql> select json_contains(@j, '{"a": 1}');
    +-------------------------------+
    | json_contains(@j, '{"a": 1}') |
    +-------------------------------+
    | 1 |
    +-------------------------------+
    1 row in set (0.00 sec)

    -- 使用 json_contains_path() 函数判断是否存在某 JSON 路径
    mysql> select json_contains_path(@j, 'one', '$.a', '$.e');
    +-----------------------------------------------+
    | json_contains_path(@j, 'one', '$.a', '$.e') |
    |-----------------------------------------------|
    | 1 |
    +-----------------------------------------------+
    1 row in set (0.00 sec)

    -- 使用 json_contains_path() 函数判断是否存在某 JSON 路径
    mysql> select json_contains_path(@j, 'all', '$.a', '$.e');
    +-----------------------------------------------+
    | json_contains_path(@j, 'all', '$.a', '$.e') |
    |-----------------------------------------------|
    | 0 |
    +-----------------------------------------------+
    1 row in set (0.00 sec)
    +

    函数的完整定义和用法可以参考官方文档,本文不再一一举例说明。

    +

    修改 JSON

    +

    对于 MySQL 的 JSON 类型的数据,若要修改数据,可以使用类似如下的 SQL:

    +
    mysql> select * from tbl where data->'$.id' = 2;
    +---------------------------+
    | data |
    +---------------------------+
    | {"id": 2, "name": "Will"} |
    +---------------------------+
    1 row in set (0.00 sec)

    -- 对 data 整个字段修改
    mysql> update tbl set data = '{"id": 2, "name": "Andy"}' where data->'$.id' = 2;
    Query OK, 0 rows affected (0.00 sec)
    Rows matched: 1 Changed: 0 Warnings: 0

    mysql> select * from tbl where data->'$.id'= 2;
    +---------------------------+
    | data |
    +---------------------------+
    | {"id": 2, "name": "Andy"} |
    +---------------------------+
    1 row in set (0.00 sec)
    +

    如果要修改 JSON 内部数据,是否可以通过 JSON 路径表达式直接赋值呢?答案是,不行,MySQL 不支持。

    +
    -- 语法错误,不支持通过 JSON 路径表达式赋值,修改 JSON 数据
    mysql> update tbl set data->'$.name' = 'Andy' where data->'$.id' = 2;
    ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '->'$.name' = 'Andy' where data->'$.id' = 2' at line 1
    +

    MySQL 提供了数个函数来修改 JSON 数据。我们先来看看 json_replace()、json_set() 和 json_insert() 这三个函数:

    +
      +
    • json_replace():替换值。替换旧值,但不插入新值
    • +
    • json_set():设置值。替换旧值,或插入新值
    • +
    • json_insert():插入值。只插入新值,不替换旧值
    • +
    +

    json_insert() 只能插入数据, json_replace() 只能更新数据,json_set() 能更新或插入数据。

    +

    替换值,json_replace() 示例:

    +
    -- 使用 json_replace() 函数
    -- 把 {"id": 2, "name": "Will"} 修改为 {"id": 2, "name": "Andy"}
    -- 路径 $.name 指向的值存在,旧值被替换为新值
    mysql> update tbl
    -> set data = json_replace(data, '$.name', 'Andy')
    -> where data->'$.id' = 2;
    Query OK, 1 row affected (0.03 sec)
    Rows matched: 1 Changed: 1 Warnings: 0
    +

    设置值,json_set() 示例:

    +
    -- 使用 json_set() 函数
    -- 把 {"id": 2, "name": "Will"} 修改为 {"id": 2, "city": "北京", "name": "Bill"}
    -- 路径 $.name 指向的值存在,旧值被替换为新值;路径 $.city 指向的值不存在,将插入新值
    mysql> update tbl
    -> set data = json_set(data, '$.name', 'Bill', '$.city', '北京')
    -> where data->'$.id'= 2;
    Query OK, 1 row affected (0.00 sec)
    Rows matched: 1 Changed: 1 Warnings: 0

    mysql> select * from tbl where data->'$.id'= 2;
    +---------------------------------------------+
    | data |
    +---------------------------------------------+
    | {"id": 2, "city": "北京", "name": "Bill"} |
    +---------------------------------------------+
    1 row in set (0.00 sec)
    +

    插入值,json_insert() 示例:

    +
    -- 使用 json_set() 函数
    -- 把 {"id": 2, "name": "Will"} 修改为 {"id": 2, "address": "故宫"}
    -- 路径 $.name 指向的值存在,将不替换这个旧值;路径 $.address 指向的值不存在,将插入新值
    mysql> update tbl
    -> set data = json_insert(data, '$.name', 'Bill', '$.address', '故宫')
    -> where data->'$.id'= 2;
    Query OK, 1 row affected (0.04 sec)
    Rows matched: 1 Changed: 1 Warnings: 0

    mysql> select * from tbl where data->'$.id'= 2;
    +---------------------------------------------------------------------+
    | data |
    +---------------------------------------------------------------------+
    | {"id": 2, "name": "Will", "address": "故宫"} |
    +---------------------------------------------------------------------+
    1 row in set (0.00 sec)
    +

    现在,我们来看下修改 JSON 数组的两个函数,json_array_insert() 和 json_array_append(),函数定义如下:

    +
    json_array_insert(json_doc, path, val[, path, val] ...)
    json_array_append(json_doc, path, val[, path, val] ...)
    +

    json_array_insert(),参数 path 必须指向 JSON 数组某个位置的元素,若该位置存在值,将会把 val 插入该位置,然后其他元素向右移动;若该位置超出数组大小范围,将会把 val 插入到数组末尾。SQL 示例如下:

    +
    mysql> set @j = '["a", {"b": [1, 2]}, [3, 4]]';

    -- 在数组的索引 1 的位置上插入值 5,原本索引 1 位置上的 {"b": [1, 2]} 被挤到后边
    mysql> select json_array_insert(@j, '$[1]', 5);
    +------------------------------------+
    | json_array_insert(@j, '$[1]', 5) |
    |------------------------------------|
    | ["a", 5, {"b": [1, 2]}, [3, 4]] |
    +------------------------------------+
    1 row in set (0.00 sec)

    -- 插入位置超出数组大小范围,将会把值插入到数组末尾
    mysql> select json_array_insert(@j, '$[100]', 5);
    +--------------------------------------+
    | json_array_insert(@j, '$[100]', 5) |
    |--------------------------------------|
    | ["a", {"b": [1, 2]}, [3, 4], 5] |
    +--------------------------------------+
    1 row in set (0.00 sec)

    -- path 指向不是 JSON 数组的元素,SQL 执行报错
    mysql> select json_array_insert(@j, '$[1].b', 5);
    (3165, 'A path expression is not a path to a cell in an array.')
    +

    json_array_append(),如果参数 path 指向的 JSON 是数组,将在数组末尾添加元素;如果参数 path 指向的 JSON 是值或对象,该值或对象将被包裹为数组,然后在这个数组末尾添加元素。

    +
    mysql> set @j = '["a", {"b": [1, 2]}, [3, 4]]';

    -- path 指向的 JSON 是数组,将在数组末尾添加元素
    mysql> select json_array_append(@j, '$', 5);
    +---------------------------------+
    | json_array_append(@j, '$', 5) |
    +---------------------------------+
    | ["a", {"b": [1, 2]}, [3, 4], 5] |
    +---------------------------------+
    1 row in set (0.00 sec)

    -- path 指向的 JSON 是值或对象,该值或对象将被包裹为数组,然后在这个数组末尾添加元素
    mysql> select json_array_append(@j, '$[1]', 5);
    +-----------------------------------+
    | json_array_append(@j, '$[1]', 5) |
    +-----------------------------------+
    | ["a", [{"b": [1, 2]}, 5], [3, 4]] |
    +-----------------------------------+
    1 row in set (0.00 sec)
    +

    除了上文提到的函数,还有 json_merge_patch()、json_merge_preserve()、json_remove() 这个些函数,可以参考官方文档的介绍,本文不再一一举例说明。

    +

    索引 JSON:生成列

    +

    现在来看下根据 JSON 列查询表数据的执行计划,如下:

    +
    mysql> explain select * from tbl where data -> "$.id" = 1 \G
    *************************** 1. row ***************************
    id: 1
    select_type: SIMPLE
    table: tbl
    partitions: NULL
    type: ALL
    possible_keys: NULL
    key: NULL
    key_len: NULL
    ref: NULL
    rows: 2
    filtered: 100.00
    Extra: Using where
    1 row in set, 1 warning (0.00 sec)
    +

    可以看到,因为没有加索引,访问类型是全表扫描 type: ALL。来试下在 JSON 类型的 data 列上添加索引,会提示如下错误:

    +
    mysql> alter table tbl add index (data);
    ERROR 3152 (42000): JSON column 'data' cannot be used in key specification.
    +

    对于索引 JSON 类型列问题,MySQL 文档有如下阐述[2:1]

    +
    +

    JSON columns, like columns of other binary types, are not indexed directly; instead, you can create an index on a generated column that extracts a scalar value from the JSON column. See Indexing a Generated Column to Provide a JSON Column Index, for a detailed example.

    +
    +

    就是说,不能直接在 JSON 列上创建索引;替代方式是,先创建提取 JSON 纯量的生成列(generated column),然后在这个生成列上创建索引。回过头来,ERROR 3152,这个报错提示信息其实让人有点困惑,对没仔细阅读文档的人来说,可能会误以为 MySQL 不支持索引 JSON 列(Bug #81364[25])。于是,在 MySQL 8.0 错误提示信息优化为:

    +
    +

    ERROR 3152 (42000): JSON column '%s' supports indexing only via generated columns on a specified JSON path.

    +
    +

    生成列以及在生成列上创建索引,是 MySQL 5.7 开始支持的新特性。但其实,在 SQL:2003 标准中,生成列就早已经被定义为可选特性,“Optional Features of SQL/Foundation:2003, T175 Generated columns”。这个特性在其他 DBMS 中很早就有支持。2007 年 9 月发布的 Oracle Database 11g 开始支持生成列,不过它们称之为称之为虚拟列(virtual column)。2008 年 8 月发布的 SQL Server 2008 开始支持计算列(computed column),实现的就是 SQL 标准中的生成列。在相近的时间点,MySQL 创建了WL#411: Computed virtual columns as MS SQL server has[26]。之后,MySQL 的社区贡献者 Andrey Zhakov 实现了 WL#411 描述的特性,并发布了实现的代码补丁[27][28][29]。可惜的是 MySQL 官方很长一段时间都没把这个补丁合并进来,直到 2015 年的 MySQL 5.7(7年后)才官方实现 WL#411[30],同时 WL#411 的标题也被更新为符合 SQL 标准术语的 “Generated columns”。与之相对比的是,2010 年 4 月发布的 MariaDB 5.2 就开始支持虚拟列[31],实现上同样也是基于 Andrey Zhakov 贡献的代码。关于生成列或虚拟列,Wikipedia 的 Virtual column 词条[32]总结了各大 DBMS 的支持情况,可以参阅。总结下,标准 SQL 定义生成列的语法和 SQL Server 2008、Oracle 11g、MariaDB、MySQL 的区别[30:1][33]

    +
    Standard             MSSQL 2008      Oracle 11g           MariaDB 10.1           MySQL 5.7               
    -------- ----------- ---------- ------------ ---------
    column_name column_name column_name column_name column_name
    [data type] [data type] data_type data type
    GENERATED ALWAYS AS AS GENERATED ALWAYS AS [GENERATED ALWAYS] AS [GENERATED ALWAYS] AS
    (expression) (expression) (expression) (expression) (expression)
    [PERSISTENT] [VIRTUAL] [VIRTUAL | PERSISTENT] [VIRTUAL | STORED]
    [constraints] [constraints] [constraints] [constraints] [constraints]
    [COMMENT 'string'] [COMMENT 'string']
    +

    回到正题,我们现在来试试 MySQL 的生成列:

    +
    -- 添加生成列
    mysql> alter table tbl add id int as (data -> "$.id");
    Query OK, 0 rows affected (0.15 sec)
    Records: 0 Duplicates: 0 Warnings: 0

    mysql> select * from tbl;
    +-----------------------------------------------+------+
    | data | id |
    +-----------------------------------------------+------+
    | {"id": 1, "name": "Will"} | 1 |
    | {"id": 2, "name": "printf(\"hello world\");"} | 2 |
    +-----------------------------------------------+------+
    2 rows in set (0.00 sec)
    +

    上面的示例,创建生成列 id,生成列对应的表达式是 data -> "$.id"。现在再试试在生成列 id 上,创建索引:

    +
    -- 在生成列上创建索引 idx_id
    mysql> create index idx_id on tbl (id);
    Query OK, 0 rows affected (0.05 sec)
    Records: 0 Duplicates: 0 Warnings: 0

    -- 执行计划
    mysql> explain select * from tbl where id = 1 \G
    *************************** 1. row ***************************
    id: 1
    select_type: SIMPLE
    table: tbl
    partitions: NULL
    type: ref
    possible_keys: idx_id
    key: idx_id
    key_len: 5
    ref: const
    rows: 1
    filtered: 100.00
    Extra: NULL
    1 row in set, 1 warning (0.00 sec)

    -- 执行计划
    mysql> explain select * from tbl where data -> "$.id" = 1 \G
    *************************** 1. row ***************************
    id: 1
    select_type: SIMPLE
    table: tbl
    partitions: NULL
    type: ref
    possible_keys: idx_id
    key: idx_id
    key_len: 5
    ref: const
    rows: 1
    filtered: 100.00
    Extra: NULL
    1 row in set, 1 warning (0.00 sec)
    +

    从上面的执行计划可以看到,查询条件用 id 或者 data -> "$.id" 都能使用索引 idx_id

    +

    JSON 二进制格式

    +

    内部实现上,保存到数据库的 JSON 数据并非以 JSON 文本存储,而是二进制格式,具体可以参见,WL#8132: JSON datatype and binary storage format,当然也可以直接阅读源码 json_binary.h[34]、json_binary.cc[35]或 doxygen[36]

    +

    MySQL 的 JSON 二进制格式,其中有一点比较值得注意,WL#8132 提到:

    +
    +

    The keys are sorted, so that lookup can use binary search to locate the key quickly.

    +
    +

    就是,为了能利用二分搜索快速定位键,存入数据库的JSON 对象的键是被排序过的。来看下下面的 SQL:

    +
    mysql> truncate tbl;
    mysql> insert into tbl values ('{"b": "c", "a": {"y": 1, "x": 2}}');
    Query OK, 1 row affected (0.02 sec)

    mysql> select * from tbl;
    +-----------------------------------+
    | data |
    +-----------------------------------+
    | {"a": {"x": 2, "y": 1}, "b": "c"} |
    +-----------------------------------+
    1 row in set (0.00 sec)
    +

    上面的 SQL 可以看到,insert 写入时键并没有按次序排列,而用 select 将 JSON 数据反序列化读出,发现实际保存的键是有序的。排序规则是,先按字符串长度排序,若长度相同按字母排序。同样的,键关联的值,按键排序后的次序排列。对键排序,显然只能针对 JSON 对象,若要存储 JSON 数组,值按索引位置排序。

    +

    MySQL 5.7.22 新增 json_storage_size() 函数,用于返回 json 文档二进制表示占用的存储空间。先来看下 SQL 示例:

    +
    mysql> select json_storage_size('"abc"');
    +----------------------------+
    | json_storage_size('"abc"') |
    +----------------------------+
    | 5 |
    +----------------------------+
    1 row in set (0.00 sec)

    mysql> select json_storage_size('[42, "xy", "abc"]');
    +----------------------------------------+
    | json_storage_size('[42, "xy", "abc"]') |
    +----------------------------------------+
    | 21 |
    +----------------------------------------+
    1 row in set (0.00 sec)

    mysql> select json_storage_size('{"b": 42, "a": "xy"}');
    +-------------------------------------------+
    | json_storage_size('{"b": 42, "a": "xy"}') |
    +-------------------------------------------+
    | 24 |
    +-------------------------------------------+
    1 row in set (0.00 sec)
    +

    WL#8132 给出了 JSON 二进制格式的 BNF 语法描述。参考这个语法描述,可以推算出上文示例中的 "abc"[42, "xy", "abc"]{"b": 42, "a": "xy"} 对应的二进制表示。先来看下 "abc" 纯量,语法推导过程如下:

    +
    doc
    => type value // 使用产生式 doc ::= type value
    => 0x0c value // 使用产生式 type ::= 0x0c (utf8mb4 string 类型)
    => 0x0c string // 使用产生式 value ::= string
    => 0x0c data-length utf8mb4-data // 使用产生式 string ::= data-length utf8mb4-data
    => 0x0c 0x03 utf8mb4-data // 使用产生式 data-length ::= uint8*
    => 0x0c 0x03 0x61 0x62 0x63
    +

    对应的二进制值,共 5 个字节,依次为 0x0c 0x03 0x61 0x62 0x63,其中 0x61 0x62 0x63,就是 16 进制表示的字符串 abc。占用 5个字节,与 json_storage_size() 函数返回的结果一致。相应的语法树如下:

    +

    mysql-jsonb-syntax-tree-w350

    +

    从二进制的角度看,纯量 "abc" 的 JSON 二进制表示如下:

    +

    mysql-jsonb-scalar-w350

    +

    [42, "xy", "abc"] 的推导过程,如下:

    +
    doc 
    => type value // 使用产生式 doc ::= type value
    => 0x02 array // 使用产生式 type ::= 0x02 (small JSON array 类型)
    => 0x02 element-count size value-entry* value* // 使用产生式 array ::= element-count size value-entry* value*
    => 0x02 0x03 0x00 size value-entry* value* // 使用产生式 element-count ::= uint16 (使用 little-endian)
    => 0x02 0x03 0x00 0x14 0x00 value-entry* value* // 使用产生式 size ::= uint16 (使用 little-endian)
    => 0x02 0x03 0x00 0x14 0x00 type offset-or-inlined-value value-entry* value* // 使用产生式 value-entry ::= type offset-or-inlined-value
    => 0x02 0x03 0x00 0x14 0x00 0x06 offset-or-inlined-value value-entry* value* // 使用产生式 type ::= 0x06 (uint16 类型)
    => 0x02 0x03 0x00 0x14 0x00 0x06 0x2a 0x00 value-entry* value* // 使用产生式 offset-or-inlined-value ::= uint16
    ... 省略
    => 0x02 0x03 0x00 0x14 0x00 0x06 0x2a 0x00 0x0c 0x0d 0x00 0x0c 0x10 0x00 value*
    => 0x02 0x03 0x00 0x14 0x00 0x06 0x2a 0x00 0x0c 0x0d 0x00 0x0c 0x10 0x00 string value // 使用产生式 value ::= string
    => 0x02 0x03 0x00 0x14 0x00 0x06 0x2a 0x00 0x0c 0x0d 0x00 0x0c 0x10 0x00 data-length utf8mb4-data value // 使用产生式 string ::= data-length utf8mb4-data
    => 0x02 0x03 0x00 0x14 0x00 0x06 0x2a 0x00 0x0c 0x0d 0x00 0x0c 0x10 0x00 0x02 utf8mb4-data value // 使用产生式 data-length ::= uint8*
    => 0x02 0x03 0x00 0x14 0x00 0x06 0x2a 0x00 0x0c 0x0d 0x00 0x0c 0x10 0x00 0x02 0x78 0x78 value
    ... 省略
    => 0x02 0x03 0x00 0x14 0x00 0x06 0x2a 0x00 0x0c 0x0d 0x00 0x0c 0x10 0x00 0x02 0x78 0x79 0x03 0x61 0x62 0x63
    +

    [42, "xy", "abc"] 对应的二进制表示,共 21 个字节,依次为 0x02 0x03 0x00 0x14 0x00 0x06 0x2a 0x00 0x0c 0x0d 0x00 0x0c 0x10 0x00 0x02 0x78 0x79 0x03 0x61 0x62 0x63。如下图:

    +

    mysql-jsonb-array

    +

    相对来说,产生式 array ::= element-count size value-entry* value*,是整个JSON 数组二进制表示语法的核心。element-count,表示元素个数。上图中,第 4、5 个字节是 size 字段,十进制值为 20(0x14),是完整二进制表示去掉开头 type 字段后的大小(文档没有明确这个字段的含义,不过通过源码推断出来)。另外,value-entrytypeoffset-or-inlined-value 字段组成。type 很好理解,不做解释。offset-or-inlined-value 字段,官方文档给出了含义,含义如下:

    +
    // This field holds either the offset to where the value is stored,
    // or the value itself if it is small enough to be inlined (that is,
    // if it is a JSON literal or a small enough [u]int).
    offset-or-inlined-value ::=
    uint16 | // if used in small JSON object/array
    uint32 // if used in large JSON object/array
    +

    就是说,如果实际要保存的值足够小,将直接内联在这个字段中,否则将保存偏移量(offset),也就是指向实际值的指针。在示例中,保存 xy 对应的 offset 值为 13(0x0d),指向的相对地址是 14。因为这里的 offset 并不是以相对地址 0 为基准地址,是以相对地址 1 为基准地址(图中箭头 B 指向的位置),所以偏移量是 13 而不是 14(这个字段的明确含义也是从源码推断而来)。类似的,保存 abc 对应的 offset 值为 16(0x10),指向的相对地址是 17。

    +

    阅读文档容易发现,element-countsizeoffset 字段占用的字节大小是固定的,小 JSON(64KB 以内)是 2 字节,大 JSON 是 4 字节。所以,若要查找 JSON 数组的第 pos 个元素的 value-entry 的偏移量,可以使用下面的式子快速定位:

    +
    entry_offset = offset_size * 2 + (1 + offset_size) * pos
    +

    JSON 数组二进制表示的其他字段比较容易理解,文档都有解释,就不展开阐述了。

    +

    现在来看下,JSON 对象 {"b": 42, "a": "xy"} 的二进制表示,如下图:

    +

    mysql-jsonb-object

    +

    对于 JSON 对象二进制表示的语法,核心的产生式是 object ::= element-count size key-entry* value-entry* key* value*element-countsizevalue-entry 字段,在 JSON 数组中也有,不再赘述。而 key-entry 字段,类似于 value-entrykey-entry 中的 key-offset 保存的是偏移量,是指向键的指针。另外,正如上文提到的 MySQL 会对 JSON 键排序,所以上图示例的第 20 和 21 个字节值分别是 0x610x62,即 ab,而非 ba。同样的,键关联的值,按键排序后的次序排列,依次是 "xy"42

    +

    参考资料

    +
    +
    +
      +
    1. MySQL 5.7 Reference Manual, What Is New in MySQL 5.7 https://dev.mysql.com/doc/refman/5.7/en/mysql-nutshell.html ↩︎

      +
    2. +
    3. MySQL 5.7 Reference Manual, 12 Data Types, 12.6 The JSON Data Type http://dev.mysql.com/doc/refman/5.7/en/json.html ↩︎ ↩︎

      +
    4. +
    5. 2012-09 PostgreSQL 9.2 released https://www.postgresql.org/about/news/postgresql-92-released-1415/ ↩︎

      +
    6. +
    7. JSON Support in Oracle Database 12c Release 1 (12.1.0.2) https://oracle-base.com/articles/12c/json-support-in-oracle-database-12cr1 ↩︎

      +
    8. +
    9. Oracle Database 12c Release 1 (12.1.0.2) New Features, 1.9 JSON Support https://docs.oracle.com/database/121/NEWFT/chapter12102.htm#NEWFT505 ↩︎

      +
    10. +
    11. Facebook DocStore: Document column type [Deprecated] https://github.com/facebook/mysql-5.6/wiki/Document-column-type-[Deprecated] ↩︎

      +
    12. +
    13. 2015-04 DocStore: Document Database for MySQL at Facebook (slides) https://web.archive.org/web/20161022061349/https://www.percona.com/live/mysql-conference-2015/sites/default/files/slides/Facebook DocStore Percona 2015.pdf ↩︎

      +
    14. +
    15. 2014-03 SQL/JSON Proposals, Part 1 https://www.wiscorp.com/pub/DM32.2-2014-00024R1_JSON-SQL-Proposal-1.pdf ↩︎

      +
    16. +
    17. 2014-03 SQL/JSON Proposals, Part 2 https://www.wiscorp.com/pub/DM32.2-2014-00025r1-sql-json-part-2.pdf ↩︎

      +
    18. +
    19. 2014-03 SQL Support for JSON (slides) https://web.archive.org/web/20150919002536/http://jtc1bigdatasg.nist.gov/_workshop/08_SQL_Support_for_JSON_abstract.pdf ↩︎

      +
    20. +
    21. 2017-06 What’s New in SQL:2016 https://modern-sql.com/blog/2017-06/whats-new-in-sql-2016 ↩︎

      +
    22. +
    23. WL#7909: Server side JSON functions https://dev.mysql.com/worklog/task/?id=7909 ↩︎

      +
    24. +
    25. WL#8132: JSON datatype and binary storage format https://dev.mysql.com/worklog/task/?id=8132 ↩︎

      +
    26. +
    27. WL#8249: JSON comparator https://dev.mysql.com/worklog/task/?id=8249 ↩︎

      +
    28. +
    29. WL#8607: Inline JSON path expressions in SQL https://dev.mysql.com/worklog/task/?id=8607 ↩︎

      +
    30. +
    31. MySQL 5.7 Reference Manual, 13 Functions and Operators, 13.16 JSON Functions https://dev.mysql.com/doc/refman/5.7/en/json-functions.html ↩︎

      +
    32. +
    33. 2015-04 JSON Labs Release: JSON Functions, Part 1 — Manipulation JSON Data http://mysqlserverteam.com/json-labs-release-json-functions-part-1-manipulation-json-data/ ↩︎

      +
    34. +
    35. 2015-04 JSON Labs Release: JSON Functions, Part 2 — Querying JSON Data http://mysqlserverteam.com/mysql-5-7-lab-release-json-functions-part-2-querying-json-data/ ↩︎

      +
    36. +
    37. JSONPath - XPath for JSON https://goessner.net/articles/JsonPath/ ↩︎

      +
    38. +
    39. 2015-10 Inline JSON Path Expressions in MySQL 5.7 http://mysqlserverteam.com/inline-json-path-expressions-in-mysql-5-7/ ↩︎

      +
    40. +
    41. PostgreSQL 11.10 Documentation, 9.15. JSON Functions and Operators https://www.postgresql.org/docs/11/functions-json.html ↩︎

      +
    42. +
    43. What is the difference between ->> and -> in Postgres SQL? https://stackoverflow.com/a/47270495 ↩︎

      +
    44. +
    45. 2015-10 SQLite Release 3.9.0 https://sqlite.org/releaselog/3_9_0.html ↩︎

      +
    46. +
    47. SQLite: The JSON1 Extension https://www.sqlite.org/json1.html ↩︎

      +
    48. +
    49. Bug #81364: Indexing JSON column should suggest generated columns https://bugs.mysql.com/bug.php?id=81364 ↩︎

      +
    50. +
    51. WL#411: Computed virtual columns as MS SQL server has https://web.archive.org/web/20080917094638/http://forge.mysql.com/worklog/task.php?id=411 ↩︎

      +
    52. +
    53. Bug #46491: Patch: Virtual columns (WL#411) https://bugs.mysql.com/bug.php?id=46491 ↩︎

      +
    54. +
    55. 2008-09 MySQL virtual columns https://datacharmer.blogspot.com/2008/09/mysql-virtual-columns.html ↩︎

      +
    56. +
    57. MySQL virtual columns preview https://web.archive.org/web/20120629093123/http://forge.mysql.com/wiki/MySQL_virtual_columns_preview ↩︎

      +
    58. +
    59. WL#411: Generated columns https://dev.mysql.com/worklog/task/?id=411 ↩︎ ↩︎

      +
    60. +
    61. MariaDB: Generated (Virtual and Persistent/Stored) Columns https://mariadb.com/kb/en/generated-columns/ ↩︎

      +
    62. +
    63. Virtual column https://en.wikipedia.org/wiki/Virtual_column ↩︎

      +
    64. +
    65. 2016-02 Generated columns in MariaDB and MySQL https://planet.mysql.com/entry/?id=5994068 ↩︎

      +
    66. +
    67. MySQL 5.7 Source Code: sql/json_binary.h https://github.com/mysql/mysql-server/blob/5.7/sql/json_binary.h ↩︎

      +
    68. +
    69. MySQL 5.7 Source Code: sql/json_binary.cc https://github.com/mysql/mysql-server/blob/5.7/sql/json_binary.cc ↩︎

      +
    70. +
    71. MySQL 8.0 Source Code Documentation: json_binary.h File Reference (doxygen) https://dev.mysql.com/doc/dev/mysql-server/8.0.16/json__binary_8h.html#details ↩︎

      +
    72. +
    +
    +]]>
    + + MySQL + + + MySQL + 数据库 + +
    + + MySQL binlog:格式、增量恢复、闪回、Java 解析 + /2018/06/mysql-binlog/ + MySQL 的 binlog 日志文件,记录了数据库表的全部修改操作。本文简单整理 MySQL binlog 相关知识,以及如何使用 binlog 恢复或闪回数据库数据。

    +

    STATEMENT 格式的 binlog

    +

    要想开启 binlog,需要在启动 MySQL 时传入 --log-bin 参数。或者也可以在 MySQL 配置文件 /etc/my.cnf,设置 log_bin 开启 binlog。MySQL 5.7 开始,开启 binlog 后,--server-id 参数也必须指定,否则 MySQL 服务器会启动失败。

    + +

    binlog_format 支持 STATEMENT, ROW, MIXED 三种格式,MySQL 5.5 和 5.6 默认为 STATEMENT,MySQL 5.7.7 开始默认为 ROW。若 SQL 使用 UUID(), RAND(), VERSION() 等函数,或者使用存储过程、自定义函数,基于 STATEMENT 的主从复时,是不安全的(很多人可能会认为 NOW(), CURRENT_TIMESTAMP 这些函数也是不安全的,事实上是安全的)[ doc1, doc2 ]。基于 ROW 的主从复制,是最安全的复制方式。

    +

    现在先来看下 STATEMENT 格式的 binlog,/etc/my.cnf 文件修改的内容如下:

    +
    server_id = 1
    log_bin = mysql-bin
    binlog_format = STATEMENT
    binlog_row_image=FULL
    +

    重启 MySQL 后,在数据目录 datadir 下,比如 /var/lib/mysql/,将会生成相应的 binlog 文件,mysql-bin.indexmysql-bin.000001.index 后缀的文件保存全部 binlog 文件名。mysql-bin.000001 文件记录 binlog 内容。每次 MySQL 启动或者 flush 日志,都将按序号创建一个新的日志文件。另外,当日志文件大小超过 max_binlog_size 时,也会创建一个新的日志文件。

    +

    现在来试一试 binlog 功能。假设在 testdb 库在有 hello 表,并对其中某行做修改操作:

    +
    mysql> select * from hello;
    +----+-------+
    | id | name |
    +----+-------+
    | 1 | Andy |
    | 2 | Bill |
    | 3 | Candy |
    +----+-------+
    4 rows in set (0.00 sec)

    mysql> update hello set name = 'Will' where id = 3;
    Query OK, 1 row affected (0.02 sec)
    Rows matched: 1 Changed: 1 Warnings: 0
    +

    binlog 为二进制文件,需要使用 mysqlbinlogdoc, man)命令查看:

    +
    $ sudo mysqlbinlog /var/lib/mysql/mysql-bin.000001  # 直接在 mysql 服务器上读取 binlog 文件
    $ mysqlbinlog -R -h192.168.2.107 -uroot -p123456 mysql-bin.000001 # 或者,远程读取 binlog 文件
    +

    执行 update 后相应新增的 binlog 文件内容:

    +
    # at 154
    #180617 22:47:49 server id 1 end_log_pos 219 CRC32 0x4bd9d69b Anonymous_GTID last_committed=0 sequence_number=1 rbr_only=no
    SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
    # at 219
    #180617 22:47:49 server id 1 end_log_pos 302 CRC32 0x476fafc9 Query thread_id=2 exec_time=0 error_code=0
    SET TIMESTAMP=1529246869/*!*/;
    SET @@session.pseudo_thread_id=2/*!*/;
    SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
    SET @@session.sql_mode=1075838976/*!*/;
    SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
    /*!\C utf8 *//*!*/;
    SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33/*!*/;
    SET @@session.lc_time_names=0/*!*/;
    SET @@session.collation_database=DEFAULT/*!*/;
    BEGIN
    /*!*/;
    # at 302
    #180617 22:47:49 server id 1 end_log_pos 423 CRC32 0x7f2c2c7a Query thread_id=2 exec_time=0 error_code=0
    use `testdb`/*!*/;
    SET TIMESTAMP=1529246869/*!*/;
    update hello set name = 'Will' where id = 3
    /*!*/;
    # at 423
    #180617 22:47:49 server id 1 end_log_pos 454 CRC32 0x68da744a Xid = 12
    COMMIT/*!*/;
    +

    ROW 格式的 binlog

    +

    修改 /etc/my.cnfbinlog_formatROW,再重启 MySQL。格式修改后,会生成一个新的 binlog 文件 mysql-bin.000002

    +
    mysql> show create table hello;
    +-------+-------------------------------------------------------------------------+
    | Table | Create Table
    +-------+-------------------------------------------------------------------------+
    | hello | CREATE TABLE `hello` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT,
    `name` varchar(20) DEFAULT NULL,
    PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 |
    +-------+-------------------------------------------------------------------------+
    1 row in set (0.00 sec)

    mysql> select * from hello where id;
    +----+------+
    | id | name |
    +----+------+
    | 1 | Andy |
    | 2 | Lily |
    | 3 | Will |
    +----+------+
    1 row in set (0.00 sec)

    mysql> update hello set name = 'David' where id = 3;
    Query OK, 1 row affected (0.02 sec)
    Rows matched: 1 Changed: 1 Warnings: 0
    +

    查看 ROW 格式的 binlog,需要使用 sudo mysqlbinlog -v --base64-output=DECODE-ROWS /var/lib/mysql/mysql-bin.000002 命令。执行 update 后相应新增的 binlog 内容:

    +
    # at 154
    #180617 22:54:13 server id 1 end_log_pos 219 CRC32 0x2ce70d4d Anonymous_GTID last_committed=0 sequence_number=1 rbr_only=yes
    /*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
    SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
    # at 219
    #180617 22:54:13 server id 1 end_log_pos 293 CRC32 0x8183fddf Query thread_id=2 exec_time=0 error_code=0
    SET TIMESTAMP=1529247253/*!*/;
    SET @@session.pseudo_thread_id=2/*!*/;
    SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
    SET @@session.sql_mode=1075838976/*!*/;
    SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
    /*!\C utf8 *//*!*/;
    SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33/*!*/;
    SET @@session.lc_time_names=0/*!*/;
    SET @@session.collation_database=DEFAULT/*!*/;
    BEGIN
    /*!*/;
    # at 293
    #180617 22:54:13 server id 1 end_log_pos 346 CRC32 0x0fc7e1a4 Table_map: `testdb`.`hello` mapped to number 110
    # at 346
    #180617 22:54:13 server id 1 end_log_pos 411 CRC32 0xb58e729d Update_rows: table id 110 flags: STMT_END_F
    ### UPDATE `testdb`.`hello`
    ### WHERE
    ### @1=3
    ### @2='Will'
    ### SET
    ### @1=3
    ### @2='David'
    # at 411
    #180617 22:54:13 server id 1 end_log_pos 442 CRC32 0xef964db8 Xid = 13
    COMMIT/*!*/;
    +

    若执行如下 SQL:

    +
    mysql> insert hello (name) values ('Frank');
    Query OK, 1 row affected (0.02 sec)
    +

    相应生成的 binlog 内容:

    +
    # at 442
    #180617 22:55:47 server id 1 end_log_pos 507 CRC32 0x79de08a7 Anonymous_GTID last_committed=1 sequence_number=2 rbr_only=yes
    /*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
    SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
    # at 507
    #180617 22:55:47 server id 1 end_log_pos 581 CRC32 0x56f9eb6a Query thread_id=2 exec_time=0 error_code=0
    SET TIMESTAMP=1529247347/*!*/;
    BEGIN
    /*!*/;
    # at 581
    #180617 22:55:47 server id 1 end_log_pos 634 CRC32 0xedb73620 Table_map: `testdb`.`hello` mapped to number 110
    # at 634
    #180617 22:55:47 server id 1 end_log_pos 684 CRC32 0x525a6a70 Write_rows: table id 110 flags: STMT_END_F
    ### INSERT INTO `testdb`.`hello`
    ### SET
    ### @1=4
    ### @2='Frank'
    # at 684
    #180617 22:55:47 server id 1 end_log_pos 715 CRC32 0x09a0d4de Xid = 14
    COMMIT/*!*/;
    +

    若执行如下 SQL:

    +
    mysql> delete from hello where id = 2;
    Query OK, 1 row affected (0.02 sec)
    +

    相应生成的 binlog 内容:

    +
    # at 715
    #180617 22:56:44 server id 1 end_log_pos 780 CRC32 0x9f52450e Anonymous_GTID last_committed=2 sequence_number=3 rbr_only=yes
    /*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
    SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
    # at 780
    #180617 22:56:44 server id 1 end_log_pos 854 CRC32 0x0959bc8d Query thread_id=2 exec_time=0 error_code=0
    SET TIMESTAMP=1529247404/*!*/;
    BEGIN
    /*!*/;
    # at 854
    #180617 22:56:44 server id 1 end_log_pos 907 CRC32 0x2945260f Table_map: `testdb`.`hello` mapped to number 110
    # at 907
    #180617 22:56:44 server id 1 end_log_pos 956 CRC32 0xc70df255 Delete_rows: table id 110 flags: STMT_END_F
    ### DELETE FROM `testdb`.`hello`
    ### WHERE
    ### @1=2
    ### @2='Bill'
    # at 956
    #180617 22:56:44 server id 1 end_log_pos 987 CRC32 0x0c98f18e Xid = 15
    COMMIT/*!*/;
    +

    使用 binlog 增量恢复

    +

    MySQL 逻辑备份通常会结合全量备份增量备份,使用 mysqldump 定期全量备份数据库,然后利用 binlog 保存增量数据。恢复数据时,就是用 mysqldump 备份的数据恢复到备份的时间点。数据库在备份时间点到当前时间的增量修改,则通过 mysqlbinlog 将 binlog 中的增量数据恢复到数据库。现在假设已经使用 mysqldump 将数据库还原到:

    +
    mysql> select * from hello;
    +----+------+
    | id | name |
    +----+------+
    | 1 | Andy |
    | 2 | Lily |
    | 3 | Will |
    +----+------+
    3 rows in set (0.00 sec)
    +

    之后执行的 SQL:

    +
    update hello set name = 'David' where id = 3;
    insert hello (name) values ('Frank');
    delete from hello where id = 2;
    +

    不管是使用 STATEMENT 还是 ROWmysqlbinlog 命令都可以将 binlog 增量恢复到数据库 [ doc ]。

    +

    观察 binlog 可以看到,从最开始的 update hello set name = 'David' where id = 3; 到最终的 delete from hello where id = 2;,时间上从 "2018-06-17 22:54:13" 到 "2018-06-17 22:56:44",所以基于时间点恢复,命令如下:

    +
    $ sudo mysqlbinlog --start-datetime="2018-06-17 22:54:13" --stop-datetime="2018-06-17 22:56:44" mysql-bin.000002 | mysql -uroot -p123456
    +

    binlog 的事件位置号是从 "154" 到 "956",但需要注意的是 用 --start-position--stop-position 指定位置点范围,逻辑上对应的是 start <= position < stop,所以基于时间点恢复,命令如下:

    +
    $ sudo mysqlbinlog --start-position=154 --stop-position=957 mysql-bin.000002 | mysql -uroot -p123456
    +

    两种方式任意执行,都能将数据恢复到:

    +
    mysql> select * from hello;
    +----+-------+
    | id | name |
    +----+-------+
    | 1 | Andy |
    | 3 | David |
    | 4 | Frank |
    +----+-------+
    3 rows in set (0.00 sec)
    +

    使用 binlog2sql 闪回

    +

    binlog2sql,作者为曹单锋,大众点评 DBA。binlog2sql,从 MySQL binlog 解析出你要的 SQL。根据不同选项,你可以得到原始 SQL、回滚 SQL、去除主键的 INSERT SQL 等。binlog2sql,底层实现依赖 python-mysql-replication,由该库完成 MySQL 复制协议和 binlog 格式的解析。

    +
    $ python binlog2sql/binlog2sql.py -h192.168.2.107 -uroot -p123456 --start-position=154 --stop-position=957 --start-file='mysql-bin.000002'
    UPDATE `testdb`.`hello` SET `id`=3, `name`='David' WHERE `id`=3 AND `name`='Will' LIMIT 1; #start 4 end 411 time 2018-06-17 22:54:13
    INSERT INTO `testdb`.`hello`(`id`, `name`) VALUES (4, 'Frank'); #start 442 end 684 time 2018-06-17 22:55:47
    DELETE FROM `testdb`.`hello` WHERE `id`=2 AND `name`='Bill' LIMIT 1; #start 715 end 956 time 2018-06-17 22:56:44
    +

    生成回滚 sql:

    +
    $ python binlog2sql/binlog2sql.py --flashback -h192.168.2.107 -uroot -p123456 --start-position=154 --stop-position=956 --start-file='mysql-bin.000002'
    INSERT INTO `testdb`.`hello`(`id`, `name`) VALUES (2, 'Bill'); #start 715 end 956 time 2018-06-17 22:56:44
    DELETE FROM `testdb`.`hello` WHERE `id`=4 AND `name`='Frank' LIMIT 1; #start 442 end 684 time 2018-06-17 22:55:47
    UPDATE `testdb`.`hello` SET `id`=3, `name`='Will' WHERE `id`=3 AND `name`='David' LIMIT 1; #start 154 end 411 time 2018-06-17 22:54:13
    +

    闪回的现实原理很简单,先通过 MySQL 复制协议com-binlog-dump 命令 dump 出 binlog,然后按照 binlog 的格式规范解析 binlog,将 binlog 转换成 SQL,再将这些 SQL 转换反向逻辑的 SQL,最后再倒序执行。具体可以看,binlog2sql 作者的文章 [ ref ]。

    +

    Java 解析 binlog

    +

    上文中的 binlog2sql 其实底层依赖 python-mysql-replication 库,这是 Python 库。如果想使用 Java 解析 binlog 可以使用 mysql-binlog-connector-javagithub)库。目前开源的 CDC 工具,如 Zendesk maxwell、Redhat debezium、LinkedIn Databus 等都底层依赖 mysql-binlog-connector-java 或者其前身 open-replicator。使用 mysql-binlog-connector-java 的示例代码如下:

    +
    BinaryLogClient client = new BinaryLogClient("192.168.2.107", 3306, "root", "123456");
    client.setBinlogFilename("mysql-bin.000001");
    client.setBinlogPosition(4);
    client.setBlocking(false);
    client.registerEventListener(event -> {
    System.out.println(event);
    });
    client.connect();
    +

    输出(省略部分内容):

    +
    ...
    Event{header=EventHeaderV4{timestamp=1529247253000, eventType=TABLE_MAP, serverId=1, headerLength=19, dataLength=34, nextPosition=346, flags=0}, data=TableMapEventData{tableId=110, database='testdb', table='hello', columnTypes=8, 15, columnMetadata=0, 40, columnNullability={1}}}
    Event{header=EventHeaderV4{timestamp=1529247253000, eventType=EXT_UPDATE_ROWS, serverId=1, headerLength=19, dataLength=46, nextPosition=411, flags=0}, data=UpdateRowsEventData{tableId=110, includedColumnsBeforeUpdate={0, 1}, includedColumns={0, 1}, rows=[
    {before=[3, Will], after=[3, David]}
    ]}}
    ...
    Event{header=EventHeaderV4{timestamp=1529247347000, eventType=TABLE_MAP, serverId=1, headerLength=19, dataLength=34, nextPosition=634, flags=0}, data=TableMapEventData{tableId=110, database='testdb', table='hello', columnTypes=8, 15, columnMetadata=0, 40, columnNullability={1}}}
    Event{header=EventHeaderV4{timestamp=1529247347000, eventType=EXT_WRITE_ROWS, serverId=1, headerLength=19, dataLength=31, nextPosition=684, flags=0}, data=WriteRowsEventData{tableId=110, includedColumns={0, 1}, rows=[
    [4, Frank]
    ]}}
    ...
    Event{header=EventHeaderV4{timestamp=1529247404000, eventType=TABLE_MAP, serverId=1, headerLength=19, dataLength=34, nextPosition=907, flags=0}, data=TableMapEventData{tableId=110, database='testdb', table='hello', columnTypes=8, 15, columnMetadata=0, 40, columnNullability={1}}}
    Event{header=EventHeaderV4{timestamp=1529247404000, eventType=EXT_DELETE_ROWS, serverId=1, headerLength=19, dataLength=30, nextPosition=956, flags=0}, data=DeleteRowsEventData{tableId=110, includedColumns={0, 1}, rows=[
    [2, Bill]
    ]}}
    +

    参考资料

    +
      +
    1. MySQL Replication: 5.1.1 Advantages and Disadvantages of Statement-Based and Row-Based Replication https://dev.mysql.com/doc/mysql-replication-excerpt/5.7/en/replication-sbr-rbr.html
    2. +
    3. Unsafe Statements for Statement-based Replication https://mariadb.com/kb/en/library/unsafe-statements-for-statement-based-replication/
    4. +
    5. MySQL 5.7 Reference Manual: 4.6.7 mysqlbinlog https://dev.mysql.com/doc/refman/5.7/en/mysqlbinlog.html
    6. +
    7. MySQL Internals Manual: 14.9 Replication Protocol https://dev.mysql.com/doc/internals/en/replication-protocol.html
    8. +
    9. MySQL Internals Manual: 20 The Binary Log https://dev.mysql.com/doc/internals/en/binary-log.html
    10. +
    11. MySQL闪回原理与实战 https://github.com/danfengcao/binlog2sql/blob/master/example/mysql-flashback-priciple-and-practice.md
    12. +
    13. https://dev.mysql.com/doc/dev/mysql-server/8.0.11/classbinary__log_1_1Table__map__event.html#details
    14. +
    15. https://dev.mysql.com/doc/dev/mysql-server/8.0.11/classbinary__log_1_1Rows__event.html#details
    16. +
    +]]>
    + + MySQL + + + MySQL + 数据库 + binlog + +
    + + MySQL数据库字段类型杂记 + /2017/01/mysql-data-types/ + 文本整理MySQL字段类型的常见问题和用法。

    +

    数值类型

    +

    int和int(3)

    +

    新手在定义整数字段时,常常想当然通过,如int(3),来限制整数的有效长度,然而这样仅仅只是指定了显示宽度。选择有效长度不同的整数,需要使用tinyint(1个字节)、smallint(2个字节)、mediumint(3个字节)、int(4个字节)或bigint(8个字节)。MySQL的相关文档如下[doc]:

    + +
    +

    MySQL supports an extension for optionally specifying the display width of integer data types in parentheses following the base keyword for the type. For example, INT(4) specifies an INT with a display width of four digits.

    +
    +
    +

    The display width does not constrain the range of values that can be stored in the column. Nor does it prevent values wider than the column display width from being displayed correctly. For example, a column specified as SMALLINT(3) has the usual SMALLINT range of -32768 to 32767, and values outside the range permitted by three digits are displayed in full using more than three digits.

    +
    +
    +

    When used in conjunction with the optional (nonstandard) attribute ZEROFILL, the default padding of spaces is replaced with zeros. For example, for a column declared as INT(4) ZEROFILL, a value of 5 is retrieved as 0005.

    +
    +

    如下示例,字段bar类型是int(3),但依然能够正确保存数值12345

    +
    mysql> create table test (foo int(3) zerofill, bar int(3) zerofill, baz int);
    Query OK, 0 rows affected (0.16 sec)

    mysql> insert into test values (42, 12345, 12345);
    Query OK, 1 row affected (0.00 sec)

    mysql> select * from test;
    +------+-------+-------+
    | foo | bar | baz |
    +------+-------+-------+
    | 042 | 12345 | 12345 |
    +------+-------+-------+
    1 row in set (0.00 sec)
    +

    bit和bool

    +

    MySQL同时支持bitbool类型,但bool仅仅是tinyint(1)的同义词,创建的字段值的范围并不是01truefalse,而是-128127。如下所示:

    +
    mysql> create table test (foo bool, bar bit);
    Query OK, 0 rows affected (0.10 sec)

    mysql> desc test;
    +---------+------------+--------+-------+-----------+---------+
    | Field | Type | Null | Key | Default | Extra |
    |---------+------------+--------+-------+-----------+---------|
    | foo | tinyint(1) | YES | | <null> | |
    | bar | bit(1) | YES | | <null> | |
    +---------+------------+--------+-------+-----------+---------+
    2 rows in set (0.00 sec)
    +

    字符串类型

    +

    长度和编码

    +

    从MySQL 4.1开始(2004年10月),用字符单位解释在字符列定义中的长度规范。(以前的一些MySQL版本以字节解释长度)。官方文档描述如下[doc]

    +
    +

    In MySQL 4.1 and up , string data types include some features that you may not have encountered in working with versions of MySQL prior to 4.1:

    +
    +
    +

    MySQL interprets length specifications in character column definitions in character units. (Before MySQL 4.1, column lengths were interpreted in bytes.) This applies to CHAR, VARCHAR, and the TEXT types.

    +
    +

    MySQL服务器默认的字符集latin1,使用的校对规则latin1_swedish_ci [doc](校对规则是在字符集内用于比较字符的一套规则)。若要保存中文,典型的做法是使用utf8编码。但MySQL的utf8编码最多只能保存使用utf8编码后长度是3个字节的字符,即只支持基本多文种平面。使用MySQL的utf8保存常见的字符基本上没有问题,但对于生僻字或emoji字符就无能为力了。emoji的中的笑脸(grinning face)的Unicode编码,如下 [ref1][ref2]:

    + + + + + + + + + + + + + + + + + +
    表情UnicodeUTF-16UTF8
    😀U+1F6040xD83D 0xDE040xF0 0x9F 0x98 0x84
    +

    emoji位于辅助多文种平面,utf8需要4个字节保存。为了解决这个问题,MySQL 5.5.3开始支持utf8mb4,支持辅助多文种平面,每个字符最大4个字节 [doc]。除了utf8,MySQL还支持ucs2utf16utf32等,完整列表如下 [ref]

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    字符集支持的字符每个字符需要的存储空间
    utf8基本多文种平面1, 2, 或 3 个字节
    ucs2基本多文种平面2字节
    utf8mb4基本多文种平面和辅助多文种平面1, 2, 3,或4字节
    utf16基本多文种平面和辅助多文种平面2或4字节
    utf16le基本多文种平面和辅助多文种平面2或4字节
    utf32基本多文种平面和辅助多文种平面4字节
    +

    ##varchar和text

    +

    MySQL支持多种字符串类型, 如下表所示:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    类型最大字节长度最大utf8字符数
    char(M)M,M为0~255之间的整数85个utf8字符
    varchar(M)M,M为0~65,535之间的整数21,844个utf8字符
    tinytext 255 (28−1) 字节85个utf8字符
    text65,535 (216−1) 字节 = 64 KB21,844个utf8字符
    mediumtext16,777,215 (224−1) 字节 = 16 MB5,592,405个utf8字符
    longtext4,294,967,295 (232−1) 字节 = 4 GB1,431,655,765个utf8字符
    +

    字符串类型实际支持的最大字符数与编码有关。比如,varchar类型在utf8编码下最大支持保存21,844 (65,535 / 3 = 21,844) 个字符,而utf8mb4编码下最大支持保存16,383 (65,535 / 4 = 16,383) 个字符。

    +

    另外,MySQL表行最大总长度为65,535字节 [doc], 所以varchar类型字段的最大字符数会被表中其他字段所占用的存储空间挤掉。blobtext类型的字段不会受表行总长度的限制,因为字段存储的实际内容和表行是分离的,只会占用表行的9到12个字节。

    +
    mysql> create table test ( foo varchar(21845) character set utf8 );
    ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
    mysql> create table test ( foo varchar(21844) character set utf8 );
    Query OK, 0 rows affected (0.19 sec)

    mysql> create table test2 ( foo varchar(16384) character set utf8mb4 );
    ERROR 1074 (42000): Column length too big for column 'foo' (max = 16383); use BLOB or TEXT instead
    +

    日期和时间类型

    +

    MySQL支持的日期和时间类型如下表所示 [doc]:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    日期和时间类型字节最小值最大值
    date41000-01-019999-12-31
    datetime81000-01-01 00:00:00.0000009999-12-31 23:59:59.999999
    timestamp41970-01-01 00:00:01.0000002038-01-19 03:14:07.999999
    time3-838:59:59.000000838:59:59.000000
    year119012155
    +

    参考资料

    +
      +
    1. MySQL 5.7 Reference Manual, 12 Data Types http://dev.mysql.com/doc/refman/5.7/en/data-types.html
    2. +
    3. MySQL 5.7 Reference Manual, 10.1 Character Set Support http://dev.mysql.com/doc/refman/5.5/en/charset.html
    4. +
    5. MySQL 5.7 Reference Manual, C.10.4 Limits on Table Column Count and Row Size http://dev.mysql.com/doc/refman/5.7/en/column-count-limit.html
    6. +
    7. Difference between “int” and “int(3)” data types in mysql http://stackoverflow.com/q/5562322
    8. +
    9. Which MySQL Datatype to use for storing boolean values? http://stackoverflow.com/q/289727
    10. +
    11. MySQL: Large VARCHAR vs. TEXT? http://stackoverflow.com/q/2023481
    12. +
    13. TINYTEXT, TEXT, MEDIUMTEXT, and LONGTEXT maximum storage sizes http://stackoverflow.com/q/13932750
    14. +
    +]]>
    + + MySQL + + + MySQL + 数据库 + +
    + + 栈帧与调用惯例 + /2018/01/stack-frame-calling-convention/ + 栈与栈帧 +

    要想知道函数是怎么被调用的,需要了解栈帧和调用惯例相关知识。俞甲子2009 的“第10章 内存: 栈与堆”对相关概念有很好的介绍。本文是对相关知识的学习笔记。

    + +栈与栈帧布局 +

    附注,栈帧之间的划分边界,其实有两种不一样说法。在有些资料中 [ wikipedia; 俞甲子2009 ],callee 参数被划分在 callee 栈帧,但在 Intel 官方一些权威文档中 [ Intel ASDM, Vol.1, Ch.6; Intel X86-psABI ],callee 参数被划分在 caller 栈帧。

    +

    调用惯例

    +

    调用惯例,规定以下内容:(1) 函数参数的传递顺序和方式;(2) 栈的清理方式;(3) 名称修饰(name mangling)。常见的 x86 调用惯例列表有:cdecl(C 语言默认)、stdcall(Win32 API 标准)、fastcall、pascal。这些调用惯例如下下表所示(更加全面的列表参见 wikipedia):

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    调用惯例栈帧清理参数传递名称修饰
    cdel调用者 caller从右至左入栈 RTL下划线+函数名,如 _sum
    stdcall被调用者 callee从右至左入栈 RTL下划线+函数名+@+参数字节数,如 _sum@8
    fastcall被调用者 callee头两参数存入寄存器 ECX 和 EDX,其余参数从右至左入栈 RTL@+函数名+@+参数字节数,如 @sum@8
    pascal被调用者 callee从左至右入栈 LTR较为复杂,参见 pascal 文档
    +

    下面举例说明,cdecl 和 stdcall 两种调用惯例。

    +

    cdecl 调用惯例

    +

    cdecl,调用者负责清理堆栈(caller clean-up),参数从右至左(Right-to-Left,RTL)压入栈。举例说明 [ ref1 ref2 ]:

    +
    // cdecl 调用惯例
    int __cdecl sum(int a, int b) {
    return a + b;
    }
    // 调用
    int c = sum(2, 3);
    +

    编译器生成的等价汇编代码:

    +
    ; 调用者清理堆栈(caller clean-up),参数 RTL 入栈
    push 3
    push 2
    call _sum ; 将返回地址压入栈, 同时 sum 的地址装入 eip
    add esp, 8 ; 清理堆栈, 两个参数占用 8 字节
    +
    ; sum 函数等价汇编代码
    ; // function prolog
    push ebp
    mov ebp, esp
    ; // return a + b;
    mov eax, [ebp + 12]
    add eax, [ebp + 8] ; 返回值规定保存在 eax
    ; // function epilog
    mov esp, ebp ; 设置栈顶 esp
    pop ebp ; 恢复 old ebp
    ret ; 将栈中保存的返回地址装入 eip
    +

    stdcall 调用惯例

    +

    stdcall,被调用者负责清理堆栈(callee clean-up),参数从右至左(Right-to-Left,RTL)压入栈。举例说明:

    +
    // stdcall 调用惯例
    int __stdcall sum(int a, int b) {
    return a + b;
    }
    // 调用
    int c = sum(2, 3);
    +

    编译器生成的等价汇编代码:

    +
    ; 被调用者清理堆栈(callee clean-up),参数 RTL 入栈
    push 3
    push 2
    call _sum@8 ; 将返回地址压入栈, 同时 sum 的地址装入 eip
    +
    ; sum 函数等价汇编代码
    ; // function prolog
    push ebp
    mov ebp, esp
    ; // return a + b;
    mov eax, [ebp + 12]
    add eax, [ebp + 8] ; 返回值规定保存在 eax
    ; // function epilog
    mov esp, ebp ; 设置栈顶 esp
    pop ebp ; 恢复 old ebp
    ret 8 ; 清理堆栈,并将栈中保存的返回地址装入 eip
    +

    gcc 汇编代码

    +

    hello1.c 文件内容如下:

    +
    int __cdecl sum(int a, int b) {
    return a + b;
    }

    int main() {
    sum(1, 2);
    sum(3, 4);
    return 0;
    }
    +

    生成汇编代码:

    +
    $ gcc -m32 -S -masm=intel hello1.c -o hello1.s
    $ gcc -m32 hello1.s -o hello
    $ ./hello || echo $?
    0
    +

    生成的 hello1.s,内容如下:

    +
      .section  __TEXT,__text,regular,pure_instructions
    .macosx_version_min 10, 12
    .intel_syntax noprefix
    .globl _sum
    .p2align 4, 0x90
    _sum: ## @sum
    ## BB#0:
    push ebp
    mov ebp, esp
    sub esp, 8 ; 预先分配 8 字节栈空间,保存 2 个布局变量
    mov eax, dword ptr [ebp + 12] ; 堆栈中读取参数 2
    mov ecx, dword ptr [ebp + 8] ; 堆栈中读取参数 1
    mov dword ptr [ebp - 4], ecx ; 布局变量 1
    mov dword ptr [ebp - 8], eax ; 布局变量 2
    mov eax, dword ptr [ebp - 4]
    add eax, dword ptr [ebp - 8]
    add esp, 8 ; 清理 8 字节栈空间
    pop ebp
    ret

    .globl _main
    .p2align 4, 0x90
    _main: ## @main
    ## BB#0:
    push ebp
    mov ebp, esp
    sub esp, 40 ; 预先分配 40 字节栈空间
    mov eax, 1
    mov ecx, 2
    mov dword ptr [ebp - 4], 0
    mov dword ptr [esp], 1
    mov dword ptr [esp + 4], 2
    mov dword ptr [ebp - 8], eax ## 4-byte Spill
    mov dword ptr [ebp - 12], ecx ## 4-byte Spill
    call _sum
    mov ecx, 3
    mov edx, 4
    mov dword ptr [esp], 3
    mov dword ptr [esp + 4], 4
    mov dword ptr [ebp - 16], eax ## 4-byte Spill
    mov dword ptr [ebp - 20], ecx ## 4-byte Spill
    mov dword ptr [ebp - 24], edx ## 4-byte Spill
    call _sum
    xor ecx, ecx
    mov dword ptr [ebp - 28], eax ## 4-byte Spill
    mov eax, ecx
    add esp, 40 ; 清理 40 字节栈空间
    pop ebp
    ret

    .subsections_via_symbols
    +

    GCC 生成的汇编代码并没有使用 push 而是通过 sub esp, 40 直接预先分配栈空间,然后使用 mov 指令将参数写进栈中,清理栈使用 add esp, 40。逻辑上,还是符合 cdecl 调用惯例,调用者负责清理堆栈(caller clean-up),参数从右至左(Right-to-Left,RTL)压入栈。这样做的好处是,如果同时多次调用 sum,清理栈空间的指令,只需要最后的时候调用一次就可以了。统一使用 sub espadd esp 去操作 esp 值,避免 push 指令操作 esp。

    +

    现在再来看看,stdcall 调用惯例下,GCC 生成的汇编代码。把 sum 函数改为 __stdcall,运行下面的命令:

    +
    $ gcc -m32 -S -masm=intel hello2.c -o hello2.s
    $ diff -C1 hello1.s hello2.s
    +
    *** hello1.s    Thu Feb 05 22:43:59 2018
    --- hello2.s Thu Feb 05 22:45:24 2018
    ***************
    *** 18,20 ****
    pop ebp
    ! ret

    --- 18,20 ----
    pop ebp
    ! ret 8

    ***************
    *** 35,36 ****
    --- 35,37 ----
    call _sum
    + sub esp, 8
    mov ecx, 3
    ***************
    *** 43,44 ****
    --- 44,46 ----
    call _sum
    + sub esp, 8
    xor ecx, ecx
    +

    反汇编代码

    +

    反汇编 objdumpgdb/lldb,或者商业工具使用,IDA Pro 或者 Hopper Disassembler [ wiki ]

    +

    objdump 反汇编

    +
    $ gobjdump -d -Mintel hello1                # 使用 GNU objdump
    $ objdump -d -x86-asm-syntax=intel hello1 # 使用 llvm-objdump
    +
    hello1:	file format Mach-O 32-bit i386

    Disassembly of section __TEXT,__text:
    __text:
    1f30: 55 push ebp
    1f31: 89 e5 mov ebp, esp
    1f33: 83 ec 08 sub esp, 8
    1f36: 8b 45 0c mov eax, dword ptr [ebp + 12]
    1f39: 8b 4d 08 mov ecx, dword ptr [ebp + 8]
    1f3c: 89 4d fc mov dword ptr [ebp - 4], ecx
    1f3f: 89 45 f8 mov dword ptr [ebp - 8], eax
    1f42: 8b 45 fc mov eax, dword ptr [ebp - 4]
    1f45: 03 45 f8 add eax, dword ptr [ebp - 8]
    1f48: 83 c4 08 add esp, 8
    1f4b: 5d pop ebp
    1f4c: c3 ret
    1f4d: 0f 1f 00 nop dword ptr [eax]
    1f50: 55 push ebp
    1f51: 89 e5 mov ebp, esp
    1f53: 83 ec 28 sub esp, 40
    1f56: b8 01 00 00 00 mov eax, 1
    1f5b: b9 02 00 00 00 mov ecx, 2
    1f60: c7 45 fc 00 00 00 00 mov dword ptr [ebp - 4], 0
    1f67: c7 04 24 01 00 00 00 mov dword ptr [esp], 1
    1f6e: c7 44 24 04 02 00 00 00 mov dword ptr [esp + 4], 2
    1f76: 89 45 f8 mov dword ptr [ebp - 8], eax
    1f79: 89 4d f4 mov dword ptr [ebp - 12], ecx
    1f7c: e8 af ff ff ff call -81 <_sum>
    1f81: b9 03 00 00 00 mov ecx, 3
    1f86: ba 04 00 00 00 mov edx, 4
    1f8b: c7 04 24 03 00 00 00 mov dword ptr [esp], 3
    1f92: c7 44 24 04 04 00 00 00 mov dword ptr [esp + 4], 4
    1f9a: 89 45 f0 mov dword ptr [ebp - 16], eax
    1f9d: 89 4d ec mov dword ptr [ebp - 20], ecx
    1fa0: 89 55 e8 mov dword ptr [ebp - 24], edx
    1fa3: e8 88 ff ff ff call -120 <_sum>
    1fa8: 31 c9 xor ecx, ecx
    1faa: 89 45 e4 mov dword ptr [ebp - 28], eax
    1fad: 89 c8 mov eax, ecx
    1faf: 83 c4 28 add esp, 40
    1fb2: 5d pop ebp
    1fb3: c3 ret

    _sum:
    1f30: 55 push ebp
    1f31: 89 e5 mov ebp, esp
    1f33: 83 ec 08 sub esp, 8
    1f36: 8b 45 0c mov eax, dword ptr [ebp + 12]
    1f39: 8b 4d 08 mov ecx, dword ptr [ebp + 8]
    1f3c: 89 4d fc mov dword ptr [ebp - 4], ecx
    1f3f: 89 45 f8 mov dword ptr [ebp - 8], eax
    1f42: 8b 45 fc mov eax, dword ptr [ebp - 4]
    1f45: 03 45 f8 add eax, dword ptr [ebp - 8]
    1f48: 83 c4 08 add esp, 8
    1f4b: 5d pop ebp
    1f4c: c3 ret
    1f4d: 0f 1f 00 nop dword ptr [eax]

    _main:
    1f50: 55 push ebp
    1f51: 89 e5 mov ebp, esp
    1f53: 83 ec 28 sub esp, 40
    1f56: b8 01 00 00 00 mov eax, 1
    1f5b: b9 02 00 00 00 mov ecx, 2
    1f60: c7 45 fc 00 00 00 00 mov dword ptr [ebp - 4], 0
    1f67: c7 04 24 01 00 00 00 mov dword ptr [esp], 1
    1f6e: c7 44 24 04 02 00 00 00 mov dword ptr [esp + 4], 2
    1f76: 89 45 f8 mov dword ptr [ebp - 8], eax
    1f79: 89 4d f4 mov dword ptr [ebp - 12], ecx
    1f7c: e8 af ff ff ff call -81 <_sum>
    1f81: b9 03 00 00 00 mov ecx, 3
    1f86: ba 04 00 00 00 mov edx, 4
    1f8b: c7 04 24 03 00 00 00 mov dword ptr [esp], 3
    1f92: c7 44 24 04 04 00 00 00 mov dword ptr [esp + 4], 4
    1f9a: 89 45 f0 mov dword ptr [ebp - 16], eax
    1f9d: 89 4d ec mov dword ptr [ebp - 20], ecx
    1fa0: 89 55 e8 mov dword ptr [ebp - 24], edx
    1fa3: e8 88 ff ff ff call -120 <_sum>
    1fa8: 31 c9 xor ecx, ecx
    1faa: 89 45 e4 mov dword ptr [ebp - 28], eax
    1fad: 89 c8 mov eax, ecx
    1faf: 83 c4 28 add esp, 40
    1fb2: 5d pop ebp
    1fb3: c3 ret
    +

    lldb 反汇编

    +

    使用 lldb 反汇编:

    +
    $ lldb hello1
    (lldb) target create "hello1"
    Current executable set to 'hello1' (i386).
    (lldb) settings set target.x86-disassembly-flavor intel
    (lldb) disassemble --name main
    hello1`main:
    hello1[0x1f50] <+0>: push ebp
    hello1[0x1f51] <+1>: mov ebp, esp
    hello1[0x1f53] <+3>: sub esp, 0x28
    hello1[0x1f56] <+6>: mov eax, 0x1
    hello1[0x1f5b] <+11>: mov ecx, 0x2
    hello1[0x1f60] <+16>: mov dword ptr [ebp - 0x4], 0x0
    hello1[0x1f67] <+23>: mov dword ptr [esp], 0x1
    hello1[0x1f6e] <+30>: mov dword ptr [esp + 0x4], 0x2
    hello1[0x1f76] <+38>: mov dword ptr [ebp - 0x8], eax
    hello1[0x1f79] <+41>: mov dword ptr [ebp - 0xc], ecx
    hello1[0x1f7c] <+44>: call 0x1f30 ; sum
    hello1[0x1f81] <+49>: mov ecx, 0x3
    hello1[0x1f86] <+54>: mov edx, 0x4
    hello1[0x1f8b] <+59>: mov dword ptr [esp], 0x3
    hello1[0x1f92] <+66>: mov dword ptr [esp + 0x4], 0x4
    hello1[0x1f9a] <+74>: mov dword ptr [ebp - 0x10], eax
    hello1[0x1f9d] <+77>: mov dword ptr [ebp - 0x14], ecx
    hello1[0x1fa0] <+80>: mov dword ptr [ebp - 0x18], edx
    hello1[0x1fa3] <+83>: call 0x1f30 ; sum
    hello1[0x1fa8] <+88>: xor ecx, ecx
    hello1[0x1faa] <+90>: mov dword ptr [ebp - 0x1c], eax
    hello1[0x1fad] <+93>: mov eax, ecx
    hello1[0x1faf] <+95>: add esp, 0x28
    hello1[0x1fb2] <+98>: pop ebp
    hello1[0x1fb3] <+99>: ret

    (lldb) disassemble --name sum
    hello1`sum:
    hello1[0x1f30] <+0>: push ebp
    hello1[0x1f31] <+1>: mov ebp, esp
    hello1[0x1f33] <+3>: sub esp, 0x8
    hello1[0x1f36] <+6>: mov eax, dword ptr [ebp + 0xc]
    hello1[0x1f39] <+9>: mov ecx, dword ptr [ebp + 0x8]
    hello1[0x1f3c] <+12>: mov dword ptr [ebp - 0x4], ecx
    hello1[0x1f3f] <+15>: mov dword ptr [ebp - 0x8], eax
    hello1[0x1f42] <+18>: mov eax, dword ptr [ebp - 0x4]
    hello1[0x1f45] <+21>: add eax, dword ptr [ebp - 0x8]
    hello1[0x1f48] <+24>: add esp, 0x8
    hello1[0x1f4b] <+27>: pop ebp
    hello1[0x1f4c] <+28>: ret
    hello1[0x1f4d] <+29>: nop dword ptr [eax]

    +

    参考资料

    +
      +
    1. 链接、装载与库,俞甲子,2009:第10章 内存: 栈与堆,豆瓣
    2. +
    3. IDA Pro权威指南,Eagle,第2版2011:6.2.1 调用约定,豆瓣
    4. +
    5. 2001-09 Calling Conventions Demystified https://www.codeproject.com/Articles/1388/Calling-Conventions-Demystified
    6. +
    7. Calling Conventions https://en.wikibooks.org/wiki/X86_Disassembly/Calling_Conventions
    8. +
    9. https://en.wikipedia.org/wiki/X86_calling_conventions
    10. +
    +]]>
    + + 计算机系统 + + + 编译器 + OS + C + ASM + ABI + +
    + + 软件开发书籍资料整理 + /2016/12/software-dev-books/ + 本文整理软件开发、项目管理、软件工程相关的书籍。

    + +

    开发类书籍

    +
      +
    1. 2011-03 What is the single most influential book every programmer should read? (stackoverflow.com) https://news.ycombinator.com/item?id=2272722
    2. +
    3. 2012-08 国外程序员推荐:每个程序员都应读的书 (译SO帖子) http://blog.jobbole.com/5886/
    4. +
    5. 2011-08 Jurgen Appelo:2011年最热门的敏捷书籍排行榜 http://www.infoq.com/cn/news/2011/08/top-agile-books
    6. +
    +

    软件开发综合类书籍

    +
      +
    1. 1993、2004,Steve McConnell,《代码大全》(Code Complete: A Practical Handbook of Software Construction, Microsoft Press, 2nd 2004),豆瓣:全书944页,1994年Jolt震撼大奖,1999–2002任IEEE Software主编
    2. +
    3. 2006,Pete Goodliffe,《编程匠艺》(Code Craft: The Practice of Writing Excellent Code, amazon),豆瓣:全书582页
    4. +
    +

    设计模式与重构类书籍(代码组织结构、修改、阅读)

    +
      +
    1. 1994,GoF,《设计模式:可复用面向对象软件的基础》(Design Patterns: Elements of Reusable Object-Oriented Software, amazon),豆瓣
    2. +
    3. 2001、2004,Shalloway & Trott,**《**设计模式解析》(Design Patterns Explained, 2nd 2004),图灵2010豆瓣:全书312页,Java描述
    4. +
    5. 2012,《元素模式》(Elemental Design Patterns, amazon),豆瓣
    6. +
    7. Martin Fowler, wiki
    8. +
    +
      +
    • 1996,《分析模式:可复用的对象模型》(Analysis Patterns: Reusable Object Models, amazon),豆瓣
    • +
    • 1999,《重构:改善既有代码的设计》(Refactoring: Improving the Design of Existing Code, amazon),home豆瓣:经典,内容类似参考手册形式,可读性不高
    • +
    • 2002,《企业应用架构模式(Po****EAA)》(Patterns of Enterprise Application Architecture, amazon),home豆瓣
    • +
    +
      +
    1. Robert C. Martin,wiki:1991年创立Object Mentor公司[ref]
    2. +
    +
      +
    • 2002,《敏捷软件开发:原则、模式与实践(PPP**)》(Agile Software Development: Principles, Patterns and Practices, amazon),豆瓣:全书476页,2003年Jolt震撼大奖,该书面向代码层面,最早整理汇编SOLID原则**
    • +
    • 2008,《代码整洁之道》(Clean Code: A Handbook of Agile Software Craftsmanship, amazon),豆瓣:全书388页,每个程序员都应读的最具影响力的书排名第13,“虽然《代码整洁之道》和《代码大全》有很多共同之处,但它有更为简洁更为实际的清晰例子”[ref]
    • +
    • 2011,《程序员的职业素养》(The Clean Coder: A Code of Conduct for Professional Programmers, amazon),豆瓣:全书178页,内容充斥着作者自己经历故事,大量围绕“我”的文字,不够精简,很难抓到作者阐述要点
    • +
    +
      +
    1. 2000,Schmidt, Stal, Buschmann, Rohnert,《面向模式的软件体系结构,卷2:用于并发和网络化对象的模式(****POSA)》(Pattern-Oriented Software Architecture, amazon),共5卷图灵图灵2013豆瓣
    2. +
    +

    其他书籍

    +
      +
    1. 2004,Joshua Kerievsky,《重构与模式》(Refactoring to Patterns, amazon),豆瓣:2005年Jolt生产力大奖,amazon有评论批评该书例子过于复杂[ref]
    2. +
    3. 2004,Michael Feathers,《修改代码的艺术》(Working Effectively with Legacy Code, amazon),豆瓣:作者Object Mentor公司成员,该书更直白的书名应为“遗留代码修改FAQ”,简介“本书是继《重构》和《重构与模式》之后探讨修改代码技术的又一里程碑式的著作,而且从涵盖面和深度上都超过了前两部经典”
    4. +
    5. 2011,Boswell & Foucher,《编写可读代码的艺术》(The Art of Readable Code, O'Reilly, amazon),豆瓣:全书178页
    6. +
    7. 2003,Diomidis Spinellis,《代码阅读》(Code Reading: The Open Source Perspective, amazon),豆瓣:2004年Jolt生产力大奖
    8. +
    9. 2006,Diomidis Spinellis,《代码质量》(Code Quality: The Open Source Perspective, amazon),豆瓣:2007年Jolt生产力大奖
    10. +
    11. 1998,《反模式:危机中软件架构和项目的重构》(AntiPatterns, amazon),豆瓣:1999年Jolt生产力大奖
    12. +
    13. 2014,《软件设计重构》(Refactoring for Software Design Smells) ,豆瓣
    14. +
    +

    软件代码实例书籍

    +
      +
    1. 2008,Oram & Wilson,《开源软件架构 AOSA》(The Architecture of Open Source Applications, amazon),图灵(卷1、卷2均有部分翻译),home:Oram是O'Reilly Media的编辑,Wilson是Dr. Dobb's 杂志的特约编辑
    2. +
    3. 2010,Oram & Wilson,《软件之道:软件开发争议问题剖析》(Making Software: What Really Works, and Why We Believe It, O'Reilly, amazon),豆瓣
    4. +
    5. 2007,Oram & Wilson,《代码之美:38位大师级程序员解释其思考方式》(Beautiful Code: Leading Programmers Explain How They Think, O'Reilly, amazon),豆瓣:2008年Jolt震撼大奖
    6. +
    7. 2009,Diomidis Spinellis,《架构之美》(Beautiful Archiecture: Leading Thinkers Reveal the Hidden Beauty in Software Design, O'Reilly, amazon),豆瓣:编者是《代码阅读》作者
    8. +
    +

    AOSA部分译文:

    +
      +
    1. AOSA 卷1:NoSQL生态系统 http://www.oschina.net/translate/the-nosql-ecosystem
    2. +
    3. AOSA 卷4 https://github.com/aosabook/500lines
    4. +
    5. 2014-07 AOSA: 500 Lines or Less (Early preview) (github.com) https://news.ycombinator.com/item?id=8004077
    6. +
    +

    编程实践与ThoughtWorks书籍

    +
      +
    1. 1999,Andy Hunt & David Thomas,《注重实效的程序员》(The Pragmatic Programmer: From Journeyman to Master,amazon),豆瓣:两位作者是敏捷宣言17人,“Pragmatic Bookshelf”系列书籍第1本,两位作者为“Pragmatic Programmers, LLC”公司创立者[ref]
    2. +
    3. 2006,Subramaniam & Andy Hunt,《敏捷开发修炼:高效程序员的45个习惯》(Practices of an Agile Developer, Pragmatic, amazon),豆瓣:2007年Jolt生产力大奖
    4. +
    5. 2008,Andy Hunt,《程序员的思维修炼:开发认知潜能的九堂课》(Pragmatic Thinking and Learning, Pragmatic, amazon):注重实效的思考与学习
    6. +
    7. 2008,Neal Ford,《卓有成效的程序员》(The Productive Programmer, O'Reilly, amazon),豆瓣:Neal Ford is an Application Architect at ThoughtWorks
    8. +
    9. 2008,《软件开发沉思录:ThoughtWorks文集》(The Thoughtworks Anthology, Pragmatic, amazon),豆瓣
    10. +
    11. 2012,《软件开发与创新:ThoughtWorks文集》(The ThoughtWorks Anthology, Volume 2, Pragmatic, amazon),豆瓣
    12. +
    +
    +
      +
    1. 2005,Rothman & Derby,《门后的秘密》(Behind Closed Doors: Secrets of Great Management, Pragmatic),豆瓣
    2. +
    3. 2005,Richardson & Gwaltney,《软件项目成功之道》(Ship it! A Practical Guide to Successful Software Projects, Pragmatic, amazon),豆瓣
    4. +
    5. 2007,Rothman,《项目管理修炼之道》,(Manage It!: Your Guide to Modern, Pragmatic Project Management, Pragmatic),豆瓣:2008年Jolt生产力大奖
    6. +
    7. 2009,Paul Butcher,《软件调试修炼之道》(Debug It!: Find, Repair, and Prevent Bugs in Your Code, Pragmatic
    8. +
    9. 2009,《软件开发者路线图》(Apprenticeship Patterns: Guidance for the Aspiring Software Craftsman,O'Reilly, amazon),豆瓣
    10. +
    +

    软件工程项目管理类

    +

    https://en.wikipedia.org/wiki/Template:Software_engineering
    +https://en.wikipedia.org/wiki/History_of_software_engineering

    +

    综合类书籍

    +
      +
    1. 2002,Robert Glassmsa,《软件工程的事实与谬误》(Facts and Fallacies of Software Engineering, amazon),豆瓣
    2. +
    +

    轻量级软件开发方法(XP与Scrum)

    +
      +
    1. 1999、2005,Kent Beck,《解析极限编程:拥抱变化(XPE)》(Extreme Programming Explained: Embrace Change, 2nd 2005),豆瓣:2000年Jolt生产力大奖
    2. +
    3. 2000,Beck & Fowler,《规划极限编程》(Planning Extreme Programming, amazon),豆瓣
    4. +
    5. 2001,Pete McBreen,《软件工艺》(Software Craftsmanship: The New Imperative, amazon),豆瓣:2002年Jolt生产力大奖
    6. +
    7. 2002,Kent Beck,《测试驱动开发(TDD)》(Test-Driven Development: By Example, amazon),豆瓣:2003年Jolt生产力大奖
    8. +
    9. 2007,Kent Beck,《实现模式》(Implementation Patterns, AW, amazon),豆瓣
    10. +
    11. 2004,Ken Schwaber,《Scrum敏捷项目管理》(Agile Project Management with Scrum. Microsoft Press, amazon),豆瓣
    12. +
    13. 2001、2006,Alistair Cockburn,《敏捷软件开发》(Agile Software Development: The Cooperative Game, 2nd 2006, amazon),豆瓣:2002年Jolt生产力大奖、2007年Jolt震撼大奖,该书面向项目管理层面
    14. +
    15. 2007,Shore & Warden,《敏捷开发的艺术》(The Art of Agile Development, amazon),豆瓣
    16. +
    17. 2009,Mike Cohn,《Scrum敏捷软件开发》(Succeeding with Agile: Software Development using Scrum),豆瓣
    18. +
    19. 2008,Henrik Kniberg,《硝烟中的Scrum和XP》,infoq minibook
    20. +
    21. 2011,Henrik Kniberg,《精益开发实战:用看板管理大型项目》(Lean from the Trenches: Managing Large-Scale Projects with Kanban, amazon),豆瓣
    22. +
    +

    2009-05 敏捷书籍推荐 http://www.infoq.com/cn/news/2009/05/recommended-agile-books
    +2010-09 DZone's Top 10 Agile and Lean Development Books http://agile.dzone.com/articles/dzones-top-10-agile-and-lean
    +2010-08 最热门的敏捷书籍 http://www.infoq.com/cn/news/2010/08/top-agile-books
    +2011-08 2011年最热门的敏捷书籍排行榜 http://www.infoq.com/cn/news/2011/08/top-agile-books

    +
    +

    软件项目管理(Fred Brooks & Tom DeMarco)

    +
      +
    1. 1975、1995,Fred Brooks,《人月神话:大型系统开发管理文集》(The Mythical Man-Month: Essays on Software Engineering, AW, 2nd 1995, amazon),豆瓣
    2. +
    3. 2010,Fred Brooks,《设计原本:计算机科学巨匠Frederick P.Brooks的思考》(The Design of Design: Essays from a Computer Scientist, AW, amazon),豆瓣
    4. +
    5. 1987、1999,Tom DeMarco,《人件》(Peopleware: Productive Projects and Teams, 2nd 1999, 3rd 2013),豆瓣,第3版豆瓣
    6. +
    7. 2012,《进化:从孤胆极客到高效团队》(Team Geek, amazon),豆瓣:2013年Jolt大奖提名,两位作者为Google项目团队的负责人
    8. +
    9. 2007,《软件人才管理的艺术》(Managing Humans, amazon),豆瓣
    10. +
    11. 1997,Tom DeMarco,《最后期限》(The Deadline: A Novel About Project Management, amazon),豆瓣:1998年Jolt生产力大奖
    12. +
    13. 2003,Tom DeMarco,《与熊共舞:软件项目风险管理》(Waltzing with Bears, amazon),豆瓣:2004年Jolt震撼大奖
    14. +
    15. 2008,Tom DeMarco,《项目百态:深入理解软件项目行为模式》(Adrenaline Junkies and Template Zombies: Understanding Patterns of Project Behavior, amazon),豆瓣:2009年Jolt震撼大奖
    16. +
    17. 2005、2008,Scott Berkun,《项目管理之美》(Making Things Happen: Mastering Project Management, O'Reilly, amazon),豆瓣:2006年Jolt生产力大奖
    18. +
    19. 1999、2003,Edward Yourdon,《死亡之旅》(Death March, Prentice Hall, 2nd 2003, amazon),豆瓣
    20. +
    +

    著名软件项目

    +
      +
    1. 1994,《观止:微软创建NT和未来的夺命狂奔》(Show Stopper!, amazon),豆瓣
    2. +
    3. 2008,Scott Rosenberg,《梦断代码》(Dreaming In Code, amazon),豆瓣
    4. +
    +
    +

    Steve McConnell,wiki

    +
      +
    1. 1993,Steve Maguire,《编程精粹:编写高质量C语言代码》(Writing Solid Code, amazon),豆瓣:与代码大全齐名,1994年Jolt生产力大奖
    2. +
    3. 1996,《快速软件开发》(Rapid Development: Taming Wild Software Schedules, Microsoft Press, amazon),豆瓣:1997年Jolt震撼大奖
    4. +
    5. 1997,《微软项目:求生法则》(Software Project Survival Guide, Microsoft Press, amazon),豆瓣
    6. +
    +]]>
    + + 编程 + + + 书籍 + CS + +
    + + ZooKeeper 学习笔记 + /2017/11/zookeeper-note/ + ZooKeeper 介绍 +

    ZooKeeper(wikihomegithub) 是用于分布式应用的开源的分布式协调服务。通过暴露简单的原语,分布式应用能在之上构建更高层的服务,如同步、配置管理和组成员管理等。在设计上易于编程开发,并且数据模型使用了熟知的文件系统目录树结构 [ doc ]。

    + +

    共识与 Paxos

    +

    在介绍 ZooKeeper 之前,有必要了解下 Paxos 和 Chubby。2006 年 Google 在 OSDI 发表关于 BigtableChubby 的两篇会议论文,之后再在 2007 年 PODC 会议上发表了论文“Paxos Made Live”,介绍 Chubby 底层实现的共识(consensus)协议 Multi-Paxos,该协议对 Lamport 的原始 Paxos 算法做了改进,提高了运行效率 [ ref ]。Chubby 作为锁服务被 Google 应用在 GFS 和 Bigtable 中。受 Chubby 的影响,来自 Yahoo 研究院的 Benjamin Reed 和 Flavio Junqueira 等人开发了被业界称为开源版的 Chubby 的 ZooKeeper(内部实现事实上稍有不同 [ ref ]),底层的共识协议为 ZAB。Lamport 的 Paxos 算法出了名的难懂,如何让算法更加可理解(understandable),便成了 Stanford 博士生 Diego Ongaro 的研究课题。Diego Ongaro 在 2014 年发表了介绍 Raft 算法的论文,“In search of an understandable consensus algorithm”。Raft 是可理解版的 Paxos,很快就成为解决共识问题的流行协议之一。这些类 Paxos 协议和 Paxos 系统之间的关系,如下 [ Ailijiang2016 ]:

    +Paxos 协议和 Paxos 系统 +

    Google 的 Chubby 没有开源,在云计算和大数据技术的风口下,Yahoo 开源的 ZooKeeper 便在工业界流行起来。ZooKeeper 重要的时间线如下:

    +
      +
    • 2007 年 11 月 ZooKeeper 1.0 在 SourceForge 上发布 [ ref ]
    • +
    • 2008 年 6 月开始从 SourceForge 迁移到 Apache [ ref ],在 10 月 Zookeeper 3.0 发布,并成为 Hadoop 的子项目 [ ref1 ref2 ]
    • +
    +

    关于 ZooKeeper 名字的来源,Flavio Junqueira 和 Benjamin Reed 在介绍 ZooKeeper 的书中有如下阐述:

    +
    +

    ZooKeeper 由雅虎研究院开发。我们小组在进行 ZooKeeper 的开发一段时间之后,开始推荐给其他小组,因此我们需要为我们的项目起一个名字。与此同时,小组也一同致力于 Hadoop 项目,参与了很多动物命名的项目,其中有广为人知的 Apache Pig 项目(http://pig.apache.org)。我们在讨论各种各样的名字时,一位团队成员提到我们不能再使用动物的名字了,因为我们的主管觉得这样下去会觉得我们生活在动物园中。大家对此产生了共鸣,分布式系统就像一个动物园,混乱且难以管理,而 ZooKeeper 就是将这一切变得可控。

    +
    +

    体系结构

    +

    ZooKeeper 服务由若干台服务器构成,其中的一台通过 ZAB 原子广播协议选举作为主控服务器(leader),其他的作为从属服务器(follower)。客户端可以通过 TCP 协议连接任意一台服务器。如果客户端是读操作请求,则任意一个服务器都可以直接响应请求;如果是更新数据操作(写数据或者更新数据)。则只能由主控服务器来协调更新操作;如果客户端连接的是从属服务器,则从属服务器会将更新据请求转发到主控服务器,由其完成更新操作。主控服务器将所有更新操作序列化,利用 ZAB 协议将数据更新请求通知所有从属服务器,ZAB 保证更新操作。

    +

    zookeeper-service

    +

    读和写操作,如下图所示 [ Haloi2015 ]:
    +ZooKeeper 读和写操作

    +

    ZooKeeper 的任意一台服务器都可以响应客户端的读操作,这样可以提高吞吐量。Chubby 在这点上与 ZooKeeper 不同,所有读/写操作都由主控服务器完成,从属服务器只是为了提高整个协调系统的可用性,即主控服务器发生故障后能够在从属服务器中快速选举出新的主控服务器。在带来高吞吐量优势的同时,ZooKeeper 这样做也带来潜在的问题:客户端可能会读到过期数据,因为即使主控服务器已经更新了某个内存数据,但是 ZAB 协议还未能将其广播到从属服务器。为了解决这一问题,在 ZooKeeper 的接口 API 函数中提供了 sync 操作,应用可以根据需要在读数据前调用该操作,其含义是:接收到 sync 命令的从属服务器从主控服务器同步状态信息,保证两者完全一致。这样如果在读操作前调用 sync 操作,则可以保证客户端一定可以读取到最新状态的数据。

    +

    数据模型

    +

    ZooKeeper 所提供的命名空间跟标准文件系统很相似。路径中一系列元素是用斜杠(/)分隔的。每个节点在 ZooKeper 命名空间中是用路径来识别的。在 ZooKeeper 术语下,节点被称为 znode。默认每个 znode 最大只能存储 1M 数据(可以通过配置参数修改),这与 Chubby 一样是出于避免应用将协调系统当作存储系统来用。znode 只能使用绝对路径,相对路径不能被 ZooKeeper 识别。znode 命名可以是任意 Unicode 字符。唯一的例外是,名称"/zookeeper"。命名为"/zookeeper"的 znode,由 ZooKeeper 系统自动生成,用配额(quota)管理。

    +ZooKeeper 数据模型 +

    ZooKeeper 使用

    +

    安装与配置

    +

    ZooKeeper 安装与启动:

    +
    $ brew info zookeeper
    zookeeper: stable 3.4.10 (bottled), HEAD
    Centralized server for distributed coordination of services
    https://zookeeper.apache.org/
    ... 省略
    $ brew install zookeeper
    $ zkServer start # 启动
    $ zkServer stop # 终止
    $ zkServer help
    ZooKeeper JMX enabled by default
    Using config: /usr/local/etc/zookeeper/zoo.cfg
    Usage: ./zkServer.sh {start|start-foreground|stop|restart|status|upgrade|print-cmd}
    +

    若不修改配置文件,默认是单机模式启动。若要使用集群模式,需要修改 /usr/local/etc/zookeeper/zoo.cfg(默认路径)。示例 zoo.cfg [ doc ]:

    +
    tickTime=2000
    dataDir=/var/lib/zookeeper
    clientPort=2181
    initLimit=5
    syncLimit=2
    server.1=192.168.211.11:2888:3888
    server.2=192.168.211.12:2888:3888
    server.3=192.168.211.13:2888:3888
    +

    clientPort:客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。
    +server.X=YYY:A:B

    +
      +
    • X:表示的服务器编号;
    • +
    • YYY:表示服务器的ip地址;
    • +
    • A:表示服务器节点间的通信端口,用于 follower 和 leader 节点的通信;
    • +
    • B:表示选举端口,表示选举新 leader 时服务器间相互通信的端口,当 leader 挂掉时,其余服务器会相互通信,选择出新的 leader。
    • +
    +

    若想在单台主机上试验集群模式,可以将 YYY 都修改为 localhost,并且让两个端口 A:B 也相互不同(比如:2888:3888, 2889:3889, 2890:3890),即可实现伪集群模式。示例 zoo.cfg 如下 [ doc ]:

    +
    server.1=localhost:2888:3888
    server.2=localhost:2889:3889
    server.3=localhost:2890:3890
    +

    zkCli 支持的全部命令:

    +
    $ zkCli help
    ZooKeeper -server host:port cmd args
    stat path [watch]
    set path data [version]
    ls path [watch]
    delquota [-n|-b] path
    ls2 path [watch]
    setAcl path acl
    setquota -n|-b val path
    history
    redo cmdno
    printwatches on|off
    delete path [version]
    sync path
    listquota path
    rmr path
    get path [watch]
    create [-s] [-e] path data acl
    addauth scheme auth
    quit
    getAcl path
    close
    connect host:port
    +

    节点类型及其操作

    +

    Zookeeper 支持两种类型节点:持久节点(persistent znode)和临时节点(ephemeral znode)。持久节点不论客户端会话情况,一直存在,只有当客户端显式调用删除操作才会消失。而临时节点则不同,会在客户端会话结束或者发生故障的时候被 ZooKeeper 系统自动清除。另外,这两种类型的节点都可以添加是否是顺序(sequential)的特性,这样就有了:持久顺序节点和临时顺序节点。

    +

    (1) 持久节点(persistent znode)

    +

    使用 create 创建节点(默认持久节点),以及使用 get 查看该节点:

    +
    $ zkCli -server 127.0.0.1  # 启动客户端
    [zk: localhost:2181(CONNECTED) 1] create /zoo 'hello zookeeper'
    Created /zoo
    [zk: localhost:2181(CONNECTED) 2] get /zoo
    hello zookeeper
    cZxid = 0x8d
    ctime = Thu Nov 08 20:42:55 CST 2017
    mZxid = 0x8d
    mtime = Thu Nov 08 20:42:55 CST 2017
    pZxid = 0x8d
    cversion = 0
    dataVersion = 0
    aclVersion = 0
    ephemeralOwner = 0x0
    dataLength = 15
    numChildren = 0
    +

    create 创建子节点,以及使用 ls 查看全部子节点:

    +
    [zk: localhost:2181(CONNECTED) 3] create /zoo/duck ''
    Created /zoo/duck
    [zk: localhost:2181(CONNECTED) 4] create /zoo/goat ''
    Created /zoo/goat
    [zk: localhost:2181(CONNECTED) 5] create /zoo/cow ''
    Created /zoo/cow
    [zk: localhost:2181(CONNECTED) 6] ls /zoo
    [cow, goat, duck]
    +

    delete 删除节点,以及使用 rmr 递归删除:

    +
    [zk: localhost:2181(CONNECTED) 7] delete /zoo/duck
    [zk: localhost:2181(CONNECTED) 8] ls /zoo
    [cow, goat]
    [zk: localhost:2181(CONNECTED) 9] delete /zoo
    Node not empty: /zoo
    [zk: localhost:2181(CONNECTED) 10] rmr /zoo
    [zk: localhost:2181(CONNECTED) 11] ls /zoo
    Node does not exist: /zoo
    +

    (2) 临时节点(ephemeral znode)

    +

    和持久节点不同,临时节点不能创建子节点:

    +
    $ zkCli  # 启动第1个客户端
    [zk: localhost:2181(CONNECTED) 0] create -e /node 'hello'
    Created /node
    [zk: localhost:2181(CONNECTED) 40] get /node
    hello
    cZxid = 0x97
    ctime = Thu Nov 08 21:01:25 CST 2017
    mZxid = 0x97
    mtime = Thu Nov 08 21:01:25 CST 2017
    pZxid = 0x97
    cversion = 0
    dataVersion = 0
    aclVersion = 0
    ephemeralOwner = 0x161092a0ff30000
    dataLength = 5
    numChildren = 0
    [zk: localhost:2181(CONNECTED) 1] create /node/child ''
    Ephemerals cannot have children: /node/child
    +

    临时节点在客户端会话结束或者发生故障的时候被 ZooKeeper 系统自动清除。现在试验下的针对临时节点自动清除的监视:

    +
    $ zkCli  # 启动第2个客户端
    [zk: localhost:2181(CONNECTED) 0] create -e /node 'hello'
    Node already exists: /node
    [zk: localhost:2181(CONNECTED) 1] stat /node true
    cZxid = 0x97
    ctime = Thu Nov 08 21:01:25 CST 2017
    mZxid = 0x97
    mtime = Thu Nov 08 21:01:25 CST 2017
    pZxid = 0x97
    cversion = 0
    dataVersion = 0
    aclVersion = 0
    ephemeralOwner = 0x161092a0ff30000
    dataLength = 5
    numChildren = 0
    +

    若客户端1,退出 quit 或崩溃,客户端2将收到监视事件:

    +
    [zk: localhost:2181(CONNECTED) 2]
    WATCHER::

    WatchedEvent state:SyncConnected type:NodeDeleted path:/node
    +

    (3) 顺序节点(sequential znode)

    +

    顺序节点在其创建时 ZooKeeper 会自动在 znode 名称上附加上顺序编号。顺序编号,由父 znode 维护,并且单调递增。顺序编号,由 4 字节的有符号整数组成,并被格式化为 0 填充的 10 位数字。

    +
    [zk: localhost:2181(CONNECTED) 1] create /test ''
    Created /test
    [zk: localhost:2181(CONNECTED) 2] create -s /test/seq ''
    Created /test/seq0000000000
    [zk: localhost:2181(CONNECTED) 3] create -s /test/seq ''
    Created /test/seq0000000001
    [zk: localhost:2181(CONNECTED) 4] create -s /test/seq ''
    Created /test/seq0000000002
    [zk: localhost:2181(CONNECTED) 5] ls /test
    [seq0000000000, seq0000000001, seq0000000002]
    +

    客户端 API

    + +

    ZooKeeper 提供的主要 znode 操作 API 如下表所示:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    API 操作描述CLI 命令
    create创建 znodecreate
    delete删除 znodedelete/rmr/delquota
    exists检查 znode 是否存在stat
    getChildren读取 znode 全部的子节点ls/ls2
    getData读取 znode 数据get/listquota
    setData设置 znode 数据set/setquota
    getACL读取 znode 的 ACLgetACL
    setACL设置 znode 的 ACLsetACL
    sync同步sync
    +

    Java 的 ZooKeeper 类实现了上述提供的 API。

    +

    Zookeeper 底层是 Java 实现,zkCli 命令行工具底层也是 Java 实现,对应的 Java 实现类为 org.apache.zookeeper.ZooKeeperMain [ src1 src2 ]。ZooKeeper 3.5.x 下,CLI 命令与底层实现 API 对应关系:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    命名 CLIJava API (ZooKeeper 类)
    addauth scheme authpublic void addAuthInfo(String scheme, byte[] auth)
    closepublic void close()
    create [-s] [-e] path data aclpublic String create(final String path, byte data[], List acl, CreateMode createMode)
    delete path [version]public void delete(String path, int version)
    delquota [-n|-b] pathpublic void delete(String path, int version)
    get path [watch]public byte[] getData(String path, boolean watch, Stat stat)
    getAcl pathpublic List getACL(final String path, Stat stat)
    listquota pathpublic byte[] getData(String path, boolean watch, Stat stat)
    ls path [watch]public List getChildren(String path, Watcher watcher, Stat stat)
    ls2 path [watch]-
    quitpublic void close()
    rmr pathpublic void delete(final String path, int version)
    set path data [version]public Stat setData(String path, byte[] data, int version)
    setAcl path aclpublic Stat setACL(final String path, List acl, int aclVersion)
    setquota -n|-b val pathpublic Stat setData(String path, byte[] data, int version)
    stat path [watch]public Stat exists(String path, boolean watch)
    sync pathpublic void sync(String path, AsyncCallback.VoidCallback cb, Object ctx)
    +

    监视点(watch)

    +

    ZooKeeper 提供了处理变化的重要机制一一监视点(watch)。通过监视点,客户端可以对指定的 znode 节点注册一个通知请求,在发生变化时就会收到一个单次的通知。当应用程序注册了一个监视点来接收通知,匹配该监视点条件的第一个事件会触发监视点的通知,并且最多只触发一次。例如,当 znode 节点也被删除,客户端需要知道该变化,客户端在 /z 节点执行 exists 操作并设置监视点标志位,等待通知,客户端会以回调函数的形式收到通知。

    +

    ZooKeeper 的 API 中的读操作:getData、getChildren 和 exists,均可以选择在读取的 znode 节点上设置监视点。使用监视点机制,我们需要实现 Watcher 接口类,该接口唯一方法为 process:

    +
    void process(WatchedEvent event)
    +

    WatchedEvent 数据结构包括以下信息:

    +
      +
    • ZooKeeper会话状态(KeeperState):Disconnected、SyncConnected、AuthFailed、ConnectedReadOnly 、SaslAuthenticated、Expired。
    • +
    • 事件类型(EventType):NodeCreated 、NodeDeleted 、NodeDataChanged、NodeChildrenChanged 和 None 。
    • +
    • 若事件类型不是 None,还包括 znode 路径。
    • +
    +

    若收到 WatchedEvent, 在 zkCli 中会输出类似如下结果:

    +
    WatchedEvent state:SyncConnected type:NodeDeleted path:/node
    +

    监视点有两种类型:数据监视点和子节点监视点。创建、删除或设置一个 znode 节点的数据都会触发数据监视点,exists 和 getData 这两个操作可以设置数据监视点。只有 getChildren 操作可以设置子节点监视点,这种监视点只有在 znode 子节点创建或删除时才被触发。对于每种事件类型,我们通过以下调用设置监视点:

    +

    NodeCreated
    +   通过 exists 调用设置一个监视点。
    +NodeDeleted
    +   通过 exists 或 getData 调用设置监视点。
    +NodeDataChanged
    +   通过 exists 或getData 调用设置监视点。
    +NodeChildrenChanged
    +   通过 getChildren 调用设置监视点。

    +

    Java 示例代码

    +

    在 Java 下使用 ZooKeeper 需要先添加如下 maven 依赖:

    +
    <dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.4.11</version>
    <type>pom</type>
    </dependency>
    +

    ZookeeperDemo 示例,展示了建立连接会话,以及对 znode 的创建、读取、修改、删除和设置监视点等操作:

    +
    import java.io.IOException;
    import org.apache.commons.lang3.time.DateFormatUtils;
    import org.apache.zookeeper.*;
    import org.apache.zookeeper.data.Stat;

    public class ZookeeperDemo {

    public static void main(String[] args) throws KeeperException, InterruptedException, IOException {
    // 创建服务器连接
    ZooKeeper zk = new ZooKeeper("127.0.0.1:2181", 100, new Watcher() {
    // 监控所有被触发的事件
    public void process(WatchedEvent event) {
    System.out.printf("WatchedEvent state:%s type:%s path:%s\n", event.getState(), event.getType(), event.getPath());
    }
    });

    // 创建节点
    zk.create("/zoo", "hello ZooKeeper".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    // 读取节点数据
    Stat stat = new Stat();
    System.out.println(new String(zk.getData("/zoo", false, stat)));
    printStat(stat);

    // 创建子节点
    zk.create("/zoo/duck", "hello duck".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    zk.create("/zoo/goat", "hello goat".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    zk.create("/zoo/cow", "hello cow".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

    // 读取子节点列表,并设置监视点
    System.out.println(zk.getChildren("/zoo", true));

    // 读取子节点数据,并设置监视点
    System.out.println(new String(zk.getData("/zoo/duck", true, null)));

    // 修改子节点数据
    zk.setData("/zoo/duck", "hi duck".getBytes(), -1);
    // 读取修改后的子节点数据
    System.out.println(new String(zk.getData("/zoo/duck", true, null)));

    // 删除子节点
    zk.delete("/zoo/duck", -1);
    zk.delete("/zoo/goat", -1);
    zk.delete("/zoo/cow", -1);
    // 删除父节点
    zk.delete("/zoo", -1);

    // 关闭连接
    zk.close();
    }

    private static void printStat(Stat stat) {
    System.out.println("cZxid = 0x" + Long.toHexString(stat.getCzxid()));
    System.out.println("ctime = " + DateFormatUtils.format(stat.getCtime(), "yyyy-MM-dd HH:mm:ss"));
    System.out.println("mZxid = 0x" + Long.toHexString(stat.getMzxid()));
    System.out.println("mtime = " + DateFormatUtils.format(stat.getMtime(), "yyyy-MM-dd HH:mm:ss"));
    System.out.println("pZxid = 0x" + Long.toHexString(stat.getPzxid()));
    System.out.println("cversion = " + stat.getCversion());
    System.out.println("dataVersion = " + stat.getVersion());
    System.out.println("aclVersion = " + stat.getAversion());
    System.out.println("ephemeralOwner = 0x" + Long.toHexString(stat.getEphemeralOwner()));
    System.out.println("dataLength = " + stat.getDataLength());
    System.out.println("numChildren = " + stat.getNumChildren());
    }
    }
    +

    输出结果:

    +
    WatchedEvent state:SyncConnected type:None path:null
    hello ZooKeeper
    cZxid = 0x1e1
    ctime = 2017-11-20 12:18:36
    mZxid = 0x1e1
    mtime = 2017-11-20 12:18:36
    pZxid = 0x1e1
    cversion = 0
    dataVersion = 0
    aclVersion = 0
    ephemeralOwner = 0x0
    dataLength = 15
    numChildren = 0
    [cow, goat, duck]
    hello duck
    WatchedEvent state:SyncConnected type:NodeDataChanged path:/zoo/duck
    hi duck
    WatchedEvent state:SyncConnected type:NodeDeleted path:/zoo/duck
    WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/zoo
    +

    ZooInspector

    +

    ZooInspector 是 ZooKeeper 3.3.0 开始官方提供的可视化查看和编辑 ZooKeeper 实例的工具 [ ZOOKEEPER-678 ]。源码位于目录 src/contrib/zooinspector 下,GitHub 地址为:link。可以根据 README.txt 的说明运行使用。或者可以直接用 ZOOKEEPER-678 下提供的可执行 jar 包。

    +ZooInspector +

    参考资料

    +
      +
    1. 官方文档:ZooKeeper http://zookeeper.apache.org/doc/current/index.html
    2. +
    3. 2010-11 许令波:分布式服务框架 Zookeeper https://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/
    4. +
    5. ZooKeeper:分布式过程协同技术详解,Benjamin Reed & Flavio Junqueira,2013,豆瓣
    6. +
    7. Apache ZooKeeper Essentials, Haloi 2015,豆瓣
    8. +
    9. 从Paxos到Zookeeper,阿里倪超 2015,豆瓣
    10. +
    11. 大数据日知录:架构与算法,张俊林 2014,第5章 分布式协调系统,豆瓣
    12. +
    13. 2010,Patrick Hunt, Mahadev Konar, Flavio Paiva Junqueira, Benjamin Reed: ZooKeeper: Wait-free Coordination for Internet-scale Systems. USENIX ATC 2010,dblpmsausenix
    14. +
    +]]>
    + + 架构 + + + 架构 + ZooKeeper + 分布式 + 共识 + Paxos + +
    + + 可靠性工程概述 + /2023/11/reliability-engineering/ + 为了应对负载的增长,目前大型网站普遍都采用分布式架构。相对于采用单体架构的系统,分布式系统中有大量的服务器及设备,各模块之间存在错综复杂的依赖关系,存在更多的不确定性。整个系统的故障率会随设备的增加而呈指数级增加,单一节点问题可能会被无限放大,日常运行过程中一定会伴随故障发生。所以,可靠性开始成为大型网站关注的最重要的质量属性之一,并因此发展出了站点可靠性工程(Site reliability engineering,SRE)。站点可靠性工程,是从可靠性工程发展而来的,从可靠性工程中借鉴了概念和成果。本文溯本求源,内容主要是总结概括,可靠性工程的历史演进和核心概念,软件可靠性工程的核心概念,以及可靠性设计的方法。

    + +

    历史演进

    +

    可靠性工程起源于第二次世界大战[1]。“二战”期间,美国 60% 的机载电子设备运到远东后不能使用,50% 的电子设备在存储期间失效。经过分析,发现这些电子设备故障的主要原因是电子管的可靠性太差,为此美国在 1943 年成立电子管研究委员会,在 1952 年美国国防部成立一个由军方、工业部门及学术界组成的小组,名为“电子设备可靠性咨询小组”(AGREE,Advisory Group on the Reliability of Electronic Equipment)。1957 年 6 月,AGREE 小组出版报告《军用电子设备可靠性》(Reliability of Military Electronic Equipment),该报告是公认的可靠性工程的奠基性文件,研究报告提出一整套可靠性设计、试验和管理方法,确立了可靠性工程发展方向,标志着可靠性工程学科诞生。此后,它不断向工业和民用产品领域渗透,20 世纪 60 年代推广到核工业, 70 年代在化学工业普及,并陆续扩散到其他工程领域。

    +

    随着可靠性工程学科的发展演进,围绕故障展开,逐渐衍生出对产品的维修性(maintainability)、可用性(availability)、保障性(supportability)、测试性(testability)、安全性(safety)等质量特性的工程学研究。“维修性工程”和“安全性工程”是从“可靠性工程”中分离出来的,而“保障性工程”和“测试性工程”又是从“维修性工程”中独立出来的。新的 XX 性陆续分出,因为这些特性紧密相关,已经分出的 XX 性围绕可靠性又重新集成起来,在 20 世纪 80 年代呈现综合化发展趋势。可靠性的含义不断扩展,从狭义可靠性演变为广义可靠性,从狭义可靠性工程演变为广义可靠性工程。

    +

    1980 年代初期,为了避免因为扩展可靠性固有的含义引发的可靠性定性含义和可靠性的定量含义之间的理解混乱,Jean-Claude Laprie 选择“可信性”(dependability)作为术语,根据国际电工委员会标准,可信性的定义是,用以描述可用性及其影响因素(可靠性、维修性和维修保障性)的集合性术语,可信性仅用于非定量术语的一般描述。某些情况下,可信性还包含耐久性(durability)、安全性(safety)、安全保密性(security)等其他特性。可信性可以理解为广义可靠性

    +

    当今在国际上有两个比较完整的可靠性标准化体系,一个是美国军用标准(MIL-STD),另一个是国际电工委员会(IEC)标准。美国军用标准多年来一直扮演着研究开发可靠性相关标准文件的带头角色,也是最早制定可靠性标准的。最早的可靠性定义是由美国 AGREE 在 1957 年的报告中提出的,1966 年美国的 MIL-STD-721B 又给出了传统的或经典的可靠性定义,即产品在规定的条件下和规定的时间内完成规定功能的能力。最主要的可靠性国际标准组织是国际电工委员会的 TC56 技术委员会,TC56 的发展时间线[2]

    +
      +
    • 1965,国际电工委员会 IEC 成立名为“电子元件和设备可靠性”(Reliability of Electronic Components and Equipment)的技术委员会,即 TC56。
    • +
    • 1973,TC56 更名为“可靠性与维修性”(Reliability and Maintainability)技术委员会。
    • +
    • 1985,TC56 技术委员会成立了软件可靠性工作组,开始制定软件可靠性和维修性标准。
    • +
    • 1989,TC56 更名为“可信性”(Dependability)技术委员会,此名称一直沿用至今。
    • +
    • 1990,TC56 在与国际标准化组织(ISO)协商后,工作范围应不再局限于电工技术领域,而是解决所有学科的通用可靠性问题,从而使 IEC/TC56 成为所谓的横向委员会。
    • +
    +

    我国与 IEC/TC56 对口的专业技术标准化组织是,TC24 全国电工电子产品可靠性与维修性标准化技术委员会(简称“可标委”),成立于 1982 年,挂靠在工业和信息化部电子第五研究所(又名中国电子产品可靠性与环境试验研究所)。

    +

    可信性与质量六性

    +

    除了上文的“可信性”集合性术语外,有些资料将广义可靠性解释为,“可用性 + 可靠性 + 维修性”,这三个质量特性也被缩写为 RAM。RAM 有时候会再加上安全性(Safety),被缩写为 RAMS。使用 RAMS 缩写的典型例子是国际电工委员会的 IEC 62278:2002 标准(等同的国家标准 GB/T 21562-2008)。

    +

    另外,常见的可靠性相关的缩写是 RMS 和 RMTSS。RMS 代表可靠性、维修性、保障性,或称“三性”。RMTSS 代表可靠性、维修性、测试性、保障性、安全性,或称“五性”。质量“三性”或“五性”,也是我国军用武器装备的军用标准要求的通用质量特性。我国武器装备的军用标准学习和借鉴的是美国军用标准,军用装备的质量特性分为专用质量特性和通用质量特性。专用质量特性,反映的是不同系统或者装备自身的特点和个性特征,主要指的是功能和性能,如某型飞机的最大(最小)飞行速度、巡航速度、飞行高度等指标。通用质量特性,则表征不同装备的共性特征。通用质量特性是逐渐演变的,从一开始的“二性”演变为“六性”[3][4],通用质量特性包含的特性如下:

    +
      +
    • 二性:可靠性、维修性(也缩写为 R&M)
    • +
    • 三性:可靠性、维修性、保障性(也缩写为 RMS)
    • +
    • 五性:可靠性、维修性、测试性、保障性、安全性(也缩写为 RMTSS)
    • +
    • 六性:可靠性、维修性、保障性、测试性、安全性、环境适应性
    • +
    +

    通用质量特性与可信性的含义大体上相同。质量特性、可信性、可靠性的关系,如下图所示:

    +质量特性、可信性、可靠性的关系 +

    根据国际电工委员会 IEC 60050 (191):1990(等同的国家标准 GB/T 3187-1994 《可靠性、维修性术语》)、IEC 60050-192:2015(等同于 GB/T 2900.99-2016 《电工术语 可信性》)以及国家军用标准 GJB 451A-2005 《可靠性维修性保障性术语》(与美国军用标准 MIL-STD-721C 相似)等标准文档,相关特性的定义和度量指标如下:

    +
      +
    • 可信性(dependability:用以描述可用性及其影响因索(可靠性、维修性和维修保障性)的集合性术语。可信性仅用于非定量术语的一般描述。
    • +
    • 可靠性(reliability:在给定的条件,给定的时间区间,能无故障地执行要求的能力。可靠性一般用可靠度(reliability)、平均故障间隔时间(MTBF)、使用寿命(useful life)等参数来度量。
    • +
    • 可用性(availability:在所要求的外部资源得到提供的情况下,产品在给定的条件下,在给定的时刻或时间区间内处于能完成要求的功能的状态的能力。此能力是产品的可靠性、维修性和维修保障性的综合反映。可用性的度量指标称为可用度(availability),表示为平均可用时间同平均可用时间与平均不可用时间的和之比。
    • +
    • 维修性(maintainability:在给定的条件下,使用所述的程序和资源实施维修时,产品在给定的使用条件下保持或恢复能完成要求的功能的状态的能力。维修性反映产品修理的难易程度,主要使用平均修复时间(MTTR)来度量。
    • +
    • 保障性(supportability:在规定的运行剖面和给定的后勤与维修资源下,保防能维待要求的可用性的能力。维修保障(maintenance support),是维修产品的资源的供给,资源包括人力资源、保障设备、材料和备件、维修设施、文档和信息以及维修信息系统。保障性一般用平均保障延误时间、资源满足率、资源利用率等参数来度量。
    • +
    • 测试性(testability):是指产品能及时并准确地确定其状态(可工作、不可工作或性能下降),并隔离其内部故障的能力。测试性反映产品是否易于测试、出现故障时是否易于检测和隔离,一般用检测时间、技术准备时间、故障检测率、故障隔离率等参数来度量。
    • +
    • 安全性(safety):是指产品所具有的不导致人员伤亡、系统毁坏、重大财产损失或不危及人员健康和环境的能力。安全性可理解为产品在任何情况下对人员、系统、财产和环境都不构成安全威胁。它可定义为产品在规定的条件下和规定的时间内,以可接受的风险执行规定功能的能力。安全性一般用事故概率、损失率、安全可靠度等参数来度量。
    • +
    • 环境适应性(environmental worthiness):是指产品在其寿命期内预计可能遇到的各种环境作用下能实现其所有预定功能、性能和(或)不被破坏的能力。它反映了产品对各种环境的适应能力,即在其可能遇到的各种环境下均能正常工作的能力,是可靠性的一种特殊情况。环境适应性鉴定试验通过的判定准则是,在所有试验条件下“零故障”。
    • +
    +

    通用质量特性的“六性”之间是紧密联系的[4:1][5]

    +
      +
    • 维修性是对可靠性的补充,如果产品不发生故障就不需要修复性维修。
    • +
    • 可用性是产品的可靠性、维修性和维修保障性的综合反映。
    • +
    • 保障性为产品正常使用与维修提供外部资源的支持,提供使用保障和维修保障,可靠性和维修性依赖于保障性。
    • +
    • 测试性是维修性的基础,维修依赖于测试,产品要修理一定要先发现故障和隔离故障,所以测试性设计得好,维修时间就可大大缩短。
    • +
    • 安全性本是可靠性的一部分,是避免人员伤亡、健康损害、财产或环境损害风险的可靠性。可靠性是安全性的基础,很多安全性问题都是因为产品不可靠造成的,所以提高产品可靠性也能提高安全性,当然并非所有安全性问题都是不可靠引起的。
    • +
    • 环境适应性是可靠性的一种特殊情况,是可靠性研究的前提,研究可靠性首先要确定产品是否有足够的环境适应性。
    • +
    +

    通用质量特性的“六性”工作围绕故障(failure)而展开,也被人称为“故障六性”[6][4:2]。可靠性的目标是减少故障;维修性的目标是修复故障;测试性的目标是检测故障;保障性保证出现故障时可以快速供应维修资源;安全性旨在出现故障以后降低风险;环境适应性鉴定试验通过的判定准则是,在所有试验条件下“零故障”[5:1]

    +故障六性 +

    可靠性是产品质量特性之一,是一种面向时间的质量特性(time oriented quality characteristic)[7]。Lloyd Condra 在书中对可靠性和质量的关系的解释是,“可靠性是质量随着时间的变化(reliability is quality over time)”,“为了衡量产品的质量水平,我们对现在的产品进行评判,而为了度量产品的可靠性水平,则要对产品未来会是什么样子进行评判”。这里的讨论的质量其实指的是符合性质量,质量管理一开始是从符合性质量开始的,质量管理的主要工作是质量检验(Quality Inspection),检测产品是否符合规格,质量检验的结果即合格品率。质量管理的关注焦点是产品的合格品率,而可靠性关注焦点是产品在用户使用过程中合格水平随着时间的保持能力,如下图所示 [5:2]

    +质量与可靠性关系示意图 +

    故障与失效的区别

    +

    可靠性工程中有两个基本而重要的术语“fault”和“failure”。在我国的可靠性标准文档中,把“fault”翻译为“故障”,把“failure”翻译为“失效”或“故障”,也就是说,“失效”对应的英文只有“failure”;而“故障”对应的英文是“fault”或“failure”[8][9]

    +

    我国第一个定义可靠性相关的常用术语的国家标准是 GB 3187-1982 《可靠性基本名词术语及定义》,该标准对英文术语“failure”的中文翻译是“失效”或“故障”,并把“mean time between failures”翻译是“平均无故障时间”:[8:1]

    +
    +

    2.2.1 失效(故障) failure:产品丧失规定的功能。对可修复产品通常也称故障。
    +2.5.5 平均寿命(平均无故障时间) mean life (mean time between failures):寿命(无故障时间)的平均值。

    +
    +

    替代 GB 3187-1982 的新国家标准是 GB/T 3187-1994 《可靠性、维修性术语》(等同于 IEC 60050-191:1991),该标准把“failure”仅翻译为“失效”,不再又称“故障”。完整的术语定义如下:

    +
    +

    4.1.1 失效 failure
    +产品终止完成规定功能的能力这样的事件。
    +4.2.1 故障 fault
    +产品不能执行规定功能的状态。预防性维修或共他计划性活动或缺乏外部资源的情况除外。故障通常是产品本身失效后的状态,但也可能在失效前就存在。

    +
    +

    基于上述的定义,对于性能随时间逐渐退化的产品,故障(fault)与失效(failure)的区别,如下图所示[10]

    +故障(fault)与失效(failure)的区别 +

    国外历来都是将“fault”和“failure”的定义加以区分的,我国新的标准文档也区分翻译为“故障”和“失效”,但是实际上在我国的电工行业中的惯用情况是把“fault”和“failure”都翻译为“故障”,很多书籍资料也不严格区分。比如,中国质量协会的《可靠性工程师手册》(第 2 版 2017[5:3]),不严格区分“故障”与“失效”术语,统一都使用“故障”,书中的解释如下:

    +
    +

    在我国的可靠性工程应用中,一般不对故障与失效进行严格的区分,如失效树分析也称为故障树分析,故障模式、影响分析也称为失效模式、影响分析。因此本书也不做严格区分,多数情况下故障一词也可用失效代替。

    +
    +

    一般而言,故障是产品本身失效后的状态,此时产品处于故障状态,这时故障和失效是不需要严格加以区分。对无故障容忍能力的产品而言,故障即失效。然而,对有故障容忍能力的产品,产品可以出故障,但不会失效,这时我们就必须区分失效和故障的概念[9:1]。故障容忍(容错,fault tolerance),是在某些故障出现时继续运行的能力,只有当所有冗余的硬件同时有故障时,产品才失效。

    +

    可靠性的度量

    +

    可靠性的度量指标是可靠度reliability),根据国际电工委员会的标准文档,可靠度的定义是:在给定的条件下在时间区间 (t1, t2) 内按要求执行的概率。当 t1=0 和 t2=t,则 R(0,t) 可简化为 R(t),并称为产品的可靠度函数(reliability function)。

    +

    若在 t=0 时产品的总数为N0N_0,在 0 ~ t 的时间内累计的故障数为Nf(t)N_f(t),正常的产品数为Ns(t)N_s(t),则有:

    +

    N0=Nf(t)+Ns(t)N_0 = N_f(t) + N_s(t)

    +

    产品在 t 时刻的可靠度的估计值为:

    +

    R(t)^=Ns(t)N0\hat{R(t)}=\frac{N_s(t)}{N_0}

    +

    显然,当 t=0 时,R(0) = 1,当 t=∞ 时,R(∞) = 0。

    +

    可靠度的反面是不可靠度(unreliability),含义是:在规定的条件下,在规定的时间内,不能完成规定功能的概率。不可靠度函数通常记为F(t)F(t),不可靠度的估计值的计算公式为:

    +

    F(t)^=Nf(t)N0=N0Ns(t)N0=1R(t)^\hat{F(t)} = \frac{N_f(t)}{N_0} = \frac{N_0 - N_s(t)}{N_0} = 1 - \hat{R(t)}

    +

    示例:假设在 t=0,投入工作的 10000 只灯泡,以天作为度量时间的单位,在 t= 365 天时,发现有 300 只灯泡坏了,这时的可靠度和不可靠度的计算如下:

    +

    R(365)^=10003001000=0.97\hat{R(365)} = \frac{1000 - 300}{1000} = 0.97F(365)^=3001000=0.03\hat{F(365)} = \frac{300}{1000} = 0.03

    +

    对不可靠度函数求导,其导数称为故障概率密度函数,通常记为f(t)f(t)

    +

    f(t)=limΔt0F(t+Δt)F(t)Δtf(t) = \lim_{\Delta t \to 0} \frac{F(t + \Delta t) - F(t)} {\Delta t}

    +

    某时刻尚未发生故障的产品,在该时刻后单位时间内发生故障的概率,称为产品的故障率failure rate),记为记为λ(t)λ(t)。故障率的计算公式如下:

    +

    λ(t)^=Ns(t)Ns(t+Δt)Ns(t)Δt=间隔时间内的故障数间隔起点的存活数×时间间隔\hat{λ(t)} = \frac{N_s(t) - N_s(t + \Delta t)} {N_s(t) \Delta t} = \frac{间隔时间内的故障数}{间隔起点的存活数 × 时间间隔}

    +

    λ(t)=limΔt0Ns(t)Ns(t+Δt)Ns(t)Δt=limΔt0F(t+Δt)F(t)R(t)Δt=f(t)R(t)λ(t) = \lim_{\Delta t \to 0} \frac{N_s(t) - N_s(t + \Delta t)} {N_s(t) \Delta t} = \lim_{\Delta t \to 0} \frac{F(t + \Delta t) - F(t)}{R(t)\Delta t} = \frac{f(t)}{R(t)}

    +

    在长期的可靠性实践中,人们发现许多产品的故障率随时间的变化曲线形似浴盆,所以习惯性的将故障率曲线称为“浴盆曲线”(bathtub curve),如下图所示[5:4]。大多数电子产品的故障率曲线的形状就是浴盆曲线。

    +产品典型的故障率曲线 +

    故障率随时间的变化大致可以分为以下三个阶段:早期故障期(early failure period)、偶然故障期(random failure period)、耗损故障期(wear-out failure period)。三个阶段有时也被称为:早夭期(infant mortality period)、使用寿命期(useful life period)和耗损期(wear-out period)。故障率曲线与人类的死亡率曲线相似,曲线的三个阶段分别对应人类生命周期的婴幼儿时期、壮年期以及老年期。在偶然故障期,产品的故障率可降到一个较低的水平,且基本处于平稳状态,可以近似认为故障率为常数。

    +

    如果产品的故障率为常数,那么其故障的概率分布可以用指数分布(exponential distribution)描述,指数分布是唯一具有恒定故障率的连续概率分布。恒定故障率的特性也被称为“无记忆性”(memorylessness),该特性说明故障率在任何时刻都与系统已工作过的时间长短没有关系。服从指数分布的概率密度函数为:

    +

    f(t)=λeλtf(t) = {\lambda} e^{-\lambda t}

    +

    服从指数分布的可靠度函数、不可靠度函数和故障率函数依次为:

    +

    R(t)=eλtR(t) = e^{-\lambda t}F(t)=1eλtF(t) = 1 - e^{-\lambda t}λ(t)=λ\lambda(t) = \lambda

    +

    公式中的λ\lambda为常数。

    +

    上面提到的这些指标是概率相关的度量指标。另外,还有一些是时间相关的度量指标:

    +
      +
    • 平均故障间隔时间(MTBF,mean time between failures):相邻两次故障间的持续时间的平均值。失效间隔时间(time between failures)包括可用时间和不可用时间。MTBF 只能用于可修复产品。
    • +
    • 平均故障间隔工作时间(MTBF /MOTBF,mean operating time between failures):相邻两次故障间的累计工作时间的平均值。MOTBF 只能用于可修复产品,该值也被成为可修复产品的平均寿命(mean life)。
    • +
    • 平均故障前工作时间MTTF,mean operating time to failure):故障前工作时间的平均值。等同于,平均失效前时间(MTTF,mean time to failure)。MTTF 可以用于不可修复产品和可修复产品。MTTF 值也被成为不可修复产品的平均寿命(mean life)。
    • +
    • 平均恢复时间MTTR,mean time to restoration):恢复时间的平均值。最新的国际电工委员会 IEV 标准文档,废弃了平均恢复时间(mean time to recovery)和平均修理时间(mean time to repair)。平均恢复时间是维修性的主要度量指标。
    • +
    • 可用性availability):或者翻译为“可用度”,可以表示为平均可用时间除以平均可用时间与平均不可用时间之和。可用性是反映可靠性和维修的综合性指标。
    • +
    +

    根据国际电工委员会标准文档 IEC 60050-192:2015(等同的国家标准文档是 GB/T 2900.99-2016《电工术语 可信性》),MTBF 和 MOTBF 缩写代表的都是平均故障间隔工作时间(mean operating time between failures),统计的值是故障间隔工作时间operating time between failures),即相邻两次故障间的累计工作时间;而故障间隔时间time between failures),包括可用时间和不可用时间。所以,平均故障间隔时间平均故障间隔工作时间的含义是不同的,前者同时统计包括工作时间(operating time)和非工作时间(non-operating time),而后者只统计工作时间(operating time)。但是在很多其他文档中,比如维基百科的词条“平均故障间隔时间”(Mean time between failures)词条,“平均失效间隔时间”的缩写也是 MTBF。也就说, MTBF 即是“平均故障间隔时间”的缩写,也是“平均故障间隔工作时间”的缩写,但两者含义却不同,需要读者自行辨别。本文使用 MTBF,统一都表示“平均故障间隔时间”。

    +

    MTBF 只能用于可修复产品,MTTF 用于不可修复产品和可修复产品。对于不可修复产品,MTTF 等同于 MTBF,对于可修复产品,MTTF 等同于 MOTBF。MTBF 是 MTTR 和 MTTF 的总和,即MTBF=MTTR+MTTFMTBF = MTTR + MTTF

    +

    产品的平均寿命(mean life)的理论值为故障概率密度函数的期望值,记为 θ。该期望值也是可修复产品的 MOTBF 的理论值,是不可修复产品的 MTTF 的理论值。平均寿命或 MTTF 的计算公式如下:

    +

    MTTF=θ=E(T)=0tf(t)dxMTTF = θ = E(T) = \int_{0}^\infty t f(t)\,\mathrm{d}x

    +

    如果概率密度函数服从指数分布,那么平均寿命或 MTTF 值为:

    +

    MTTF=θ=1/λMTTF = θ = 1/\lambda

    +

    对于服从指数分布的产品,当产品工作时间到达平均寿命时,可靠度的值 36.8%:

    +

    R(θ)=e1=36.8%R(θ) = e^{-1} = 36.8\%

    +

    假设某可修复产品的正常工作时间为{TFF1,TFF2...,TFFn}\left\{ {TFF}_1, {TFF}_2 ..., {TFF}_n \right\},故障时间为{TTR1,TTR2...,TTRn}\left\{ {TTR}_1, {TTR}_2 ..., {TTR}_n \right\},如下图所示:

    +MTBF、MTTF 和 MTTR 示意图 +

    MTBF、MTTF、MTTR 和可用性(availability)的估计值的计算公式如下:

    +

    MTBF=i=1nTBFin=total uptime + total downtimetotal number of failuresMTBF = \frac{\sum_{i=1}^n {TBF}_i}{n} = \frac{\text{total uptime + total downtime}}{\text{total number of failures}}

    +

    MTTF=i=1nTTFin=total uptimetotal number of failuresMTTF = \frac{\sum_{i=1}^n {TTF}_i}{n} = \frac{\text{total uptime}}{\text{total number of failures}}

    +

    MTTR=i=1nTTRin=total downtimetotal number of failuresMTTR = \frac{\sum_{i=1}^n {TTR}_i}{n} = \frac{\text{total downtime}}{\text{total number of failures}}

    +

    可用性=MTTFMTTF+MTTR=MTTFMTBF=total uptimetotal uptime+total downtime可用性 = \frac {MTTF} {MTTF + MTTR} = \frac {MTTF} {MTBF} = \frac{\text{total uptime}}{\text{total uptime} + \text{total downtime}}

    +

    对于电子设备,MTBF 近似常量,比如,典型的企业级固态硬盘 SSD 的 MTBF 值可能是 200 万小时[11],也就是 228 年,年故障率 AFR(Annualized Failure Rate) 为 0.44%(1/228)。

    +

    可以利用数学和统计方法对可靠性进行预计和度量,并分析可靠性数据。但是可靠性的量化涉及大量不确定性,由于可靠性经常关系到制造和使用产品的人,人的行为和表现不像植物对肥料的反应、气象模型对海洋温度的反应那样服从于数学分析和预测,而且产品可能在大范围变化的环境中工作,因此还会有其他不确定性因素被引入。数学和统计方法虽然在适当的场合是非常有价值的,但是由于涉及大量不确定性,在实际的可靠性工程中的作用有限,在实际的工程实践中优先需要确定的是故障的原因和解决方案[12]

    +

    软件可靠性工程

    +

    软件可靠性工程是从硬件可靠性工程发展而来的[13]。在软件工程学建立初期,一些软件工程专家利用和改造硬件可靠性工程学的成果,使之移植到软件领域,从而开创了软件可靠性学科。

    +

    类似的,起源于 Google 的“站点可靠性工程”(SRE, Site reliability engineering)也源自可靠性工程,区别是站点可靠性工程关注的是大型网站和网络服务这样的软件系统 [14][15]

    +

    术语与概念

    +

    国家标准 GB/T 11457-2006 《信息技术 软件工程术语》,对软件可靠性的定义如下:

    +
    +

    2.1662 系统可靠性 system reliability
    +包括全部硬件和软件子系统在内的某个系统,在规定的环境及时间里正确执行所要求的任务或使命的概率。
    +2.1528 软件可靠性 software reliability
    +a) 在规定条件下,在规定的时间内,软件不引起系统失效的概率。该概率是系统输人和系统使用的函数,也是软件中存在的缺陷的函数。系统输人将确定是否会遇到已存在的缺陷(如果有缺陷存在的话)。
    +b) 在规定的时间周期内所述条件下程序执行所需要的功能的能力。

    +
    +

    GB/T 11457-2006 吸收了 IEEE Std 610.12-1990 全部术语,包括术语“软件可靠性”,国标的术语定义只是对 IEEE 术语定义的中文翻译。IEEE 最早在标准文档中定义“软件可靠性”是在 IEEE Std 729-1983,这个标准之后被 IEEE Std 610.12-1990 替代。

    +

    IEEE 对“软件可靠性”术语给出两个定义,定义 a) 是定量的定义,也就是“可靠度”,定义 b) 是定性的定义。对比后容易发现,硬件可靠性和软件可靠性的定义是相同的。这种相容性,使这种可靠性定义能够用于既包括软件又包括硬件的系统。

    +

    故障相关的术语,国家标准 GB/T 11457-2006 《信息技术 软件工程术语》的定义是:

    +
    +

    2.163 隐错 bug
    +见:出错 error(2.561) 和故障 fault(2.609)。
    +2.421 缺陷 defect
    +见:故障 fault(2.609)。
    +2.561 出错, 误差, 差错 error
    +a) 计算的、观察的或测量的值或条件与实际的、规定的或理论上正确的值或条件的差别。例如,在计算的结果和正确的结果之间差30m;
    +b) 不正确的步骤、过程或数据定义。例如,在计算机程序中的不正确的指定;
    +c) 不正确的结果。例如,当正确的结果是10,而计算的结果是12;
    +d) 产生不正确结果的人为动作。例如,在编程或操作的一部分上的不正确动作。
    +注:当上述所有四种定义是公共使用时,一种区分赋给定义 a) 为字差错(error),定义 b) 为字过错(fault),定义 c) 为字失效(failure)和定义 d) 为字错误(mistake)。
    +2.601 失效 failure
    +系统或部件不能按规定的性能要求执行它所要求的功能。注:故障容忍在人们的动作(弄错-mistake)、它的显示(硬件或软件故障 fault)、故障的结果(失效 failure)和不正确(差错-error)结果的总数之间进行区分
    +2.609 故障, 缺陷 fault
    +a) 硬件设备或部件中的缺陷。例如,短路或断线。
    +b) 在计算机程序中不正确的步骤、过程或数据定义。注:此定义最初由容错(fault tolerance)系统使用。在通常用法中,术语“差错(error)”和“隐错(bug)”表示同样含义。

    +
    +

    基于 IEEE 的定义,容易发现术语“fault、“bug”和“defect”是同义词,术语“error”同时具有“mistake”、“fault”和“failure”的含义。这些术语之间的因果关系是,开发者在软件开发过程中产生人为失误(mistake),导致在软件中存在缺陷(fault, bug, defect),在软件运行时如果用户遭遇缺陷(fault, bug, defect),会引发失效(failure),如下图所示:

    +软件故障的因果关系 +

    失效(failure)是指系统或部件在特定约束下不能完成所要求的功能,用户在测试或实际使用中会观察到失效(failure)。失效(failure)是系统运行行为对用户要求的偏离,是一种面向用户的概念。故障(fault)是在系统运行时引起或可能潜在地引起失效(failure)的缺陷(defect),是一种面向开发者的概念。

    +

    可靠性的度量

    +

    早期的软件可靠性度量工作试图将硬件可靠性理论中的数学公式外推来进行软件可靠性的预测。大多数与硬件相关的可靠性模型依据的是由于“磨损”而导致的故障,而不是由于设计缺陷而导致的故障。在硬件中,由于物理磨损(如温度、腐蚀、振动的影响)导致的故障远比与设计缺陷有关的故障多。不幸的是,软件恰好相反。实际上,所有软件故障都可以追溯到设计或实现问题,磨损根本没有影响[16]

    +

    软件系统的故障主要是人为差错造成,涉及大量不确定性,利用数学和统计方法对可靠性进行预计和度量,在实际的工程实践中的作用有限。少数常用的与可靠性相关的度量指标是:MTBF、MTTR 和可用性。

    +

    MTBF 指标衡量的是系统无故障运行的能力,也就是可靠性。MTTR 指标衡量的是系统快速从故障中恢复的能力,这种能力在硬件产品下被称为“维修性”(maintainability),但在软件系统下通常为称“韧性”(resilience)。术语“maintainability”,在硬件上下文中通常被翻译为“维修性”,而在软件上下文中通常被翻译为“维护性”或“可维护性”,软件可维护性指的是软件可被修改的能力,修改可能包括修复缺陷、增加或完善功能等。

    +

    MTBF 反映的是硬件产品的寿命,是硬件产品质量的最重要的指标之一。与硬件不同,软件的 MTBF 不可控,而故障恢复的工作流程清晰,可干预程度高,研发团队可以对各环节展开精细化管理,轻松、高效地达成 MTTR 优化目标,所以软件系统的 MTTR 相对 MTBF 更加重要[17][18]

    +

    可用性是衡量可靠性和韧性的综合性指标。想要提高系统的可用性,需要做的是延长无故障时间(MTTF)和缩短故障恢复时间(MTTR)。

    +

    可靠性设计

    +

    Laprie 等人把提高系统可靠性的方法总结为四种

    +
      +
    • 故障避免(fault avoidonce,简称“避错”):在系统的设计和实现过程中使用一些开发方法来减少故障发生,并在系统投入使用之前发现系统中的故障。
    • +
    • 故障排除(fault removal,简称“排错”):故障排除可以细分为两个子类别:开发期间的排除和使用期间的排除。在系统使用之前通过验证和确认(V&V)来发现和去除系统中的故障;如果系统已经投入使用,通过维护周期将其消除。
    • +
    • 故障容忍(fault tolerance,简称“容错”):容错是使系统在其某些组件中出现一个或多个故障时能够继续提供服务的能力,尽管该服务可能处于降级级别。容错技术主要是采用冗余redundancy)方法来消除故障的影响,冗余的含意是指当系统无故障时取消冗余资源不会影响系统正常运行。
    • +
    • 故障预报(fault forecasting):通过收集故障数据,建立可靠性建模,预测可能的故障。
    • +
    +

    针对软件可靠性设计,软件故障避免技术,包括采用优秀的软件设计方法、使用强类型的程序设计语言、全面的编译器检查等;软件故障排除技术,主要是代码评审和软件测试;故障预报,能提高硬件可靠性,但是很少应用于软件可靠性。

    +

    系统的资源包括硬件资源、软件资源、信息资源、时间资源,所以冗余区分 4 种方式:

    +
      +
    • 硬件冗余(hardware redundancy):通过配置额外的硬件组件实现冗余
    • +
    • 软件冗余(software redundancy):通过配置额外的软件版本实现冗余,例如 N 版本编程(NVP
    • +
    • 信息冗余(information redundancy):通过对信息中外加一部分信息码或将信息存放在多个内存单元或将信息进行备份等实现冗余,例如循环冗余校验码、数据库备份等。
    • +
    • 时间冗余(time redundancy):多次执行相同的操作(重试)实现冗余,例如多次执行程序或传输数据的多个副本。
    • +
    +

    硬件冗余和软件冗余被合称为结构冗余(structural redundancy)。相对与时间冗余,硬件冗余、软件冗余、信息冗余被合称为空间冗余(space redundancy)。

    +

    在工程领域,利用冗余提高可靠性的例子很多,比如汽车的备胎、大货车的多个轮子、飞机的四台发动机或双台发动机、火箭的多台引擎和多台计算机等。《像火箭科学家一样思考》书中的“为什么冗余不是多余的”小节[19]中有这样一段阐述:

    +
    +

    航天器上的计算机也使用冗余装置。在地球上,电脑往往免不了崩溃或死机,而在有压力的太空环境中,计算机发生故障的概率有增无减,因为计算机在太空中要经历无数振动、冲击、变化的电流和波动的温度。正因为如此,航天飞机的计算机是4倍冗余的,即飞机上有4台计算机在运行着同样的软件。这4台计算机会通过一个多数投票系统就下一步动作进行单独投票。如果其中一台计算机发生故障,开始乱输出数据,其他3台计算机就会投票将其排除在外(没错,伙计们,火箭科学比你想象的更民主)。
    +冗余装置要正常工作,就必须独立运行。一架航天飞机配备4台计算机,这听起来非常棒,但由于它们运行着相同的软件,所以只要一个软件出现错误,4台计算机就会同时瘫痪。因此,航天飞机还配备了第5个备用飞行系统。该系统安装有一款不同的软件,而这款软件由不同于其他4款软件的分包商提供。如果某个一般性的软件错误使4台相同的主计算机瘫痪,则备用系统将启动,并会将航天飞机送回地球。

    +
    +

    在航天飞机上配备 4 台计算机属于硬件冗余,第 5 个备用飞行系统属于软件冗余。

    +

    IDC 数据中心等级划分(data centre tiers)主要是根据线路、电源、冷却等核心组件的冗余程度而划分的,不同的等级代表不同的可靠性和可用性。按 Uptime Institute 和 TIA-942 标准的建议,数据中心由低到高划分为 T1、T2、T3、T4 共 4 个等级,T1 级为基本型、T2 级为冗余型、T3 级为可并行维护冗余型、T4 级为容错型。4 个等级的冗余程度分别是,T1 级无冗余,T2 级部分 N+1 冗余,T3 级全部 N+1 冗余,T4 级 2N 或 2N+1 冗余。按我国国家标准《GB 50174-2017 数据中心设计规范》,数据中心由高到低划分为 A、B、C 三级,A 级为容错型,B 级为冗余型,C 级为基本型。不同的数据中心等级的对比,如下表所示(表格参考自 [20]):

    +数据中心等级划分 +

    大多数商业数据中心都介于 T3 级和 T4 级之间,平衡了建设成本和可靠性。金融等行业的数据中心,如银行的数据中心,通常会同时遵循最高等级的国家标准 A 级和 Uptime Institute 的 Tier 4 级标准来建设。

    +

    在生物学中,冗余是生物体的一种重要特征。生物体中的冗余结构和功能可以提高生物体的适应性和生存能力。例如,人体的很多器官是冗余的,比如耳朵、眼睛、肾、肺。冗余的器官如果出现“故障”,虽然不会让人完全失去该器官的机能,但会导致机能降级。其中一个眼睛如果完全失去视力,不会让人失明,不过视觉上无法识别远近。其中一个耳朵如果完全没有听力,不会让人失聪,但无法透过耳朵识别声音的位置。

    +

    尽管冗余是一种很好的提高可靠性的措施,但额外的冗余增加到某种程度之后,就会无谓地增加设备的复杂性和成本,遵循边际效益递减规律。典型的例子是客机,随着发动机本身可靠性的提高,出于安全性和成本之间的权衡,之前的四发动机的客机越来越少见,逐渐被更省油、更低维护成本的双发动机的客机取代。

    +

    参考资料

    +
    +
    +
      +
    1. 秦咏红,吕乃基:工程系统可靠性的演进,东北大学学报,2011年第4期295-299,cqvip ↩︎

      +
    2. +
    3. 可靠性概论,工信部电子第五研究所潘勇,2015,豆瓣:第11章 可靠性标准 ↩︎

      +
    4. +
    5. 2022-09 【标准解读】用标准语言解读装备“六性” https://mp.weixin.qq.com/s/FqfLL_ovGIZ-GO998HB4uw ↩︎

      +
    6. +
    7. 2021-07 张健:装备通用质量特性关系概述 https://mp.weixin.qq.com/s/nXmrTrz7c5EnEh4C_h4JEg ↩︎ ↩︎ ↩︎

      +
    8. +
    9. 可靠性工程师手册,中国质量协会,第2版 2017,豆瓣 ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

      +
    10. +
    11. 2018-01 北航康锐:可靠性的历史与今世 | 可靠性系统工程三部曲(上) https://mp.weixin.qq.com/s/275pk9Z-V4T3lntI-ZzYCA ↩︎

      +
    12. +
    13. 可靠性工程(Reliability Engineering),Kapur & Pecht,2014,豆瓣:第1章 21世纪的可靠性工程 ↩︎

      +
    14. +
    15. 2002-03 褚善元:failure和fault的定名问题 http://www.term.org.cn/CN/abstract/abstract10076.shtml ↩︎ ↩︎

      +
    16. +
    17. 2002-03 朱美娴:关于failure和fault定义的研讨 http://www.term.org.cn/CN/abstract/abstract10081.shtml ↩︎ ↩︎

      +
    18. +
    19. System Reliability Theory, Rausand, etc., 3rd 2020,豆瓣:3 Failures and Faults, Figure 3.3 Illustration of the difference between failure and fault for a degrading item. ↩︎

      +
    20. +
    21. 2021-09 揭秘:SSD 的“可靠性”到底可不可靠 https://memblaze.com/innovate/technical-articles/169.html ↩︎

      +
    22. +
    23. 实用可靠性工程(Practical Reliability Engineering),O'Connor, etc.,第5版2012,豆瓣 ↩︎

      +
    24. +
    25. 陈光宇,黄锡滋:软件可靠性学科发展现状及展望,电子科技大学学报社科版,2002年第3期99-102,cqvip ↩︎

      +
    26. +
    27. SRE:Google运维解密,Beyer, etc. 2016,豆瓣:序言 ↩︎

      +
    28. +
    29. SRE原理与实践:构建高可靠性互联网应用,张观石,2022,豆瓣:第1章 互联网软件可靠性概论 ↩︎

      +
    30. +
    31. 软件工程:实践者的研究方法,Pressman,第8版2014,豆瓣:第21章 软件质量保证,21.7 软件可靠性 ↩︎

      +
    32. +
    33. 2010-07 John Allspaw: Thoughts on systems safety, software operations, and sociotechnical systems https://www.kitchensoap.com/2010/11/07/mttr-mtbf-for-most-types-of-f/ ↩︎

      +
    34. +
    35. 2023-07 LigaAI:研发质量指标大 PK:MTTR vs MTBF,谁是靠谱王? https://segmentfault.com/a/1190000043971564 ↩︎

      +
    36. +
    37. 像火箭科学家一样思考,Ozan Varol,2020,豆瓣:第1章 与不确定性共舞,为什么冗余不是多余的 ↩︎

      +
    38. +
    39. 2020-12 艾瑞咨询:2020年中国数据中心行业研究报告 https://report.iresearch.cn/report/202012/3699.shtml ↩︎

      +
    40. +
    +
    +]]>
    + + 架构 + + + 架构 + 可靠性 + SRE + +
    + + 流行互联网网站技术栈整理 + /2023/12/popular-websites-tech-stack/ + 技术栈是构建应用的技术集合,由编程语言、框架、库、服务器、数据库、工具等组合而成。组成技术栈的技术是与具体业务无关的基础软件。互联网公司选择的技术栈,倾向于使用开源软件,相对于专有软件,开源软件具有高质量、免费、开放、灵活等优势。互联网的早期开拓者 Yahoo 的技术栈选择是经典案例,受开源运动的影响,在 2000 左右 Yahoo 从最初基于自定义的专属软件迁移了到 LAMP 技术栈。

    + +

    在“开源”(open source)一词出现之前,技术社区的黑客选择使用“自由软件”(free software)这个词。但是“自由软件”这个词与对知识产权的敌意、共产主义和其它观点相联系,几乎不受管理者和投资者的欢迎,于是 1998 年 2 月 3 日在由 Eric Raymond 等人参加的会议上“开源”一词诞生,2 月下旬开源软件促进会成立 OSI,Eric Raymond 担任主席。自由软件和开源软件被合称为 FOSS。缩写“LAMP”代表的是 Linux-Apache-MySQL-PHP,这些软件都是自由软件或开源软件。

    +

    案例汇总与解析

    +

    技术发展时间线

    +

    在互联网诞生早期,开源技术栈、开源社区尚未成熟,互联网公司不得不自研专有软件,随着开源软件的成熟,技术栈的选择开始从专有软件逐渐转向开源软件。先来看下,主要 Web 技术和服务端技术的发展时间线:

    +
      +
    • 1994.03,Linux 1.0 对外发布,源码采用 GPL 协议。
    • +
    • 1994.10,网景公司的 Web 浏览器 Netscape 首次对外发布。
    • +
    • 1995.04,Apache HTTP Server 首次对外开源发布,版本为 0.6.2,源码采用 Apache 协议
    • +
    • 1995.12,JavaScript 语言诞生,创造者为来自网景公司的 Brendan Eich。
    • +
    • 1995.05,Java 语言诞生,创造者为 Sun 公司。Java 平台早期并不真正开源,虽然 1998 年 JDK 1.2 开始以 SCSL 协议开放源代码,但 SCSL 协议限制太大,饱受批评,直到 2006.11 才以 GPL 协议真正开源。
    • +
    • 1995.06,PHP 语言诞生,源码采用 PHP 协议(BSD 风格的协议)。
    • +
    • 1995.12,HTML 标准规范首次发布,版本为 HTML 2.0
    • +
    • 1996.05,Sun 公司首次对外发布 Java Servlet API。
    • +
    • 1996.10,MySQL 首次公开对外发布,最初的公开发行版仅提供了 Solaris 的二进制发行版,一个月后,源代码和 Linux 二进制文件发布,源码采用的是专有协议“MySQL Free Public License”,到 2000.06 改为 GPL 协议。
    • +
    • 1996.10,PostgreSQL 的诞生日是在 10 月 22 日,在这一天 PostgreSQL.org 网站上线。PostgreSQL 之前的项目名为 Postgres,之所以改名是为了反映其对 SQL 的支持。源码采用 PostgreSQL 协议(类似 BSD 或 MIT 协议)。
    • +
    • 1996.12,微软发布 ASP 技术,到 2002 年 ASP 被 ASP.NET 替代。
    • +
    • 1998.12,缩写“LAMP”诞生,代表 Linux-Apache-MySQL-PHP。
    • +
    • 1999.12,Sun 公司首次对外发布 J2EE,版本为 1.2,包括 Servlet、JSP、EJB 等技术。
    • +
    • 2002.08,Nginx 首次对外发布,源码采用 BSD 协议。最初,研发 Nginx 目的是为了解决 C10k 问题。之后,Nginx 逐渐替代 Apache HTTP Server,LAMP 技术栈改为 LNMP 技术栈。
    • +
    • 2003.06,Java 的 Spring 框架首次对外发布,版本为 0.9,源码采用 Apache 协议。
    • +
    • 2004.08,Ruby on Rails 框架首次对外发布,源码采用 MIT 协议。
    • +
    • 2005.02,“Ajax”术语诞生,早期使用 Ajax 技术的经典案例是 Google 在 2004 发布的 Gmail 和 2005 发布的 Google Maps。
    • +
    • 2005.07,Python 的 Django 框架首次对外发布,源码采用 BSD 协议。
    • +
    • 2007.02,HBase 宣布在 Hadoop 项目中成立,成为 Hadoop 的子项目。HBase 是 Google 的 BigTable(OSDI'2006)论文的开源实现。
    • +
    • 2007.01,iPhone 手机首次对外发布,同年 6 月 iPhone 正式发售,11 月 Android 系统首次对外公布,移到互联网开始大爆发。
    • +
    • 2008.07,Facebook 对外开源 Cassandra 项目,项目受 Amazon 的 Dynamo(SOSP'2007)论文和 Google 的 BigTable(OSDI'2006)论文的。
    • +
    • 2009.06,“NoSQL”术语诞生。“NoSQL”术语诞生于在旧金山举行的一场关于“开源、分布式、非关系数据库”的技术聚会,该技术聚会被命名为“NoSQL meetup”。NoSQL 的两大起源是 BigTable 和 Dynamo。
    • +
    • 2009.11,Google 对外公开 Go 语言,BSD 协议开源。
    • +
    • 2011.04,451 Group 咨询公司的分析师 Matthew Aslett 创造“NewSQL”术语,是对用于 OLTP 的分布式关系型数据库的统称。最具代表性的 NewSQL 是 Google 的 Spanner(OSDI'2012)和 Amazon 的 Aurora(2014.10 发布的云原生数据库产品)。
    • +
    +

    技术栈案例汇总

    +

    按编程语言区别,主要流行的互联网产品的创建时间和早期的技术栈选择(也可以参见 wiki):

    +
      +
    • C/C++ 技术栈: +
        +
      • Yahoo!(1994,2002 转向 PHP)、Amazon(1994,之后转向以 Java 为主)、eBay(1995,2002 全面转向 Java)、Google 搜索(1998)[1][2]新浪网(1998,之后转 PHP,2008 年 PHP 占据 90% 以上的 Web 开发)[3]腾讯 QQ(1999)、QQ 空间(2005)、微信(2011)[4]百度搜索(2000)、Yandex 搜索(2000)[5]
      • +
      +
    • +
    • PHP(LAMP 或 LNMP)技术栈: +
        +
      • Wikipedia(2001)[6]Facebook(2004,2006 核心服务转向 C++)、Flickr(2004)[7]Etsy(2005)[8]WordPress(2005)、新浪博客(2005)[9]百度百科(2006,2006 开始百科、知道、文库、贴吧等产品以 PHP 为主实现)[10]Tumblr(2007,2011 转向 Scala)[11]哔哩哔哩(2009,2017 转向 Golang)[12]新浪微博(2009,2011 转向 Java)[13]腾讯微博(2010)[14]美团(2010,2011 转向 Java)[15]滴滴(2012,2017 业务系统转向 Golang)[16]
      • +
      +
    • +
    • Ruby on Rails 技术栈: +
        +
      • Twitter(2006,2009 核心服务转向 Scala 和 Java)、Shopify(2006)[17]SoundCloud(2007,2012 业务转向多种 JVM 语言和基础设施转向 Golang)[18][19][20]Heroku(2007)[21]GitHub(2008)[22]Airbnb(2008,2016 开始服务化并部分转向 Java)[23][24]
      • +
      +
    • +
    • Python 技术栈: +
        +
      • Reddit(2005,少部分高性逻辑用 C 语言)[25]YouTube(2005)[26]豆瓣(2005)[27]Disqus(2007)[28]Dropbox(2007,2013 基础设施转向 Golang)[29][30][31]Quora(2009,高性能服务用 C++)[32]Pinterest(2009,部分服务转向 Java)[33][34]Instagram(2010,少部分高性逻辑用 C++)[35][36][37]Uber(2010,2015 转向 Golang 和 Java 等)[38]知乎(2011,2018 核心业务转向 Golang)[39]字节跳动(2012,今日头条、抖音等,2014 开始引入 Golang,2016 业务大规模转向 Golang)[40][41]
      • +
      +
    • +
    • Java 技术栈: +
        +
      • 淘宝(2003,2004 PHP 全面转向 Java)、LinkedIn(2003)、Google Gmail(2004)[42]Google Docs(2006)、Google+(2011)[43]人人网(2005)[44]Netflix(2007)[45]
      • +
      +
    • +
    • .NET 技术栈 +
        +
      • 携程(1999,2017 全面转向 Java)[46]京东(2004,2012 全面转向 Java)[47]Stack Overflow(2008)、Bing 搜索(2009)等
      • +
      +
    • +
    +

    值得一提的是,PHP 之父 Rasmus Lerdorf,在 2002 年至 2009 年期间为供职于 Yahoo!,2011 年起至今供职于 Etsy。Python 之父 Guido van Rossum,在 2005 年至 2012 年期间供职于 Google,在 2013 年至 2019 年期间供职于 Dropbox。国内最有影响力的 PHP 技术专家是惠新宸,是加入 PHP 语言官方开发组的首位国人,曾先后供职于雅虎中国、百度、新浪微博、链家网等公司。

    +

    编程语言选择

    +

    2000 年前创建的网站,因为开源技术栈尚未成熟,编程语言基本上都是选择 C++ 开发。在开源技术栈成熟后,多数网站会选择拥抱开源。具体选择哪个编程语言,PHP、Ruby、Python、Java 等,主要由技术负责人的技术偏好决定。根据 w3techs 统计,历年网站使用的服务端编程语言统计占比,2012 年至今 10 多年,PHP 占比稳居榜首,每年都是 75% 以上。大型网站通常都是公司内的技术团队研发的,技术栈由技术团队选择,而很多小型网站,很可能会直接使用开源的 CMS 系统搭建。根据 w3techs 统计,前 100 万网站中有 43.0% 使用 WordPress 构建。WordPress 的服务端编程语言就是 PHP,数据库是 MySQL。大型网站选择 PHP 越来越少,因为 PHP 是解释型脚本语言,相对编译型编程语言有性能劣势。另外,PHP 的优势是快速开发 Web 动态网页,但是随着前后端分离开发模式的流行,Web 页面从服务端渲染逐渐转向客户端渲染,PHP 的优势不再,后端工程师只需要向前端提供 REST API 接口,展示层的实现完全由前端工程师实现。

    +

    早期部分网站选择 .NET 技术栈,比如京东携程。但是,Java 平台生态更完善,有非常多的经验可以借鉴。另外,.NET 平台本身虽然不收费,但是 Windows 操作系统是收费的,开发工具也不便宜。于是京东在 2012 年从 .NET 迁移到 Java,携程在 2017 左右从 .NET 迁移到 Java。目前在国内,多数互联网大厂都选择 Java 技术栈,如淘宝、美团、京东、微博、携程等,Java 相对来说是主流选择。

    +

    编程语言的另外一个流行趋势是 Go 语言。Go 语言诞生于 Google,在 2009 年 11 月对外公开。在发明 Go 语言前,Google 内部主要使用的语言是 C++、Java 和 Python 等,但是 Go 发明者认为这些语言无法同时满足高效编译、高效执行和易于编程的特性诉求,所以创造了 Go 语言[48]。Go 比 C++ 能更高效编译和易于编程,比 Java 更易于编程,比 Python 能更高效执行。在 GoCon Tokyo 2014 会议上,Go 语言研发团队的 Brad Fitzpatrick 对各种编程语言在编程乐趣和执行速度(Fun vs. Fast)的对比[49],如下图所示:

    +编程语言 Fun vs. Fast +

    早期由 Go 语言实现的经典开源项目主要是基础设施软件,比如 YouTube 的 Vitess 数据库分片中间件(2012.02 对外开源)、Docker 容器(2013.03 对外开源)、Red Hat 的 CoreOS 团队的 Etcd 分布式配置服务(2013.07 对外开源,实现 Raft 共识协议)、前 Google 工程师创建的 CockroachDB 分布式数据库(2014.02 对外开源,受 Google Spanner 启发)、Google 的 Kubernetes 容器编排系统(2014.06 对外开源)、SoundCloud 的 Prometheus 监控工具(2015.01 对外开源)等。大规模使用 Go 语言的代表性的国外的互联网公司有 SoundCloud[19:1][20:1]Dropbox[30:1][31:1]Uber[38:1] 等,国内的有七牛云字节跳动[40:1][41:1]哔哩哔哩[12:1]滴滴[16:1]知乎[39:1]百度[50][51]腾讯[52]等,在这些互联网公司 Go 语言通常主要被用于构建基础设施软件(网关、数据存储、监控、视频处理等)或高性能要求的业务服务,部分公司的大量核心业务也从 Python、PHP 等迁移到 Go 语言。使用 Go 语言的公司的更加完整的列表,可以参见官方整理的“GoUsers”。

    +

    数据库选择

    +

    数据库方面,根据 DB-Engines Ranking 的统计,流行的关系数据库主要是 4 个,开源免费的 MySQL 和 PostgreSQL,专有收费的 Oracle 和 Microsoft SQL Server。多数互联网产品使用的数据库是 MySQL,部分是 PostgreSQL 或 Oracle。一些早期使用 Oracle 数据库的网站选择部分或完全从 Oracle 数据库中迁出,代表性的案例是,Amazon 从 Oracle 完全迁移到 Amazon RDS 和 NoSQL,淘宝从 Oracle 完全迁移到 MySQL。以 PostgreSQL 为主数据库的互联网应用有 Skype、Reddit、Spotify、Disqus、Heroku、Instagram 等[53]

    +

    MySQL 相对 PostgreSQL 更加流行的主要原因是[54][55],在早期 MySQL 入门槛更低。MySQL 就支持在 Windows 下安装,而 PostgreSQL 只能在 Cygwin 下安装,MySQL 对 Windows 平台的支持使得初学者更容易上手,并且 MySQL 更加易于管理,能够快速简单地启动和使用,而且 MySQL 拥有一个非常简洁、易于导航和用户友好的在线文档和支持社区。另外一个重要原因是,MySQL 很早就默认支持复制(replication),而 PostgreSQL 的复制是第三方的,而且极其难用。之后的几年即便 PostgreSQL 完善了不足,但错过了流行的时间窗口,MySQL 成为了主流选择,有更完善的生态。不过,受 MySQL 被 Oracle 公司收购的影响,近几年 PostgreSQL 开始越来越流行,根据 DB-Engines Ranking 的统计,最新的 PostgreSQL 的流行度分数是 10 年前的三倍,流行度与前三名越来越接近。

    +

    传统关系数据库,因为在面对大数据量和高负载量时的性能和可扩展性较差,以及对数据模型的支持有限,逐渐演变出了分布式非关系数据库 NoSQL 和分布式关系数据库 NewSQL。NoSQL 数据库的按数据模型分类包括:键值数据库(比如 Redis、DynamoDB 等)、列族数据库(比如 Cassandra、HBase 等)、文档数据库(比如 MongoDB)、图数据库(比如 Neo4j)等。Redis,是内存型键值数据库,是目前缓存场景的主流解决方案。

    +

    技术栈和架构演进

    +

    容易发现多数网站的技术栈的演进模式类似。在创建网站早期通常选择使用 PHP、Ruby、Python 脚本语言和框架来开发,这些脚本语言和框架具有更快的开发效率,能快速交付上线。随着网站流量的增长,面临性能和可扩展性问题,通常会将网站服务化,从单体架构向面向服务的 SOA 和微服务架构演进,一大部分网站在服务化过程中会选择将核心业务改由其他性能更佳的编译型编程语言来实现,如 Java、Scala、C++、Go,原先的脚本语言可能全部废弃,也可能仅用于前端展示层的 Web 动态页面渲染,比如 Facebook、Twitter 等。当然也有一部分网站,演进为 SOA 和微服务架构后,业务逻辑的实现一直以最初的脚本语言为主。

    +

    在架构微服务化后,很多网站实现的微服务之间采用基于 HTTP 协议的 REST 方式通信(或者使用的 RPC 框架支持跨语言 RPC 调用),各个微服务的实现在理论上编程语言不需要统一,可以根据该微服务的性能要求或负责该微服务的团队的技术偏好自由选择,所以真实世界的互联网公司内部各个业务子系统的技术栈可能不统一。但是内部技术栈不统一会带来额外的维护成本。另外,考虑技术栈的迁移重构成本,新的业务子系统使用新的技术栈,而有些旧的业务子系统很可能继续使用旧的技术栈。除了业务子系统外,很可能团队内部有自研的中间件、运维工具等,这些组件由中间件团队、运维团队研发,很可能会选择与业务系统不一样的技术栈。

    +

    注意,解决网站的可扩展性问题,不一定需要演进为服务化架构。架构服务化意味着将完整的单体服务按业务的功能领域做垂直拆分,而实际上在应用服务层可以通过部署多个相同副本的单体服务的方式实现系统的水平扩展,网站的可扩展性问题主要在数据存储层上。拆分应用服务的好处在于能实现组织团队的规模化。解决数据库的扩展性的策略有,数据复制(数据缓存、数据库主从读写分离)、数据垂直拆分、数据水平拆分(也叫数据分片,sharding)。数据库被拆分后,如果单个事务内的数据分散在多个节点就要解决分布式事务问题,但是实现分布式事务代价太大,通常的选择是牺牲一致性,仅满足最终一致性(BASE)。

    +

    没有拆分应用服务,始终采用单体架构的经典案例是 Instagram,2019 年 Instagram 在技术博客上有这样一段话[37:1]

    +
    +

    Our server app is a monolith, one big codebase of several million lines and a few thousand Django endpoints, all loaded up and served together. A few services have been split out of the monolith, but we don’t have any plans to aggressively break it up.

    +
    +

    Instagram 解决可扩展性问题,主要在数据存储层[35:1][36:1]。在 Instagram,PostgreSQL 被用于存储用户信息、媒体元数据、用户关系等数据,照片媒体数据存储在亚马逊 S3 服务上。Instagram 对 PostgreSQL 数据库做了主从读写分离、数据垂直拆分和数据水平分片。另外,Instagram 从 2012 年开始使用 Cassandra 数据库,Cassandra 被用于存储 Feed 流、活动等数据。类似的,Reddit 也是单体架构,在数据存储层做了可扩展性改造[25:1]。对 PostgreSQL 数据库做了主从读写分离和垂直拆分,拆分为四个主数据库,链接、帐户、子版块、评论、投票和杂项,每个主数据库都从数据库。另外,投票数据存储在 Cassandra 数据库。

    +

    Yahoo!(1994)

    +

    Yahoo!,1994 年创立,早期网站操作系统是 FreeBSD,Web 服务器是自研的 Filo Server,数据库是自研的 DBM 文件,Web 动态页面脚本是自研的 yScript,业务逻辑编程语言是 C++。1996 年 Web 服务器改用 Apache HTTP Server,1999 年部分数据库改用 MySQL(同时也使用 Oracle 数据库),2002 年编程语言从 yScript 和 C++ 改为 PHP,操作系统也从 FreeBSD 逐渐转向 Linux[56][57][58]。在 2002.10 的 PHPCon 2002 会议上,Yahoo! 工程师 Michael Radwin 介绍了 Yahoo! 从专有软件向开源软件转向的原因和演进过程,以及选择 PHP 而不选择 ASP、Perl、JSP 等其他技术的原因[56:1]。Yahoo! 转向开源软件的原因主要是,避免维护专有软件的成本,开源软件从早期的不成熟最终变得成熟,具有更好的性能,更容易与第三方软件集成,以及开源社区逐渐发展壮大。2005 年,Yahoo! 的技术架构如下图所示[57:1]

    +Yahoo! 技术架构(2005) +

    2000 年 ~ 2010 年,Yahoo! 是世界上流量最大的网站,虽然期间被 Google 短暂超越,但随后又反超,一直到到 2010 年后才被 Google 彻底超越。2000 年前后 Yahoo! 转向到 MySQL 和 PHP,并在技术上助力 LAMP 生态的发展壮大,对 LAMP 技术栈的流行起到巨大的推动作用。值得一提的是,知名 MySQL 专家 Jeremy Zawodny,《高性能MySQL》2004 年第 1 版(豆瓣)的作者,在 1999.12 ~ 2008.06 期间为 Yahoo! 工程师;PHP 之父 Rasmus Lerdorf 在 2002.09 ~ 2009.11 期间为 Yahoo! 工程师。

    +

    Amazon(1994)

    +

    Amazon,1994 年创立,早期是单服务、单数据库的单体架构,使用的编程语言是 C++,2000 年开始从单体架构向 SOA 和微服务架构演进,使用最多的语言变为 Java,C++ 被用在高性能要求的系统和底层基础设施组件。Amazon 架构演进过程如下图所示[59]

    +Amazon 架构演进 +

    Amazon.com 的技术栈演进过程:

    +
      +
    • 1995 ~ 2000:Unix(Sun)、Obidos、Oracle、C++ +
        +
      • Obidos 是亚马逊内部 Web 动态页面渲染引擎,编程语言是 C++。
      • +
      +
    • +
    • 2000 ~ 2006:Linux、Obidos、Oracle、C++ +
        +
      • 2000 年,开始将 Sun 服务器替换为 HP/Linux 服务器,并同时开始拆分应用服务,向 SOA 架构演进。
      • +
      • 2005 年初,开始将 Obidos 框架替换为 Gurupa 框架,Gurupa 是 Web 页面渲染引擎,同时也是 SOA 框架。Web 动态页面的编程语言从 C++ 替换为 Perl/Mason,同时应用服务开始被更细粒度的拆分。
      • +
      +
    • +
    • 2006 年开始:Linux、Gurupa、Oracle、Perl & Java & C++ +
        +
      • 2019.10,彻底去掉 Oracle 数据库,迁移到 Amazon RDS 和 NoSQL。
      • +
      +
    • +
    +

    当前 Amazon.com 网站的主要技术栈[59:1][60][61][62]

    +
      +
    • 应用服务: +
        +
      • 展示层:Perl/Mason
      • +
      • 业务逻辑层:Java(主要)、C++ 等
      • +
      • RPC框架:Gurupa 框架(自研闭源) +
          +
        • 2006 年更早之前使用 Obidos 框架
        • +
        +
      • +
      • 消息队列MQAmazon SQS
      • +
      +
    • +
    • 数据存储[63]: +
        +
      • 关系数据库:Amazon RDS for PostgreSQL[64]、Amazon Aurora (PostgreSQL) +
          +
        • 2019 年 10 月彻底去掉 Oracle 数据库,迁移到 Amazon RDS 和 NoSQL。
        • +
        +
      • +
      • 键值存储Amazon DynamoDB
      • +
      • 缓存:Amazon ElastiCache for Redis[65]
      • +
      • Blob文件存储Amazon S3
      • +
      +
    • +
    • 数据分析Amazon Kinesis、Amazon EMR、AWS LambdaAmazon Redshift
    • +
    +

    eBay(1995)

    +

    eBay,1995 年创立,早期使用的编程语言是 Perl,1997 年迁移到 C++,2002 年迁移到 Java。eBay 的技术栈演进过程[66][67]

    +
      +
    • 1995 ~ 1997:FreeBSD、Apache、GDBM、Perl
    • +
    • 1997 ~ 2002:Windows、IIS、Oracle、C++ +
        +
      • 1999.02,开始应用服务器池化和水平扩展;数据库服务器垂直扩展(替换为高端服务器 Sun E10000)
      • +
      • 1999.11,开始数据库水平扩展,按功能垂直拆分、数据水平分片。
      • +
      +
    • +
    • 2002 ~ 2006:Windows、IBM WebSphere、Oracle、Java(J2EE) +
        +
      • 2002 年,开始将 C++ 替换为 Java,使用 J2EE 框架
      • +
      +
    • +
    • 2006 年开始:Ubuntu、Tomcat、Oracle、Java(Spring/Spring Boot) +
        +
      • 2007 年初,开始向 SOA 架构演进,再然后演进为微服务架构[68][69]
      • +
      +
    • +
    +

    2016 年,eBay 的技术架构如下图所示[69:1]

    +eBay 技术架构(2016) +

    当前 eBay 的主要技术栈[66:1][67:1][69:2][70]

    +
      +
    • 应用服务: +
        +
      • 展示层:Java、Spring MVC
      • +
      • 业务逻辑层:Java、Spring、Spring Boot
      • +
      • RPC框架:Raptor、Raptor.io(自研闭源,基于 Spring、Spring Boot)
      • +
      • 消息队列MQ:BES (business event stream)(自研闭源)、BES2(自研闭源,基于 Kafka 实现,BES2 API 完全兼容 BES1)[71]
      • +
      +
    • +
    • 数据存储[72]: +
        +
      • 关系数据库:Oracle(主)、MySQL(次)
      • +
      • NoSQL:Apache Cassandra、MongoDB
      • +
      • 搜索引擎:Elasticsearch[73]
      • +
      +
    • +
    • 数据分析[74]:Apache Kafka、Apache Flink、Apache Kylin(自研开源,MOLAP 数仓)、ClickHouse(ROLAP 实时数仓) 等 +
        +
      • Apache Kylin,2014.10 对外开源,2014.11 成为 Apache 孵化器项目,2015.12 从 Apache 孵化器毕业。
      • +
      +
    • +
    +

    淘宝(2003)

    +

    淘宝技术架构[75][76][77][78][79],是从 LAMP 架构演变而来的。在 2003 年 5 月最早上线时,淘宝是对购买得到的采用 LAMP 架构网站源码进行二次开发的网站。为了应对网站流量的增长,2003 年底数据库从 MySQL 切换到 Oracle,2004 年初编程语言从 PHP 迁移到 Java,同时硬件演变为 IBM 小型机和 EMC 高端硬件存储,依赖的基础设施被统称为“IOE”(IBM 小型机、Oracle 数据库、EMC 存储设备),这个架构被称为 2.0 架构。

    +

    2007 年底开始拆分第一个业务中心是用户中心(UIC,User Information Center),在 2008 年初上线。2008 年初,启动“千岛湖”项目,拆分出了交易中心(TC,Trade Center)和类目属性中心(Forest)。2008 年 10 月,为了打通淘宝网和淘宝商城(后来的天猫)的数据,启动“五彩石”项目,拆分出了店铺中心(SC,Shop Center)、商品中心(IC,Item Center)、评价中心(RC,Rate Center)。到 2009 年初,“五彩石”项目结束,阿里电商架构也从之前的单体架构演进为了 SOA 服务化架构,被称为 3.0 架构,同时淘宝网和淘宝商城也完成了数据整合,并淘宝网和淘宝商城的共享业务沉淀到多个业务中心。在 2009 年,共享业务事业部成立,在组织架构上共享业务事业部和淘宝、天猫平级。在业务中心的上层业务服务有,交易管理(TM,Trade Manager)、商品管理(IM,Item Manager)、店铺系统(ShopSystem)、商品详情(Detail)、评价管理(RateManager)等。2009 年淘宝的服务化拆分如下图所示[77:1]

    +淘宝的服务化拆分(2009) +

    在各个应用服务拆分的同时,数据库也按业务功能做了垂直拆分,2008 年 Oracle 被拆分为商品、交易、用户、评价、收藏夹等 10 来套。当时的淘宝的分布式架构设计,包括 Java + Oracle 技术栈的选择,以及应用服务和数据库的拆分策略,很大程度上参考的是 eBay 的架构[75:1][78:1]。对照 eBay 架构师在 2006 年 11 月对外分享的 eBay 架构的 slides[66:2],容易发现两者大同小异。

    +

    因为使用 Oracle 成本太高,2008 年 8 月淘宝数据库设计了异构数据库读写分离架构,写库为集中式的 Oracle,读库使用分库分表的 MySQL,该数据库架构方案基于自研的数据库中间件 TDDL 实现[80]。之后的几年,数据库逐渐向 MySQL 迁移。2008 年 9 月前微软亚洲研究院常务副院长王坚博士加盟阿里巴巴集团,担任首席架构师,2009 年 11 月时任阿里 CTO 的王坚博士决策启动阿里“去IOE”工程。淘宝的“去IOE”工程的关键时点[81]

    +
      +
    • 2009.07,王坚博士开始担任阿里首席技术官 CTO。
    • +
    • 2009.11,王坚博士决策启动阿里“去IOE”工程。
    • +
    • 2010.01,大淘宝核心系统“去IOE”工作启动。
    • +
    • 2010.07,淘宝商品库完成“去I”。
    • +
    • 2011.07,淘宝商品库从 Oracle 迁移到 MySQL,完成“去IOE”。
    • +
    • 2011.09,淘宝交易库从 Oracle 迁移到 MySQL,完成“去IOE”。
    • +
    • 2012.12,完成大淘宝“去IOE”。
    • +
    +

    值得注意的是,在 2011 年淘宝商品库和交易库“去IOE”的同时,为了满足数据库的性能要求,底层硬件从 HDD 机械硬盘改为 SSD 固态硬盘。而庆幸的是,当时的前几年正好是 SSD 大爆发的时间点[82]。在消费级 SSD 市场,2010 年苹果的 MacBook Air 开始全面改用 SSD,2012 年苹果的 MacBook Pro 开始全面改用 SSD。在数据库服务器层面,因为 SSD 在随机读写的性能具有巨大优势,2010 年开始机械硬盘改用 SSD 成为趋势,当时的 MySQL 新版代码也专门针对 SSD 做了性能优化[83]

    +

    2009 年初淘宝演变为 SOA 架构后,服务拆分粒度越来越细,到 2009 年底拆分出的总服务数达到 187 个,到 2010 年底达到 329 个[77:2]。因为系统依赖关系越来越复杂,当时最大问题是稳定性问题,系统的稳定性建设成为重点工作。到 2013 年阿里电商系统开始 4.0 架构改造,即异地多活架构改造,内部称为单元化项目。2013 年 8 月完成杭州同城双活,2014 年双 11 前的 10 月完成杭州和上海近距离两个单元的异地双活,2015 年双 11 完成三地四单元的异地多活[76:1][79:1],至此也完成了 3.0 到 4.0 架构的升级。在阿里电商系统迁移到阿里云公共云方面,2015 年阿里电商系统开始采用混合云弹性架构,当阿里本地保有云无法支撑时,就快速在公有云上扩建新的单元,当流量过去后,再还资源给公有云。2015 年 10% 的双 11 大促流量使用了阿里云的机器来支撑,2016 年 50% 以上的双 11 大促流量使用了阿里云的机器来支撑[76:2]。2019 年初,阿里电商开启了全面上公共云的改造,到 2019 年双 11,阿里电商系统实现了全部核心应用上公共云,2021 年双 11,阿里电商系统实现了 100% 上公共云。

    +

    当前阿里电商系统(淘宝、天猫等)的主要技术栈[78:2][79:2]

    +
      +
    • 应用服务: +
        +
      • 展示层:Java
      • +
      • 业务逻辑:Java、Spring、Spring Boot 等
      • +
      • RPC框架:HSF(2008 自研闭源)、Apache Dubbo(2008 自研,2011.10 对外开源)
      • +
      • 消息队列MQApache RocketMQ(自研,2013.09 对外开源) +
          +
        • 2007 年自研 Notify;2011 年自研 MetaQ;2013.09,对外开源发布 RocketMQ 3.0。RocketMQ 3.0 和 MetaQ 3.0 等价,阿里内部使用的称为 MetaQ 3.0,外部开源称之为 RocketMQ 3.0。
        • +
        +
      • +
      • 链路追踪:鹰眼 EagleEye(2012 自研闭源) +
          +
        • 2012 年内部发布鹰眼 1.0,参考 Google 2010 年的 Dapper 论文
        • +
        +
      • +
      • 注册和配置服务:ConfigServer(2008 自研闭源)、Nacos(自研,2018.07 对外开源) +
          +
        • 2008 年,淘宝团队内部自研 ConfigServer 并发布 1.0,被用于 HSF 的服务发现。2018.07,Nacos 对外开源,是 ConfigServer 的开源实现,在阿里内部 Nacos 被用在钉钉、考拉、饿了么、优酷等业务线。
        • +
        +
      • +
      +
    • +
    • 数据存储: +
        +
      • 关系数据库:MySQL (阿里云 RDS,底层基于 MySQL 自研 AliSQL)、自研 TDDL 中间件、阿里云分布式式数据库 PolarDB-X、MySQL 的 X-Engine 存储引擎 +
          +
        • 2008 年,淘宝团队内部自研 TDDL 中间件,用于实现数据库的读写分离、分库分表。
        • +
        • 2014 年,淘宝 TDDL 团队和阿里云 RDS 团队合作,在阿里云上输出产品分布式数据库服务 DRDS,2014.06 DRDS 开始公测,2014.12 正式上线。DRDS 脱胎于阿里 B2B 团队开源的 Cobar 分布式数据库引擎(2012.06 对外开源),同时借鉴了淘宝 TDDL 丰富的分布式数据库实践经验。
        • +
        • 2020 年,阿里云发布分布式式数据库 PolarDB-X,融合了分布式 SQL 引擎 DRDS 与分布式自研存储 X-DB(X-Cluster)。
        • +
        • MySQL 的 X-Engine 存储引擎,早期代码源自 Facebook 的 RocksDB 4.8.1(2016.07 发布),被应用在阿里的交易历史库、钉钉历史库等核心系统。
        • +
        +
      • +
      • 缓存Tair(2009 自研,2010.06 对外开源,分布式键值存储,支持基于内存和文件的两种存储方式) +
          +
        • 2009.04,Tair 1.0 正式诞生,并被应用于淘宝核心系统、MDB缓存、用户中心等业务。
        • +
        • 2010.06,Tair 对外开源。
        • +
        • 2014.05,阿里云推出基于 Tair 的缓存产品 OCS。
        • +
        • 2019.11,阿里云发布 Redis 企业版,即 Tair 3.0,兼容 Redis 5.0。
        • +
        +
      • +
      • 列族数据库:Apache HBase,为淘宝推荐、手淘消息等提供支撑的数据库 +
          +
        • 早期淘宝交易订单的所有数据都存储在单独的 Oracle 数据库;2010 年拆分为在线库和历史库,三个月之前的历史订单迁移进单独的 Oracle 历史库;2011 年交易历史库整体迁移到 HBase;2018 年历史库迁移到基于 X-Engine 存储引擎的 PolarDB-X 集群[84]
        • +
        +
      • +
      • 搜索引擎:Havenask(自研,2022.12 对外开源) +
          +
        • 支持了淘宝、天猫、菜鸟、优酷、高德、饿了么等在内整个阿里的搜索业务。阿里云的 OpenSearch 产品底层基于 Havenask 实现。
        • +
        +
      • +
      • Blob文件存储:阿里云 OSS +
          +
        • 早期采用 NetApp 提供的 NAS 存储设备;2007.06 开始基于自研的 TFS(Taobao File System);2010.09 对外开源 TFS;2016 迁移到阿里云 OSS[85]
        • +
        +
      • +
      +
    • +
    • 数据分析:阿里云 Flink、阿里云 MaxCompute(离线数仓)、阿里云 Hologres(实时数仓)等 +
        +
      • 早期阿里内部三大实时计算引擎并存,Galaxy、JStorm、Blink(Apache Flink 的分支),2017 年开始统一到 Blink。2019.01,阿里收购 Apache Flink 母公司 Data Artisans,随后阿里的 Blink 正式开源,之后 Blink 和 Flink 完成合并。2021 年开始,阿里内部的实时计算使用的是 Blink 团队与 Flink 创始团队联合打造了 Flink 企业版平台,即 VVP(Ververica Platform)。
      • +
      +
    • +
    +

    2016 年,阿里产品专家倪超对外介绍的阿里电商技术架构,如下图所示[86]

    +阿里电商技术架构(2016) +

    类似的,阿里巴巴中间件首席架构师《企业IT架构转型之道》(豆瓣)作者钟华在 2017 年对外介绍的阿里电商技术架构图[87]

    +阿里电商中台架构(2017) +

    2017 年,阿里中间件技术部专家谢吉宝对外介绍的阿里中间件技术大图[79:3]

    +阿里中间件技术大图(2017) +

    阿里 HSF 与 Dubbo 的历史演进时间线:

    +
      +
    • 2008 年,阿里淘宝团队自研 HSF 框架,5 月发布 HSF 1.1。
    • +
    • 2009 年初,由阿里 B2B 团队研发的 Dubbo 发布 1.0 版本。阿里内部淘系(淘宝、天猫、一淘等)主要使用的服务框架是 HSF,而阿里 B2B 使用的则是 Dubbo,二者独立,各行其道,彼此不通[88]
    • +
    • 2010.04,重构后发布 Dubbo 2.0 版本。
    • +
    • 2011.10,Dubbo 对外开源,版本为 2.0.7。因为在功能完善性、架构优雅性、使用简便性等方面有其相对独特的优势,开源后被国内很多互联网公司广泛使用[89],包括去哪儿,京东、当当网、网易考拉、有赞等。
    • +
    • 2012 年,阿里内部架构调整,开始统一技术基础设施,合并重复项目,决定把 Dubbo 合并到 HSF 里面去[90]。随后,HSF 发布 2.0 的版本,兼容 Dubbo 的协议,HSF 推出后很快就在阿里集团全面铺开[88:1]。Dubbo 项目在阿里内部被抛弃,在 2012.10 发布 2.5.3 版本之后就停止更新,2013 年和 2014 年更新了 2 次 Dubbo 2.4 的维护版本,然后停止了所有维护工作。
    • +
    • 2014.10,当当网开源 Dubbox,基于 Dubbo 2.5.3 的代码,为 Dubbo 新增了 REST 风格远程调用、Kryo/FST 序列化等特性。
    • +
    • 2016.01,阿里云互联网中间件产品 EDAS 正式商用,EDAS 所提供的分布式服务框架源自阿里的 HSF。
    • +
    • 2017.09,Dubbo 重启维护,对外发布恢复维护后的第一个版本是 2.5.4。之所以重启是因为阿里云上的客户大部分使用 Dubbo,阿里云想要将基于 Dubbo 的解决方案作为自己的一个产品,卖给这些客户[88:2][90:1]
    • +
    • 2018.01,Dubbo 2.6.0 发布,合并了当当网提供的 Dubbox 分支。
    • +
    • 2018.02,阿里宣布将 Dubbo 捐献给 Apache,进入 Apache 孵化器。
    • +
    • 2018.11,阿里云 EDAS 产品版本升级,新版本实现 SpringCloud 和 Dubbo 用户代码零侵入就能迁移至 EDAS。
    • +
    • 2018.12,Dubbo 3.0 正式进入开发阶段,Dubbo 3.0 是 HSF 与 Dubbo 的融合版本。
    • +
    • 2019.01,Dubbo 2.7.0 发布,包名切换到 org.apache,全面拥抱 Java 8。
    • +
    • 2019.05,Dubbo 从 Apache 毕业,成为 Apache 的顶级项目。
    • +
    • 2020 年,在双十一前在阿里内部率先由阿里考拉实现了 Dubbo 3.0 的全面部署。
    • +
    • 2021.06,Dubbo 3.0 正式发布。
    • +
    • 2022 年,阿里集团几乎所有的业务线(包括淘宝、天猫、饿了么、钉钉等)全面从 HSF2 迁移到 Dubbo3。阿里内部使用的是 HSF3,HSF3 与以往的 HSF2 完全不同,HSF3 完全就是基于标准 Dubbo3 的 SPI 扩展库[91][92]
    • +
    +

    阿里 RocketMQ 的历史演进时间线:

    +
      +
    • 2007,自研 Notify,最早底层的消息存储采用本地文件存储,参考 ActiveMQ 实现了单机 kv 存储引擎,2008 年底层的消息存储改用 Oracle,2010 年从 Oracle 迁移到高可用 MySQL 存储集群[93]
    • +
    • 2011.01,基于 Kafka 的设计用 Java 完全重写并发布 MetaQ 1.0。
    • +
    • 2012.03,MetaQ 1.x 对外开源,项目名为 Metamorphosis
    • +
    • 2012.09,淘宝内部发布 MetaQ 2.0 版本,MetaQ 2.0 对架构进行了重新设计,对消息日志文件存储目录结构做了改造[94]。改造后的 MetaQ 架构与 Kafka 存在很大差异,这个版本的 MetaQ 可以认为是第一代的 RocketMQ。
    • +
    • 2013.07,淘宝内部发布 MetaQ 3.0 版本,增加了主从复制(replication)、延迟消息等特性。 +
        +
      • 值得注意的是,Kafka 的复制特性,直到 2013.12 发布的 0.8.0 版本才开始支持。MetaQ 实现的复制特性类似与 MySQL 的主从复制,而 Kafka 实现的复制是集群间的分区复制(Intra-cluster Replication),复制的单位是分区(partition),参见 KAFKA-50。分区,在其他系统中也被叫做分片(shard),含义相同。
      • +
      +
    • +
    • 2013.09,对外开源发布 RocketMQ 3.0。RocketMQ 3.0 和 MetaQ 3.0 等价,阿里内部使用的称为 MetaQ 3.0,外部开源称之为 RocketMQ 3.0[95]
    • +
    • 2014.10,阿里云消息队列 ONS(云开放消息服务,Open Notification Service)对外公测,ONS 是基于阿里消息中间件 MetaQ(RocketMQ)打造的云消息产品。
    • +
    • 2016.11,阿里巴巴将 RocketMQ 捐赠给 Apache,成为 Apache 孵化器项目。
    • +
    • 2017.09,RocketMQ 从孵化器毕业,正式成为 Apache 顶级项目。
    • +
    +

    LinkedIn(2003)

    +

    LinkedIn,2003 年创立,采用纯 Java 技术栈,早期是单体架构,到 2008 年演化为 SOA 架构[96]。到 2010 年拆分的服务数超过 150 个,到 2015 年拆分的服务数超过 750 个[97]

    +

    2008 年,LinkedIn 对外介绍的技术架构如下图所示[96:1]

    +LinkedIn 技术架构(2008) +

    2012 年,LinkedIn 对外介绍的关注在数据基础设施上的技术架构图[98]

    +LinkedIn 数据基础设施架构(2012) +

    当前 LinkedIn 的主要技术栈[96:2][97:1]

    +
      +
    • 应用服务: +
        +
      • 展示层:Java、Spring MVC、
      • +
      • 业务逻辑层:Java、Spring
      • +
      • RPC框架: +
          +
        • Rest.li(自研开源),REST + JSON 框架。2023.04,对外宣布 Rest.li 项目不再活跃,为了提升性能,迁移到 Protobuf + gRPC。
        • +
        +
      • +
      • 消息队列MQ:ActiveMQ
      • +
      +
    • +
    • 数据存储[98:1][99][100]: +
        +
      • 关系数据库:Oracle(主)、MySQL(次)
      • +
      • 缓存:Memcached
      • +
      • 键值存储Voldemort(自研,2009.01 对外开源) +
          +
        • 2009.01 对外开源,设计受 Amazon Dynamo 论文影响。2018 年之后 LinkedIn 不在使用 Voldemort,数据迁移到 LinkedIn 的 Venice 数据库
        • +
        +
      • +
      • 文档数据库Espresso(自研闭源),分布式文档数据库 +
          +
        • 2011 年初开始计划和设计,2012.06 在生产环境部署,底层实现基于 MySQL、Lucene、ZooKeeper。
        • +
        +
      • +
      • 图数据库:LIquid(自研闭源)
      • +
      • 搜索引擎:基于 Lucene
      • +
      • Blob文件存储Ambry(自研,2016.05 对外开源)
      • +
      +
    • +
    • 数据分析[98:2][99:1][100:1]: +
        +
      • 数据采集: +
          +
        • Databus(自研,2013.02 对外开源) +
            +
          • 数据变更抓取 CDC 工具,支持 Oracle 和 MySQL,2012.10 在 SoCC 2012 会议上发表论文,2013.02 对外开源。
          • +
          +
        • +
        • Apache Kafka(自研,2011.01 对外开源) +
            +
          • 2011.07 成为 Apache 孵化器项目,2012.10 从 Apache 孵化器毕业
          • +
          +
        • +
        +
      • +
      • 计算引擎:Apache Hadoop、Apache Samza(自研开源)、Apache Spark、Apache Flink +
          +
        • Apache Samza,2013.09 对外开源,2015.01 从 Apache 孵化器毕业
        • +
        +
      • +
      • 数据仓库:Apache Hive、Presto、Venice
      • +
      +
    • +
    +

    Facebook(2004)

    +

    Facebook,2004 年创立,早期采用 LAMP 技术栈,为了应对负载增长开始服务化,将核心业务从 LAMP 中移出到新的服务,新的服务改用使用 C++、Java 等编写。为了解决 PHP 进程与非 PHP 进程的 RPC 通信问题,2006 年内部研发了跨语言的 RPC 库 Thrift,2007.04 对外开源。PHP 代码用于实现前端展示层的 Web 动态页面渲染,以及对服务层的数据聚合。

    +

    2010 年,Facebook 工程师 Aditya Agarwal 对外介绍的 Facebook 技术架构如下图所示[101]

    +Facebook 技术架构(2010) +

    Facebook 的技术栈图[102]

    +Facebook 技术架构(2008) +

    Facebook 的 NewsFeed 服务的架构图[102:1]

    +Facebook NewsFeed 技术架构(2008) +

    Facebook 的 Search 服务的架构图[102:2]

    +Facebook Search 技术架构(2008) +

    当前 Facebook 的主要技术栈[101:1][102:3][103]

    +
      +
    • 应用服务: +
        +
      • 展示层:PHP(早期采用 LAMP 技术栈)、HHVM2011.12 对外开源)、Hack(2014.03 对外发布)
      • +
      • 业务逻辑层:Hack、C++(主要用于实现性能敏感服务,包括 Ads、News Feed、Search 等)、Rust、Java 等[104][105]
      • +
      • RPC框架Apache Thrift(自研开源) +
          +
        • 2005 年末开始研发;2007.04 对外开源;2008.05 成为 Apache 孵化器项目;2010.10 从 Apache 孵化器毕业。
        • +
        +
      • +
      • 消息队列MQ:Wormhole(自研闭源) +
          +
        • 2013.06 对外介绍;2015.05 在 NSDI 2015 会议上发表论文。Wormhole 是发布-订阅系统,消息发布者直接读取数据存储系统的写事务日志,投递给对消息感兴趣的订阅者,订阅者可能是 News Feed、Cache、Index Servers 等。
        • +
        +
      • +
      +
    • +
    • 数据存储: +
        +
      • 关系数据库:MySQL、MySQL 存储引擎 MyRocks(自研,2015.11 对外开源) +
          +
        • RocksDB 是 Facebook 在 2012.04 创建的内嵌的键值数据库,基于 Google 开源的 LevelDB 代码。
        • +
        • MyRocks 是 Facebook 基于 RocksDB 数据库实现的 MySQL 存储引擎,2014 年开始研究 RocksDB 和 MySQL 的集成,2015.11 对外开源,在 2016.04 在 Percona Live 2016 会议上最早对外介绍。
        • +
        • 2017.08,Facebook 将 UDB 数据库(User Database,存储社交活动数据)从 InnoDB 完全迁移到了 MyRocks,迁移后存储空间使用量减少了一半,而 CPU 和 IO 使用率没有明显变化。
        • +
        • 2018.06,Facebook 在博客上对外介绍已经将 Messenger 应用的数据从 HBase 迁移到了 MyRocks,迁移后存储空间使用量减少 90%,读取延迟比以前的系统低 50 倍。值得注意的是,Messenger 应用的数据最早存储在 Facebook 自研的 Cassandra 上,2010 年底发布新版的 Messenger 开始,改为存储在 HBase 上。
        • +
        +
      • +
      • 键值存储ZippyDB(自研闭源),基于 RocksDB 实现的分布式键值数据库,2013 年开始在 Facebook 部署使用
      • +
      • 缓存Mcrouter(自研开源),实现分布式扩展的 Memcached +
          +
        • Facebook 早在 2005.04 就已经开始使用 Memcached;2013.04NSDI 2013 会议上发表论文,描述对 Memcached 的分布式扩展性改造。
        • +
        +
      • +
      • 图数据库TAO(自研闭源),底层是 Memcache 和 MySQL
      • +
      • 搜索引擎Unicorn(自研闭源),基于标准的搜索引擎的概念,但增加了社交图谱搜索的特性。Facebook 搜索功能(包括 Facebook Graph Search 产品)底层实现基于 Unicorn。 +
          +
        • 2013.03 Facebook Graph Search 产品对外推出,2014.12 开始原始的图谱搜索公开可见度降低,2019.06 几乎完全弃用。
        • +
        • 2015 年初,Instagram 的搜索引擎从 Elasticsearch 迁移到 Unicorn[106]
        • +
        +
      • +
      • Blob文件存储:Haystack(自研闭源) +
          +
        • 2009.04 对外介绍;2010.10 在 OSDI 2010 会议上发表论文。基于 Haystack 论文的开源实现包括:SeaweedFS、bilibili 的 BFS 等。
        • +
        +
      • +
      +
    • +
    • 数据分析[107][108]: +
        +
      • 日志采集Scribe(自研,2008.10 对外开源)
      • +
      • 计算引擎:XStream(Puma、Stylus、Swift)
      • +
      • 数据仓库Apache Hive(自研,2008.08 对外开源)、Presto(自研,2013.11 对外开源)、Laser、Scuba
      • +
      +
    • +
    +

    Twitter(2006)

    +

    Twitter,2006 年创立,早期采用 Ruby on Rails 技术栈,数据库是 MySQL,2009 年开始服务化,将核心业务从 Ruby on Rails 中移出到新的服务,新的服务用 Scala、Java 编写[109][110]

    +

    2013 年,Twitter 工程师总结的 Twitter 从单体架构向分布式架构演进的过程,如下图所示[110:1]

    +Twitter 单体架构 +Twitter 服务化架构(2013) +

    当前 Twitter 的主要技术栈[109:1][110:2]

    +
      +
    • 应用服务: +
        +
      • 展示层:Ruby on Rails
      • +
      • 业务逻辑层:Scala(主要)、Java
      • +
      • RPC框架Finagle(自研,2011.08 对外开源) +
          +
        • 使用 Finagle 框架的公司包括:Foursquare(2010 PHP 转向 Scala)、Pinterest(Python + Java)、SoundCloud(Ruby + JVM)、Tumblr(PHP + Scala) 等。
        • +
        +
      • +
      • 消息队列MQ:Kestrel(2008.11 对外开源) -> DistributedLog -> Kafka
      • +
      • 链路追踪Zipkin(自研开源) +
          +
        • 2012.06,对外开源,是 Google Dapper 链路追踪系统的开源实现。
        • +
        • 2015 年中,项目从 Twitter 转交到 OpenZipkin 开源组织。
        • +
        +
      • +
      +
    • +
    • 数据存储[111]: +
        +
      • 关系数据库:MySQL、Manhattan(自研闭源,基于 MySQL 的分布式数据库) +
          +
        • 最初所有数据都存储在 MySQL 上。
        • +
        • 2009 年底,计划从 MySQL 迁移到 Cassandra,打算用 Cassandra 存储推文 Tweets 数据,但最终改变了策略,继续使用 MySQL,Cassandra 仅被用于存储分析数据[112]
        • +
        • 2010.04,对外开源数据库分片框架 Gizzard,基于 Gizzard 的分布式数据库 T-bird 被用于存储推文 Tweets 数据[113]
        • +
        • 2014.04,对外介绍自研的基于 MySQL 的分布式数据库 Manhattan,被用于存储推文 Tweets 等主要数据,Cassandra 被废弃。
        • +
        • 2018 年中,开始将 Manhattan 底层使用的 MhBtree 存储引擎改为基于 RocksDB 存储引擎。
        • +
        +
      • +
      • 缓存和键值存储:Redis、Memcached
      • +
      • 图数据库FlockDB(自研开源)
      • +
      • 搜索引擎:Earlybird[114](自研闭源)、Elasticsearch[115],用于推文 Tweets、用户、消息等搜索 +
          +
        • 2010 年,自研基于 Lucene 实现的 Earlybird 搜索引擎,替代旧的基于 MySQL 实现的搜索[114:1]
        • +
        +
      • +
      • Blob文件存储:Blobstore(自研闭源) + +
      • +
      +
    • +
    • 数据分析[116]:Kafka、Cloud BigTable、Cloud BigQuery 等
    • +
    +

    参考资料

    +
    +
    +
      +
    1. 2007 Jeff Dean: Software Engineering Advice from Building Large-Scale Distributed Systems (Stanford CS295 class lecture, Spring, 2007) https://research.google.com/people/jeff/stanford-295-talk.pdf ↩︎

      +
    2. +
    3. 2008-11 Google Architecture http://highscalability.com/blog/2008/11/22/google-architecture.html ↩︎

      +
    4. +
    5. 2008-06 新浪夏清然、徐继哲:自由软件和新浪网. 程序员 2008年第6期54-55 http://lib.cqvip.com/Qikan/Article/Detail?id=27523653 http://www.zeuux.com/blog/content/3620/ ↩︎

      +
    6. +
    7. 2016-01 微信张文瑞:从无到有:微信后台系统的演进之路 https://www.infoq.cn/article/the-road-of-the-growth-weixin-background ↩︎

      +
    8. +
    9. 2008-02 Yandex Architecture http://highscalability.com/yandex-architecture ↩︎

      +
    10. +
    11. 2007-08 Wikimedia architecture http://highscalability.com/wikimedia-architecture ↩︎

      +
    12. +
    13. 2007-11 Flickr Architecture http://highscalability.com/flickr-architecture ↩︎

      +
    14. +
    15. 2016-03 What does Etsy's architecture look like today? http://highscalability.com/blog/2016/3/23/what-does-etsys-architecture-look-like-today.html ↩︎

      +
    16. +
    17. 2011-05 新浪刘晓震:新浪博客应用架构分享 (PHPChina 2011) https://web.archive.org/web/0/http://www.phpchina.com/?action-viewnews-itemid-38418 https://www.modb.pro/doc/121035 ↩︎

      +
    18. +
    19. 2013-11 百度张东进:百度PHP基础设施构建思路 (QCon上海2013, slides, 30p) https://www.modb.pro/doc/121042 ↩︎

      +
    20. +
    21. 2013-05 The Tumblr Architecture Yahoo Bought for a Cool Billion Dollars http://highscalability.com/blog/2013/5/20/the-tumblr-architecture-yahoo-bought-for-a-cool-billion-doll.html ↩︎

      +
    22. +
    23. 2017-06 B站任伟:B站高性能微服务架构 https://zhuanlan.zhihu.com/p/33247332 ↩︎ ↩︎

      +
    24. +
    25. 2021-05 微博刘道儒:十年三次重大架构升级,微博应对“极端热点”的进阶之路 https://www.infoq.cn/article/qgwbh0wz5bvw9apjos2a ↩︎

      +
    26. +
    27. 2012-08 腾讯张松国:腾讯微博架构介绍 (ArchSummit深圳2012, slides, 59p) https://www.slideshare.net/dleyanlin/08-13994311 ↩︎

      +
    28. +
    29. 2016-02 美团夏华夏:从技术细节看美团架构 (ArchSummit北京2014) https://www.infoq.cn/article/see-meituan-architecture-from-technical-details http://bj2014.archsummit.com/node/596/ https://www.modb.pro/doc/8311 ↩︎

      +
    30. +
    31. 2019-06 滴滴杜欢:大型微服务框架设计实践 (Gopher China 2019) https://www.infoq.cn/article/EfOlY8_rubh4LfoXzF8B https://www.modb.pro/doc/35485 ↩︎ ↩︎

      +
    32. +
    33. 2018-08 E-Commerce at Scale: Inside Shopify's Tech Stack - Stackshare.io https://shopify.engineering/e-commerce-at-scale-inside-shopifys-tech-stack ↩︎

      +
    34. +
    35. 2013-03 Phil Calçado @ SoundCloud: From a monolithic Ruby on Rails app to the JVM (slides, 75p) https://www.slideshare.net/pcalcado/from-a-monolithic-ruby-on-rails-app-to-the-jvm ↩︎

      +
    36. +
    37. 2012-07 Go at SoundCloud https://developers.soundcloud.com/blog/go-at-soundcloud ↩︎ ↩︎

      +
    38. +
    39. 2014-04 Peter Bourgon @ SoundCloud: Go: Best Practices for Production Environments (GopherCon 2014) http://peter.bourgon.org/go-in-production/ ↩︎ ↩︎

      +
    40. +
    41. 2009-04 Heroku - Simultaneously Develop and Deploy Automatically Scalable Rails Applications in the Cloud http://highscalability.com/blog/2009/4/24/heroku-simultaneously-develop-and-deploy-automatically-scala.html ↩︎

      +
    42. +
    43. 2021-07 GitHub’s Journey from Monolith to Microservices https://www.infoq.com/articles/github-monolith-microservices/ ↩︎

      +
    44. +
    45. 2017-12 Building Services at Airbnb, Part 1 https://medium.com/airbnb-engineering/c4c1d8fa811b ↩︎

      +
    46. +
    47. 2020-11 Jessica Tai @ Airbnb: How to Tame Your Service APIs: Evolving Airbnb’s Architecture https://www.infoq.com/presentations/airbnb-api-architecture/ ↩︎

      +
    48. +
    49. 2013-08 Reddit: Lessons Learned from Mistakes Made Scaling to 1 Billion Pageviews a Month http://highscalability.com/blog/2013/8/26/reddit-lessons-learned-from-mistakes-made-scaling-to-1-billi.html ↩︎ ↩︎

      +
    50. +
    51. 2012-03 7 Years of YouTube Scalability Lessons in 30 Minutes http://highscalability.com/blog/2012/3/26/7-years-of-youtube-scalability-lessons-in-30-minutes.html ↩︎

      +
    52. +
    53. 2016-04 豆瓣田忠博:豆瓣的服务化体系改造 (QCon北京2016, slides, 37p) http://2016.qconbeijing.com/presentation/2834/ ↩︎

      +
    54. +
    55. 2010-09 Disqus: Scaling the World's Largest Django App (DjangoCon 2010, slides) https://www.slideshare.net/zeeg/djangocon-2010-scaling-disqus ↩︎

      +
    56. +
    57. 2021-05 Dropbox: Atlas: Our journey from a Python monolith to a managed platform https://dropbox.tech/infrastructure/atlas--our-journey-from-a-python-monolith-to-a-managed-platform ↩︎

      +
    58. +
    59. 2014-07 Dropbox: Open Sourcing Our Go Libraries https://dropbox.tech/infrastructure/open-sourcing-our-go-libraries ↩︎ ↩︎

      +
    60. +
    61. 2017-07 Tammy Butow @ Dropbox: Go Reliability and Durability at Dropbox https://about.sourcegraph.com/blog/go/go-reliability-and-durability-at-dropbox-tammy-butow ↩︎ ↩︎

      +
    62. +
    63. 2011-02 Adam D'Angelo: Why did Quora choose C++ over C for its high performance services? Does the Quora codebase use a limited subset of C++? https://qr.ae/pKwCE3 ↩︎

      +
    64. +
    65. 2012-02 A Short on the Pinterest Stack for Handling 3+ Million Users http://highscalability.com/blog/2012/2/16/a-short-on-the-pinterest-stack-for-handling-3-million-users.html ↩︎

      +
    66. +
    67. 2015-08 Finagle and Java Service Framework at Pinterest (slides) https://www.slideshare.net/yongshengwu/finaglecon2015pinterest ↩︎

      +
    68. +
    69. 2013-03 Instagram 5位传奇工程师背后的技术揭秘 https://web.archive.org/web/0/http://www.csdn.net/article/2013-03-28/2814698-The-technologie- behind-Instagram ↩︎ ↩︎

      +
    70. +
    71. 2017-03 Lisa Guo: Scaling Instagram Infrastructure(QCon London 2017, 87p) https://www.infoq.com/presentations/instagram-scale-infrastructure/ ↩︎ ↩︎

      +
    72. +
    73. 2019-08 Static Analysis at Scale: An Instagram Story https://instagram-engineering.com/8f498ab71a0c ↩︎ ↩︎

      +
    74. +
    75. 2016-07 The Uber Engineering Tech Stack, Part I: The Foundation https://web.archive.org/web/0/https://eng.uber.com/tech-stack-part-one/ ↩︎ ↩︎

      +
    76. +
    77. 2018-11 知乎社区核心业务 Golang 化实践 https://zhuanlan.zhihu.com/p/48039838 ↩︎ ↩︎

      +
    78. +
    79. 2022-10 字节马春辉:字节大规模微服务语言发展之路 https://www.infoq.cn/article/n5hkjwfx1gxklkh8iham ↩︎ ↩︎

      +
    80. +
    81. 2021-07 字节成国柱:字节跳动微服务架构体系演进 https://mp.weixin.qq.com/s/1dgCQXpeufgMTMq_32YKuQ ↩︎ ↩︎

      +
    82. +
    83. Why does Google use Java instead of Python for Gmail? https://qr.ae/pKkduC ↩︎

      +
    84. +
    85. 2011-07 揭秘Google+技术架构 http://www.infoq.com/cn/news/2011/07/Google-Plus ↩︎

      +
    86. +
    87. 2009-12 人人网架构师张洁:人人网使用的开源软件列表 https://web.archive.org/web/0/http://ugc.renren.com/2009/12/13/a-list-of-open-source-software-in-renren ↩︎

      +
    88. +
    89. 2018-12 Netflix OSS and Spring Boot — Coming Full Circle https://netflixtechblog.com/4855947713a0 ↩︎

      +
    90. +
    91. 携程为什么突然技术转型从 .NET 转 Java? https://www.zhihu.com/question/56259195 ↩︎

      +
    92. +
    93. 京东技术解密,2014,豆瓣:12 少年派的奇幻漂流——从.Net到Java ↩︎

      +
    94. +
    95. Golang Frequently Asked Questions: Why did you create a new language? https://go.dev/doc/faq#creating_a_new_language ↩︎

      +
    96. +
    97. 2014-05 Brad Fitzpatrick: Go: 90% Perfect, 100% of the time: Fun vs. Fast https://go.dev/talks/2014/gocon-tokyo.slide#28 ↩︎

      +
    98. +
    99. 2021-08 百度Geek说:短视频go研发框架实践 https://my.oschina.net/u/4939618/blog/5191598 ↩︎

      +
    100. +
    101. 2023-07 百度Geek说:从 php5.6 到 golang1.19 - 文库 App 性能跃迁之路 https://my.oschina.net/u/4939618/blog/10086661 ↩︎

      +
    102. +
    103. 2022-03 2021年,腾讯研发人员增长41%,Go首次超越C++成为最热门语言 https://mp.weixin.qq.com/s/zj-DhASG4S-3z56GTYjisg ↩︎

      +
    104. +
    105. 2020-05 Which Major Companies Use PostgreSQL? What Do They Use It for? https://learnsql.com/blog/companies-that-use-postgresql-in-business/ ↩︎

      +
    106. +
    107. 2009-05 Why is MySQL more popular than PostgreSQL? https://news.ycombinator.com/item?id=619871 ↩︎

      +
    108. +
    109. Why is MySQL more popular than PostgreSQL? https://qr.ae/pKPJcE ↩︎

      +
    110. +
    111. 2002-10 Michael Radwin: Making the Case for PHP at Yahoo! (PHPCon 2002, slides) https://web.archive.org/web/0/http://www.php-con.com/2002/view/session.php?s=1012 https://speakerdeck.com/yulewei/making-the-case-for-php-at-yahoo ↩︎ ↩︎

      +
    112. +
    113. 2005-10 Michael Radwin: PHP at Yahoo! (PHP Conference 2005, slides) https://speakerdeck.com/yulewei/php-at-yahoo-zend2005 ↩︎ ↩︎

      +
    114. +
    115. 2007-06 Federico Feroldi: PHP in Yahoo! (slides) https://www.slideshare.net/fullo/federico-feroldi-php-in-yahoo ↩︎

      +
    116. +
    117. 2021-02 AWS re:Invent 2020: Amazon.com’s architecture evolution and AWS strategy https://www.youtube.com/watch?v=HtWKZSLLYTE ↩︎ ↩︎

      +
    118. +
    119. What programming languages are used at Amazon? https://qr.ae/pKFwnw ↩︎

      +
    120. +
    121. 2011-04 Charlie Cheever: How did Google, Amazon, and the like initially develop and code their websites, databases, etc.? https://qr.ae/pKKyB0 ↩︎

      +
    122. +
    123. 2016-04 Is Amazon still using Perl Mason to render its content? https://qr.ae/pKFwFm ↩︎

      +
    124. +
    125. 2019-10 Migration Complete – Amazon’s Consumer Business Just Turned off its Final Oracle Database https://aws.amazon.com/blogs/aws/migration-complete-amazons-consumer-business-just-turned-off-its-final-oracle-database/?nc1=h_ls ↩︎

      +
    126. +
    127. Amazon RDS for PostgreSQL customers https://aws.amazon.com/rds/postgresql/customers/?nc1=h_ls ↩︎

      +
    128. +
    129. Amazon ElastiCache for Redis customers https://aws.amazon.com/elasticache/redis/customers/?nc1=h_ls ↩︎

      +
    130. +
    131. 2006-11 Randy Shoup & Dan Pritchett: The eBay Architecture (SDForum2006, slides, 37p) http://www.addsimplicity.com/downloads/eBaySDForum2006-11-29.pdf ↩︎ ↩︎ ↩︎

      +
    132. +
    133. 2007-05 eBay Architecture http://highscalability.com/blog/2008/5/27/ebay-architecture.html ↩︎ ↩︎

      +
    134. +
    135. 2011-10 Tony Ng: eBay Architecture (slides, 46p) https://www.slideshare.net/tcng3716/ebay-architecture ↩︎

      +
    136. +
    137. 2016-11 Ron Murphy: Microservices at eBay (slides, 20p) https://www.modb.pro/doc/120378 ↩︎ ↩︎ ↩︎

      +
    138. +
    139. 2020-09 High Efficiency Tool Platform for Framework Migration https://innovation.ebayinc.com/tech/engineering/high-efficiency-tool-platform-for-framework-migration/ ↩︎

      +
    140. +
    141. 2023-10 BES2:打造eBay下一代高可靠消息中间件 https://mp.weixin.qq.com/s/ThhkO1WM7ck1WO8RqjTCJA ↩︎

      +
    142. +
    143. 2013-06 Cassandra at eBay - Cassandra Summit 2013 (slides) https://www.slideshare.net/jaykumarpatel/cassandra-at-ebay-cassandra-summit-2013 ↩︎

      +
    144. +
    145. 2017-03 Sudeep Kumar: 'Elasticsearch as a Service' at eBay https://www.elastic.co/elasticon/conf/2017/sf/elasticsearch-as-a-service-at-ebay ↩︎

      +
    146. +
    147. 2016-08 How eBay Uses Apache Software to Reach Its Big Data Goals https://www.linux.com/news/how-ebay-uses-apache-software-reach-its-big-data-goals/ ↩︎

      +
    148. +
    149. 淘宝技术这十年,子柳,2013,豆瓣 ↩︎ ↩︎

      +
    150. +
    151. 尽在双11:阿里巴巴技术演进与超越,2017,豆瓣:第1章 阿里技术架构演进 ↩︎ ↩︎ ↩︎

      +
    152. +
    153. 2011-06 淘宝吴泽明范禹:淘宝业务发展及技术架构 (slides, 43p) https://www.modb.pro/doc/116697 ↩︎ ↩︎ ↩︎

      +
    154. +
    155. 2014-12 阿里云王宇德、张文生:淘宝迁云架构实践 https://web.archive.org/web/1/http://www.csdn.net/article/a/2014-12-09/15821474 ↩︎ ↩︎ ↩︎

      +
    156. +
    157. 2017-07 阿里谢吉宝唐三:阿里电商架构演变之路 (首届阿里巴巴中间件技术峰会, slides, 33p) https://www.modb.pro/doc/121185 ↩︎ ↩︎ ↩︎ ↩︎

      +
    158. +
    159. 2010-11 淘宝赵林丹臣:淘宝数据库架构演进历程 (iDataForum2010, slides, 38p) https://www.slideshare.net/ssuser1646de/ss-10163048 ↩︎

      +
    160. +
    161. 2019-10 阿里刘振飞:十年磨一剑:从2009启动“去IOE”工程到2019年OceanBase拿下TPC-C世界第一 https://mp.weixin.qq.com/s/7B6rp17XVhpAWZr1-6DHqQ https://developer.aliyun.com/article/722414 ↩︎

      +
    162. +
    163. 2016-02 SSD的30年发展史 https://mp.weixin.qq.com/s/JsHKFilB5fvLY9V9z_xsXw ↩︎

      +
    164. +
    165. 2010-04 Yoshinori Matsunobu: SSD Deployment Strategies for MySQL (slides, 52p) https://www.slideshare.net/matsunobu/ssd-deployment-strategies-for-mysql ↩︎

      +
    166. +
    167. 2020-04 阿里王剑英、和利:淘宝万亿级交易订单背后的存储引擎 https://mp.weixin.qq.com/s/MkX1Pr8tERrzK29XG9zMUQ https://help.aliyun.com/zh/rds/apsaradb-rds-for-mysql/storage-engine-that-processes-trillions-of-taobao-order-records ↩︎

      +
    168. +
    169. 2022-03 阿里云罗庆超:阿里巴巴集团上云之 TFS 迁移 OSS 技术白皮书 https://developer.aliyun.com/article/876301 ↩︎

      +
    170. +
    171. 2016-12 阿里倪超:阿里巴巴Aliware十年微服务架构演进历程中的挑战与实践 https://www.sohu.com/a/121588928_465959 ↩︎

      +
    172. +
    173. 2017-10 阿里钟华古谦:企业IT架构转型之道 (杭州云栖大会2017, slides, 18p) https://www.modb.pro/doc/121695 ↩︎

      +
    174. +
    175. 2021-09 阿里郭浩:Dubbo 和 HSF 在阿里巴巴的实践:携手走向下一代云原生微服务 https://mp.weixin.qq.com/s/_Ug3yEh9gz5mLE_ag1DjwA ↩︎ ↩︎ ↩︎

      +
    176. +
    177. 2012-11 阿里巴巴分布式服务框架 Dubbo 团队成员梁飞专访 http://www.iteye.com/magazines/103 ↩︎

      +
    178. +
    179. 2019-01 Dubbo 作者梁飞亲述:那些辉煌、沉寂与重生的故事 https://www.infoq.cn/article/3F3Giujjo-QwSw2wEz7u ↩︎ ↩︎

      +
    180. +
    181. Dubbo 用户案例:阿里巴巴升级 Dubbo3 全面取代 HSF2 https://cn.dubbo.apache.org/zh-cn/users/alibaba/ https://github.com/apache/dubbo-website/blob/ee727525aa61d68b397cc6ddedb322001f0ca4da/content/zh/users/alibaba.md ↩︎

      +
    182. +
    183. 2023-01 阿里巴巴升级 Dubbo3 全面取代 HSF2 https://cn.dubbo.apache.org/zh-cn/blog/2023/01/16/阿里巴巴升级-dubbo3-全面取代-hsf2/ ↩︎

      +
    184. +
    185. 2017-11 阿里林清山隆基:阿里消息中间件架构演进之路:notify和metaq https://zhuanlan.zhihu.com/p/302600352 ↩︎

      +
    186. +
    187. 2013-07 淘宝张乐伟韩彰:淘宝消息中间件技术演变:MetaQ 1.0、MetaQ 2.0、MetaQ 3.0(sildes, 30p)https://www.modb.pro/doc/109298 ↩︎

      +
    188. +
    189. 2017-03 阿里冯嘉鼬神:Apache RocketMQ背后的设计思路与最佳实践 https://developer.aliyun.com/article/71889 ↩︎

      +
    190. +
    191. 2008-05 LinkedIn - A Professional Network built with Java Technologies and Agile Practices (JavaOne2008, slides) https://www.slideshare.net/linkedin/linkedins-communication-architecture ↩︎ ↩︎ ↩︎

      +
    192. +
    193. 2015-07 Josh Clemm: A Brief History of Scaling LinkedIn https://engineering.linkedin.com/architecture/brief-history-scaling-linkedin https://www.slideshare.net/joshclemm/how-linkedin-scaled-a-brief-history ↩︎ ↩︎

      +
    194. +
    195. Aditya Auradkar, Chavdar Botev, etc.: Data Infrastructure at LinkedIn. ICDE 2012: 1370-1381,dblp, semanticscholar, slides ↩︎ ↩︎ ↩︎

      +
    196. +
    197. 2012-06 Sid Anand: LinkedIn Data Infrastructure Slides (Version 2) (slides) https://www.slideshare.net/r39132/linkedin-data-infrastructure-slides-version-2-13394853 ↩︎ ↩︎

      +
    198. +
    199. 2021-12 Evolving LinkedIn’s analytics tech stack https://engineering.linkedin.com/blog/2021/evolving-linkedin-s-analytics-tech-stack ↩︎ ↩︎

      +
    200. +
    201. 2010-05 Aditya Agarwal: Scale at Facebook (Qcon London 2010) https://www.infoq.com/presentations/Scale-at-Facebook/ ↩︎ ↩︎

      +
    202. +
    203. 2008-11 Aditya Agarwal: Facebook architecture (QCon SF 2008, slides, 34p) https://www.slideshare.net/mysqlops/facebook-architecture https://www.infoq.com/presentations/Facebook-Software-Stack/ ↩︎ ↩︎ ↩︎ ↩︎

      +
    204. +
    205. 2011-04 Michaël Figuière: What is Facebook's architecture? https://qr.ae/pKYg12 ↩︎

      +
    206. +
    207. 2013-10 Where does Facebook use C++? https://qr.ae/pKCIee ↩︎

      +
    208. +
    209. 2022-07 Programming languages endorsed for server-side use at Meta https://engineering.fb.com/2022/07/27/developer-tools/programming-languages-endorsed-for-server-side-use-at-meta/ ↩︎

      +
    210. +
    211. 2015-07 Instagram: Search Architecture https://instagram-engineering.com/eeb34a936d3a ↩︎

      +
    212. +
    213. Guoqiang Jerry Chen, Janet L. Wiener, etc.: Realtime Data Processing at Facebook. SIGMOD Conference 2016: 1087-1098,dblp, semanticscholar ↩︎

      +
    214. +
    215. 2021-10 XStream: stream processing platform at facebook (Flink Forward Global 2021, slides) https://www.slideshare.net/aniketmokashi/xstream-stream-processing-platform-at-facebook ↩︎

      +
    216. +
    217. 2013-01 Johan Oskarsson: The Twitter stack https://blog.oskarsson.nu/post/40196324612/the-twitter-stack ↩︎ ↩︎

      +
    218. +
    219. 2013-10 Chris Aniszczyk: Evolution of The Twitter Stack (slides) https://www.slideshare.net/caniszczyk/twitter-opensourcestacklinuxcon2013 ↩︎ ↩︎ ↩︎

      +
    220. +
    221. 2017-01 The Infrastructure Behind Twitter: Scale https://blog.twitter.com/engineering/en_us/topics/infrastructure/2017/the-infrastructure-behind-twitter-scale ↩︎

      +
    222. +
    223. 2010-07 Cassandra at Twitter Today https://blog.twitter.com/engineering/en_us/a/2010/cassandra-at-twitter-today ↩︎

      +
    224. +
    225. 2011-12 How Twitter Stores 250 Million Tweets a Day Using MySQL http://highscalability.com/blog/2011/12/19/how-twitter-stores-250-million-tweets-a-day-using-mysql.html ↩︎

      +
    226. +
    227. 2013-11 Michael Busch: Search at Twitter (Lucene Revolution 2013, slides) https://www.slideshare.net/lucenerevolution/twitter-search-lucenerevolutioneu2013-copy https://www.youtube.com/watch?v=AguWva8P_DI ↩︎ ↩︎

      +
    228. +
    229. 2022-10 Stability and scalability for search https://blog.twitter.com/engineering/en_us/topics/infrastructure/2022/stability-and-scalability-for-search ↩︎

      +
    230. +
    231. 2021-10 Processing billions of events in real time at Twitter https://blog.twitter.com/engineering/en_us/topics/infrastructure/2021/processing-billions-of-events-in-real-time-at-twitter- ↩︎

      +
    232. +
    +
    +]]>
    + + 架构 + + + MySQL + 架构 + 技术栈 + Java + +
    +
    diff --git a/sitemap.txt b/sitemap.txt new file mode 100644 index 00000000..25458a16 --- /dev/null +++ b/sitemap.txt @@ -0,0 +1,87 @@ +https://nullwy.me/2023/11/amazon-architecture-evolution/ +https://nullwy.me/2023/12/popular-websites-tech-stack/ +https://nullwy.me/2023/11/reliability-engineering/ +https://nullwy.me/2017/11/zookeeper-note/ +https://nullwy.me/2018/01/stack-frame-calling-convention/ +https://nullwy.me/2016/12/software-dev-books/ +https://nullwy.me/2017/01/mysql-data-types/ +https://nullwy.me/2018/06/mysql-binlog/ +https://nullwy.me/2019/06/mysql-5.7-json/ +https://nullwy.me/2016/12/mybatis-generator/ +https://nullwy.me/2020/05/kong-gateway/ +https://nullwy.me/2016/11/java-official-doc/ +https://nullwy.me/2017/05/java-method-parameter/ +https://nullwy.me/2018/01/java-ffi/ +https://nullwy.me/2017/03/java-executor/ +https://nullwy.me/2016/11/java-books/ +https://nullwy.me/2018/10/java-agent/ +https://nullwy.me/2016/12/java-8-stream-api/ +https://nullwy.me/2023/07/io-multiplexing-network-server/ +https://nullwy.me/2023/07/innodb-locking/ +https://nullwy.me/2019/01/elastic-stack/ +https://nullwy.me/2016/11/database-books/ +https://nullwy.me/2016/11/lang-and-compiler-books/ +https://nullwy.me/2016/12/itext-pdf/ +https://nullwy.me/2017/04/javac-api/ +https://nullwy.me/about/index.html +https://nullwy.me/tags/index.html +https://nullwy.me/categories/index.html +https://nullwy.me/ +https://nullwy.me/tags/MySQL/ +https://nullwy.me/tags/%E6%95%B0%E6%8D%AE%E5%BA%93/ +https://nullwy.me/tags/%E4%B9%A6%E7%B1%8D/ +https://nullwy.me/tags/CS/ +https://nullwy.me/tags/%E6%9E%B6%E6%9E%84/ +https://nullwy.me/tags/%E5%8F%AF%E6%89%A9%E5%B1%95%E6%80%A7/ +https://nullwy.me/tags/%E6%8A%80%E6%9C%AF%E6%A0%88/ +https://nullwy.me/tags/%E5%BE%AE%E6%9C%8D%E5%8A%A1/ +https://nullwy.me/tags/SOA/ +https://nullwy.me/tags/ELK/ +https://nullwy.me/tags/Elastic/ +https://nullwy.me/tags/%E6%97%A5%E5%BF%97/ +https://nullwy.me/tags/InnoDB/ +https://nullwy.me/tags/%E9%94%81/ +https://nullwy.me/tags/MVCC/ +https://nullwy.me/tags/IO/ +https://nullwy.me/tags/%E6%9C%8D%E5%8A%A1%E5%99%A8/ +https://nullwy.me/tags/%E7%BD%91%E7%BB%9C/ +https://nullwy.me/tags/%E5%B9%B6%E5%8F%91/ +https://nullwy.me/tags/%E5%B7%A5%E5%85%B7/ +https://nullwy.me/tags/%E4%BB%A3%E7%A0%81/ +https://nullwy.me/tags/Java/ +https://nullwy.me/tags/%E5%AD%97%E8%8A%82%E7%A0%81/ +https://nullwy.me/tags/javaagent/ +https://nullwy.me/tags/byte-buddy/ +https://nullwy.me/tags/JNI/ +https://nullwy.me/tags/JNA/ +https://nullwy.me/tags/JNR/ +https://nullwy.me/tags/FFI/ +https://nullwy.me/tags/Pyhon/ +https://nullwy.me/tags/Ruby/ +https://nullwy.me/tags/JVM/ +https://nullwy.me/tags/Kong/ +https://nullwy.me/tags/API/ +https://nullwy.me/tags/Nginx/ +https://nullwy.me/tags/OpenResty/ +https://nullwy.me/tags/%E7%BD%91%E5%85%B3/ +https://nullwy.me/tags/%E8%AF%AD%E8%A8%80/ +https://nullwy.me/tags/%E7%BC%96%E8%AF%91%E5%99%A8/ +https://nullwy.me/tags/javac/ +https://nullwy.me/tags/Lombok/ +https://nullwy.me/tags/MyBatis/ +https://nullwy.me/tags/binlog/ +https://nullwy.me/tags/OS/ +https://nullwy.me/tags/C/ +https://nullwy.me/tags/ASM/ +https://nullwy.me/tags/ABI/ +https://nullwy.me/tags/ZooKeeper/ +https://nullwy.me/tags/%E5%88%86%E5%B8%83%E5%BC%8F/ +https://nullwy.me/tags/%E5%85%B1%E8%AF%86/ +https://nullwy.me/tags/Paxos/ +https://nullwy.me/tags/%E5%8F%AF%E9%9D%A0%E6%80%A7/ +https://nullwy.me/tags/SRE/ +https://nullwy.me/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%B3%BB%E7%BB%9F/ +https://nullwy.me/categories/%E6%9E%B6%E6%9E%84/ +https://nullwy.me/categories/MySQL/ +https://nullwy.me/categories/Java/ +https://nullwy.me/categories/%E7%BC%96%E7%A8%8B/ diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 00000000..fadaf6a6 --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,673 @@ + + + + + https://nullwy.me/2023/11/amazon-architecture-evolution/ + + 2023-12-06 + + monthly + 0.6 + + + + https://nullwy.me/2023/12/popular-websites-tech-stack/ + + 2023-12-06 + + monthly + 0.6 + + + + https://nullwy.me/2023/11/reliability-engineering/ + + 2023-12-05 + + monthly + 0.6 + + + + https://nullwy.me/2017/11/zookeeper-note/ + + 2023-12-05 + + monthly + 0.6 + + + + https://nullwy.me/2018/01/stack-frame-calling-convention/ + + 2023-12-05 + + monthly + 0.6 + + + + https://nullwy.me/2016/12/software-dev-books/ + + 2023-12-05 + + monthly + 0.6 + + + + https://nullwy.me/2017/01/mysql-data-types/ + + 2023-12-05 + + monthly + 0.6 + + + + https://nullwy.me/2018/06/mysql-binlog/ + + 2023-12-05 + + monthly + 0.6 + + + + https://nullwy.me/2019/06/mysql-5.7-json/ + + 2023-12-05 + + monthly + 0.6 + + + + https://nullwy.me/2016/12/mybatis-generator/ + + 2023-12-05 + + monthly + 0.6 + + + + https://nullwy.me/2020/05/kong-gateway/ + + 2023-12-05 + + monthly + 0.6 + + + + https://nullwy.me/2016/11/java-official-doc/ + + 2023-12-05 + + monthly + 0.6 + + + + https://nullwy.me/2017/05/java-method-parameter/ + + 2023-12-05 + + monthly + 0.6 + + + + https://nullwy.me/2018/01/java-ffi/ + + 2023-12-05 + + monthly + 0.6 + + + + https://nullwy.me/2017/03/java-executor/ + + 2023-12-05 + + monthly + 0.6 + + + + https://nullwy.me/2016/11/java-books/ + + 2023-12-05 + + monthly + 0.6 + + + + https://nullwy.me/2018/10/java-agent/ + + 2023-12-05 + + monthly + 0.6 + + + + https://nullwy.me/2016/12/java-8-stream-api/ + + 2023-12-05 + + monthly + 0.6 + + + + https://nullwy.me/2023/07/io-multiplexing-network-server/ + + 2023-12-05 + + monthly + 0.6 + + + + https://nullwy.me/2023/07/innodb-locking/ + + 2023-12-05 + + monthly + 0.6 + + + + https://nullwy.me/2019/01/elastic-stack/ + + 2023-12-05 + + monthly + 0.6 + + + + https://nullwy.me/2016/11/database-books/ + + 2023-12-05 + + monthly + 0.6 + + + + https://nullwy.me/2016/11/lang-and-compiler-books/ + + 2023-12-04 + + monthly + 0.6 + + + + https://nullwy.me/2016/12/itext-pdf/ + + 2023-12-04 + + monthly + 0.6 + + + + https://nullwy.me/2017/04/javac-api/ + + 2022-10-30 + + monthly + 0.6 + + + + https://nullwy.me/about/index.html + + 2021-10-20 + + monthly + 0.6 + + + + https://nullwy.me/tags/index.html + + 2017-05-23 + + monthly + 0.6 + + + + https://nullwy.me/categories/index.html + + 2017-05-23 + + monthly + 0.6 + + + + + https://nullwy.me/ + 2023-12-06 + daily + 1.0 + + + + + https://nullwy.me/tags/MySQL/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/%E6%95%B0%E6%8D%AE%E5%BA%93/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/%E4%B9%A6%E7%B1%8D/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/CS/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/%E6%9E%B6%E6%9E%84/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/%E5%8F%AF%E6%89%A9%E5%B1%95%E6%80%A7/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/%E6%8A%80%E6%9C%AF%E6%A0%88/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/%E5%BE%AE%E6%9C%8D%E5%8A%A1/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/SOA/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/ELK/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/Elastic/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/%E6%97%A5%E5%BF%97/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/InnoDB/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/%E9%94%81/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/MVCC/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/IO/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/%E6%9C%8D%E5%8A%A1%E5%99%A8/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/%E7%BD%91%E7%BB%9C/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/%E5%B9%B6%E5%8F%91/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/%E5%B7%A5%E5%85%B7/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/%E4%BB%A3%E7%A0%81/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/Java/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/%E5%AD%97%E8%8A%82%E7%A0%81/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/javaagent/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/byte-buddy/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/JNI/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/JNA/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/JNR/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/FFI/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/Pyhon/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/Ruby/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/JVM/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/Kong/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/API/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/Nginx/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/OpenResty/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/%E7%BD%91%E5%85%B3/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/%E8%AF%AD%E8%A8%80/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/%E7%BC%96%E8%AF%91%E5%99%A8/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/javac/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/Lombok/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/MyBatis/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/binlog/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/OS/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/C/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/ASM/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/ABI/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/ZooKeeper/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/%E5%88%86%E5%B8%83%E5%BC%8F/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/%E5%85%B1%E8%AF%86/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/Paxos/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/%E5%8F%AF%E9%9D%A0%E6%80%A7/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/tags/SRE/ + 2023-12-06 + weekly + 0.2 + + + + + + https://nullwy.me/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%B3%BB%E7%BB%9F/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/categories/%E6%9E%B6%E6%9E%84/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/categories/MySQL/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/categories/Java/ + 2023-12-06 + weekly + 0.2 + + + + https://nullwy.me/categories/%E7%BC%96%E7%A8%8B/ + 2023-12-06 + weekly + 0.2 + + + diff --git a/tags/ABI/index.html b/tags/ABI/index.html new file mode 100644 index 00000000..13b48985 --- /dev/null +++ b/tags/ABI/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: ABI | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    ABI + 标签 +

    +
    + + +
    + 2018 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/API/index.html b/tags/API/index.html new file mode 100644 index 00000000..89daf3c6 --- /dev/null +++ b/tags/API/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: API | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    API + 标签 +

    +
    + + +
    + 2020 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/ASM/index.html b/tags/ASM/index.html new file mode 100644 index 00000000..6a17e19c --- /dev/null +++ b/tags/ASM/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: ASM | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    ASM + 标签 +

    +
    + + +
    + 2018 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/C/index.html b/tags/C/index.html new file mode 100644 index 00000000..55827775 --- /dev/null +++ b/tags/C/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: C | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    C + 标签 +

    +
    + + +
    + 2018 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/CS/index.html b/tags/CS/index.html new file mode 100644 index 00000000..e654fddf --- /dev/null +++ b/tags/CS/index.html @@ -0,0 +1,529 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: CS | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    CS + 标签 +

    +
    + + +
    + 2016 +
    + + + + + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/ELK/index.html b/tags/ELK/index.html new file mode 100644 index 00000000..e414cc83 --- /dev/null +++ b/tags/ELK/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: ELK | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    ELK + 标签 +

    +
    + + +
    + 2019 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/Elastic/index.html b/tags/Elastic/index.html new file mode 100644 index 00000000..0aebfe4f --- /dev/null +++ b/tags/Elastic/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: Elastic | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    Elastic + 标签 +

    +
    + + +
    + 2019 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/FFI/index.html b/tags/FFI/index.html new file mode 100644 index 00000000..00cdcd2e --- /dev/null +++ b/tags/FFI/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: FFI | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    FFI + 标签 +

    +
    + + +
    + 2018 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/IO/index.html b/tags/IO/index.html new file mode 100644 index 00000000..a72c5ba8 --- /dev/null +++ b/tags/IO/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: IO | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    IO + 标签 +

    +
    + + +
    + 2023 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/InnoDB/index.html b/tags/InnoDB/index.html new file mode 100644 index 00000000..9fb9f039 --- /dev/null +++ b/tags/InnoDB/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: InnoDB | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    InnoDB + 标签 +

    +
    + + +
    + 2023 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/JNA/index.html b/tags/JNA/index.html new file mode 100644 index 00000000..9d65aca3 --- /dev/null +++ b/tags/JNA/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: JNA | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    JNA + 标签 +

    +
    + + +
    + 2018 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/JNI/index.html b/tags/JNI/index.html new file mode 100644 index 00000000..5aac8366 --- /dev/null +++ b/tags/JNI/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: JNI | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    JNI + 标签 +

    +
    + + +
    + 2018 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/JNR/index.html b/tags/JNR/index.html new file mode 100644 index 00000000..ec828f3a --- /dev/null +++ b/tags/JNR/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: JNR | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    JNR + 标签 +

    +
    + + +
    + 2018 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/JVM/index.html b/tags/JVM/index.html new file mode 100644 index 00000000..aed61453 --- /dev/null +++ b/tags/JVM/index.html @@ -0,0 +1,532 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: JVM | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    JVM + 标签 +

    +
    + + +
    + 2017 +
    + + + + +
    + 2016 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/Java/index.html b/tags/Java/index.html new file mode 100644 index 00000000..7594ee2d --- /dev/null +++ b/tags/Java/index.html @@ -0,0 +1,698 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: Java | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    Java + 标签 +

    +
    + + +
    + 2023 +
    + + +
    + 2018 +
    + + + + +
    + 2017 +
    + + + + + + +
    + 2016 +
    + + + + + + + + + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/Kong/index.html b/tags/Kong/index.html new file mode 100644 index 00000000..795cb66b --- /dev/null +++ b/tags/Kong/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: Kong | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    Kong + 标签 +

    +
    + + +
    + 2020 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/Lombok/index.html b/tags/Lombok/index.html new file mode 100644 index 00000000..11ad7a5e --- /dev/null +++ b/tags/Lombok/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: Lombok | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    Lombok + 标签 +

    +
    + + +
    + 2017 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/MVCC/index.html b/tags/MVCC/index.html new file mode 100644 index 00000000..7ae9c0c4 --- /dev/null +++ b/tags/MVCC/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: MVCC | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    MVCC + 标签 +

    +
    + + +
    + 2023 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/MyBatis/index.html b/tags/MyBatis/index.html new file mode 100644 index 00000000..24b73e4a --- /dev/null +++ b/tags/MyBatis/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: MyBatis | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    MyBatis + 标签 +

    +
    + + +
    + 2016 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/MySQL/index.html b/tags/MySQL/index.html new file mode 100644 index 00000000..d0e2cfac --- /dev/null +++ b/tags/MySQL/index.html @@ -0,0 +1,601 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: MySQL | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    MySQL + 标签 +

    +
    + + +
    + 2023 +
    + + + + +
    + 2019 +
    + + +
    + 2018 +
    + + +
    + 2017 +
    + + +
    + 2016 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/Nginx/index.html b/tags/Nginx/index.html new file mode 100644 index 00000000..8716a077 --- /dev/null +++ b/tags/Nginx/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: Nginx | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    Nginx + 标签 +

    +
    + + +
    + 2020 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/OS/index.html b/tags/OS/index.html new file mode 100644 index 00000000..b7c0f87f --- /dev/null +++ b/tags/OS/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: OS | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    OS + 标签 +

    +
    + + +
    + 2018 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/OpenResty/index.html b/tags/OpenResty/index.html new file mode 100644 index 00000000..9e3534fd --- /dev/null +++ b/tags/OpenResty/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: OpenResty | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    OpenResty + 标签 +

    +
    + + +
    + 2020 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/Paxos/index.html b/tags/Paxos/index.html new file mode 100644 index 00000000..ff36476c --- /dev/null +++ b/tags/Paxos/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: Paxos | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    Paxos + 标签 +

    +
    + + +
    + 2017 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/Pyhon/index.html b/tags/Pyhon/index.html new file mode 100644 index 00000000..0c7f20ee --- /dev/null +++ b/tags/Pyhon/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: Pyhon | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    Pyhon + 标签 +

    +
    + + +
    + 2018 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/Ruby/index.html b/tags/Ruby/index.html new file mode 100644 index 00000000..8711266a --- /dev/null +++ b/tags/Ruby/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: Ruby | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    Ruby + 标签 +

    +
    + + +
    + 2018 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/SOA/index.html b/tags/SOA/index.html new file mode 100644 index 00000000..db4450da --- /dev/null +++ b/tags/SOA/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: SOA | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    SOA + 标签 +

    +
    + + +
    + 2023 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/SRE/index.html b/tags/SRE/index.html new file mode 100644 index 00000000..44960777 --- /dev/null +++ b/tags/SRE/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: SRE | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    SRE + 标签 +

    +
    + + +
    + 2023 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/ZooKeeper/index.html b/tags/ZooKeeper/index.html new file mode 100644 index 00000000..5f3ccd53 --- /dev/null +++ b/tags/ZooKeeper/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: ZooKeeper | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    ZooKeeper + 标签 +

    +
    + + +
    + 2017 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/binlog/index.html b/tags/binlog/index.html new file mode 100644 index 00000000..aad6c56a --- /dev/null +++ b/tags/binlog/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: binlog | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    binlog + 标签 +

    +
    + + +
    + 2018 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/byte-buddy/index.html b/tags/byte-buddy/index.html new file mode 100644 index 00000000..798460e7 --- /dev/null +++ b/tags/byte-buddy/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: byte-buddy | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    byte-buddy + 标签 +

    +
    + + +
    + 2018 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/index.html b/tags/index.html new file mode 100644 index 00000000..18fed298 --- /dev/null +++ b/tags/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + tags | nullwy's blog + + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + + + + + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/javaagent/index.html b/tags/javaagent/index.html new file mode 100644 index 00000000..f8c8b408 --- /dev/null +++ b/tags/javaagent/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: javaagent | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    javaagent + 标签 +

    +
    + + +
    + 2018 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tags/javac/index.html b/tags/javac/index.html new file mode 100644 index 00000000..65afc02a --- /dev/null +++ b/tags/javac/index.html @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: javac | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    javac + 标签 +

    +
    + + +
    + 2017 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/tags/\344\271\246\347\261\215/index.html" "b/tags/\344\271\246\347\261\215/index.html" new file mode 100644 index 00000000..4023102c --- /dev/null +++ "b/tags/\344\271\246\347\261\215/index.html" @@ -0,0 +1,549 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: 书籍 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    书籍 + 标签 +

    +
    + + +
    + 2016 +
    + + + + + + + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/tags/\344\273\243\347\240\201/index.html" "b/tags/\344\273\243\347\240\201/index.html" new file mode 100644 index 00000000..73999ec9 --- /dev/null +++ "b/tags/\344\273\243\347\240\201/index.html" @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: 代码 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    代码 + 标签 +

    +
    + + +
    + 2016 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/tags/\345\205\261\350\257\206/index.html" "b/tags/\345\205\261\350\257\206/index.html" new file mode 100644 index 00000000..21749127 --- /dev/null +++ "b/tags/\345\205\261\350\257\206/index.html" @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: 共识 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    共识 + 标签 +

    +
    + + +
    + 2017 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/tags/\345\210\206\345\270\203\345\274\217/index.html" "b/tags/\345\210\206\345\270\203\345\274\217/index.html" new file mode 100644 index 00000000..6633e754 --- /dev/null +++ "b/tags/\345\210\206\345\270\203\345\274\217/index.html" @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: 分布式 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    分布式 + 标签 +

    +
    + + +
    + 2017 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/tags/\345\217\257\346\211\251\345\261\225\346\200\247/index.html" "b/tags/\345\217\257\346\211\251\345\261\225\346\200\247/index.html" new file mode 100644 index 00000000..04571395 --- /dev/null +++ "b/tags/\345\217\257\346\211\251\345\261\225\346\200\247/index.html" @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: 可扩展性 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    可扩展性 + 标签 +

    +
    + + +
    + 2023 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/tags/\345\217\257\351\235\240\346\200\247/index.html" "b/tags/\345\217\257\351\235\240\346\200\247/index.html" new file mode 100644 index 00000000..bcf4f31f --- /dev/null +++ "b/tags/\345\217\257\351\235\240\346\200\247/index.html" @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: 可靠性 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    可靠性 + 标签 +

    +
    + + +
    + 2023 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/tags/\345\255\227\350\212\202\347\240\201/index.html" "b/tags/\345\255\227\350\212\202\347\240\201/index.html" new file mode 100644 index 00000000..2d2bdc29 --- /dev/null +++ "b/tags/\345\255\227\350\212\202\347\240\201/index.html" @@ -0,0 +1,512 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: 字节码 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    字节码 + 标签 +

    +
    + + +
    + 2018 +
    + + +
    + 2017 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/tags/\345\267\245\345\205\267/index.html" "b/tags/\345\267\245\345\205\267/index.html" new file mode 100644 index 00000000..21549320 --- /dev/null +++ "b/tags/\345\267\245\345\205\267/index.html" @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: 工具 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    工具 + 标签 +

    +
    + + +
    + 2016 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/tags/\345\271\266\345\217\221/index.html" "b/tags/\345\271\266\345\217\221/index.html" new file mode 100644 index 00000000..d5d94f79 --- /dev/null +++ "b/tags/\345\271\266\345\217\221/index.html" @@ -0,0 +1,512 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: 并发 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    并发 + 标签 +

    +
    + + +
    + 2023 +
    + + +
    + 2017 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/tags/\345\276\256\346\234\215\345\212\241/index.html" "b/tags/\345\276\256\346\234\215\345\212\241/index.html" new file mode 100644 index 00000000..f87df92a --- /dev/null +++ "b/tags/\345\276\256\346\234\215\345\212\241/index.html" @@ -0,0 +1,512 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: 微服务 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    微服务 + 标签 +

    +
    + + +
    + 2023 +
    + + +
    + 2020 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/tags/\346\212\200\346\234\257\346\240\210/index.html" "b/tags/\346\212\200\346\234\257\346\240\210/index.html" new file mode 100644 index 00000000..6d9aff97 --- /dev/null +++ "b/tags/\346\212\200\346\234\257\346\240\210/index.html" @@ -0,0 +1,509 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: 技术栈 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    技术栈 + 标签 +

    +
    + + +
    + 2023 +
    + + + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/tags/\346\225\260\346\215\256\345\272\223/index.html" "b/tags/\346\225\260\346\215\256\345\272\223/index.html" new file mode 100644 index 00000000..5ae9b92d --- /dev/null +++ "b/tags/\346\225\260\346\215\256\345\272\223/index.html" @@ -0,0 +1,601 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: 数据库 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    数据库 + 标签 +

    +
    + + +
    + 2023 +
    + + +
    + 2019 +
    + + +
    + 2018 +
    + + +
    + 2017 +
    + + +
    + 2016 +
    + + + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/tags/\346\227\245\345\277\227/index.html" "b/tags/\346\227\245\345\277\227/index.html" new file mode 100644 index 00000000..a1c7f942 --- /dev/null +++ "b/tags/\346\227\245\345\277\227/index.html" @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: 日志 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    日志 + 标签 +

    +
    + + +
    + 2019 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/tags/\346\234\215\345\212\241\345\231\250/index.html" "b/tags/\346\234\215\345\212\241\345\231\250/index.html" new file mode 100644 index 00000000..127dbe35 --- /dev/null +++ "b/tags/\346\234\215\345\212\241\345\231\250/index.html" @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: 服务器 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    服务器 + 标签 +

    +
    + + +
    + 2023 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/tags/\346\236\266\346\236\204/index.html" "b/tags/\346\236\266\346\236\204/index.html" new file mode 100644 index 00000000..aea15f5c --- /dev/null +++ "b/tags/\346\236\266\346\236\204/index.html" @@ -0,0 +1,618 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: 架构 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    架构 + 标签 +

    +
    + + +
    + 2023 +
    + + + + + + + + +
    + 2020 +
    + + +
    + 2019 +
    + + +
    + 2017 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/tags/\347\274\226\350\257\221\345\231\250/index.html" "b/tags/\347\274\226\350\257\221\345\231\250/index.html" new file mode 100644 index 00000000..5ac2f379 --- /dev/null +++ "b/tags/\347\274\226\350\257\221\345\231\250/index.html" @@ -0,0 +1,512 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: 编译器 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    编译器 + 标签 +

    +
    + + +
    + 2018 +
    + + +
    + 2017 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/tags/\347\275\221\345\205\263/index.html" "b/tags/\347\275\221\345\205\263/index.html" new file mode 100644 index 00000000..25975328 --- /dev/null +++ "b/tags/\347\275\221\345\205\263/index.html" @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: 网关 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    网关 + 标签 +

    +
    + + +
    + 2020 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/tags/\347\275\221\347\273\234/index.html" "b/tags/\347\275\221\347\273\234/index.html" new file mode 100644 index 00000000..bcaf22b5 --- /dev/null +++ "b/tags/\347\275\221\347\273\234/index.html" @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: 网络 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    网络 + 标签 +

    +
    + + +
    + 2023 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/tags/\350\257\255\350\250\200/index.html" "b/tags/\350\257\255\350\250\200/index.html" new file mode 100644 index 00000000..fba69628 --- /dev/null +++ "b/tags/\350\257\255\350\250\200/index.html" @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: 语言 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    语言 + 标签 +

    +
    + + +
    + 2016 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/tags/\351\224\201/index.html" "b/tags/\351\224\201/index.html" new file mode 100644 index 00000000..3868ca88 --- /dev/null +++ "b/tags/\351\224\201/index.html" @@ -0,0 +1,489 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 标签: 锁 | nullwy's blog + + + + + + + + + + + + + + + + + + + + +
    +
    + +
    +
    + + + + + +
    + + + + + + + + +
    + +
    + +
    +
    + + +
    + + 0% +
    + + +
    +
    +
    + + +
    + + + + + +
    +
    +
    +

    锁 + 标签 +

    +
    + + +
    + 2023 +
    + + + +
    +
    + + + + + + + + +
    + + + + +
    + + + + + + + + +
    +
    + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +