Nov 15, 2012

Learning git

If you are a software developer you should already use some sort of SCM (if not I urge you to start to learn/use one now!). 

If you have not tried Git yet you should give it a try (but keep in mind it may take some time until you really appreciate its power).

I have been working with Git for at least 2 years and I am amazed how flexible / powerful it is. Actually it is so powerful I still learn new stuff about it almost every other day! Bellow you can find some useful resources to learn a little bit more about it:

Have fun!

Oct 15, 2012

Modern times

When I was a child (not so long ago :) I used to turn on the TV and wait for some time until it warmed up (ok, don't laugh). Exactly, it was a B&W valved tube tv.

Then, at my adolescence, my father bought us a new, shine, top technology color TV; it did not used valves any more and as a result live became better (not only I could turn the TV on and start watching my favorite programs instantaneously - or play video game - but now it had colors!!

Some more time passed (just a few years) and we fast forward to current days.

Now, after a long working day, leaving my office and walking 3 meters, I take a seat in front of my shine new, 51", full hd, 3D plasma TV, turn it on and... it takes 10 ~ 20 seconds to 
start displaying any interesting content (sure the TV maker logo appears in less than 5 secs but it is not that interesting any more)! What? Are we retrogressing ?

I really don't care if these TVs are actually computers... please tv makers, do it right! make it "boot" instantaneously, don't make me wait. I can foresee how the TVs ads will look like in the near future:
you do need to have this flub glob shob TV! It has more features than a computer scientist with a PHD is able to handle and it starts in (put some low number here) seconds!
What will be the next step? getting BSODs (calm down *nix fan boys I did not forget you ;) or Core dumps while watching TV?

You may think I'm kidding about the BSOD stuff, but I am not; for sure my cable TV setupbox already "implemented" this feature (the only deviation from the original BSOD is that you get absolutely no feedback so you are left wondering what happened and the only option is to restart it (hopping it fixes the problem); seriously, it is so crap that sometimes I need to restart it multiple times to get it working again (the cable tv support staff is so used to these issues that the first thing they ask you is to reset the setupbox :m ).

What do you think?

Oct 10, 2012

Icons, Icons, Icons....

From time to time I find myself looking for icons for my own projects....

If you ever had the same need check this out.

I really recommend it :)

Happy programming.

Sep 25, 2012

Angry user...

Sorry, I could not resist the pun :)

Well, some time ago (to be more precise 1 1/2 years ago) I've bought a (Chinese) Android Tablet so I could experiment, play games and may be try to develop some program (of course I've failed miserable to write any application for it :(. You can see a picture of the device bellow (it ended up to be much more resistant than what I expected! You can see its cracked 
screen due to 2 ~ 3 not so smooth landings - thanks to my young daughter):

Anyway, I use it regularly for reading ebooks, email reading and playing basic games. Talking about games I used to play "Angry Birds" (all free editions) on this device with no problems at all; but at some point in time something has changed and since then I am not able to play it anymore. The symptoms are always the same: I launch the game, its "splash screen" shows up followed by some screens and finally the "loading" screen shows up but then the application just dies without any trace! 


I had just accepted the fact that I'd not be able to play this game again on this device but last weekend I was recovering from a small surgery and I decided to investigate it a little bit more.


First thing I did was to install a log viewer (I'm using aLogCat) to check if I could find anything on Android logs. Indeed it was pretty easy to find the information I was looking for:


E/HttpRequestHelper( 4956): Exception from HttpClient.execute.
E/HttpRequestHelper( 4956): java.net.UnknownHostException: rovio.events.medio.com
E/HttpRequestHelper( 4956): at java.net.InetAddress.lookupHostByName(InetAddress.java:513)
E/HttpRequestHelper( 4956): at java.net.InetAddress.getAllByNameImpl(InetAddress.java:278)
E/HttpRequestHelper( 4956): at java.net.InetAddress.getAllByName(InetAddress.java:242)
E/HttpRequestHelper( 4956): at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:136)
E/HttpRequestHelper( 4956): at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
E/HttpRequestHelper( 4956): at


Huum... ok, so the application tried to resolve the host "rovio.events.medio.com" and it failed bringing the whole app down! WTF? (I tried to access this host from my desktop and the result is the same (
Interesting enough, medio.com as well events.medio.com does exist) so I assume the problem is directly related to the subdomain "rovio" on events.medio.com.

Searching on net for this error did not bring any useful answer. Also I've tried to clear Angry Birds application data, 
re-install it and even a device factory reset (due to other issues) to no avail :(. 

Have you seem this error? Any ideas how to fix it? I doubt I am the first one to stumble on it!

Sep 15, 2012

Shopping abroad


If you by stuff while travelling abroad (more specifically to European and some Asiatic countries) you may be paying more than you need to! This is because in such countries there are some taxes that tourists do not need to pay but they are included in the product price anyway.

Bellow I show the basic steps to make sure you'll get a tax refund:


  1. Find a participant store
  2. Buy and pay (of course) your stuff
  3. Tell the clerk that you want to get a tax-refund (at this point he/she will fill a form with information regarding your purchases / you)
  4. At the airport do the procedure to get your refund.
I'll not explain all these steps in details here; instead I'll focus on how to proceed at the airport (step 4) because that was the most confusing part for me. For more information, including the complete list of countries you can check here.

Also, keep in mind that the following description is based on my own experience (mostly travelling to Germany) and it may be different in other countries (although I believe that they are either pretty similar if not the same in all countries).


So, when you get ready to return:


  1. At the check-in post inform the clerk that you have a tax-refund to claim. She/he should follow the usual procedure but instead of dispatching your bags immediately it will be handed back to you (with the baggage identification stickers on it).
  2. Now you need to go tho the customs where a custom official will check your purchases, receipts and stamp the form filled at the store. At this moment your bags will be dispatched.
  3. With your form stamped go to the "tax-free" post (usually within the board area, i.e, after the security checks) and present the just stamped form and your passport.
  4. Get some of your hard earned money  back.

Regarding refund methods I have used two different ones: i) cash, ii) credit in a credit card; sometimes the tax-refund clerk asks you which method do you want, sometimes he/she will pick one for you :)

