You are here: Home ยป Blog

In JDeveloper, the integrated weblogic server creates its runtime domain in a directory like $HOME/.jdeveloper/system12.1.3.0.41.140521.1008/DefaultDomain or $HOME/.jdeveloper/system/11.1.1.7.40.65.57.5/DefaultDomain.

While $HOME and the fixed DefaultDomain are well known, it is not so easy to determine the actual name of the system directory - one could assume that there is only one and use system* as the name, but there could be more than one, especially if more than one JDeveloper version is installed at the same time and each of them had been creating its own WLS domain. What we actually need is to get the JDeveloper version since that is what is used in the system directory name.

Assumed that $JDEV_HOME is the installation directory of the JDeveloper installation for which we would like to get its domain home directory (like /opt/Oracle/Middleware/Oracle_Home/jdeveloper), then the file $JDEV_HOME/jdev/bin/version.properties contains the full version number of JDeveloper, which is identical to the version number used in the system directory name:

$ grep VER_FULL $JDEV_HOME/jdev/bin/version.properties
VER_FULL=12.1.3.0.41.140521.1008

To extract the version number, we can use a simple sed script like

$ sed -n 's/^VER_FULL=\([0-9.]*\).*$/\1/p' $JDEV_HOME/jdev/bin/version.properties
12.1.3.0.41.140521.1008

(we need to make sure not to include the terminating line feed, hence we only collect digits and dots after the =).

Finally we can now generate the complete directoy path to the domain directory:

$ JDEV_VER=`sed -n 's/^VER_FULL=\([0-9.]*\).*$/\1/p' $JDEV_HOME/jdev/bin/version.properties`
$ DOMAIN_HOME="${HOME}/.jdeveloper/system${JDEV_VER}/DefaultDomain"
$ ls $DOMAIN_HOME/servers
AdminServerTag  DefaultServer

This can be useful for any kind of automation tasks.


Using column aliases in a WHERE clause

Posted on Wednesday, May 20 2015 at 12:18 | Category: SQL & Databases | 1 Comment(s)

Just wanted to answer a question on StackOverflow, where someone had a data model like this:

CREATE TABLE tvalues (cid NUMBER, cvalue NUMBER);
INSERT INTO tvalues VALUES(1, 200);
INSERT INTO tvalues VALUES(2, 1500);
INSERT INTO tvalues VALUES(3, 3200);
INSERT INTO tvalues VALUES(4, 4500);
COMMIT;
SELECT * FROM tvalues;
CID  CVALUE
------------
  1    200
  2   1500
  3   3200
  4   4500

The question was how to get the cid of the row so that a given value is between the value of the previous row and the value of the row for which to return the id (e.g. given value = 4000 should return id=4). Obviously, since in a relational database system, rows do not have an inherent order (there is no "next" or "previous" row), we need a sort criteria which I simply assumed to be the CID column.

The solution I had in mind was to use an analytical function like LEAD() or LAG(). These functions allow to access the next or the previous row (see how the analytical function requires an ORDER definition, otherwise it would not know what the next or previous row is):

SELECT cid, LAG(cvalue, 1, 0) OVER(ORDER BY cid) cmin, cvalue cmax
FROM tvalues;
CID     CMIN        CMAX
--------------------------
  1        0         200
  2      200        1500
  3     1500        3200
  4     3200        4500

This returns a nice range-wise view of the data. Now the final solution should be easy: simply restrict the result set so that the given value is between the minimum and the maximum value:

SELECT cid, LAG(cvalue, 1, 0) OVER(ORDER BY cid) cmin, cvalue cmax
FROM tvalues
WHERE cmin < 4000 AND cmax > 4000;

However, this query returns an error message:

ORA-00904: "CMAX": invalid identifier
The reason is that it is generally not possible to use column aliases in the WHERE clause (or in any other part of the SELECT statement, with a few exceptions like ORDER BY). This also has nothing to do with the analytical functions - the following simple query does not work either:
SELECT cvalue avalue
FROM tvalues
WHERE avalue > 1000;
ORA-00904: "AVALUE": invalid identifier
00904. 00000 -  "%s: invalid identifier"

