How to use assert in android? - java

I want to use assert obj != null : "object cannot be null" on Android device. The assert doesn't seem to work, so I searched online and I found this local solution:
adb shell setprop debug.assert 1
it does work on my local machine.
I want to run this command using my Eclipse project(so it would be in the source control).
How can I do it?

Assert won't work in Android because most of the time a person isn't running in debug mode, but rather some optimized code. Thus, the proper solution is to manually throw an exception, with code like this:
if (obj==null) throw new AssertionError("Object cannot be null");
It should be noted that by design, Asserts are intended for debug code, and not for release time code. So this might not be the best use of throwing an Assert. But this is how you can do it still, so...

Tested on Android 4.x device, it is possible to use Java assert on Android device:
Edit /system/build.prop (for example by X-plore), add line at end of file: debug.assert=1
Reboot phone
Now your Android device is sensible to assert checks, and will throw AssertionError when assert check fails.
EDIT:
Another easy approach, enabling asserts from PC until device is restarted:
platform-tools\adb shell setprop debug.assert 1
You may for example create a .bat file (on Windows) and run it when device is attached.

Create your own assert method:
public static <T> T assertNotNull(T object) {
if (object == null)
throw new AssertionError("Object cannot be null");
return object;
}
Returning same object allows for using this in assignments for brevity.

if (somevar == null) throw new RuntimeException();
Replace RuntimeException() with an appropriate exception subtype.

Sharing my class which I use for assertions on Android, its simpler, has nice naming and very elegant because it allows you to write asserts like this:
Assert.that(obj!=null, "Object should not be null");
Here's the code for the class:
public class Assert {
public static void that(boolean condition, String message) {
if (!condition) {
throw new AssertionError(message);
}
}
}
Hope it helps!

To make assertion available in Java Virtual Machine, using -enableassertions or -ea command-line options
on Window's Command prompt,
java –ea YourApp
on Android Studio 3.0, on Tools/Edit Configurations/VM options, input -enableassertions or -ea

Related

Preventing java agents from attaching at runtime

Reposting this here as advised by security.stackexchange
How can I prevent Java Agents from attaching to my running java application at runtime?
I am able to prevent users from launching my application with a javaagent at startup by scanning the command line arguments:
List<String> args = ManagementFactory.getRuntimeMXBean().getInputArguments();
for(String arg : args)
{
if(arg.contains("-javaagent"))
{
System.out.println("Detected Java Agent: " + arg);
logIncident(0x01);
Runtime.getRuntime().exit(0);
}
}
However this does not prevent people from attaching at runtime visualvm style.
I heard that you can use the -XX:+DisableAttachMechanism flag to disable this, however when I tried to use jinfo -flag +DisableAttachMechanism <PID> I got an exception telling me that it is not possible to modify this argument at runtime.
Another possibility I considered was modifying the system security manager to disallow all AttachPermission's (I believe that this needs to be allowed for java agents to attach), but I'm not sure where to start.
Would really appreciate any guidance on how to implement the ideas Ive already come up with, as well as suggestions for any new ideas.
Edit:
I created a custom security manager to deny all AttachPermissions however it appears to not be triggered in the jar being attached to but rather the agent itself. Now I am looking to enable DisableAttachMechanism at runtime, but I cant seem to find any references to this in OpenJDK source?
Exit if this returns true:
private static boolean acceptsJavaAgentsAttachingToThisJvm() {
HotSpotDiagnosticMXBean vm = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
VMOption opt = vm.getVMOption("DisableAttachMechanism");
return "false".equals(opt.getValue()) || opt.isWriteable();
}
which should defend against casual usecases.

JavaFX: Getting Stage of running Applications