One mistake I've made at least twice was to forget that in some flight connections you don't take your bags back at the intermediate airport. For instance in one of my travels I was returning from Germany to Brasil but my flight had a connection in France, i.e, I'd fly from Germany -> France -> Brasil. Since the instructions are to follow this procedure when you are leaving EU I planed to  do this in France, but wait, I did not got my bags back in France, so no refund for me this time. In this case I should have done the process in Germany.


BTW: Last time I got back 13 euros which represents more or less 10% of my expenses (this value may vary for each country of course).


Hope this help others....

Sep 4, 2012

C#/.Net Generic constraints

Hi

Despite having no doubt about the usefulness of type constraints in C# generics (this is a key feature to help avoiding bugs when writing generic code in C#) I always had  the impression that it should be able to express more constraints than what the C# language / compiler exposes.

Well, some
 time ago this blog entry called my attention on my RSS reader and motivated me to go and scan the .Net specification (more specifically § II.10.1.7 in the CLI Metadata Definition and Semantics document which can be downloaded from here) and to my surprise I found out that in addition to the valid C# generic constraints CLI also support constraining a generic argument to delegates, arrays and even enums! That is nice.

Next question is: does the C# compiler abides by these rules when consuming assemblies?


To answer this question I wrote a small class library (
in C#) that exposes some generic types and manually (ildasm/ilasm) added each of these constraints. After that I created one application (C#) that uses this library and confirmed that C# compiler does respect these constraints (at least in VS 2010 which uses CSC 4.0.30319.1). Bellow you can see the result of trying to use these generic types with incompatible types:
Generic parameter 'E' was constrained to enums
Generic parameter 'E' was constrained to enums

Generic parameter 'A' was constrained to arrays. 
You can download the sample application from here.

The bottom line:  Generic constrains in .Net  are more useful than what you may be lead to believe ;)

As always, don't be shy! Let me know what you think.

Hope you find this useful.

Aug 31, 2012

My adventures with Arduino continues...

Hi

In this post I listed some components/shields/breakout boards that I want to try with Arduino. Well, last weak one of the missing components in order to test my ethernet breakout board (one very similar to the one in this post) arrived.