The reason is that the select list (the projection) is the last part which is processed in an SQL statement, hence the SQL parser does not yet know the column aliases when it processes other parts of the query, like the WHERE statement (btw, while investigating this, someone else posted a very similar answer to the original question).

The final solution is easy: the query just needs to be wrapped into another query as a sub query:

SELECT * FROM (
   SELECT cid, LAG(cvalue, 1, 0) OVER(ORDER BY cid) cmin, cvalue cmax
   FROM tvalues
) WHERE cmin < 4000 AND cmax > 4000;
CID     CMIN        CMAX
--------------------------
4	3200	    4500

Tracing shared library calls with ltrace and latrace

Posted on Tuesday, May 05 2015 at 13:13 | Category: C, Linux | 3 Comment(s)

Tracing shared library calls with ltrace

Similar to strace, which can be used to trace system calls, ltrace can be used to trace shared library calls. This can be very useful to get insight into the program flow of applications while analyzing an issue.

Consider the following simple sample:

hello.c:

include <stdio.h>

void helloFunc(const char* s) {
   printf(s);
}

hello.h:


void helloFunc(const char* s);

helloMain.c:

#include "hello.h"

int main() {
   helloFunc("Hello World, how are you?");
   return 0;
}

We create a shared library from hello.c:

$ gcc -fPIC --shared -o libhello.so hello.c
And we create the executable from helloMain.c which links against the library created before:
$ gcc -o hello helloMain.c -lhello -L.

We can now use ltrace to see which library calls are executed:

$ export LD_LIBRARY_PATH=.
$ ltrace ./hello 
__libc_start_main(0x40069d, 1, 0x7fffe2f3b778, 0x4006c0 <unfinished ...>
helloFunc(0x400744, 0x7fffe2f3b778, 0x7fffe2f3b788, 0)              = 25
Hello World, how are you?+++ exited (status 0) +++

One drawback with ltrace is that it only traces calls from the executable to the libraries the executable is linked against - it does not trace calls between libraries! Hence, the call to the printf() function (which itself resides in the libc shared library) is not shown in the output. Also, there is no option to include the library name in the output for each of the called functions.

Tracing shared library calls with latrace

Especially for larger applications, a better alternative to ltrace is latrace which uses the LD_AUDIT feature from the libc library (available from libc 2.4 onward). On Ubuntu, it can be installed with

$ sudo apt-get install latrace
When using latrace with the sample program from above, there are two important differences:
  • First, latrace also traces library calls between shared libraries, so the output includes the printf call executed from our own shared library.
  • Second, the shared library name which contains the symbol is printed after each function call:
$ latrace ./hello
10180     _dl_find_dso_for_object [/lib64/ld-linux-x86-64.so.2]  
10180     __libc_start_main [/lib/x86_64-linux-gnu/libc.so.6]  
10180       helloFunc [./libhello.so]  
10180         printf [/lib/x86_64-linux-gnu/libc.so.6]  
10180       __tls_get_addr [/lib64/ld-linux-x86-64.so.2]  
10180       __cxa_finalize [/lib/x86_64-linux-gnu/libc.so.6]  
Hello World, how are you?
./hello finished - exited, status=0

By default, function parameters are not shown, but this can be enabled with the -A option:

$ latrace -A ./hello
10190     _dl_find_dso_for_object [/lib64/ld-linux-x86-64.so.2]  
10190     __libc_start_main(main = 0x40069d, argc = 1, ubp_av = 0x7fffccd35248, auxvec = 0x4006c0, init = 0x400730, fini = 0x7f3d16b21560, rtld_fini = 0x7fffccd35238) [/lib/x86_64-linux-gnu/libc.so.6] {
10190       helloFunc [./libhello.so]  
10190         printf(format = "Hello World, how are you?") [/lib/x86_64-linux-gnu/libc.so.6] {
Hello World, how are you?10190         } printf = 25
10190       __tls_get_addr [/lib64/ld-linux-x86-64.so.2]  
10190       __cxa_finalize(ptr = 0x7f3d1650b030) [/lib/x86_64-linux-gnu/libc.so.6] {
10190       } __cxa_finalize = void

With -A, ltrace uses some configuration files at /etc/latrace.d to define the parameter format for a set of well-known functions such as printf. We can see in the output that, even though helloFunc() takes a parameter, this parameter is not shown in the output (since it is not defined in the configuration files).

We can use the -a option to specify our own argument definition file. An argument definition file is essentially a header file which defines the prototypes for all functions for which the arguments should be displayed in the output. On Ubuntu, the default argument definition files are stored at /etc/latrace.d/headers/, and there is a master file /etc/latrace.d/headers/latrace.h which includes the other header files. We can use the same approach in our own definition file, by first including the master file from /etc/latrace.d/headers/latrace.h and then add the prototypes for each function we want to trace. For our ssample above, the file could look like

#include "/etc/latrace.d/headers/latrace.h"
void helloFunc(const char* s);

Assumed this file is called mylatrace.h, wen can now use the -a option to pass the file to latrace:

$ latrace -a mylatrace.h -A ./hello
10801     _dl_find_dso_for_object [/lib64/ld-linux-x86-64.so.2]  
10801     __libc_start_main(main = 0x40069d, argc = 1, ubp_av = 0x7fff4b89fb58, auxvec = 0x4006c0, init = 0x400730, fini = 0x7f1927ea1560, rtld_fini = 0x7fff4b89fb48) [/lib/x86_64-linux-gnu/libc.so.6] {
10801       helloFunc(s = "Hello World, how are you?") [./libhello.so] {
10801         printf(format = "Hello World, how are you?") [/lib/x86_64-linux-gnu/libc.so.6] {
10801         } printf = 25
10801       } helloFunc = void
10801       __tls_get_addr [/lib64/ld-linux-x86-64.so.2]  
Hello World, how are you?10801       __cxa_finalize(ptr = 0x7f192788b030) [/lib/x86_64-linux-gnu/libc.so.6] {
10801       } __cxa_finalize = void
./hello finished - exited, status=0

As you can see in the output, we now also see that helloFunc() is called with one parameter s which is set to "Hello World, how are you?".


Examining nested stack traces

Posted on Tuesday, April 21 2015 at 09:06 | Category: Java | 0 Comment(s)

I often read Java Stack traces bottom up when I examine them for the first time - simply because this is the code path which was executed when the exception occurred. However, it can happen that the last line of a stack trace shows something like ... 2 more - so, one might ask why can't the runtime just dump those missing lines, along with all the other stack trace elements? Real life server stack traces sometimes contain dozens of lines, it should not matter to print those additional lines, right? And often those lines contain just the information you require to see from where the problematic code which caused the exception was called ...

The thing is: those lines are actually in the stack trace. Lets consider this example:

Exception in thread "main" java.lang.RuntimeException: java.lang.RuntimeException: Exception thrown
	at com.example.TraceTest.doSomething(TraceTest.java:13)
	at com.example.TraceTest.run(TraceTest.java:6)
	at com.example.TraceTest.main(TraceTest.java:22)
Caused by: java.lang.RuntimeException: Exception thrown
	at com.example.TraceTest.throwAnException(TraceTest.java:18)
	at com.example.TraceTest.doSomething(TraceTest.java:11)
	... 2 more

As you can see, the last line reads ... 2 more, but it might be crucial for the further analysis to know from where the doSomething() method was called. In order to get this information, we need to look further up in the stack trace: There, we again find the doSomething() method at the top and see that it was called from the run() method. In other words, the initial entry point for the code flow is the last element of the first stack trace block - from there, we can follow to the next stack trace block to see where the exception was finally thrown:

 

The reason for this is that the original exception was wrapped as nested exception into another exception. The following is the code which was used for the test above:

package com.example;

public class TraceTest {
    
    public void run() {
        doSomething();
    }

    private void doSomething() {
        try {
            throwAnException();
        }catch(RuntimeException re) {
            throw new RuntimeException(re);
        }
    }

    private void throwAnException() {
        throw new RuntimeException("Exception thrown");
    }

    public static void main(String[] args) {
        new TraceTest().run();
    }
}

Real stack traces might also contain more than one nested exception, so it might be necessary to follow them more than once.

In any case, the stack trace still contains the whole code path from the entry point (usually main) to the place where the exception was thrown.

See also how to print the full stacktrace in java on StackOverflow.


Displaying results 9 to 12 out of 115