What does “Any CPU” really mean?

There’s a new “Prefer 32-bit” option in Visual Studio 2012 that tripped us up, and can trip you up too.

Running through some standard JNBridgePro test examples recently, we were surprised that the examples didn’t work, and the embedded Java side failed. The examples were created using Visual Studio 2012, set Any CPU, and, since we were running the tests on a 64-bit machine and were using shared memory, we supplied a 64-bit JRE as part of the configuration.

After a bit of investigation, we discovered a new setting in the VS 2012 project that isn’t in previous versions of Visual Studio: in the project’s properties, under the Build tab, there is a new checkbox: “Prefer 32-bit.” The checkbox only seems to be enabled when Any CPU is selected, and it was automatically checked. And indeed the running process was 32-bit. What was happening? Didn’t “Any CPU” mean that the application would run as 64 bit on a 64-bit system, and 32 bit on a 32-bit system? And how does “Any CPU/Prefer 32-bit” differ from simple x86?

We did some research and discovered an explanation in a Microsoft blog post here. It turns out that the meaning of “Any CPU” has changed a bit. I won’t go into too many details, but would suggest that anyone doing .NET development read the blog post. In a nutshell, the new “Prefer 32-bit” is connected to Microsoft’s new support for ARM architectures as of .NET 4.5. It also seems to have something to do with Microsoft’s retreat from encouraging 64-bit and “Any CPU” development in deference to 32-bit development, as the complexity of supporting both 32-bit and 64-bit environments has become apparent. In making the changes, Microsoft has made some design decisions that we feel are to the detriment of users. (Also note that we still strongly believe in supporting “Any CPU” and x64 development. Read more about the bitness challenge in this blog post.)

In the first design decision we take issue with, Microsoft has decided to make “Any CPU/Prefer 32-bit” the default in Visual Studio 2012 when creating .NET 4.5 applications. This is unfortunate because users assume “Any CPU” meant the same thing as it previously did (the application will run as 64 bit on 64-bit systems), and because the new “Prefer 32-bit” setting is somewhat hidden and not immediately obvious. In our experience, most users set the Target Platform (Any CPU/x86/x64/etc.) in the configuration manager, where there’s no mention of the “Prefer 32-bit” setting – “Prefer 32-bit” is only visible (and settable) in the project properties, where most developers don’t have a reason to look, but where it’s already been set, without telling the developer.

Second, setting “Prefer 32-bit” as the default leads to inconsistencies in creating new projects versus migrating exiting ones. “Prefer 32-bit” is set in new “Any CPU” projects created in VS 2012, but it isn’t set when migrating an existing project from VS 2010. Props to Microsoft for not altering the behavior of existing projects when migrating from VS 2010 to 2012, but why not go a step further and make “Any CPU” behavior consistent by leaving the “Prefer 32-bit” setting turned off by default in new projects created with VS 2012?

The inconsistent behavior is what really what makes this change so annoying. Microsoft could have offered the “Prefer 32-bit” capability and not surprise unsuspecting users by just leaving the setting turned off by default. Users would happily create new applications without problem, and without suspecting that “Any CPU” could possibly mean anything different than what it meant before. Interestingly enough, users could still target ARM platforms if “Any CPU” running on ARM was guaranteed to run as 32 bit (until 64-bit ARM chips become generally available, at which time such applications will run as 64 bit). Microsoft could also allow developers to specifically target ARM in the same way as they can now specifically target x86, x64, and IA64. I can almost guarantee that this would be less confusing than the current use of “Any CPU” and “Prefer 32-bit,” particularly since very few .NET developers are going to be targeting ARM, at least not for a long time.

So what does this mean for users of JNBridgePro and the JNBridge adapters? First, as mentioned earlier, we still strongly believe in “Any CPU” and x64 development, and are working hard to create products that can be used in “Any CPU” applications. There are some subtleties and complications in making this transparent to the user, but we’ve done a lot of work on this, which you can see in JNBridgePro 7.0, and will soon see in new releases of the adapters. We’ve discussed the work that we’ve done here. The next version of JNBridgePro will have even more support for “Any CPU” applications; particularly, when using shared memory, you’ll be able to specify paths to both a 32-bit and a 64-bit jvm.dll, and the proper JRE will be loaded depending on whether it’s a 32-bit or a 64-bit process. This will make Any CPU applications using shared memory even easier to deploy on any system without changes.

Second, we want all our users to know that JNBridgePro will still work in all “Any CPU” applications using shared memory, even when “Prefer 32-bit” is turned on. When it is, simply use a 32-bit JRE, and when it isn’t turned on, use a 32-bit or 64-bit JRE as is appropriate to the platform. The V.next of JNBridgePro, with the aforementioned ability to specify both 32-bit and 64-bit JREs, will make this process even more transparent.

We’re always trying to stay ahead of Microsoft’s changes, whether they’re ill-advised or not. The change to the meaning of “Any CPU,” and the new default “Prefer 32-bit” setting are just one example of how we’ve stayed on top of .NET’s evolution, so that your applications using JNBridgePro and the adapters continue to work despite the changes to .NET, and will continue to work in the future.