Like I child with a new toy I took the evening to try it out. After some time I finally got it connected (unfortunately there's not much information about the ethernet breakout board I've got in the net) but to my frustration I could not get it to work. :(


Basically I connected my Arduino Mega to the breakout as follows:

ENC28J60    Arduino
-------------------------
CLKOUT       NC
WOL            NC
SO               50
SI                51
SCK             52
CS               53
RESET          RESET
VCC             3v3
Gnd             Gnd

When I power up the Arduino board I can see that a red led also lights up on the ethernet breaakout board but its statuses leds does not blink / flash.

After a lot of time checking it my guess is that either the breakout board is defective or that it requires a crossover cable (I've tried various cables connecting it both my router and my computer directly) (
ENC28J60  datasheet claims that it supports "One 10Base-T Port with Automatic Polarity Detection and Correction" but this doesn't looks to be the same as auto MDI/MDIX to me).

Well next steps:
  • Ask for help on Arduino forums (already did)
  • Try to get a crossover cable to check.
  • Try to exchange it with a new one
  • Hope that someone have already faced this issue
As soon as I get any update to this I'll post comments here.

BTW, if you have any idea how to test / get this working, drop me a comment.

In time: I just received a "bluetooth" breakout board :) but this will need to wait to get tested.

Happy programming.

Aug 15, 2012

Windows 8 / Visual Studio 2012

Hi

Getting back to the subject I am more comfortable with, MS just released Windows 8 / VS 2012 (for MSDN and Technet subscribers). Off course I am downloading both right now but this is the first time, since Windows 95 launch, that I am not going to install the new MS OS as soon as it gets released. 


To be honest I am not even considering installing it (on my main dev machine) in the next 6 ~ 12 months! Contrast that to what I've been doing in the past 
(I've used Vista / Windows 7 RC!) and you can see how "excited" I am about it (maybe I install it on a virtual machine so I can experiment with it). Anyway, sooner or later I'll end up formatting my dev machine and the question is: am I going to give Windows 8 a try? Or shall I take a more drastic approach and install Ubuntu? This bring me to the second MS release.. VS 2012.

One of the main reasons I'm procrastinating migrating to a Linux OS is that I really enjoy developing using .Net (yeah, I do know Mono; the problem is: the bulk of .Net development is still concentrated on MS platform. Also, 
IMHO, *nix lacks a good .Net IDE).

Of course my friends (at least the ones in the software development field) knows that that is not completely  true: I also enjoy MS technology in general (COM+ pops up as one example).


What do you think? Should I dive into Windows 8?


BTW: Visual Studio download finished! This one for sure I'll get installed in the next few days ;)

Happy codding!

Aug 8, 2012

Connecting Nokia 5110 LCD breakout to Arduino

Hi

As I said in my last post, I have been playing with some hardware parts for Arduino.


In the "still to go" list I had:

  • Ethernet breakout
  • External EEPROM
  • RTC (DS 1307)
  • Nokia 5110 LCD
My plan was to tackle at least 2 of them during last weekend but I had a problem: all of this parts requires external components that I didn't have at hand. So I went to a local component shop but unfortunately I could not find most of the parts. 

The only part I had the required "missing" components was the Nokia LCD so I googled for "Nokia 5110 LCD  on Arduino" and voilá! The third entry in the results links to one great source of information about Arduino (and electronics in general). Now I was ready to start; I pulled my Arduino board, breadboard, the LCD (and required components) and put myself to connect them together.


My first disappointment came when I uploaded the sample application and nothing happened :(
Oopss.. maybe I have messed up with the connections... , let's see, pin x goes to y, pin z goes to w... no, everything looks connected correctly. After some head scratching I finally decided to do what I should have done from the beginning: Make sure the pin on my LCD breakout board matched the one in the Laydada  guide and of course they didn't! Compare the two pictures below (the red one is  mine and the blue one is the one used by ladyada):
As you can see they have different pinouts! Next step was to carefully reconnect the LCD and power on my Arduino (crossing my fingers hoping nothing bad had happened to neither my Arduino nor the LCD); this time everything but the backlight worked as expected; for some reason I could not explain the backlight refused to light up.  I checked and re-checked the connections many times but could not spot the problem. 

But at some point, during my investigation I could swear having seen the  backlight turning on and off; after some more testing I found out: by mistake I connected the backlight pin to the Arduino ground and that did the trick. But wait, both the LCD breakout schematic (not shown here) and the board itself does states that I should connect 3.3v on that pin... I have no idea what's happening here, but it is working. 

Next stop: external EEPROM.


Happy programming.

Aug 2, 2012

Now we are talking :)

Hi

Just a quick update on my Arduino experiments.


Some of my new "toys" just arrived....

I managed to get the following working so far:


  • Ultrasonic sensor (HC-SR04)
  • LCD 16 x 2
  • SD card
  • Temperature sensor (18B20)

Still to go:

  • Ethernet breakout
  • External EEPROM
  • RTC (DS 1307)
  • Nokia 5110 LCD

I am having lots of fun ;)

Lets get back to play with the ethernet breakout. 


See you.

Jul 28, 2012

My new remote control (as a prototype so far)

Hi.


Moving on with my Arduino experiments I decided to experiment with the infrared library (I said in the original post that one should be able to find a library for almost any piece of hardware he/she want to connect to Arduino) :).


After some research I found this library which worked almost out of the box. The only problem with this library is that it don't have the definitions for my TV (Samsung) so the only option would be to use "raw" data which is not as convenient as the "sendXXX()/decodeXXX()" methods. After a little bit more research I was able to find this post which describes how to change the IR library to work with Samsung TVs).