For testing a application with TestFX i need to get the actual primary stage of a running application. This means that i haven't the code, i can just run the application through a jar.
Is there any possible solution for this? Scenic View does this already, but i was not able to reproduce this functionallity, especially because it seems that they use the deprecated funtion
Windows.impl_getWindows
which is not working in my case.
Try this:
import com.sun.javafx.robot.impl.FXRobotHelper;
static Collection<Stage> getAllJavaFXStages() {
try {
return FXRobotHelper.getStages();
} catch ( NullPointerException npe ) {
// nasty NPE if no stages exist
return Collections.emptyList();
}
}
```
Based on my own testing framework code: Automaton.
EDIT:
If you want to get a Stage from a different JVM instance than where you're running your code, then there's no simple way.
You're right, ScenicView does it, but it uses tools.jar to do it. This is not a standard jar you get in your runtime, so you must add it manually (placing it in jre/lib/ext should do it, you'll normally find it in lib only).
I tracked down the code where ScenicView seems to be doing it in their BitBucket repo.
Check the function getRunningJavaFXApplications for example.
Have fun using that in your tests!

How to detect that code is running inside eclipse IDE

How to detect that code is running inside eclipse IDE
I am not aware of a generic way to get this kind of information.
One suggestion:
When you start a Java program (or a web server) inside Tomcat, simply add an argument that will indicate that this program is launched by Eclipse.
You can do that by opening the "Open Run Dialog" ("Run" menu), then select your type of application and add in the "Arguments" tab a -DrunInEclipse=true.
In your Java code, you can check the value of the property:
String inEclipseStr = System.getProperty("runInEclipse");
boolean inEclipse = "true".equalsIgnoreCase(inEclipseStr);
This way, if the program is not running inside Eclipse (or unfortunately if you forgot to set the property) the property will be null and then the boolean inEclipse will be equal to false.
Although I agree that having the code detecting a single IDE as the dev env is not an optimal solution, the following code works.
Like others proposed, using a flag at runtime is better.
public static boolean isEclipse() {
boolean isEclipse = System.getProperty("java.class.path").toLowerCase().contains("eclipse");
return isEclipse;
}
1) Create a helper method like:
public boolean isDevelopmentEnvironment() {
boolean isEclipse = true;
if (System.getenv("eclipse42") == null) {
isEclipse = false;
}
return isEclipse;
}
2) Add an environment variable to your launch configuration:
3) Usage example:
if (isDevelopmentEnvironment()) {
// Do bla_yada_bla because the IDE launched this app
}
Actually the code is not being run inside Eclipse, but in a separate Java process started by Eclipse, and there is per default nothing being done by Eclipse to make it any different than any other invocation of your program.
Is the thing you want to know, if your program is being run under a debugger? If so, you cannot say for certain. You CAN, however, inspect the arguments used to invoke your program and see if there is anything in there you do not like.
If your workspace matches some pattern like "/home/user/workspace/Project" you can use the code below:
Boolean desenv = null;
boolean isDevelopment() {
if (desenv != null) return desenv;
try {
desenv = new File(".").getCanonicalPath().contains("workspace");
}
catch (IOException e) {
e.printStackTrace();
}
return desenv;
}
A more generic and precise way, that can be used on any IDE would be loop at:
ManagementFactory.getRuntimeMXBean().getInputArguments()
looking for "-Xdebug" || (starting with) "-agentlib:jdwp=".
I came with this from #saugata comment here.
This is excellent if you want to throw a conditional exception preventing the application from simply exiting. Use a boolean like "ideWait" and add it to Eclipse watch expressions as ideWait=false, so whenever you stop at that throw, and "drop to frame" you can continue debugging happily (I mean it!)
I don't think there is any way to do this. But what I would suggest is just a command line argument such as 'debug'. Then in your main method just do
if (args.length > 0 && args[0].equalsIgnoreCase("debug")) {
// do whatever extra work you require here or set a flag for the rest of the code
}
This way you can also get your extra code to run whenever you want just by specifiying the debug parameter but under normal conditions it will never execute.
This might work if your alternative execution work flow provides a different set of dependencies:
boolean isRunningInEclipe = false;
try {
Workbench.getInstance();
isRunningInEclipe = true;
} catch (NoClassDefFoundError error) {
//not running in Eclipse that would provide the Workbench class
}
You could detect if you're inside a JAR or not, as per Can you tell on runtime if you're running java from within a jar?
Eclipse will run your app from the classes/ dir, whereas most of your end users will be running the app from a JAR.
System.out.println("Is my parent eclipse[.exe]? " +
ProcessHandle.current()
.parent()
.flatMap(parent -> parent.info().command())
.orElse("")
.matches("^.*eclipse(\\.exe)?$"));
You may try something like this:
if (ClassLoader.getSystemResource("org/eclipse/jdt/core/BindingKey.class")!=null){
System.out.println("Running within Eclipse!!!");
} else {
System.out.println("Running outside Eclipse!!!");
}

Pinning a Java application to the Windows 7 taskbar

I use Launch4j as a wrapper for my Java application under Windows 7, which, to my understanding, in essence forks an instance of javaw.exe that in turn interprets the Java code. As a result, when attempting to pin my application to the task bar, Windows instead pins javaw.exe. Without the required command line, my application will then not run.
As you can see, Windows also does not realize that Java is the host application: the application itself is described as "Java(TM) Platform SE binary".
I have tried altering the registry key HKEY_CLASSES_ROOT\Applications\javaw.exe to add the value IsHostApp. This alters the behavior by disabling pinning of my application altogether; clearly not what I want.
After reading about how Windows interprets instances of a single application (and a phenomenon discussed in this question), I became interested in embedding a Application User Model ID (AppUserModelID) into my Java application.
I believe that I can resolve this by passing a unique AppUserModelID to Windows. There is a shell32 method for this, SetCurrentProcessExplicitAppUserModelID. Following Gregory Pakosz suggestion, I implemented it in an attempt to have my application recognized as a separate instance of javaw.exe:
NativeLibrary lib;
try {
lib = NativeLibrary.getInstance("shell32");
} catch (Error e) {
Logger.out.error("Could not load Shell32 library.");
return;
}
Object[] args = { "Vendor.MyJavaApplication" };
String functionName = "SetCurrentProcessExplicitAppUserModelID";
try {
Function function = lib.getFunction(functionName);
int ret = function.invokeInt(args);
if (ret != 0) {
Logger.out.error(function.getName() + " returned error code "
+ ret + ".");
}
} catch (UnsatisfiedLinkError e) {
Logger.out.error(functionName + " was not found in "
+ lib.getFile().getName() + ".");
// Function not supported
}
This appears to have no effect, but the function returns without error. Diagnosing why is something of a mystery to me. Any suggestions?
Working implementation
The final implementation that worked is the answer to my follow-up question concerning how to pass the AppID using JNA.
I had awarded the bounty to Gregory Pakosz' brilliant answer for JNI that set me on the right track.
For reference, I believe using this technique opens the possibility of using any of the APIs discussed in this article in a Java application.
I don't have Windows 7 but here is something that might get you started:
On the Java side:
package com.stackoverflow.homework;
public class MyApplication
{
static native boolean setAppUserModelID();
static
{
System.loadLibrary("MyApplicationJNI");
setAppUserModelID();
}
}
And on the native side, in the source code of the `MyApplicationJNI.dll library:
JNIEXPORT jboolean JNICALL Java_com_stackoverflow_homework_MyApplication_setAppUserModelID(JNIEnv* env)
{
LPCWSTR id = L"com.stackoverflow.homework.MyApplication";
HRESULT hr = SetCurrentProcessExplicitAppUserModelID(id);
return hr == S_OK;
}
Your question explicitly asked for a JNI solution. However, since your application doesn't need any other native method, jna is another solution which will save you from writing native code just for the sake of forwarding to the windows api. If you decide to go jna, pay attention to the fact that SetCurrentProcessExplicitAppUserModelID() is expecting a UTF-16 string.
When it works in your sandbox, the next step is to add operating system detection in your application as SetCurrentProcessExplicitAppUserModelID() is obviously only available in Windows 7:
you may do that from the Java side by checking that System.getProperty("os.name"); returns "Windows 7".
if you build from the little JNI snippet I gave, you can enhance it by dynamically loading the shell32.dll library using LoadLibrary then getting back the SetCurrentProcessExplicitAppUserModelID function pointer using GetProcAddress. If GetProcAddress returns NULL, it means the symbol is not present in shell32 hence it's not Windows 7.
EDIT: JNA Solution.
References:
The JNI book for more JNI examples
Java Native Access (JNA)
There is a Java library providing the new Windows 7 features for Java. It's called J7Goodies by Strix Code. Applications using it can be properly pinned to the Windows 7 taskbar. You can also create your own jump lists, etc.
I have implemented access to the SetCurrentProcessExplicitAppUserModelID method using JNA and it works quite well when used as the MSDN documentation suggests. I've never used the JNA api in the way you have in your code snippet. My implementation follows the typical JNA usage instead.
First the Shell32 interface definition:
interface Shell32 extends StdCallLibrary {
int SetCurrentProcessExplicitAppUserModelID( WString appID );
}
Then using JNA to load Shell32 and call the function:
final Map<String, Object> WIN32API_OPTIONS = new HashMap<String, Object>() {
{
put(Library.OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE);
put(Library.OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE);
}
};
Shell32 shell32 = (Shell32) Native.loadLibrary("shell32", Shell32.class,
WIN32API_OPTIONS);
WString wAppId = new WString( "Vendor.MyJavaApplication" );
shell32.SetCurrentProcessExplicitAppUserModelID( wAppId );
Many of the API's in the last article you mentioned make use of Windows COM which is quite difficult to use directly with JNA. I have had some success creating a custom DLL to call these API's (eg. using the SHGetPropertyStoreForWindow to set a different app ID for a submodule window) which I then use JNA to access at runtime.
Try to use JSmooth. I use always this one. In JSmooth is there an option under Skeleton by Windowed Wrapper called
Lauch java app in exe process
See on this image.
(source: andrels.com)
Also command line arguments can be passed.
I think this can be a solution for you.
Martijn
SetCurrentProcessExplicitAppUserModelID (or SetAppID()) would in fact do what you're trying to do. However, it might be easier to modify your installer to set the AppUserModel.ID property on your shortcut - quoting from the Application User Model ID document mentioned above:
In the System.AppUserModel.ID property of the application's shortcut file. A shortcut (as an IShellLink, CLSID_ShellLink, or a .lnk file) supports properties through IPropertyStore and other property-setting mechanisms used throughout the Shell. This allows the taskbar to identify the proper shortcut to pin and ensures that windows belonging to the process are appropriately associated with that taskbar button.
Note: The System.AppUserModel.ID property should be applied to a shortcut when that shortcut is created. When using the Microsoft Windows Installer (MSI) to install the application, the MsiShortcutProperty table allows the AppUserModelID to be applied to the shortcut when it is created during installation.
The latest jna-platform library now includes JNA bindings for SetCurrentProcessExplicitAppUserModelID:
https://github.com/java-native-access/jna/pull/680
I fixed mine without any ID settings.
There is an option in Launch4J if you are using it and you say you do then...
You can change the header to JNI Gui and then wrap it around the jar with the JRE.
The good thing is that it runs .exe in the process now instead on running javaw.exe with your jar. It probably does it under the hood (not sure).
Also I have noticed also that it takes around 40-50% less CPU resource which is even better!
And the pinning works fine and all that window features are enabled.
I hope it helps to someone as I spent nearly 2 days trying to solve that issue with my undecorated javafx app.

