Why sun.swing.AccessibleMethod is gone from JDK 8? - java

I'm wondering if someone know why sun.swing.AccessibleMethod is gone from JDK 8 and if there is some alternative to this class in JDK 8?
I can't find any information about that anywhere.
I use this class in my own implementation DropHandler. Code snippet where I use sun.swing.AccessibleMethod looks like this:
private DropLocation getDropLocation(DropTargetEvent e)
{
DropLocation dropLocation = null;
if (this.component != null)
{
try
{
Point p = e instanceof DropTargetDragEvent ? ((DropTargetDragEvent)e).getLocation() : ((DropTargetDropEvent) e).getLocation();
AccessibleMethod method = new AccessibleMethod(JComponent.class,
"dropLocationForPoint",
Point.class);
dropLocation = (DropLocation) method.invokeNoChecked(this.component, p);
}
catch (NoSuchMethodException ex)
{
LOGGER.info(ex.getMessage());
}
}
return dropLocation;
}

As explained in this official post from Oracle: Why Developers Should Not Write Programs That Call 'sun' Packages (thanks to #greg-449 for providing this info):
The sun.* packages are not part of the supported, public interface.
A Java program that directly calls into sun.* packages is not guaranteed to work on all Java-compatible platforms. In fact, such a program is not guaranteed to work even in future versions on the same platform.
So, you should not have relied on sun.swing.AccessibleMethod class in the first place.
More info:
It is a bad practice to use Sun's proprietary Java classes?
As a solution for your problem, you can do the following:
Use the source code of sun.swing.AccessibleMethod to create a custom class.
Replace the usage of AccessibleMethod by your own custom class.

What’s the point about this AccessibleMethod class?
The following uses standard Java API which exists since Java 1.2:
try {
Method method = JComponent.class
.getDeclaredMethod("dropLocationForPoint", Point.class);
method.setAccessible(true);
dropLocation = (DropLocation) method.invoke(this.component, p);
} catch(NoSuchMethodException|IllegalAccessException|InvocationTargetException ex) {
Logger.info(ex.getMessage());
}
However, don’t come back and ask why JComponent.dropLocationForPoint has been removed, if that happens in the future. If you are accessing non-standard APIs you may encounter such problems. To be exact, there were always Java implementations not having these features your code relies on...

Related

Problems with SmbFile.createNewFile() behaviour

I wonder what the catch is with createNewFile() in recent versions of jCIFS and ng (SMB2 specifically). The documentation says it should fail on execution if a file already exists, but that is not the case in my code, the file is always overwritten instead of throwing a SmbException. I need to be able to rename the file so it is not overwritten, but due to server load and quantity I cannot use exists(). This snippet worked perfectly on SMB1:
for (int i = 0; !fileCreated && (i < maxCopies); i++) {
try {
smbFile.createNewFile();
fileCreated = true;
} catch (SmbException e) {
smbFile = new SmbFile(smbFilePath.concat(String.valueOf(i)), auth);
}
}
I've been searching high and low and trying out different versions of SMB2, but createNewFile() always does the opposite of what the javadoc says it should. Is there a simple way (using attributes for example) to make it work just as in SMB1?
EDIT: Solution by jcifs-ng developer on GitHub
Apparently I got the behavior wrong when implementing the SMB2
version. Create disposition should be FILE_CREATE not FILE_OPEN_IF,
then ( O_EXCL in SMB1). Let me look into making that change, and how
much havoc this will cause. You could potentially work around this by
explicitly calling openOutputStream and passing O_EXCL as open flag.

c# And/Or vb.net equivalent of apache commons Validate

In Java, if Apache Commons Lang jar is in the classpath, we can do one line Validates, like
Validate.isTrue(someBoolean, "This should be true");
In effect the above is the same as:
if (! someBoolean) {
throw new RuntimeException("This should be true");
}
Is there something in the .net world that will do the same?
I know I have seen code somewhere that did something similar but I can't remember where or the systax.
Any help is much appreciated.
You can, of course, write your own:
public static class Validate
{
public static void IsTrue(bool value)
{
if (!value) throw new InvalidOperationException(message)
}
}
Also, in C# or VB you can use code contracts:
Contract.Requires(someBoolean, "This should be true")
This requires downloading the code contracts extension from the Visual Studio extensions site. You can turn on code contracts and have them verified at compile time, and it allows specifying fairly arbitrary contract conditions.

DateTime compareTo not applicable to DateTime

The investigation and details for the accepted answer are in the comments to the question.
I have a small Java project that reads a schedule and puts Joda-Time Intervals into a sorted map (TreeMap in this case) for further processing.
This is done via a ScheduledExecutorService:
executor.scheduleWithFixedDelay(new Runnable() {
#Override
public void run() {
try {
doWork();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}, 1, 1, TimeUnit.SECONDS);
doWork() then reads a file, creates some intervals and then populates the map using this comparator (specified in the map constructor):
#Override
public int compare(Interval o1, Interval o2) {
return o1.getStart().compareTo(o2.getStart());
}
The code then breaks in the comparator when inserting the very first interval.
Usually I would think there is something wrong with the interval itself, however I have checked several possibilities and noticed multiple odd things that I got lost in:
The interval is fine, o1 and o2 are valid DateTimes with the same long timestamp.
No exception is caught. The thread just ceases work.
When I launch the app from Eclipse, everything works fine. It only breaks when launching a deployed version. By deployed I mean it was packed into a .jar and copied over to a shared directory, no containers here.
Changing
try {
doWork();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
to
try {
doWork();
} catch (Throwable e) {
e.printStackTrace();
throw new RuntimeException(e);
}
fixes it. (I.e. map gets populated fine, including the original first interval).
The last part makes me think it is a bug with JIT or JVM, rather than with the code.
I have also explored the possibility of this being a build issue, however it does not seem to be the case:
Both Eclipse and the build server use Java 7 (Eclipse 7.0.51, Build server: 7.0.25, Launched the deployed version with a 7.0.51 JRE)
Joda time library version is the same both in Eclipse and deployed lib folder (2.1)
This is NOT a new feature and the very same code works in a different branch, and has been for a couple of weeks now
I have tried stopping Eclipse from using its own cached Ivy libraries, and instead use the libraries in the deployed directory. Same stuff - works from Eclipse, doesn't work when launching jar with Java.
After a bit of remote-debugging I have reproduced something of the like: Method "compareTo" with signature "(Lorg/joda/time/ReadableInstant;)I" is not applicable on this object with the target object being class org.joda.time.DateTime when breakpointing in the comparator code.
Any help in how to debug this further would be appreciated.
EDIT:
private void doWork() {
SortedMap<Interval, String> map = new TreeMap<>(new Comparator<Interval>() {
#Override
public int compare(Interval o1, Interval o2) {
return o1.getStart().compareTo(o2.getStart());
}
});
Collection<String> col1 = new HashSet<>();
Collection<String> col2 = new HashSet<>();
String string = "";
long ts = 0;
try (FileInputStream input = new FileInputStream(fileName);
InputStreamReader isr = new InputStreamReader(input);
BufferedReader reader = new BufferedReader(isr)) {
String line = reader.readLine();
map.put(new Interval(new DateTime(), new DateTime()), "");
}
}
While this does not look like an SSCCE due to a lot of extra code, if I remove the Collection declarations or the line read, or put anything in the map before the try block (and then do the rest as is) - everything works fine. Makes me think of race conditions, however all variables involved here are local (except fileName, which is guaranteed to have been set).
Also, while trying out stuff I found that switching to Joda-time 2.3 from 2.1 apparently fixes the problem. However I do not see anything in their changelog of bugfixes that looks even remotely relevant.
Here a summarizing answer on base of my comments:
Does the remote side have a second JodaTime version? Maybe an older one before version 2.0 where the Comparable-handling changed a little bit (see generified interface ReadableInstant)? Pre 2.0 the method in question had the signature compareTo(Object) while in 2.0 and later the new signature compareTo(ReadableInstant), see also the release notes. This situation of two joda-jars and a connected classloading-issue would explain following exception message:
Method "compareTo" with signature "(Lorg/joda/time/ReadableInstant;)I" is not applicable on this object with the target object being class org.joda.time.DateTime.
(Your question was tricky and has deserved even more upvotes. Glad to hear that you found the reason in JRuby-library containing an older JodaTime-version.)

Is there a way to get, at runtime, the version of Guava in use?

I did a quick grep of the Guava source and documentation, and neither seem to have any mention of versions. I was wondering if there was a way Guava's version information can be obtained at runtime.
This version information doesn't have to be accessible via any getter, if no such thing actually exists; if it's stashed in a field somewhere that doesn't get GC'd while Guava is loaded, that would be sufficient.
Is this version information available anywhere at runtime?
I have a very specific use for this. A big part of my work is analysing Java heap dumps to identify and fix places in the code that cause exorbitant memory usage. For this task, I use fasthat, a heavily-modified version of jhat with special features useful to my work.
One of those features is to display the contents of containers. I've already implemented this for the likes of ArrayList, HashMap, ConcurrentHashMap, etc. (I implement type printers on demand, based on what I encounter in our heap dumps.) Currently, I'm implementing a type printer for Guava's CustomConcurrentHashMap.
Since the layout of structures can change between versions, my code tweaks its unpacking behaviour based on what version is in use. For example, at work, we used to use JRuby 1.2, but recently switched to JRuby 1.6, so I have type printers for both of those versions, and it selects the version based on the version information it finds in the heap dump.
So, that's the point of the second paragraph of the question: if the version information is anywhere in the heap dump, that's all I need.
And before anyone asks: heap dump data is not "live", so you cannot simply call toString or the like. You really have to walk the data structures to extract the bits out, and you really do have to use implementation details to the nth degree. ;-)
If you want to get the version of a maven built class, you can start with the class, find the jar it comes from and read the meta information which maven adds (such as the version)
A simpler way to do this, if the version is in the path, is to look at your classpath, find guava and the version you are using from the file name.
For a heap dump, the class path is in a System property.
This is more of a workaround, but I guess you could do this if there is no simpler way of accessing the Guava version:
In most Guava releases, classes / fields / methods are added / removed. You could try to look for them in the heap dump, and, depending on their existence, determine the Guava version.
Something like:
/**
* A {#link Predicate} that checks whether a class exists in the given {#link HeapDump}
*/
public class ClassExistsPredicate implements Predicate<String> {
private final HeapDump heapDump;
public ClassExistsPredicate(HeapDump heapDump) {
this.heapDump = heapDump;
}
#Override
public boolean apply(String fullyQualifiedClassName) {
// checks whether the given class exists in the heap dump
return true;
}
}
public enum GuavaVersion {
R01,
R02 {
#Override
Set<String> getAddedClasses() {
return ImmutableSet.of("com.google.common.base.Foo");
}
},
R03 {
#Override
Set<String> getAddedClasses() {
return ImmutableSet.of("com.google.common.collect.ForwardingFooIterator");
}
},
R04 {
#Override
Set<String> getAddedClasses() {
return ImmutableSet.of("com.google.common.collect.FooFoo2");
}
};
/**
* #return a {#link Set} of added class names that uniquely identify this version from the preceding one (not
* necessarily <b>all</b> classes!)
*/
Set<String> getAddedClasses() {
return ImmutableSet.of();
}
public static GuavaVersion getGuavaVersionFor(HeapDump heapDump) {
ClassExistsPredicate classExists = new ClassExistsPredicate(heapDump);
for (GuavaVersion version : Lists.reverse(Arrays.asList(GuavaVersion.values()))) {
if (Iterables.all(version.getAddedClasses(), classExists)) {
return version;
}
}
throw new RuntimeException("Unable to determine Guava version...");
}
}
Obviously, you should cache the Guava version number, since the computation might be slow... The approach could be extended to consider added methods / fields.
This approach could work with other projects, too.
You can retrieve the version from Guava's JAR manifest.
public static String getGuavaVersion() {
try {
File file = new File(Charsets.class.getProtectionDomain().getCodeSource().getLocation().toURI());
try (JarFile jar = new JarFile(file)) {
return jar.getManifest().getMainAttributes().getValue("Bundle-Version");
}
} catch (Exception ex) {
throw new RuntimeException("Unable to get the version of Guava", ex);
}
}
Unfortunately, this works only for Guava 11+. Guava 10 and older were not OSGI bundles yet.
Another option is to retrieve the version from pom.properties. This works for old versions of Guava too: https://gist.github.com/seanizer/8de050427f3f199cf8f085b2a3a2473e

Is there a way to get which classes a ClassLoader has loaded?

I am trying to implement some unit testing for an old framework. I am attempting to mock out the database layer. Unfortunately our framework is a bit old and not quite using best practices so there is no clear separation of concerns. I am bit worried that trying to mock out the database layer might make the JVM load a huge number of classes that won't even be used.
I don't really understand class loaders that well so this might not be a problem. Is there a way to take a peak at all the classes a particular ClassLoader has loaded to prove what is going on under the hood?
You can create your own Classloader and use that to load during the unit test. Have your own custom Classloader print out what it's doing.
Or if you just want to know which classes are loaded, do:
java -verbose:class
Be warned that using
java -verbose
Will produce an enormous amount of output. Log the output to a file and then use grep. If you have the 'tee' filter you could try this:
java -verbose | tee classloader.log
grep class classloader.log
I am not sure. But there is one way I see it could be done. It maybe overrly ridiculous though. You can try aspects and put a pointcut for loadclass.
Also maybe the jvm argument -verbose maybe helpful.
As an alternative way, for a particular Class-loader as you mentioned, you can use this code snippet. Just change value of obj variable if you want.
Object obj = this;
ClassLoader classLoader = obj.getClass().getClassLoader();
File file = new File("classloderClasses.txt");
if (file.exists()) {
file.delete();
}
if (classLoader != null) {
try {
Class clClass = classLoader.getClass();
while (clClass != ClassLoader.class) {
clClass = clClass.getSuperclass();
}
java.lang.reflect.Field classesField = clClass.getDeclaredField("classes");
classesField.setAccessible(true);
Vector classes = (Vector) classesField.get(classLoader);
FileOutputStream fos = new FileOutputStream("classloderClasses.txt", true);
fos.write(("******************** " + classLoader.toString() + " ******************** " + "\n").getBytes());
fos.write(Arrays.toString(classes.toArray()).getBytes());
fos.close();
} catch (Exception exception) {
exception.printStackTrace();
// TODO
}
}

Categories

Resources