So here is the prototype for my new remote control. 




So far it is pretty limited (only turn on/off the tv) but I have big plans for it :)


Happy programming.


Adriano

Jul 24, 2012

Arduwhat ?

Hi
Since I was 5 ~ 8 years old I was interested in mechanics, electronics and how things worked in general - my mother has some interesting histories about me disassembling all sort of devices (and usually not being able to put them together again); one in particular in which I got a saw as a "gift" (I was only 6 or 7 and someone gave me a real saw, not a toy, plastic one!) and went to put it into good use sawing some furniture :).

Even though having a high interest in electronics I ended up in the computer software field (just to make it clear: I do enjoy being involved in such fast changing, challenging industry :) and since then I've been having lots of fun (and some frustrations also).
As anyone involved with IT knows, keeping up to date with such a fast changing field requires a lot of effort and over time I put my electronics pretensions to rest (after all there are enough fun stuff in the computer world to play with to keep me busy for a long time...).
But about one year ago this started to change as I started to play with some basic (really basic) electronics stuff again (just for fun) and I stumbled on a small but very interesting piece of hardware: a small board with a microcontroller and a lot of software support with some nice characteristics (at least from my point of view ;) :
  • Open Source Software / Hardware
  • Inexpensive (will not cost you an arm and a leg :)
  • Simple to work with, at least not as complex as the other options I had seem before (no complex, expensive tools required)
  • Easily integrated with the "external" world (through sensors/actuators).
  • Extensible (shields, breakout boards and virtually anything you want)
  • Well supported
  • Large community
which perfectly describes this nice board called "Arduino" (since the name Arduino is trademarked most probably you'll  find compatible devices under some generic brand named with a "duino" suffix).
At this point you may be wondering what can be accomplished with such beautiful piece of hardware... well, I guess it is fair to say that you can find an Arduino C/C++ library for virtually anything you can come up (of course this is not completely true, but it is not too far from the truth). IMO, the important  question is not "is it possible to connect X to Arduino" but instead "how hard is to connect X to Arduino" and based on the list bellow (which I wrote based on information I found) I conclude that, excluding more exotic hardware, it does pretty well job on this topic (note that almost all items in the list bellow requires extra hardware): 
  • Sensors
    • Temperature, Pressure, Gas, Light, Distance, Color, Humidity, Accelerometers, etc.
  • Communications
    • Bluetooth, TCP/IP, UDP/IP, Serial, GPRS, Infrared, etc.
  • Storage
    • EEPROM, SD cards
  • Actuators/Output
    • Step Motors, Servos, DC Motors, LCDs, etc
As you can see it is quite flexible, and more importantly, all of the hardware above have at least one Arduino library ready to be used.

This post is not intended to be an Arduino introduction / course / tutorial. Instead it is meant to be only a teaser so if you want to learn more, you can find lots of information in the internet. Personally there are some sites I highly recommend you to give a visit:

Also, if you want to buy Arduino related hardware you can go to your favorite search engine and search for it and I am sure you'll be able to find lots of stores that sell them. But if you don't want to search, bellow you can find a list of sites in which you can buy Arduino parts (ps: I have no affiliation with any of them :).


Finally, some electronics interesting tools:


Well, that's it. Now let me get back to play with my just arrived Arduino!

In the next post I hope to shed some light about my current projects related to Arduino (both soft and hardware).

Hope you found this post interesting.

Jul 7, 2012

Did you know (Part II) File / Registry virtualization on Windows 7 / Vista

Hi

In this post I discussed some issues I faced regarding software running on Vista 64 bits. Well it ended up that all my troubles was happening because my program (64 bits) was launching IE 64 bits (instead of the 32 bits) and I had not installed Silverlight plugin on it! Solution: just switch my program to 32 bits and it worked as expected!

In this post I want to discuss some pitfalls when running software on x64 bit versions of Windows (most of the discussion applies equally well to Vista x64 ,Windows 7 x64 and probably to newer versions also - haven't tried it with Windows  8 but I bet that the behavior is the same).


Keep in mind that when talking about the reasons that lead Microsoft to add a specific feature I am just speculating, so take every word with a grain of salt :)


On previous Windows versions, to many (almost every single?) developer used to login as
admistrator into their workstations1 so there were way to many applications that relied on being able to change system resources (such as to create files/fonders under "Program Files"), after all they always succeed doing that since developers had the rights to do so (remember, administrator...).

At Vista launch time MS had a tough issue to deal with: how raise the bar for system security / stability without breaking such ("legacy") applications?


AFAIK a compromise was settled so Windows development team decided that for
some 32 bit applications such requests would not fail, but instead, Windows would lie to the calling process and would just create the file somewhere else (the same principle apply to registry access): this feature is known as file virtualization (the rules that governs whether file/registry will be enabled or not for a specific process can be found here)

Note that this feature is meant to allow
legacy applications2 to run on the new platform (at that time, Windows Vista) so Microsoft plans to remove it (as soon as your application gets compiled as 64 bits, virtualization will be disabled anyway).

If you are running the 64 bits version of Windows 7 (or Vista for that matter) y
ou can try it right now by downloading the test application source3 and running it with something like:

FileSystemVirtualizationTest.exe -e %windir%\test.txt "adriano's test"
For now, just run it with the arguments shown above and take a closer look in the produced output:

Virtualization ENABLED.

Virtualization is ON

14 bytes writen to C:\Windows\test.txt
It seams that the application succeed in creating a file under %windir% (which it should obviously not be allowed to) but how can we confirm that? Easy, just run the application again now providing only the file name (the application will try to read the file and dump its contents):
FileSystemVirtualizationTest.exe %windir%\test.txt

Virtualization is ON

adriano's test
and there it is! But wait! Let's open Windows Explorer and try to locate the file. Hey! I can't find the file anymore! Windows search can't find it either:

But the application does succeeded opening the file! how can that be? Launch Windows Explorer again on %windir% folder but this time paying attention to the little button: "Compatibility Files":

Ok, now that you noticed this button, press it and Windows Explorer will open a folder that looks like the one bellow:


Wow! Windows just created the file under %localappdata%\VirtualStore\Windows folder (which is a per user folder). 

This way Windows let applications believe they had successfully updated files / folders / registry keys when actually they didn't (preventing possible global system corruption). Clearly avoiding system corruption is a fair reason to support this functionality, but now, developers (and IT admins) must pay attention to scenarios with mixed 32 / 64 bits applications interacting in such ways that they need to observe changes from each other (since the first ones may be writing to the virtual store and the last ones will not see the virtual store).

Last, but not least :), make sure your application do not depend on registry/file virtualization; these mechanisms were introduced sonly to raise the likelihood of legacy applications to run without problems on Windows versions with stricter security settings (Vista, 7, etc). So if you have an application that does writes to protected file system areas, please do your users a favor: update it to write to a more appropriated location (%appdata%, %localappdata%, etc).

