myJavaBlog

java世界
随笔 - 43, 文章 - 0, 评论 - 2, 引用 - 0
数据加载中……

教你如何获取绑定变量的各种方法

1、查询v$sql视图
selectsql_id, sql_text, bind_data,HASH_VALUE from v$sql where sql_text Like '%select * from test where id1%';
它的记录频率受_cursor_bind_capture_interval 隐含参数控制,默认值900,表示每900秒记录一次绑定值,可以通过alter system set "_cursor_bind_capture_interval"=10;

此时查询到的data值得形式是这样的:BEDA0B2002004F8482D10065FFFF0F00000000000000000000C0021602C102C0021602C102F0018003691532303132303431313032504F443834363135313635F0018003691532303132303431313032504F443834363135313730F0018003691532303132303431313032504F443834363135313731F0018003691532303132303431313032504F443834363135313734F0018003691532303132303431313032504F443834363135313735F0018003691532303132303431313032504F443834363135313739F0018003691532303132303431313032504F443834363135313830F0018003691532303132303431313032504F443834363135313833F0018003691532303132303431313032504F443834363135313834F0018003691532303132303431313032504F443834363135313838F0018003691532303132303431313032504F443834363135313839F0018003691532303132303431313032504F443834363135313933F0018003691532303132303431313032504F443834363135313934F0018003691532303132303431313032504F443834363135313937F0018003691532303132303431313032504F443834363135313938F0018003691532303132303431313032504F443834363135323033F0018003691532303132303431313032504F443834363135323034F0018003691532303132303431313032504F443834363135323037
这样肯定是没法看懂的

需哟进行转换
select dbms_sqltune.extract_binds(bind_data) bind from v$sql WHERE SQL_TEXT LIKE '%FROM TEST11%';


2、查询SELECT VALUE_STRING FROM V$SQL_BIND_CAPTURE WHERE SQL_ID='abhf6n1xqgrr0';
通过v$sql_bind_capture视图,可以查看绑定变量,但是这个视图不太给力,只能捕获最后一次记录的绑定变量值。

而且两次捕获的间隔有一个隐含参数控制。默认是900秒,才会重新开始捕获。在900内,绑定变量值的改变不会反应在这个视图中。

10G以后可以通过如下方法查看AWR报告里记录的SQL的绑定变量值。

select snap_id, name, position, value_string,last_captured,WAS_CAPTUREDfrom dba_hist_sqlbind where sql_id = '576c1s91gua19' and snap_id='20433';

----------SNAP_ID就是AWR报告的快照ID

----------name,绑定变量的名称

----------position,绑定值在SQL语句中的位置,以123进行标注

---------value_string,就是绑定变量值

---------,last_captured,最后捕获到的时间

---------WAS_CAPTURED,是否绑定被捕获,where子句前面的绑定不进行捕获。

dba_hist_sqlbind视图强大的地方在于,它记录了每个AWR报告里的SQL的绑定变量值,当然这个绑定变量值也是AWR生成的时候从v$sql_bind_capture采样获得的。

通过这个视图,我们能够获得比较多的绑定变量值,对于我们排查问题,这些值一般足够了。

还有一个需要注意的地方是,这两个视图中记录的绑定变量只对where条件后面的绑定进行捕获,这点需要使用的时候注意。

3、查询dba_hist_sqlbind VALUE_STRING列
DBA_HIST_SQLBIND是视图V$SQL_BIND_CAPTURE历史快照

