Skip to content

Commit

Permalink
Fix some of the failing tests in #274 (#284)
Browse files Browse the repository at this point in the history
* Add PlatformClassLoader

Nowadays, Java is aware of three different Class Loaders: System, Platform and Thread.

* Add tid (thread id) to Thread as required in Java 11

* Add additional Constructor to secure class laoder matching Java 11 singatures

This ClassLoader is used in the service provider loading and helps to port the DateFormat test cases.

* Add defineUnnamedModule to the System class

This method is ocassinaly used by Java internals requried to make the DateFormat conversion work.

* Extend the JavaLangAccess signature

* Add missing methods to Unsafe

After resoling an error in loading modules from the classes folder, the Unsafe missed some methods.

* Fix some internals of concurrent

This fixes CountDownLatchTest, ExecutorServiceTest, SemaphoreTest

* Load unloaded error classes

JPF requries nowadays a repeatedInvocation for LoadOnJPFRequired errors.
  • Loading branch information
mmuesly authored Mar 16, 2021
1 parent cc080e0 commit a992619
Show file tree
Hide file tree
Showing 15 changed files with 394 additions and 62 deletions.
7 changes: 4 additions & 3 deletions src/classes/modules/java.base/java/lang/ClassLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import java.net.URL;
import java.nio.ByteBuffer;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
Expand Down Expand Up @@ -148,9 +147,11 @@ public InputStream getResourceAsStream (String name){
return null;
}

public native static ClassLoader getSystemClassLoader ();
public native static ClassLoader getSystemClassLoader();