Bellow you can find some links if you want to read more about file system virtualization:


Have fun!

Adriano


[1] I am guiltily of doing the same thing :(
[2] Basically all applications developed for previous Windows OSs are handled as legacy by Vista
[3] In the first drafts of this post I used Notepad++ to write to %windir% but it looks like they added a manifest in the latest versions so it will not work for our demonstration purposes. Even in my sample application I was required to remove the manifest explicitly (VS 10 included one that disabled virtualization)

Jul 5, 2012

Little handy presentation tool

Hi


Yesterday I stumbled over a really nice tool for producing screen casts (called zoomitthat allows you to zoom, draw and write directly on your desktop. If you do screen casts (or any kind of demonstration with a computer connected to a projector) I highly recommend  it (BTW I highly recommend all the Sysinternals stuff :).


Hope you find that useful.

Jun 27, 2012

Updating to git 1.7.11 on a Windows box

Hi


If you just updated to git version 1.7.11 and started to get the following error when you try to run git svn

Can't locate Git/SVN/Editor.pm in @INC (@INC contains: /lib /usr/lib/perl5/5.8.8/msys /usr/lib/perl5/5.8.8 /usr/lib/perl5/site_perl/5.8.8/msys /usr/lib/perl5/site_perl/5.8.8 /usr/lib/perl5/site_perl .) at C:\Program Files (x86)\Git/libexec/git-core\git-svn line 81.
BEGIN failed--compilation aborted at C:\Program Files (x86)\Git/libexec/git-core\git-svn line 81.
you can check the comments in this issue; in my case it fixed the problem.


See you!

Jun 10, 2012

byte code instrumentation in java...

Hi!

Are you a
"low level",  developer? Have you ever disassembled a class byte code just to see what's under the hood? If not, I urge you to give it a try; IMO having at least basic knowledge about how the platform running your app works at low level may help us (developers) to write better code.
Since I joined db4o team I had the opportunity to play a lot with Mono.Cecil, a great .Net byte code manipulation lib, but I've been kind of lazy when it comes to the Java side (sure, we do employ byte code manipulation on Java code but, to be sincere, I've never touched that area of the code).
This has been slowly changing since I have joined another project at Versant (the company behind db4o) and this lead me to this post: last weekend I was debugging some Java class library code that I had no source code for1 and I wanted to check some parameter values.
Since I was alone in my house (wife and kids went to do some shopping with my mother in law :) I decided to try 2 related technologies in the Java world: Java agents and ASM library (you can read more about Java agents here and here)2.
Simply put, Java agents is a technology used to change class bytecode when it enters into the system, meaning, instead of doing the manipulation in the bytecode and saving it to the disk using java agents one can change the in memory representation of the class (without touching the actual bytes in the disk) when the JVM tries to resolve the class. If you use Sun JVM you can simply type the following command in the command line:
java -javaagent:jar-containing-agent-code.jar[=agent-args] ...
ASM is a library that allows developers to manipulate Java bytecode in a flexible, yet relatively easy way so it is a great match to use with Java agents (if you want more details I recommend to read this ASM tutorial).

Bellow you can find the code that I wrote for the agent 
(you can download a zipped eclipse project from here); it expects the class name and method which should be instrumented in the form className#methodName (if you omit the method name all methods will be instrumented):
package com.thinkingsoftware.diagnostics;

import java.io.*;
import java.lang.instrument.*;
import java.security.*;
import java.util.*;

import org.objectweb.asm.*;

public class DumperClassTransformer implements ClassFileTransformer {

	private final String className;
	private final String methodName;

	public DumperClassTransformer(String... args) {
		this.className = args.length > 0 ? args[0] : null;
		this.methodName = args.length > 1 ? args[1] : null;
	}
	
	private static Map> wrapperMapping = new HashMap>();
	
	{
		wrapperMapping.put(Type.INT_TYPE.getDescriptor(), Integer.class);
		wrapperMapping.put(Type.FLOAT_TYPE.getDescriptor(), Float.class);
		wrapperMapping.put(Type.DOUBLE_TYPE.getDescriptor(), Double.class);
		wrapperMapping.put(Type.BOOLEAN_TYPE.getDescriptor(), Boolean.class);
	}

	@Override
	public byte[] transform(ClassLoader loader, final String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {

		if (className.startsWith("java") || className.startsWith("sun")) {
			return classfileBuffer;
		}
		
		if (this.className == null || className.equals(this.className)) {
			
			ClassReader cr = new ClassReader(classfileBuffer);
			ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
			
			ClassVisitor cv = new ClassVisitor(0, cw) {
				
				@Override
				public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
					MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
					
					if (methodName != null && !name.equals(methodName)) {
						return mv;
					}
					
					try {
						String printlnStringMethodDesc = Type.getMethodDescriptor(System.err.getClass().getMethod("println", String.class));
						
						mv.visitFieldInsn(Opcodes.GETSTATIC, Type.getInternalName(System.class), "err", Type.getDescriptor(System.err.getClass()));
						mv.visitLdcInsn(name + " :");
						mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(System.err.getClass()), "println", printlnStringMethodDesc);
						
						Type[] args = Type.getArgumentTypes(desc);						
						for(int i = 0; i < args.length; i++) {
							
							if (args[i].getSort() == Type.ARRAY) { // not supported... :(
								continue;
							}
							
							mv.visitFieldInsn(Opcodes.GETSTATIC, Type.getInternalName(System.class), "err", Type.getDescriptor(System.err.getClass()));
							mv.visitInsn(Opcodes.DUP);
							
							mv.visitInsn(Opcodes.DUP);
							mv.visitLdcInsn("\t");
							mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(System.err.getClass()), "print", printlnStringMethodDesc);
							
							mv.visitIntInsn(Opcodes.BIPUSH, i);
							mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(System.err.getClass()), "print", "(I)V");
							
							mv.visitInsn(Opcodes.DUP);
							mv.visitLdcInsn(" = ");
							mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(System.err.getClass()), "print", printlnStringMethodDesc);							
							
							Class wrapperClass = wrapperMapping.get(args[i].getDescriptor());
							
							if (wrapperClass != null) {
								
								mv.visitVarInsn(args[i].getOpcode(Opcodes.ILOAD), i + 1);

								Type.getMethodDescriptor(Type.getType(wrapperClass), args[i]);
								mv.visitMethodInsn(
										Opcodes.INVOKESTATIC, 
										Type.getDescriptor(wrapperClass), 
										"valueOf", 
										Type.getMethodDescriptor(Type.getType(wrapperClass), args[i]));
							} else {
								mv.visitVarInsn(Opcodes.ALOAD, i + 1);
							}
							
							mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getType(Object.class).getDescriptor(), "toString", Type.getMethodDescriptor(Object.class.getMethod("toString")));
							mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(System.err.getClass()), "println", printlnStringMethodDesc);
						}						
					} catch (Exception ex) {
						ex.printStackTrace();
					}
					
					return mv;
				}
			};
			
			cr.accept(cv, 0);
				
			
			byte[] byteArray = cw.toByteArray();
			
			writeFile(className, byteArray);
			
			return byteArray;			
		}
		
		return classfileBuffer;
	}

	private void writeFile(String className, byte[] byteArray) {
		FileOutputStream f;
		try {
			String tempDir = System.getProperty("java.io.tmpdir");
			String outputPath = tempDir + className + "Inst.class";
			
			System.err.println();
			System.err.println("Instrumented class stored at: " + outputPath);
			System.err.println();
			System.err.println("You can look into it actuals bytecode with the following: ");
			System.err.println("javap -v -private -classpath " + tempDir + " " + className);
			System.err.println();
			
			f = new FileOutputStream(outputPath);
			f.write(byteArray, 0,  byteArray.length);
			f.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}


If you want to try it you simply compile it and run some Java application; you should get  an output looking like:
running my agent against the following Java application

public class TestAgent {

	public TestAgent(String msg, int n) {
		this.msg = msg;	
	}

	public static void main(String []args) {
		TestAgent t = new TestAgent("Hallo Welt", -1);
		String msg = t.getMessage("Hello World", 42, 11.0f, true, t);
	}
	
	private String getMessage(String msg, int i, float f, boolean b, Object o) {
		return msg;
	}
	
	public String toString() {
		return "OLA MUNDO";
	}
	
	private String msg;
}


Fell free to use it anyway you like but keep in mind that this code is far from being complete or bug free or production ready (for instance it does not handle arrays) so strange errors may happen if you find one of these not supported cases.

As a last comment, if you want to play with ASM I do recommend you to take a look in the
Bytecode outline plugin (but be careful to use the one in the previous link instead of the one in the Objectweb page since the later seems to have issues with newer Eclipse versions).

Hope you find this interesting!


Adriano



----

1 Of course I could either download it from the web - after all it is an open source project- or disassembled it, but I wouldn't loose the change to play with new toys and possibly learn something new - not to mention that I severely suffer from the NIH syndrome :)


2 Since I am in no way an expert in the subject, take every word with a grain of salt.

May 19, 2012

API usage rant

If you have been following me recently (Facebook, Linked-in, Tweeter, etc) you probably are aware that I have been busy taking care of the building of my new house, my job and what not (not necessarily in this order ;).

Man, building a new place proved to be a huge time sink; since we've finally finished the main construction phase I expect to blog more often.

Ok, so lets start with a rant (I am really good ranting :))