4、查询wrh$_sqlstat
select dbms_sqltune.extract_bind(bind_data, 1).value_string
from wrh$_sqlstat
where sql_id = '88dz0k2qvg876'----根据绑定变量的多少增加dbms_sqltune.extract_bind(bind_data, 2).value_string等 
(转载请注明出处:[url=http://www.6rfd.com]澳门博彩[/url]
[url=http://www.9gds.com]易博网[/url])

posted @ 2012-04-18 16:53 夏凡 阅读(394) | 评论 (0)编辑 收藏

关于计划执行中各字段各模块的描述

在SQL语句的执行计划中,包含很多字段项和很多模块,其不同字段代表了不同的含义且在不同的情形下某些字段、模块显示或不显示,下
面的描述给出了执行计划中各字段的含义以及各模块的描述。
有关执行计划中各字段模块的描述请参考: 执行计划中各字段各模块描述
有关由SQL语句来获取执行计划请参考:使用EXPLAIN PLAN获取SQL语句执行计划
有关使用autotrace来获取执行计划请参考:启用AUTOTRACE功能
有关display_cursor函数的使用请参考:http://www.2cto.com/database/201202/120814.html

一、执行计划中各字段的描述
1、基本字段(总是可用的)
Id 执行计划中每一个操作(行)的标识符。如果数字前面带有星号,意味着将在随后提供这行包含的谓词信息
Operation 对应执行的操作。也叫行源操作
Name 操作的对象名称

2、查询优化器评估信息
Rows(E-Rows) 预估操作返回的记录条数
Bytes(E-Bytes) 预估操作返回的记录字节数
TempSpc 预估操作使用临时表空间的大小
Cost(%CPU) 预估操作所需的开销。在括号中列出了CPU开销的百分比。注意这些值是通过执行计划计算出来的。换句话说,父操作的开销包含子操作的开销
Time 预估执行操作所需要的时间(HH:MM:SS)

3、分区(仅当访问分区表时下列字段可见)
Pstart 访问的第一个分区。如果解析时不知道是哪个分区就设为KEY,KEY(I),KEY(MC),KEY(OR),KEY(SQ)
Pstop 访问的最后一个分区。如果解析时不知道是哪个分区就设为KEY,KEY(I),KEY(MC),KEY(OR),KEY(SQ)

4、并行和分布式处理(仅当使用并行或分布式操作时下列字段可见)
Inst 在分布式操作中,指操作使用的数据库链接的名字
TQ 在并行操作中,用于从属线程间通信的表队列
IN-OUT 并行或分布式操作间的关系
PQ Distrib 在并行操作中,生产者为发送数据给消费者进行的分配

5、运行时统计(当设定参数statistics_level为all或使用gather_plan_statistics提示时,下列字段可见)
Starts 指定操作执行的次数
A-Rows 操作返回的真实记录数
A-Time 操作执行的真实时间(HH:MM:SS.FF)

6、I/O 统计(当设定参数statistics_level为all或使用gather_plan_statistics提示时,下列字段可见)
Buffers 执行期间进行的逻辑读操作数量
Reads 执行期间进行的物理读操作数量
Writes 执行期间进行的物理写操作数量

7、内存使用统计
OMem 最优执行所需内存的预估值
1Mem 一次通过(one-pass)执行所需内存的预估值
0/1/M 最优/一次通过/多次通过(multipass)模式操作执行的次数
Used-Mem 最后一次执行时操作使用的内存量
Used-Tmp 最后一次执行时操作使用的临时空间大小。这个字段必须扩大1024倍才能和其他衡量内存的字段一致(比如,32k意味着32MB)
Max-Tmp 操作使用的最大临时空间大小。这个字段必须扩大1024倍才能和其他衡量内存的字段一致(比如,32k意味着32MB)
二、执行计划中各模块的描述与举例
1、预估的执行计划中的各字段与模块

SQL> explain plan for
2 select * from emp e,dept d
3 where e.deptno=d.deptno
4 and e.ename='SMITH';

Explained.


/**************************************************/
/* Author: Robinson Cheng */
/* Blog: http://blog.csdn.net/robinson_0612 */
/* MSN: robinson_0612@hotmail.com */
/* QQ: 645746311 */
/**************************************************/ 
SQL> set linesize 180
SQL> set pagesize 0 
SQL> select * from table(dbms_xplan.display(null,null,'advanced')); --使用dbms_xplan.display函数获得语句的执行计划
Plan hash value: 351108634 --SQL语句的哈希植

---------------------------------------------------------------------------------------- /*执行计划部分*/
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 117 | 4 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | 1 | 117 | 4 (0)| 00:00:01 |
|* 2 | TABLE ACCESS FULL | EMP | 1 | 87 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 30 | 1 (0)| 00:00:01 |
|* 4 | INDEX UNIQUE SCAN | PK_DEPT | 1 | | 0 (0)| 00:00:01 |
----------------------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id): --这部分显示的为查询块名和对象别名
-------------------------------------------------------------

1 - SEL$1 --SEL$为select 的缩写,位于块1,相应的还有DEL$,INS$,UPD$等
2 - SEL$1 / E@SEL$1 --E@SEL$1,对应到执行计划中的操作ID为2上,即在表E上的查询,E为别名,下面类同
3 - SEL$1 / D@SEL$1 
4 - SEL$1 / D@SEL$1

Outline Data --提纲部分,这部分将执行计划中的图形化方式以文本形式来呈现,即转换为提示符方式
-------------

/*+
BEGIN_OUTLINE_DATA 
USE_NL(@"SEL$1" "D"@"SEL$1") --使用USE_NL提示,即嵌套循环
LEADING(@"SEL$1" "E"@"SEL$1" "D"@"SEL$1") --指明前导表
INDEX_RS_ASC(@"SEL$1" "D"@"SEL$1" ("DEPT"."DEPTNO")) --指明对于D上的访问方式为使用索引
FULL(@"SEL$1" "E"@"SEL$1") --指明对于E上的访问方式为全表扫描 
OUTLINE_LEAF(@"SEL$1")
ALL_ROWS 
OPTIMIZER_FEATURES_ENABLE('10.2.0.3')
IGNORE_OPTIM_EMBEDDED_HINTS
END_OUTLINE_DATA
*/

Predicate Information (identified by operation id): --谓词信息部分,在执行计划中ID带有星号的每一行均对应到下面中的一行
--------------------------------------------------- 

2 - filter("E"."ENAME"='SMITH') 
4 - access("E"."DEPTNO"="D"."DEPTNO")

Column Projection Information (identified by operation id): --执行时每一步骤所返回的列,下面的不同步骤返回了不同的列
-----------------------------------------------------------

1 - (#keys=0) "E"."EMPNO"[NUMBER,22], "E"."ENAME"[VARCHAR2,10],
"E"."JOB"[VARCHAR2,9], "E"."MGR"[NUMBER,22], "E"."HIREDATE"[DATE,7],
"E"."SAL"[NUMBER,22], "E"."COMM"[NUMBER,22], "E"."DEPTNO"[NUMBER,22],
"D"."DEPTNO"[NUMBER,22], "D"."DNAME"[VARCHAR2,14], "D"."LOC"[VARCHAR2,13]
2 - "E"."EMPNO"[NUMBER,22], "E"."ENAME"[VARCHAR2,10], "E"."JOB"[VARCHAR2,9],
"E"."MGR"[NUMBER,22], "E"."HIREDATE"[DATE,7], "E"."SAL"[NUMBER,22],
"E"."COMM"[NUMBER,22], "E"."DEPTNO"[NUMBER,22]
3 - "D"."DEPTNO"[NUMBER,22], "D"."DNAME"[VARCHAR2,14], "D"."LOC"[VARCHAR2,13]
4 - "D".ROWID[ROWID,10], "D"."DEPTNO"[NUMBER,22]

Note --注释与描述部分,下面的描述中给出了本次SQL语句使用了动态采样功能
----- 
- dynamic sampling used for this statement

58 rows selected.
2、实际执行计划中的各字段与模块

SQL> select /*+ gather_plan_statistics */ * --注意此处增加了提示gather_plan_statistics并且该语句被执行
2 from emp e,dept d
3 where e.deptno=d.deptno
4 and e.ename='SMITH'; 

7369 SMITH CLERK 7902 17-DEC-80 800 20 20 RESEARCH DALLAS

SQL> select * from table(dbms_xplan.display_cursor(null,null,'iostats last')); --使用display_cursor获取实际的执行计划

SQL_ID fpx7zw59f405d, child number 0 --这部分给出了SQL语句的SQL_ID,子游标号以及原始的SQL语句
-------------------------------------
select /*+ gather_plan_statistics */ * from emp e,dept d where e.deptno=d.deptno and
e.ename='SMITH'

Plan hash value: 351108634 --SQL 语句的哈希值
--SQL语句的执行计划,可以看到下面显示的字段一部分不同于预估执行计划中的字段
-----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | 
-----------------------------------------------------------------------------------------------------------
| 1 | NESTED LOOPS | | 1 | 1 | 1 |00:00:00.01 | 10 | 1 |
|* 2 | TABLE ACCESS FULL | EMP | 1 | 1 | 1 |00:00:00.01 | 8 | 0 |
| 3 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 1 | 1 |00:00:00.01 | 2 | 1 |
|* 4 | INDEX UNIQUE SCAN | PK_DEPT | 1 | 1 | 1 |00:00:00.01 | 1 | 1 |
-----------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
--------------------------------------------------- 

2 - filter("E"."ENAME"='SMITH') 
4 - access("E"."DEPTNO"="D"."DEPTNO")

Note
----- 
- dynamic sampling used for this statement


26 rows selected.
三、总结
由上可知,在不同的情形下可以获得执行计划的不同信息,而不同信息则展现了SQL语句对应的不同情况,因此应根据具体的情形具体分析。 
(转载请注明出处:[url=http://www.k8764.com]博彩通[/url]
[url=http://www.5sfd.com]e世博[/url])

posted @ 2012-04-18 16:50 夏凡 阅读(111) | 评论 (0)编辑 收藏

教你如何使用dbms_xplan之display_cursor函数

     摘要: DBMS_XPLAN包中display_cursor函数不同于display函数,display_cursor用于显示SQL语句的真实的执行计划,在大多数情况下,显示真实的执行计划有助于更好的分析SQL语句的全过程,尤其是运行此SQL语句实时的I/O开销。通过对比预估的I/O与真实的I/O开销来判断SQL语句所存在问题,如缺少统计信息,SQL语句执行的次数,根据实际中间结果集的大小来选择合适的连接...  阅读全文

posted @ 2012-04-18 16:45 夏凡 阅读(231) | 评论 (0)编辑 收藏

单链表,你懂了吗?

首先,上一道开胃菜:怎么判断两个单链表是否相交? 
      我们假设两个单链表分别是A(有m个结点)和B(有n个结点),当然,最容易想到的肯定是两层循环,遍历A中的元素,然后分别与B中的元素进行比较,但是这样做的时间复杂度达到了O(m*n),那么有没有更简单的办法呢?肯定有! 
      我们来看看单链表的性质:每个结点只通过一个指针指向后继结点。那么是不是意味着两个单链表如若相交,它们就只能是Y形相交,而不可能是X形相交,亦即从第一个相同的结点开始,后面的结点全部一样。如果能想到这个,后面的就简单明了了:只要A链表和B链表的最后一个结点值相等,则证明A链表和B链表相交。该算法的时间复杂度也下降到O(m+n)。 
      我们进一步来思考:怎么找到第一个相交的元素呢? 
      这里就当然不能像刚才那样,但是出发点还是一样,我们同样可以保证只要两次遍历。我们假设m > n,那么如果我们将两个链表的末尾对齐,是不是从最后一个往前看(当然单链表不能往前遍历,我们先这样看)的时候,A链表会比B链表多m-n个元素,而A链表中的前m-n个元素可以忽略,直接从第m-n个元素开始和B链表一起向前遍历,比较A链表上第m-n+i个元素和B链表第i个元素(i<n)即可。第一个相同的元素即为所求。参看下图可以帮助理解: 



      实现代码如下: 
Java代码  收藏代码
  1. /** 
  2.      * 寻找两个单链表第一个相同的元素。 
  3.      * @param A 第一个单链表 
  4.      * @param B 第二个单链表 
  5.      * @return 若存在相同元素,则返回其值;否则返回-1并打印消息 
  6.      */  
  7.     public static int findSame(FLinkedList A, FLinkedList B){  
  8.         int m = A.length();  
  9.         int n = B.length();  
  10.         FLinkedNode aHead = A.getElem(0);  
  11.         FLinkedNode bHead = B.getElem(0);  
  12.         if(m >= n){  
  13.             int s = m - n;  
  14.             for(int i = 0; i < s; i ++){  
  15.                 aHead = aHead.getNext();  
  16.             } // end for  
  17.             while(aHead.getNext() != null){  
  18.                 if(aHead.getValue() == bHead.getValue()){  
  19.                     return aHead.getValue();  
  20.                 }else{  
  21.                     aHead = aHead.getNext();  
  22.                     bHead = bHead.getNext();  
  23.                 } // end if-else  
  24.             } // end while  
  25.         }else{  
  26.             int s = n - m;  
  27.             for(int i = 0; i < s; i ++){  
  28.                 bHead = bHead.getNext();  
  29.             } // end for  
  30.             while(aHead.getNext() != null){  
  31.                 if(aHead.getValue() == bHead.getValue()){  
  32.                     return bHead.getValue();  
  33.                 }else{  
  34.                     aHead = aHead.getNext();  
  35.                     bHead = bHead.getNext();  
  36.                 } // end if-else  
  37.             } // end while  
  38.         } // end if-else  
  39.         System.out.println("没有找到相同的元素!!");  
  40.         return -1;  
  41.     } // end findSame  

(代码中的FlinkedList是本人自己实现的单链表,功能和系统的LinkedList差不多,方法的功能大家看名字就基本知道了,只是它是更纯粹的单链表而已) 

      下面来看看其它的几个单链表相关的典型问题(贴代码太占空间,这里就只谈谈思路,大家可以动手试试): 

      单链表的反转 
      如题,怎么实现一个单链表A(有m个元素)的反转呢? 
      方案一:如果不能破坏原单链表,我们需要重新新建一个链表C,然后遍历原来的A链表,对C链表实行头插法建表(头插法即将新加入的结点作为链表的头结点,对应的还有尾插法,即直接在链表末尾添加元素); 
      方案二:如果可以破坏原单链表呢?暴力一点的办法是不断地交换相邻的两个元素,即首先将第一个元素通过m-1次交换使其变成链表的最后一个元素,然后又是同样的方法将现任的第一个元素通过m-2次交换使其成为链表的倒数第二个元素,以此类推。 

      单链表的排序 
      就排序原理而言,个人觉得其实不用过多考虑存储结构的问题,即不管是顺序存储还是链式存储,都不影响排序的基本原理,只是不同的存储结构会影响不同排序方法的效率而已。因为我们完全可以夸张地将顺序存储也想象为不连续的存储只是它们相邻两者的间隙极端的小。即我们将货物分别存在美国和中国的仓库里和都存放在一个仓库里是一样的,只是运费问题而已。 
      明白了这一点,那么单链表的排序就和普通的数组排序没有什么太大的区别。我们现在要做的事就是针对性地选择一个时间性能相对较好的排序算法。 
      我们知道的排序方法有很多:插入排序、冒泡排序、快速排序、归并排序、堆排序以及基数排序等等,那么这其中哪些对顺序结构和链式结构不那么感冒呢?熟悉这些排序的童鞋肯定知道,是插入排序和冒泡排序。其他的几种常见排序方法就比较偏袒顺序存储结构了。所以,如果要对链表进行排序,我会选择插入排序或者冒泡排序。(不太清楚这些基本排序原理的click here:http://wlh0706-163-com.iteye.com/blog/1465570) 

      删除单链表中的最小元素 
      我能想到的办法就是遍历两次:第一次找到单链表中最小的元素,第二次遍历删除该元素。第一次遍历的时候需要借助两个变量,一个保存当前的最小元素的值,另一个保存当前最小值的位序。第二次遍历的时候当然就是删除第一次遍历得到的最小元素的位序上的元素了。 

      删除所有重复结点 
      这个一般得借助其他的数据结构了。基本思路应该是:遍历链表,用一个数据结构保存当前已经遍历的元素,若下一个访问的链表里的元素已经存在于已经访问的元素集合中,则删除单链表中的该元素,否则继续,直至到达链表的末尾。保存已经访问过的元素可以用数组,也可以用其他的。 

      判断一个链表是否包含另一个链表 
      这个问题其实和开篇的问题一样,只是换了一种说法而已。因此只要找到第一个相同的元素就可以了。 

      找出单链表中的倒数第K个元素 
      我们首先要确保的就是单链表的元素个数大于K。 
      这里的实现思路也很巧妙:我们定义两个指针a和b,全部指向链表的头结点,然后a指针开始向后遍历,但a遍历到第K个元素的时候,b指针也开始从头开始遍历,接下来的事你应该知道了,当a指针到达链表的末尾时,b指针恰好指着链表的倒数第K个元素。这样的时间复杂度是O(n)。 

      推广一下:怎么找单链表中间的那个元素呢?Ok, u let me know! 

      PS:这些问题肯定还有更好地解法和方案,希望您不吝赐教。 
(转载请注明出处:[url=http://www.k6567.com]e世博[/url]
[url=http://www.d9732.com]澳门博彩[/url])

posted @ 2012-04-18 15:28 夏凡 阅读(198) | 评论 (0)编辑 收藏

关于java对dll的调用

为方便讨论,例子中dll只导出了一个计算两个参数和的方法。 
------------------------- 
注: 
java调用dll一般来说都是要根据头文件再去实现一下dll(c++,fortran等),有的童鞋可能会问:我只有一个dll文件,我想调用里面的方法,能不能直接用?这个据偶的水平没法解决,可能有高手会~~ 
------------------------- 
    第一步:生成编写dll文件所需的C语言头文件 
首先建立dllTest工程,在src目录下建包com.lxw; 
建立java文件DllTest.java: 
package com.lxw; 

import java.lang.System; 

public class DllTest { 
static{ 
System.loadLibrary("DllTest");  //载入dll,不用后缀 

public native static int getSum(int i,int j);//函数声明 

cmd进入dos下,进入D:\workspace\dllTest\src\com\lxw目录; 
使用命令javac DllTest.java,编译文件,在lxw目录下生成DllTest.class文件; 
使用命令cd..两次进入src目录; 
使用命令javah -jni com.lxw.DllTest即可在src目录下生成com_lxw_DllTest.h的头文件,内容如下: 
/* DO NOT EDIT THIS FILE - it is machine generated */ 
#include <jni.h> 
/* Header for class com_lxw_DllTest */ 

#ifndef _Included_com_lxw_DllTest 
#define _Included_com_lxw_DllTest 
#ifdef __cplusplus 
extern "C" { 
#endif 
/* 
* Class:     com_lxw_DllTest 
* Method:    getSum 
* Signature: (II)I 
*/ 
JNIEXPORT jint JNICALL Java_com_lxw_DllTest_getSum 
  (JNIEnv *, jclass, jint, jint); 

#ifdef __cplusplus 

#endif 
#endif 
注意生成的头文件导出的函数名字为Java_com_lxw_DllTest_getSum; 
------------------------- 
    第二步:编写dll文件 
打开vc选择新建工程DllTest,类型选择dll,可以将export symbols参数选上,帮你生成一些基本文件;也可不选;
将com_lxw_DllTest.h文件拷贝到工程目录下,我这里为:D:\vs2010projects\DllTest\DllTest; 
将jawt_md.h,jni.h,jni_md.h文件(jdk的include目录和include\win32目录)拷贝到vc目录:C:\Program Files\Microsoft Visual Studio 10.0\VC\include; 
这时工程并不包含拷贝进去的头文件,所以在工程的Header Files下右键导入com_lxw_DllTest.h文件;导入后同级的头文件还有stdafx.h和targetver.h文件,自动生成的DllTest.h可以删掉; 
在Source Files下有三个文件dllmain.cpp,DllTest.cpp,stdafx.cpp,其中dllmain是dll必须的,自动生成,stdafx也是系统自动生成的,不用管,dllmain的内容如下: 
// dllmain.cpp : Defines the entry point for the DLL application. 
#include "stdafx.h" 

BOOL APIENTRY DllMain( HMODULE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved 


switch (ul_reason_for_call) 

case DLL_PROCESS_ATTACH: 
case DLL_THREAD_ATTACH: 
case DLL_THREAD_DETACH: 
case DLL_PROCESS_DETACH: 
break; 

return TRUE; 

这个就是dll的入口函数,和main winmain类似,主要处理dll的四种状态,不详谈了,有兴趣可以自己去了解; 
DllTest.cpp文件可能会自动生成一些内容,vs2010的会实现一个int,class以及一个函数,这里将他们全部删除,编辑内容如下: 
// DllTest.cpp : Defines the exported functions for the DLL application. 
// 

#include "stdafx.h" 
#include "com_lxw_DllTest.h" 
JNIEXPORT jint JNICALL Java_com_lxw_DllTest_getSum 
(JNIEnv *, jclass, jint a, jint b){
          return a+b; 

注意包含头文件,导出函数的格式可以从com_lxw_DllTest.h拷贝,不过多了参数a,b; 
OK,编译工程,会在debug或者release目录下生成DllTest.dll文件; 
我们可以看一下此文件导出的内容: 
在dll所在目录下使用命令dumpbin -exports DllTest.dll >1.txt,打开1.txt,其中里面有内容: 
ordinal hint RVA      name 

          1    0 00001010 _Java_com_lxw_DllTest_getSum@16 = _Java_com_lxw_DllTest_getSum@16 
我们可以看到这个dll导出了一个函数,名字为_Java_com_lxw_DllTest_getSum;但是我们在后面的java文件中调用的时候使用getSum名字就可以; 
------------------------- 
    第三步:java中调用DllTest.dll 
首先必须将DllTest.dll文件拷贝到java可以识别的路径,这里我拷贝到jdk的bin目录; 
在刚才的java工程中新建java文件: 
package com.lxw; 
public class DllMain { 

public static void main(String[] args) { 
System.out.println(DllTest.getSum(10, 11)); 


注意:这里直接使用getSum函数即可;而这里的DllTest.java文件就起到类似C语言中的头文件的作用; 
---------------- 
应该没什么遗忘的了~~~  这里写的很详细了~~~  希望可以帮到大家~~~ 
(转载请注明出处:[url=http://www.a9832.com]博彩网[/url]
[url=http://www.tswa.org]博彩通[/url])

posted @ 2012-04-18 15:01 夏凡 阅读(196) | 评论 (0)编辑 收藏

静态变量、静态初始化块、变量、初始化块、构造器函数

     摘要: 面试的时候,经常会遇到这样的考题:给你两个类的代码,它们之间是继承的关系,每个类里只有构造器方法和一些变量,构造器里可能还有一段代码对变量值进行了某种运算,另外还有一些将变量值输出到控制台的代码,然后让我们判断输出的结果。这实际上是在考查我们对于继承情况下类的初始化顺序的了解。 我们大家都知道,对于静态变量、静态初始化块、变量、初始化块、构造器,它们的初始化顺序以此是(静态变量、静态初始...  阅读全文

posted @ 2012-04-18 14:56 夏凡 阅读(298) | 评论 (0)编辑 收藏

有光Android Socket的编程

     摘要: 花了大概两天的时间,终于把Android的Socket编程给整明白了。抽空和大家分享一下: Socket Programming on Android Socket 编程基础知识: 主要分服务器端编程和客户端编程。 服务器端编程步骤: 1: 创建服务器端套接字并绑定到一个端口上(0-1023是系统预留的,最好大约1024) 2: 套接字设...  阅读全文

posted @ 2012-04-18 13:58 夏凡 阅读(353) | 评论 (0)编辑 收藏

【解惑】你知道javascript中的“===”怎么用吗?

“软件编程中最重要的操作之一在于判断俩个变量是不是相同” - 来自Nicholas Zakas的书JavaScript for Web Developers.

换句话说,可能在你的编程中,你可能用过这些代码片段吧:

if (x == y) {
    // do something here
}

或者你使用最佳实践方式:

if (x === y) {
    // do something here
}

以上代码片段中不同的地方在于第二个例子使用了“===”操作符,也叫“严格等于”或者“绝对等于”。

对于Javascript新手来说呢,什么时候使用双等于号,或者什么时候使用三等于号确实有点儿迷糊。这里今天这篇文章我们将帮助大家了解这背后的故事。

有没有区别?

使用双等于号操作符的话,如果两者相等的话,结果会返回true。但是大家要注意:如果是不同类型的变量比较的话,变量强制变换就会发生。当然,这也是javascript语法的特点之一。

每 一个javascript的变量都属于一个指定的类型。例如,数字,boolean,功能和对象。如果你比较一个字符串和数字,浏览器就会在比较之前将字 符串强制的转化为数字。同样,如果你将true或者false和数字比较的话。true和false会被强制转化为数字1或者0。

这将会带来不可预知的结果,如下:

console.log(99 == "99"); // true
console.log(0 == false); // true

当然,以上例子非常不错,因为浏览器将帮助你自动转化,省了你不少劲儿。但是这有可能出错,如下:

console.log(' \n\n\n' == 0); // true
console.log(' ' == 0); // true

因为如上原因,javascript的高手都推荐你使用“===”来执行等于操作。永远不要使用“==”。

“===”永远不执行类型转化。因为你使用它来执行等于操作非常安全。

以下例子将都产生正确的结果:

console.log(99 === "99"); // false
console.log(0 === false); // false
console.log(' \n\n\n' === 0); // false
console.log(' ' === 0); // false

不等于如何操作呢?

类似,只不过这里我们使用“!==”来执行。如下:

console.log(99 !== "99"); // true
console.log(0 !== false); // true
console.log(' \n\n\n' !== 0); // true
console.log(' ' !== 0); // true
(转载请注明出处:
[url=http://www.k8764.com]博彩通[/url]
[url=http://www.5sfd.com]e世博[/url]

posted @ 2012-04-18 13:22 夏凡 阅读(148) | 评论 (0)编辑 收藏

Java程序员不能太过于于依赖String

     摘要: 我想标题可能会引进部分人的不满,抑或作者带着强烈的个人色彩,但是如果你能认真读完全文,我想你会有新的收获。   永远也不要使用(非包装类型)的String、long、int,那些原始类型没有语义,这样的变量类型很难理解、维护麻烦、而且不易扩展,接下来看一个简单的例子-----关于电影票的服务   在看这个例子之前要说的话:如果你在评论中告诉我,你坚决反对我的...  阅读全文

posted @ 2012-04-18 13:17 夏凡 阅读(135) | 评论 (0)编辑 收藏

关于提高Java编程的性能尽量要做的几点

最近的机器内存又爆满了,除了新增机器内存外,还应该好好review一下我们的代码,有很多代码编写过于随意化,这些不好的习惯或对程序语言的不了解是应该好好打压打压了。 

下面是参考网络资源总结的一些在Java编程中尽可能要做到的一些地方。 

1. 尽量在合适的场合使用单例 

使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面: 

第一,控制资源的使用,通过线程同步来控制资源的并发访问; 

第二,控制实例的产生,以达到节约资源的目的; 

第三,控制数据共享,在不建立直接关联的条件下,让多个不相关的进程或线程之间实现通信。 

2. 尽量避免随意使用静态变量 

要知道,当某个对象被定义为stataic变量所引用,那么gc通常是不会回收这个对象所占有的内存,如 

public class A{  
static B b = new B();  

此时静态变量b的生命周期与A类同步,如果A类不会卸载,那么b对象会常驻内存,直到程序终止。 

3. 尽量避免过多过常的创建Java对象 

尽量避免在经常调用的方法,循环中new对象,由于系统不仅要花费时间来创建对象,而且还要花时间对这些对象进行垃圾回收和处理,在我们可以控制的范围内,最大限度的重用对象,最好能用基本的数据类型或数组来替代对象。 

4. 尽量使用final修饰符 

带有final修饰符的类是不可派生的。在Java核心API中,有许多应用final的例子,例如java.lang.String。为String类指定final防止了使用者覆盖length()方法。另外,如果一个类是final的,则该类所有方法都是final的。Java编译器会寻找机会内联(inline)所有的final方法(这和具体的编译器实现有关)。此举能够使性能平均提高50%。 

5. 尽量使用局部变量 

调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack)中,速度较快。其他变量,如静态变量、实例变量等,都在堆(Heap)中创建,速度较慢。 

6. 尽量处理好包装类型和基本类型两者的使用场所 

虽然包装类型和基本类型在使用过程中是可以相互转换,但它们两者所产生的内存区域是完全不同的,基本类型数据产生和处理都在栈中处理,包装类型是对象,是在堆中产生实例。 

在集合类对象,有对象方面需要的处理适用包装类型,其他的处理提倡使用基本类型。 

7. 慎用synchronized,尽量减小synchronize的方法 

都知道,实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。synchronize方法被调用时,直接会把当前对象锁 了,在方法执行完之前其他线程无法调用当前对象的其他方法。所以synchronize的方法尽量小,并且应尽量使用方法同步代替代码块同步。 

8. 尽量使用StringBuilder和StringBuffer进行字符串连接 

这个就不多讲了。 

9. 尽量不要使用finalize方法 

实际上,将资源清理放在finalize方法中完成是非常不好的选择,由于GC的工作量很大,尤其是回收Young代内存时,大都会引起应用程序暂停,所以再选择使用finalize方法进行资源清理,会导致GC负担更大,程序运行效率更差。 

10. 尽量使用基本数据类型代替对象 

String str = "hello"; 
上面这种方式会创建一个“hello”字符串,而且JVM的字符缓存池还会缓存这个字符串; 

String str = new String("hello"); 
此时程序除创建字符串外,str所引用的String对象底层还包含一个char[]数组,这个char[]数组依次存放了h,e,l,l,o 

11. 单线程应尽量使用HashMap、ArrayList 

HashTable、Vector等使用了同步机制,降低了性能。 

12. 尽量合理的创建HashMap 

当你要创建一个比较大的hashMap时,充分利用另一个构造函数 

public HashMap(int initialCapacity, float loadFactor) 
避免HashMap多次进行了hash重构,扩容是一件很耗费性能的事,在默认中initialCapacity只有16,而loadFactor是 0.75,需要多大的容量,你最好能准确的估计你所需要的最佳大小,同样的Hashtable,Vectors也是一样的道理。

13. 尽量减少对变量的重复计算 

如 

for(int i=0;i<list.size();i++) 
应该改为 

for(int i=0,len=list.size();i<len;i++) 
并且在循环中应该避免使用复杂的表达式,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快。 

14. 尽量避免不必要的创建 

如 

A a = new A();  
if(i==1){list.add(a);} 
应该改为 

if(i==1){  
A a = new A();  
list.add(a);} 
15. 尽量在finally块中释放资源 

程序中使用到的资源应当被释放,以避免资源泄漏。这最好在finally块中去做。不管程序执行的结果如何,finally块总是会执行的,以确保资源的正确关闭。 

16. 尽量使用移位来代替'a/b'的操作 

"/"是一个代价很高的操作,使用移位的操作将会更快和更有效 

如 

int num = a / 4;  
int num = a / 8; 
应该改为 

int num = a >> 2;  
int num = a >> 3; 
但注意的是使用移位应添加注释,因为移位操作不直观,比较难理解 

17.尽量使用移位来代替'a*b'的操作 

同样的,对于'*'操作,使用移位的操作将会更快和更有效 

如 

int num = a * 4;  
int num = a * 8; 
应该改为 

int num = a << 2;  
int num = a << 3; 
18. 尽量确定StringBuffer的容量 

StringBuffer 的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小,就会重新分配内存,创建一个更大的数组,并将原先的数组复制过来,再 丢弃旧的数组。在大多数情况下,你可以在创建 StringBuffer的时候指定大小,这样就避免了在容量不够的时候自动增长,以提高性能。 

如: 

StringBuffer buffer = new StringBuffer(1000); 
19. 尽量早释放无用对象的引用 

大部分时,方法局部引用变量所引用的对象 会随着方法结束而变成垃圾,因此,大部分时候程序无需将局部,引用变量显式设为null。 

例如: 

Public void test(){  
Object obj = new Object();  
……  
Obj=null;  

上面这个就没必要了,随着方法test()的执行完成,程序中obj引用变量的作用域就结束了。但是如果是改成下面: 

Public void test(){  
Object obj = new Object();  
……  
Obj=null;  
//执行耗时,耗内存操作;或调用耗时,耗内存的方法  
……  

这时候就有必要将obj赋值为null,可以尽早的释放对Object对象的引用。 

20. 尽量避免使用二维数组 

二维数据占用的内存空间比一维数组多得多,大概10倍以上。 

21. 尽量避免使用split 

除非是必须的,否则应该避免使用split,split由于支持正则表达式,所以效率比较低,如果是频繁的几十,几百万的调用将会耗费大量资源,如果确实需 要频繁的调用split,可以考虑使用apache的StringUtils.split(string,char),频繁split的可以缓存结果。 

22. ArrayList & LinkedList 

一 个是线性表,一个是链表,一句话,随机查询尽量使用ArrayList,ArrayList优于LinkedList,LinkedList还要移动指 针,添加删除的操作LinkedList优于ArrayList,ArrayList还要移动数据,不过这是理论性分析,事实未必如此,重要的是理解好2 者得数据结构,对症下药。 

23. 尽量使用System.arraycopy ()代替通过来循环复制数组 

System.arraycopy() 要比通过循环来复制数组快的多 

24. 尽量缓存经常使用的对象 

尽可能将经常使用的对象进行缓存,可以使用数组,或HashMap的容器来进行缓存,但这种方式可能导致系统占用过多的缓存,性能下降,推荐可以使用一些第三方的开源工具,如EhCache,Oscache进行缓存,他们基本都实现了FIFO/FLU等缓存算法。 

25. 尽量避免非常大的内存分配 

有时候问题不是由当时的堆状态造成的,而是因为分配失败造成的。分配的内存块都必须是连续的,而随着堆越来越满,找到较大的连续块越来越困难。 

26. 慎用异常 

当创建一个异常时,需要收集一个栈跟踪(stack track),这个栈跟踪用于描述异常是在何处创建的。构建这些栈跟踪时需要为运行时栈做一份快照,正是这一部分开销很大。当需要创建一个 Exception 时,JVM 不得不说:先别动,我想就您现在的样子存一份快照,所以暂时停止入栈和出栈操作。栈跟踪不只包含运行时栈中的一两个元素,而是包含这个栈中的每一个元素。 

如 果您创建一个 Exception ,就得付出代价。好在捕获异常开销不大,因此可以使用 try-catch 将核心内容包起来。从技术上讲,您甚至可以随意地抛出异常,而不用花费很大的代价。招致性能损失的并不是 throw 操作——尽管在没有预先创建异常的情况下就抛出异常是有点不寻常。真正要花代价的是创建异常。幸运的是,好的编程习惯已教会我们,不应该不管三七二十一就 抛出异常。异常是为异常的情况而设计的,使用时也应该牢记这一原则。 
(转载请注明出处:[url=http://www.k6567.com]e世博[/url]
[url=http://www.d9732.com]澳门博彩[/url])

posted @ 2012-04-18 12:48 夏凡 阅读(113) | 评论 (0)编辑 收藏

仅列出标题
共5页: 上一页 1 2 3 4 5 下一页