public static URL getSystemResource(String name){
public native static ClassLoader getPlatformClassLoader();

public static URL getSystemResource(String name) {
return getSystemClassLoader().getResource(name);
}

Expand Down
14 changes: 10 additions & 4 deletions src/classes/modules/java.base/java/lang/System.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,10 @@
import java.nio.channels.Channel;
import java.util.Map;
import java.util.Properties;

import jdk.internal.misc.JavaLangAccess;
import jdk.internal.misc.SharedSecrets;
import sun.nio.ch.Interruptible;
import jdk.internal.reflect.ConstantPool;
import sun.nio.ch.Interruptible;
import sun.reflect.annotation.AnnotationType;


Expand Down Expand Up @@ -95,15 +94,22 @@ public void blockedOn(Thread t, Interruptible b) {
public void registerShutdownHook(int slot, Runnable r) {
throw new UnsupportedOperationException("JavaLangAccess.registerShutdownHook() not supported yet");
}

@Override
public int getStackTraceDepth(Throwable t) {
public int getStackTraceDepth(Throwable t) {
return t.getStackTraceDepth();
}

@Override
public StackTraceElement getStackTraceElement(Throwable t, int i) {
public StackTraceElement getStackTraceElement(Throwable t, int i) {
StackTraceElement[] st = t.getStackTrace();
return st[i];
}

@Override
public Module defineUnnamedModule(ClassLoader loader) {
return new Module(loader);
}
};
}

Expand Down
12 changes: 8 additions & 4 deletions src/classes/modules/java.base/java/lang/Thread.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,26 +29,30 @@
public class Thread implements Runnable {

public interface UncaughtExceptionHandler {

// note this doesn't stop the thread from being terminated
void uncaughtException (Thread t, Throwable x);
void uncaughtException(Thread t, Throwable x);
}

static int nameThreadNum; // to construct the default thread name

public static final int MIN_PRIORITY = 1;
public static final int NORM_PRIORITY = 5;
public static final int MAX_PRIORITY = 10;

public static long counter = 0;
private final long tid = ++counter;

// don't rename this - it's used by ThreadGoup.uncaughtException()
private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler; // null by default

// initialized in init(), except of the main thread (which gets explicitly initialized by the VM)
ThreadGroup group;
Runnable target;
String name;
int priority;
boolean isDaemon;

// this is an explicit thread state that gets set on a call of interrupt(), but
// only if the thread is not blocked. If it is, we only change the status.
// this gets cleared by calling interrupted()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright (C) 2014, United States Government, as represented by the
* Administrator of the National Aeronautics and Space Administration.
* All rights reserved.
*
* The Java Pathfinder core (jpf-core) platform is licensed under the
* Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.lang.invoke;


// We use this a model class in JPF to model the new VarHandle behavior for field replacing longterm the Unsafe implementation.
// See: http://cr.openjdk.java.net/~psandoz/varhandles/VarHandle-0.1.md for more information on VarHandle.
public class JPFFieldVarHandle extends VarHandle {

int fieldRef;
int classRef;

JPFFieldVarHandle() {
super(null);
}

JPFFieldVarHandle(int fieldRef) {
super(null);
this.fieldRef = fieldRef;
}

MethodType accessModeTypeUncached(AccessMode accessMode) {
return null;
}

public boolean compareAndSet(Object aqs, int expect, int update) {
//This is implemented in the corresponding peer
return false;
}

public boolean compareAndSet(Object aqs, Object expect, Object update) {
//This is implemented in the corresponding peer
return false;
}

public void set(Object called, int value) {
//This is implemented in the corresponding peer
}

public void set(Object called, Object value) {
//This is implemented in the corresponding peer
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,15 @@

/**
* This is just a dummy implementation of java.security.SecureClassLoader
*
* @author Nastaran Shafiei <nastaran.shafiei@gmail.com>
*/
public class SecureClassLoader extends ClassLoader {

protected SecureClassLoader(String name, ClassLoader parent) {
super(parent);
}

protected SecureClassLoader(ClassLoader parent) {
super(parent);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@

package jdk.internal.misc;

import sun.nio.ch.Interruptible;
import jdk.internal.reflect.ConstantPool;
import sun.nio.ch.Interruptible;
import sun.reflect.annotation.AnnotationType;

/**
Expand All @@ -44,8 +44,10 @@ public interface JavaLangAccess {
void blockedOn(Thread t, Interruptible b);

void registerShutdownHook(int slot, Runnable r);

int getStackTraceDepth(Throwable t);

StackTraceElement getStackTraceElement(Throwable t, int i);

Module defineUnnamedModule(ClassLoader loader);
}
123 changes: 110 additions & 13 deletions src/classes/modules/java.base/jdk/internal/misc/Unsafe.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@
import java.lang.reflect.Field;

/**
* Unsafe = unwanted. See comments in the native peer. We only have it because
* it is required by java.util.concurrent.
*
* Note that in the real world, this class is only callable from the system library,
* not application code
* Unsafe = unwanted. See comments in the native peer. We only have it because it is required by
* java.util.concurrent and with java 11 in jdk.internal.util.ArraysSupport
* <p>
* Note that in the real world, this class is only callable from the system library, not application
* code
*/

public class Unsafe {
Expand All @@ -38,32 +38,129 @@ public static Unsafe getUnsafe() {
}

private static native void registerNatives();

private native int addressSize0();

private native boolean isBigEndian0();

private native boolean unalignedAccess0();

public native void storeFence();


public final boolean isBigEndian() {
return true;
}


//We need those to make ArraysSupport work nicely
public static final int ARRAY_BOOLEAN_INDEX_SCALE
= theUnsafe.arrayIndexScale(boolean[].class);
/**
* The value of {@code arrayIndexScale(byte[].class)}
*/
public static final int ARRAY_BYTE_INDEX_SCALE
= theUnsafe.arrayIndexScale(byte[].class);

/**
* The value of {@code arrayIndexScale(short[].class)}
*/
public static final int ARRAY_SHORT_INDEX_SCALE
= theUnsafe.arrayIndexScale(short[].class);

/**
* The value of {@code arrayIndexScale(char[].class)}
*/
public static final int ARRAY_CHAR_INDEX_SCALE
= theUnsafe.arrayIndexScale(char[].class);

/**
* The value of {@code arrayIndexScale(int[].class)}
*/
public static final int ARRAY_INT_INDEX_SCALE
= theUnsafe.arrayIndexScale(int[].class);

/**
* The value of {@code arrayIndexScale(long[].class)}
*/
public static final int ARRAY_LONG_INDEX_SCALE
= theUnsafe.arrayIndexScale(long[].class);

/**
* The value of {@code arrayIndexScale(float[].class)}
*/
public static final int ARRAY_FLOAT_INDEX_SCALE
= theUnsafe.arrayIndexScale(float[].class);

/**
* The value of {@code arrayIndexScale(double[].class)}
*/
public static final int ARRAY_DOUBLE_INDEX_SCALE
= theUnsafe.arrayIndexScale(double[].class);

public static final int ARRAY_OBJECT_INDEX_SCALE
= theUnsafe.arrayIndexScale(Object[].class);

public static final int ARRAY_BOOLEAN_BASE_OFFSET
= theUnsafe.arrayBaseOffset(boolean[].class);

public static final int ARRAY_BYTE_BASE_OFFSET
= theUnsafe.arrayBaseOffset(byte[].class);

public static final int ARRAY_SHORT_BASE_OFFSET
= theUnsafe.arrayBaseOffset(short[].class);

public static final int ARRAY_CHAR_BASE_OFFSET
= theUnsafe.arrayBaseOffset(char[].class);

public static final int ARRAY_INT_BASE_OFFSET
= theUnsafe.arrayBaseOffset(int[].class);

public static final int ARRAY_LONG_BASE_OFFSET
= theUnsafe.arrayBaseOffset(long[].class);

public static final int ARRAY_FLOAT_BASE_OFFSET
= theUnsafe.arrayBaseOffset(float[].class);

public static final int ARRAY_DOUBLE_BASE_OFFSET
= theUnsafe.arrayBaseOffset(double[].class);

public static final int ARRAY_OBJECT_BASE_OFFSET
= theUnsafe.arrayBaseOffset(Object[].class);

public final long getLongUnaligned(Object o, long offset) {
return getLong(o, offset);
}

// field offsets are completely useless between VMs, we just return
// a numeric id for the corresponding FieldInfo here
public native int fieldOffset (Field f);
public native long objectFieldOffset (Field f);
public native int fieldOffset(Field f);

public native long objectFieldOffset(Field f);

public native long objectFieldOffset(Class<?> c, String name);

public final native boolean compareAndSetInt(Object o, long offset, int expected, int x);

public final native boolean compareAndSetLong(Object o, long offset, long expected, long x);

public final native boolean compareAndSetObject(Object o, long offset, Object expected, Object x);

// those do the usual CAS magic
public native boolean compareAndSwapObject (Object oThis, long offset, Object expect, Object update);
public native boolean compareAndSwapInt (Object oThis, long offset, int expect, int update);
public native boolean compareAndSwapLong (Object oThis, long offset, long expect, long update);
public native boolean compareAndSwapObject(Object oThis, long offset, Object expect,
Object update);

public native boolean compareAndSwapInt(Object oThis, long offset, int expect, int update);

public native boolean compareAndSwapLong(Object oThis, long offset, long expect, long update);

// that looks like some atomic conditional wait
public native void park (boolean isAbsolute, long timeout);
public native void unpark (Object thread);
public native void park(boolean isAbsolute, long timeout);

public native void unpark(Object thread);

// various accessors
public native int getInt(Object obj, long l);

public native int getIntVolatile(Object obj, long l);

@Deprecated
Expand Down
11 changes: 9 additions & 2 deletions src/main/gov/nasa/jpf/jvm/JVMClassFileContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,11 @@

package gov.nasa.jpf.jvm;

import gov.nasa.jpf.JPFException;
import gov.nasa.jpf.vm.AnnotationInfo;
import gov.nasa.jpf.vm.ClassFileContainer;
import gov.nasa.jpf.vm.ClassFileMatch;
import gov.nasa.jpf.vm.ClassLoaderInfo;
import gov.nasa.jpf.vm.ClassParseException;

import java.io.File;

/**
Expand Down Expand Up @@ -101,14 +99,23 @@ static String getClassEntryURL(String typeName) {
if (moduleName == null) {
return typeName.replace('.', File.separatorChar) + ".class";
}
//Strip eventual module prefix
if (typeName.contains("$&$")) {
typeName = typeName.split("\\$&\\$")[1];
}
return moduleName + File.separator + typeName.replace('.', File.separatorChar) + ".class";
}

/**
* @return the module name for the given typeName. Returns null if the module is an unnamed module
* or the Class object associated with the given typeName is not found.
*
* It is possible to hint the loader with the module name using $&$ as separator between module and class.
*/
static String getModuleName(String typeName) {
if (typeName.contains("$&$")) {
return typeName.split("\\$&\\$")[0];
}
try {
return Class.forName(typeName.split("\\$")[0]).getModule().getName();
} catch (ClassNotFoundException e) {
Expand Down
Loading

0 comments on commit a992619

Please sign in to comment.