Some time ago I was playing with one of my toy projects when I got an exception while adding a new entry into a dictionaryThe exception was quite self explanatory about what had happened (from the point of view of the dictionary class implementer): a duplicate key was added (which,  according to the documentation, is explicitly prohibited).

Ok, I can live with that, it was my fault after all ;) My real issue is that the message would be much more helpful had it included the actual key value (of course you override
ToString() method in all of your public classes, don't you ?).
Without this information I was forced to debug the code (of course I could catch the exception and print the key but then I'd be required to change my code just to find out what was happening) to figure out what the original exception could have told me.

To my understanding, one of the reasons for 
this is to avoid possible sensible information from leaking and, even though IMHO this is reasonable, it makes me think whether we could do it better. 

To me looks like the dictionary class developer (product owner, or whoever) was faced with the usual coast/benefit decision: make it easier, more convenient to use or make it suitable for use when sensible information is involved and he/she decided for the later.


When writing libraries I usually tend to making it easier to be used at the coast of a higher chance of developers misuse (or using it in a way that may shut then in their foots). I confess that I had never thought about this particular scenario but now I think it could be fixed (made more flexible) by allowing the user (in this case the developer) to decide what to expose in exceptions (through an enum, an interface, you name it) and choosing a safe default value.


What do you think?


Adriano

May 9, 2012

Free (open source) RAM disk for Windows (x86 / x64)

Hi


Have you ever had the need to perform some I/O intensive operation on a relative small set of files? I do, usually when I need to compile some application.

In order to speed up this operation I've recurred to the so called "RAM Disks", applications that takes part of your computer's main memory and pretends that it is an actual disk. As you can imagine read/write/etc (I/O) operations against this virtual disk are much faster than operations against your actual hard disks (be it a traditional magnetic HD or a shine new SSD).

In the past 3 years I've used at least 3 different solutions and was happy with none. My main complain is that most of them were not capable (or it was really clumsy/hard to accomplish) of creating RAM disks dynamically, i.e, one is required to create it at OS start up time. Since my needs are dynamic (I may need more disk space at some points in time during the day) it is really hard to come up with a disk size that work for me: choose a to big disk and I am wasting precious RAM space; create a disk that's to small and I may find myself facing "out of disk space" errors (then cleaning up some junk and restarting my build tasks).

Fortunately some time ago I stumbled upon a RAM disk implementation that allows me to mount and unmount disks dynamically! Since then my work flow has been much more smooth ;) The not so good side is that it is not very easy for the "not computer savvy" user.

Bottom line is: if you need a stable and flexible (but maybe not so easy to start with) RAM disk solution you can't go wrong with this one.







May 8, 2012

What's wrong with this code - fun with assembly : the answer


In the previous post I presented the following program and asked what was the problem with it:
int fact(int n)
{
    if (n == 1)
        return 1;
    else
        n = n * fact(n - 1);
}

int main(int argc, char *argv[])
{
     int n = argc > 1 ? atoi(argv[1]) : 5;
     int i = fact(n);
   
     return printf("fact(%d): %d", n, i);
}
As I said in the previous post, the problem itself is not so hard to find out: take a close look in line 6 again! We are not missing any instruction, or are we? Actually we are missing a return  so line 6 should really look like

return n * fact(n - 1);
i.e, the developer forgot to include the return.
Note that the compiler tried to alert me with the following warning, but as you know, I just ignored it :) (as I said in the previous post, you should never ignore compiler warnings)
c:\temp\fact.c(7) : warning C4715: 'fact' : not all control paths return a value
So the interesting question is: why this program works even when it is clear that it is missing a return? In order to answer this question we are going to dive into the assembly generated code for this program. To get the assembly code just type the following in a command line (assuming you have cl.exe in your path):
cl fact.c /Fa fact.asm
Even if you have little knowledge of assembly, please, bear with me; I'll try to explain the important parts. Also I've simplified both functions (fact and main) assembly code removing not important (to this discussion) bits.