What is the best way to detect whether an application is launched by Webstart

As it was made clear in my recent question, Swing applications need to explicitly call System.exit() when they are ran using the Sun Webstart launcher (at least as of Java SE 6).
I want to restrict this hack as much as possible and I am looking for a reliable way to detect whether the application is running under Webstart. Right now I am checking that the value of the system property "webstart.version" is not null, but I couldn't find any guarantees in the documentation that this property should be set by future versions/alternative implementations.
Are there any better ways (preferably ones that do not ceate a dependency on the the webstart API?)
When your code is launched via javaws, javaws.jar is loaded and the JNLP API classes that you don't want to depend on are available. Instead of testing for a system property that is not guaranteed to exist, you could instead see if a JNLP API class exists:
private boolean isRunningJavaWebStart() {
boolean hasJNLP = false;
try {
Class.forName("javax.jnlp.ServiceManager");
hasJNLP = true;
} catch (ClassNotFoundException ex) {
hasJNLP = false;
}
return hasJNLP;
}
This also avoids needing to include javaws.jar on your class path when compiling.
Alternatively you could switch to compiling with javaws.jar and catching NoClassDefFoundError instead:
private boolean isRunningJavaWebStart() {
try {
ServiceManager.getServiceNames();
return ds != null;
} catch (NoClassDefFoundError e) {
return false;
}
}
Using ServiceManager.lookup(String) and UnavailableServiceException is trouble because both are part of the JNLP API. The ServiceManager.getServiceNames() is not documented to throw. We are specifically calling this code to check for a NoClassDefFoundError.
Use the javax.jnlp.ServiceManager to retrieve a webstart service.
If it is availabe, you are running under Webstart.
See http://download.java.net/jdk7/docs/jre/api/javaws/jnlp/index.html
As you mentioned, checking the System property as follows is probably the cleanest way:
private boolean isRunningJavaWebStart() {
return System.getProperty("javawebstart.version", null) != null;
}
In a production system I have used the above technique for years.
You can also try to check to see if there are any properties that start with "jnlpx." but none of those are really "guaranteed" to be there either as far as I know.
An alternative could be to attempt to instantiate the DownloadService us suggested by Tom:
private boolean isRunningJavaWebStart() {
try {
DownloadService ds = (DownloadService) ServiceManager.lookup("javax.jnlp.DownloadService");
return ds != null;
} catch (UnavailableServiceException e) {
return false;
}
}
Of course that does have the downside of coupling your code to that API.
I have no real experience with Java web start other than looking at it a few years back.
How about start your application with a parameter that you define than you set when the app is started via Java web start.
If you want to pass in arguments to your app, you have to add them to the start-up file (aka JNLP descriptor) using or elements.
Then check to see if these properties are set.
Again this is a suggestion I have not coded for JWS and it may not be this easy.
You can check whether the current classloader is an instance of com.sun.jnlp.JNLPClassLoader (Java plugin 1) or sun.plugin2.applet.JNLP2ClassLoader (Java plugin 2). Despite the "applet" package, an applet using JNLP with the Java plugin 2 uses another classloader, sun.plugin2.applet.Applet2ClassLoader. It works with OpenJDK too.

Categories