MESSAGE DB 'Fact(%d): %d', 00H
fact:
 push ebp
 mov ebp, esp
 
 cmp dword ptr [ebp+8], 1
 jne next_fact
 mov eax, 1
 jmp finish
 
next_fact:
 mov eax, [ebp+8]
 sub eax, 1
 push eax
 call fact
 add esp, 4
 imul eax, [ebp + 8]
 mov [ebp+8], eax
 
finish:
 pop ebp
 ret
 
main:
 call fact
 add esp, 4
 mov _i$[ebp], eax
 mov ecx, _i$[ebp]
 push ecx
 mov edx, _n$[ebp]
 push edx
 push OFFSET MESSAGE
 call _printf
 add esp, 12
 mov esp, ebp
 pop ebp
 ret 0

PS: If you want to generate an assembly source with more - actually lots of - information from the original C program use the following command line arguments:


cl fact.c /Fa fact.asm /FAscu
First let have some simple facts:
  • fact function code starts at line 2 and extends through line 22 (ret instruction).
  • Argument n is stored at address [ebp + 8]
  • main function starts at line 24 and extends through line 37.
  • main calls fact function on line 25 (again, please note that for brevity/simplicity reasons I removed parts of the main function, so it became easier to understand).
Now that we have a high level view of the code lets dig a little deep into the fact function code (and on main function when appropriate).

Lines 3 and 4 represents the standard C function prologue; the first interesting instruction is the one at line 6 which compares n (remember, [ebp + 8]) with 1 branching to label next_fact (line 11) if they are not equal.


Starting at line 12 the code loads n into register eax subtracts one from it and calls itself recursively. When fact returns from a previous recursive call (line 16) the code calculates n times eax i.e, the compiler used eax register to return the calculated factorial from fact. We can confirm this behavior inspecting line 27 (inside main function) which assigns eax to local variable i after calling fact.

But just using eax register to pass the return value from fact is not enough; this program works (accidentally) only because the compiler used the same register eax to perform the calculations and to pass the return value.

So we can conclude that in this particular program, omitting the return statement renders an executable equivalent to the one that would be generated had the return statement be present.

Note that different compilers (or even different versions of the same compiler) may choose other registers to perform the calculations / pass return values from functions; actually I have found at least one version of CL (from Visual Studio 6) that used register ecx to perform the multiplication and eax to pass the return values (rendering an incorrect program).

Note also that even the same version of a compiler may generate different versions of the code (one that uses eax for both, calculations and for the return values and another that uses a different set of registers) depending on options such optimization, debug, etc.


Best