zhouping
5 years ago
52 changed files with 1236 additions and 583 deletions
@ -1,116 +0,0 @@
|
||||
/* |
||||
* Copyright 2006-2018 the original author or authors. |
||||
* |
||||
* 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 com.fr.third.org.objenesis; |
||||
|
||||
import com.fr.third.org.objenesis.instantiator.ObjectInstantiator; |
||||
import com.fr.third.org.objenesis.strategy.InstantiatorStrategy; |
||||
|
||||
import java.util.Map; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
|
||||
/** |
||||
* Base class to extend if you want to have a class providing your own default strategy. Can also be |
||||
* instantiated directly. |
||||
* |
||||
* @author Henri Tremblay |
||||
*/ |
||||
public class ObjenesisBase implements Objenesis { |
||||
|
||||
/** |
||||
* Strategy used by this Objenesi implementation to create classes |
||||
*/ |
||||
protected final InstantiatorStrategy strategy; |
||||
|
||||
/** |
||||
* Strategy cache. Key = Class, Value = InstantiatorStrategy |
||||
*/ |
||||
protected Map<Class, ObjectInstantiator<?>> cache; |
||||
|
||||
/** |
||||
* Constructor allowing to pick a strategy and using cache |
||||
* |
||||
* @param strategy Strategy to use |
||||
*/ |
||||
public ObjenesisBase(InstantiatorStrategy strategy) { |
||||
this(strategy, true); |
||||
} |
||||
|
||||
/** |
||||
* Flexible constructor allowing to pick the strategy and if caching should be used |
||||
* |
||||
* @param strategy Strategy to use |
||||
* @param useCache If {@link ObjectInstantiator}s should be cached |
||||
*/ |
||||
public ObjenesisBase(InstantiatorStrategy strategy, boolean useCache) { |
||||
if (strategy == null) { |
||||
throw new IllegalArgumentException("A strategy can't be null"); |
||||
} |
||||
this.strategy = strategy; |
||||
this.cache = useCache ? new ConcurrentHashMap<Class, ObjectInstantiator<?>>() : null; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return getClass().getName() + " using " + strategy.getClass().getName() |
||||
+ (cache == null ? " without" : " with") + " caching"; |
||||
} |
||||
|
||||
/** |
||||
* Will create a new object without any constructor being called |
||||
* |
||||
* @param clazz Class to instantiate |
||||
* @return New instance of clazz |
||||
*/ |
||||
public <T> T newInstance(Class<T> clazz) { |
||||
return getInstantiatorOf(clazz).newInstance(); |
||||
} |
||||
|
||||
/** |
||||
* Will pick the best instantiator for the provided class. If you need to create a lot of |
||||
* instances from the same class, it is way more efficient to create them from the same |
||||
* ObjectInstantiator than calling {@link #newInstance(Class)}. |
||||
* |
||||
* @param clazz Class to instantiate |
||||
* @return Instantiator dedicated to the class
|
||||
*/ |
||||
@SuppressWarnings("unchecked") |
||||
public <T> ObjectInstantiator<T> getInstantiatorOf(Class<T> clazz) { |
||||
if (clazz.isPrimitive()) { |
||||
throw new IllegalArgumentException("Primitive types can't be instantiated in Java"); |
||||
} |
||||
if (cache == null) { |
||||
return strategy.newInstantiatorOf(clazz); |
||||
} |
||||
ObjectInstantiator<?> instantiator = cache.get(clazz); |
||||
if (instantiator == null) { |
||||
ObjectInstantiator<?> newInstantiator = strategy.newInstantiatorOf(clazz); |
||||
instantiator = putIfAbsent(clazz, newInstantiator); |
||||
if (instantiator == null) { |
||||
instantiator = newInstantiator; |
||||
} |
||||
} |
||||
return (ObjectInstantiator<T>) instantiator; |
||||
} |
||||
|
||||
private ObjectInstantiator<?> putIfAbsent(Class key, ObjectInstantiator<?> newInstantiator) { |
||||
|
||||
ObjectInstantiator<?> instantiator = cache.get(key); |
||||
if (instantiator == null) { |
||||
instantiator = cache.put(key, newInstantiator); |
||||
} |
||||
return instantiator; |
||||
} |
||||
} |
@ -1,78 +0,0 @@
|
||||
/* |
||||
* Copyright 2006-2018 the original author or authors. |
||||
* |
||||
* 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 com.fr.third.org.objenesis.instantiator.util; |
||||
|
||||
import com.fr.third.org.objenesis.ObjenesisException; |
||||
|
||||
/** |
||||
* Helper class for to play with classes. It contains everything needed to play with a class
|
||||
* except the dodgy (Java 8) code you will find in {@link ClassDefinitionUtils}. |
||||
* |
||||
* @author Henri Tremblay |
||||
*/ |
||||
public final class ClassUtils { |
||||
|
||||
private ClassUtils() { } |
||||
|
||||
/** |
||||
* Will convert a class name to its name in the class definition format (e.g {@code com.fr.third.org.objenesis.EmptyClass} |
||||
* becomes {@code org/objenesis/EmptyClass}) |
||||
* |
||||
* @param className full class name including the package
|
||||
* @return the internal name |
||||
*/ |
||||
public static String classNameToInternalClassName(String className) { |
||||
return className.replace('.', '/'); |
||||
} |
||||
|
||||
/** |
||||
* Will convert a class name to its class loader resource name (e.g {@code com.fr.third.org.objenesis.EmptyClass} |
||||
* becomes {@code org/objenesis/EmptyClass.class}) |
||||
* |
||||
* @param className full class name including the package
|
||||
* @return the resource name |
||||
*/ |
||||
public static String classNameToResource(String className) { |
||||
return classNameToInternalClassName(className) + ".class"; |
||||
} |
||||
|
||||
/** |
||||
* Check if this class already exists in the class loader and return it if it does |
||||
* |
||||
* @param <T> type of the class returned |
||||
* @param classLoader Class loader where to search the class
|
||||
* @param className Class name with full path |
||||
* @return the class if it already exists or null |
||||
*/ |
||||
@SuppressWarnings("unchecked") |
||||
public static <T> Class<T> getExistingClass(ClassLoader classLoader, String className) { |
||||
try { |
||||
return (Class<T>) Class.forName(className, true, classLoader); |
||||
} |
||||
catch (ClassNotFoundException e) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
@SuppressWarnings("deprecation") |
||||
public static <T> T newInstance(Class<T> clazz) { |
||||
try { |
||||
return clazz.newInstance(); |
||||
} catch (Exception e) { |
||||
throw new ObjenesisException(e); |
||||
} |
||||
} |
||||
} |
@ -1,147 +0,0 @@
|
||||
/* |
||||
* Copyright 2006-2018 the original author or authors. |
||||
* |
||||
* 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 com.fr.third.org.objenesis.instantiator.util; |
||||
|
||||
import sun.misc.Unsafe; |
||||
import com.fr.third.org.objenesis.ObjenesisException; |
||||
import com.fr.third.org.objenesis.strategy.PlatformDescription; |
||||
|
||||
import java.lang.invoke.MethodHandle; |
||||
import java.lang.invoke.MethodHandles; |
||||
import java.lang.invoke.MethodType; |
||||
import java.security.ProtectionDomain; |
||||
|
||||
/** |
||||
* Java 11+ removed sun.misc.Unsafe.defineClass. This class bridges the gap to work from Java 1.8 up to 11. |
||||
* <p> |
||||
* It was inspired from <a href="https://github.com/jboss-javassist/javassist/blob/master/src/main/javassist/util/proxy/DefineClassHelper.java">javassist</a>. |
||||
* |
||||
* @author Henri Tremblay |
||||
*/ |
||||
public final class DefineClassHelper { |
||||
|
||||
private static abstract class Helper { |
||||
abstract Class<?> defineClass(String name, byte[] b, int off, int len, Class<?> neighbor, |
||||
ClassLoader loader, ProtectionDomain protectionDomain); |
||||
} |
||||
|
||||
private static class Java8 extends Helper { |
||||
|
||||
private final MethodHandle defineClass = defineClass(); |
||||
|
||||
private MethodHandle defineClass() { |
||||
MethodType mt = MethodType.methodType(Class.class, String.class, byte[].class, int.class, int.class, ClassLoader.class, ProtectionDomain.class); |
||||
MethodHandle m; |
||||
try { |
||||
m = MethodHandles.publicLookup().findVirtual(Unsafe.class, "defineClass", mt); |
||||
} catch(Exception e) { |
||||
throw new ObjenesisException(e); |
||||
} |
||||
Unsafe unsafe = UnsafeUtils.getUnsafe(); |
||||
return m.bindTo(unsafe); |
||||
} |
||||
|
||||
@Override |
||||
Class<?> defineClass(String className, byte[] b, int off, int len, Class<?> neighbor, ClassLoader loader, ProtectionDomain protectionDomain) { |
||||
try { |
||||
return (Class<?>) defineClass.invokeExact(className, b, off, len, loader, protectionDomain); |
||||
} catch (Throwable e) { |
||||
if(e instanceof Error) { |
||||
throw (Error) e; |
||||
} |
||||
if(e instanceof RuntimeException) { |
||||
throw (RuntimeException) e; |
||||
} |
||||
throw new ObjenesisException(e); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private static class Java11 extends Helper { |
||||
|
||||
private final Class<?> module = module(); |
||||
private final MethodHandles.Lookup lookup = MethodHandles.lookup(); |
||||
private final MethodHandle getModule = getModule(); |
||||
private final MethodHandle addReads = addReads(); |
||||
private final MethodHandle privateLookupIn = privateLookupIn(); |
||||
private final MethodHandle defineClass = defineClass(); |
||||
|
||||
private Class<?> module() { |
||||
try { |
||||
return Class.forName("java.lang.Module"); |
||||
} catch (ClassNotFoundException e) { |
||||
throw new ObjenesisException(e); |
||||
} |
||||
} |
||||
|
||||
private MethodHandle getModule() { |
||||
try { |
||||
return lookup.findVirtual(Class.class, "getModule", MethodType.methodType(module)); |
||||
} catch (Exception e) { |
||||
throw new ObjenesisException(e); |
||||
} |
||||
} |
||||
|
||||
private MethodHandle addReads() { |
||||
try { |
||||
return lookup.findVirtual(module, "addReads", MethodType.methodType(module, module)); |
||||
} catch (Exception e) { |
||||
throw new ObjenesisException(e); |
||||
} |
||||
} |
||||
|
||||
private MethodHandle privateLookupIn() { |
||||
try { |
||||
return lookup.findStatic(MethodHandles.class, "privateLookupIn", MethodType.methodType(MethodHandles.Lookup.class, Class.class, MethodHandles.Lookup.class)); |
||||
} catch (Exception e) { |
||||
throw new ObjenesisException(e); |
||||
} |
||||
} |
||||
|
||||
private MethodHandle defineClass() { |
||||
try { |
||||
return lookup.findVirtual(MethodHandles.Lookup.class, "defineClass", MethodType.methodType(Class.class, byte[].class)); |
||||
} catch (Exception e) { |
||||
throw new ObjenesisException(e); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
Class<?> defineClass(String className, byte[] b, int off, int len, Class<?> neighbor, ClassLoader loader, ProtectionDomain protectionDomain) { |
||||
try { |
||||
Object module = getModule.invokeWithArguments(DefineClassHelper.class); |
||||
Object neighborModule = getModule.invokeWithArguments(neighbor); |
||||
addReads.invokeWithArguments(module, neighborModule); |
||||
MethodHandles.Lookup prvlookup = (MethodHandles.Lookup) privateLookupIn.invokeExact(neighbor, lookup); |
||||
return (Class<?>) defineClass.invokeExact(prvlookup, b); |
||||
} catch (Throwable e) { |
||||
throw new ObjenesisException(neighbor.getName() + " has no permission to define the class", e); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Java 11+ removed sun.misc.Unsafe.defineClass, so we fallback to invoking defineClass on
|
||||
// ClassLoader until we have an implementation that uses MethodHandles.Lookup.defineClass
|
||||
private static final Helper privileged = PlatformDescription.isAfterJava11() ? |
||||
new Java11() : new Java8(); |
||||
|
||||
public static Class<?> defineClass(String name, byte[] b, int off, int len, Class<?> neighbor, |
||||
ClassLoader loader, ProtectionDomain protectionDomain) { |
||||
return privileged.defineClass(name, b, off, len, neighbor, loader, protectionDomain); |
||||
} |
||||
|
||||
private DefineClassHelper() {} |
||||
} |
@ -1,5 +1,5 @@
|
||||
/* |
||||
* Copyright 2006-2018 the original author or authors. |
||||
/** |
||||
* Copyright 2006-2017 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
@ -0,0 +1,102 @@
|
||||
/** |
||||
* Copyright 2006-2017 the original author or authors. |
||||
* |
||||
* 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 com.fr.third.org.objenesis; |
||||
|
||||
import com.fr.third.org.objenesis.instantiator.ObjectInstantiator; |
||||
import com.fr.third.org.objenesis.strategy.InstantiatorStrategy; |
||||
|
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
|
||||
/** |
||||
* Base class to extend if you want to have a class providing your own default strategy. Can also be |
||||
* instantiated directly. |
||||
* |
||||
* @author Henri Tremblay |
||||
*/ |
||||
public class ObjenesisBase implements Objenesis { |
||||
|
||||
/** Strategy used by this Objenesi implementation to create classes */ |
||||
protected final InstantiatorStrategy strategy; |
||||
|
||||
/** Strategy cache. Key = Class, Value = InstantiatorStrategy */ |
||||
protected ConcurrentHashMap<String, ObjectInstantiator<?>> cache; |
||||
|
||||
/** |
||||
* Constructor allowing to pick a strategy and using cache |
||||
* |
||||
* @param strategy Strategy to use |
||||
*/ |
||||
public ObjenesisBase(InstantiatorStrategy strategy) { |
||||
this(strategy, true); |
||||
} |
||||
|
||||
/** |
||||
* Flexible constructor allowing to pick the strategy and if caching should be used |
||||
* |
||||
* @param strategy Strategy to use |
||||
* @param useCache If {@link ObjectInstantiator}s should be cached |
||||
*/ |
||||
public ObjenesisBase(InstantiatorStrategy strategy, boolean useCache) { |
||||
if(strategy == null) { |
||||
throw new IllegalArgumentException("A strategy can't be null"); |
||||
} |
||||
this.strategy = strategy; |
||||
this.cache = useCache ? new ConcurrentHashMap<String, ObjectInstantiator<?>>() : null; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return getClass().getName() + " using " + strategy.getClass().getName() |
||||
+ (cache == null ? " without" : " with") + " caching"; |
||||
} |
||||
|
||||
/** |
||||
* Will create a new object without any constructor being called |
||||
* |
||||
* @param clazz Class to instantiate |
||||
* @return New instance of clazz |
||||
*/ |
||||
public <T> T newInstance(Class<T> clazz) { |
||||
return getInstantiatorOf(clazz).newInstance(); |
||||
} |
||||
|
||||
/** |
||||
* Will pick the best instantiator for the provided class. If you need to create a lot of |
||||
* instances from the same class, it is way more efficient to create them from the same |
||||
* ObjectInstantiator than calling {@link #newInstance(Class)}. |
||||
* |
||||
* @param clazz Class to instantiate |
||||
* @return Instantiator dedicated to the class
|
||||
*/ |
||||
@SuppressWarnings("unchecked") |
||||
public <T> ObjectInstantiator<T> getInstantiatorOf(Class<T> clazz) { |
||||
if(clazz.isPrimitive()) { |
||||
throw new IllegalArgumentException("Primitive types can't be instantiated in Java"); |
||||
} |
||||
if(cache == null) { |
||||
return strategy.newInstantiatorOf(clazz); |
||||
} |
||||
ObjectInstantiator<?> instantiator = cache.get(clazz.getName()); |
||||
if(instantiator == null) { |
||||
ObjectInstantiator<?> newInstantiator = strategy.newInstantiatorOf(clazz); |
||||
instantiator = cache.putIfAbsent(clazz.getName(), newInstantiator); |
||||
if(instantiator == null) { |
||||
instantiator = newInstantiator; |
||||
} |
||||
} |
||||
return (ObjectInstantiator<T>) instantiator; |
||||
} |
||||
} |
@ -1,5 +1,5 @@
|
||||
/* |
||||
* Copyright 2006-2018 the original author or authors. |
||||
/** |
||||
* Copyright 2006-2017 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
@ -1,5 +1,5 @@
|
||||
/* |
||||
* Copyright 2006-2018 the original author or authors. |
||||
/** |
||||
* Copyright 2006-2017 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
@ -1,5 +1,5 @@
|
||||
/* |
||||
* Copyright 2006-2018 the original author or authors. |
||||
/** |
||||
* Copyright 2006-2017 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
@ -1,5 +1,5 @@
|
||||
/* |
||||
* Copyright 2006-2018 the original author or authors. |
||||
/** |
||||
* Copyright 2006-2017 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
@ -1,5 +1,5 @@
|
||||
/* |
||||
* Copyright 2006-2018 the original author or authors. |
||||
/** |
||||
* Copyright 2006-2017 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
@ -1,5 +1,5 @@
|
||||
/* |
||||
* Copyright 2006-2018 the original author or authors. |
||||
/** |
||||
* Copyright 2006-2017 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
@ -0,0 +1,149 @@
|
||||
/* |
||||
* Copyright 2006-2019 the original author or authors. |
||||
* |
||||
* 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 com.fr.third.org.objenesis.instantiator.util; |
||||
|
||||
import com.fr.third.org.objenesis.ObjenesisException; |
||||
import com.fr.third.org.objenesis.strategy.PlatformDescription; |
||||
import sun.misc.Unsafe; |
||||
|
||||
|
||||
|
||||
import java.lang.invoke.MethodHandle; |
||||
import java.lang.invoke.MethodHandles; |
||||
import java.lang.invoke.MethodType; |
||||
import java.security.ProtectionDomain; |
||||
|
||||
/** |
||||
* Java 11+ removed sun.misc.Unsafe.defineClass. This class bridges the gap to work from Java 1.8 up to 11. |
||||
* <p> |
||||
* It was inspired from <a href="https://github.com/jboss-javassist/javassist/blob/master/src/main/javassist/util/proxy/DefineClassHelper.java">javassist</a>. |
||||
* |
||||
* @author Henri Tremblay |
||||
*/ |
||||
public final class DefineClassHelper { |
||||
|
||||
private static abstract class Helper { |
||||
abstract Class<?> defineClass(String name, byte[] b, int off, int len, Class<?> neighbor, |
||||
ClassLoader loader, ProtectionDomain protectionDomain); |
||||
} |
||||
|
||||
private static class Java8 extends Helper { |
||||
|
||||
private final MethodHandle defineClass = defineClass(); |
||||
|
||||
private MethodHandle defineClass() { |
||||
MethodType mt = MethodType.methodType(Class.class, String.class, byte[].class, int.class, int.class, ClassLoader.class, ProtectionDomain.class); |
||||
MethodHandle m; |
||||
try { |
||||
m = MethodHandles.publicLookup().findVirtual(Unsafe.class, "defineClass", mt); |
||||
} catch(NoSuchMethodException | IllegalAccessException e) { |
||||
throw new ObjenesisException(e); |
||||
} |
||||
Unsafe unsafe = UnsafeUtils.getUnsafe(); |
||||
return m.bindTo(unsafe); |
||||
} |
||||
|
||||
@Override |
||||
Class<?> defineClass(String className, byte[] b, int off, int len, Class<?> neighbor, ClassLoader loader, ProtectionDomain protectionDomain) { |
||||
try { |
||||
return (Class<?>) defineClass.invokeExact(className, b, off, len, loader, protectionDomain); |
||||
} catch (Throwable e) { |
||||
if(e instanceof Error) { |
||||
throw (Error) e; |
||||
} |
||||
if(e instanceof RuntimeException) { |
||||
throw (RuntimeException) e; |
||||
} |
||||
throw new ObjenesisException(e); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private static class Java11 extends Helper { |
||||
|
||||
private final Class<?> module = module(); |
||||
private final MethodHandles.Lookup lookup = MethodHandles.lookup(); |
||||
private final MethodHandle getModule = getModule(); |
||||
private final MethodHandle addReads = addReads(); |
||||
private final MethodHandle privateLookupIn = privateLookupIn(); |
||||
private final MethodHandle defineClass = defineClass(); |
||||
|
||||
private Class<?> module() { |
||||
try { |
||||
return Class.forName("java.lang.Module"); |
||||
} catch (ClassNotFoundException e) { |
||||
throw new ObjenesisException(e); |
||||
} |
||||
} |
||||
|
||||
private MethodHandle getModule() { |
||||
try { |
||||
return lookup.findVirtual(Class.class, "getModule", MethodType.methodType(module)); |
||||
} catch (NoSuchMethodException | IllegalAccessException e) { |
||||
throw new ObjenesisException(e); |
||||
} |
||||
} |
||||
|
||||
private MethodHandle addReads() { |
||||
try { |
||||
return lookup.findVirtual(module, "addReads", MethodType.methodType(module, module)); |
||||
} catch (NoSuchMethodException | IllegalAccessException e) { |
||||
throw new ObjenesisException(e); |
||||
} |
||||
} |
||||
|
||||
private MethodHandle privateLookupIn() { |
||||
try { |
||||
return lookup.findStatic(MethodHandles.class, "privateLookupIn", MethodType.methodType(MethodHandles.Lookup.class, Class.class, MethodHandles.Lookup.class)); |
||||
} catch (NoSuchMethodException | IllegalAccessException e) { |
||||
throw new ObjenesisException(e); |
||||
} |
||||
} |
||||
|
||||
private MethodHandle defineClass() { |
||||
try { |
||||
return lookup.findVirtual(MethodHandles.Lookup.class, "defineClass", MethodType.methodType(Class.class, byte[].class)); |
||||
} catch (NoSuchMethodException | IllegalAccessException e) { |
||||
throw new ObjenesisException(e); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
Class<?> defineClass(String className, byte[] b, int off, int len, Class<?> neighbor, ClassLoader loader, ProtectionDomain protectionDomain) { |
||||
try { |
||||
Object module = getModule.invokeWithArguments(DefineClassHelper.class); |
||||
Object neighborModule = getModule.invokeWithArguments(neighbor); |
||||
addReads.invokeWithArguments(module, neighborModule); |
||||
MethodHandles.Lookup prvlookup = (MethodHandles.Lookup) privateLookupIn.invokeExact(neighbor, lookup); |
||||
return (Class<?>) defineClass.invokeExact(prvlookup, b); |
||||
} catch (Throwable e) { |
||||
throw new ObjenesisException(neighbor.getName() + " has no permission to define the class", e); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Java 11+ removed sun.misc.Unsafe.defineClass, so we fallback to invoking defineClass on
|
||||
// ClassLoader until we have an implementation that uses MethodHandles.Lookup.defineClass
|
||||
private static final Helper privileged = PlatformDescription.isAfterJava11() ? |
||||
new Java11() : new Java8(); |
||||
|
||||
public static Class<?> defineClass(String name, byte[] b, int off, int len, Class<?> neighbor, |
||||
ClassLoader loader, ProtectionDomain protectionDomain) { |
||||
return privileged.defineClass(name, b, off, len, neighbor, loader, protectionDomain); |
||||
} |
||||
|
||||
private DefineClassHelper() {} |
||||
} |
@ -1,5 +1,5 @@
|
||||
/* |
||||
* Copyright 2006-2018 the original author or authors. |
||||
/** |
||||
* Copyright 2006-2017 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
@ -1,5 +1,5 @@
|
||||
/* |
||||
* Copyright 2006-2018 the original author or authors. |
||||
/** |
||||
* Copyright 2006-2017 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
@ -1,5 +1,5 @@
|
||||
/* |
||||
* Copyright 2006-2018 the original author or authors. |
||||
/** |
||||
* Copyright 2006-2017 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
@ -0,0 +1,96 @@
|
||||
package com.fr.third.sun.misc; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.OutputStream; |
||||
import java.io.PushbackInputStream; |
||||
|
||||
/** |
||||
* @author zhouping |
||||
* @version 10.0 |
||||
* Created by zhouping on 2019/10/28 |
||||
*/ |
||||
public class BASE64Decoder extends CharacterDecoder { |
||||
private static final char[] pem_array = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'}; |
||||
private static final byte[] pem_convert_array = new byte[256]; |
||||
byte[] decode_buffer = new byte[4]; |
||||
|
||||
public BASE64Decoder() { |
||||
} |
||||
|
||||
protected int bytesPerAtom() { |
||||
return 4; |
||||
} |
||||
|
||||
protected int bytesPerLine() { |
||||
return 72; |
||||
} |
||||
|
||||
protected void decodeAtom(PushbackInputStream var1, OutputStream var2, int var3) throws IOException { |
||||
byte var5 = -1; |
||||
byte var6 = -1; |
||||
byte var7 = -1; |
||||
byte var8 = -1; |
||||
if (var3 < 2) { |
||||
throw new CEFormatException("BASE64Decoder: Not enough bytes for an atom."); |
||||
} else { |
||||
int var4; |
||||
do { |
||||
var4 = var1.read(); |
||||
if (var4 == -1) { |
||||
throw new CEStreamExhausted(); |
||||
} |
||||
} while(var4 == 10 || var4 == 13); |
||||
|
||||
this.decode_buffer[0] = (byte)var4; |
||||
var4 = this.readFully(var1, this.decode_buffer, 1, var3 - 1); |
||||
if (var4 == -1) { |
||||
throw new CEStreamExhausted(); |
||||
} else { |
||||
if (var3 > 3 && this.decode_buffer[3] == 61) { |
||||
var3 = 3; |
||||
} |
||||
|
||||
if (var3 > 2 && this.decode_buffer[2] == 61) { |
||||
var3 = 2; |
||||
} |
||||
|
||||
switch(var3) { |
||||
case 4: |
||||
var8 = pem_convert_array[this.decode_buffer[3] & 255]; |
||||
case 3: |
||||
var7 = pem_convert_array[this.decode_buffer[2] & 255]; |
||||
case 2: |
||||
var6 = pem_convert_array[this.decode_buffer[1] & 255]; |
||||
var5 = pem_convert_array[this.decode_buffer[0] & 255]; |
||||
default: |
||||
switch(var3) { |
||||
case 2: |
||||
var2.write((byte)(var5 << 2 & 252 | var6 >>> 4 & 3)); |
||||
break; |
||||
case 3: |
||||
var2.write((byte)(var5 << 2 & 252 | var6 >>> 4 & 3)); |
||||
var2.write((byte)(var6 << 4 & 240 | var7 >>> 2 & 15)); |
||||
break; |
||||
case 4: |
||||
var2.write((byte)(var5 << 2 & 252 | var6 >>> 4 & 3)); |
||||
var2.write((byte)(var6 << 4 & 240 | var7 >>> 2 & 15)); |
||||
var2.write((byte)(var7 << 6 & 192 | var8 & 63)); |
||||
} |
||||
|
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
static { |
||||
int var0; |
||||
for(var0 = 0; var0 < 255; ++var0) { |
||||
pem_convert_array[var0] = -1; |
||||
} |
||||
|
||||
for(var0 = 0; var0 < pem_array.length; ++var0) { |
||||
pem_convert_array[pem_array[var0]] = (byte)var0; |
||||
} |
||||
|
||||
} |
||||
} |
@ -0,0 +1,62 @@
|
||||
package com.fr.third.sun.misc; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.OutputStream; |
||||
|
||||
/** |
||||
* @author zhouping |
||||
* @version 10.0 |
||||
* Created by zhouping on 2019/10/28 |
||||
*/ |
||||
public class BASE64Encoder extends CharacterEncoder { |
||||
|
||||
private static final char[] pem_array = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'}; |
||||
|
||||
public BASE64Encoder() { |
||||
|
||||
} |
||||
|
||||
protected int bytesPerAtom() { |
||||
|
||||
return 3; |
||||
} |
||||
|
||||
protected int bytesPerLine() { |
||||
|
||||
return 57; |
||||
} |
||||
|
||||
protected void encodeAtom(OutputStream var1, byte[] var2, int var3, int var4) throws IOException { |
||||
|
||||
byte var5; |
||||
if (var4 == 1) { |
||||
var5 = var2[var3]; |
||||
byte var6 = 0; |
||||
boolean var7 = false; |
||||
var1.write(pem_array[var5 >>> 2 & 63]); |
||||
var1.write(pem_array[(var5 << 4 & 48) + (var6 >>> 4 & 15)]); |
||||
var1.write(61); |
||||
var1.write(61); |
||||
} else { |
||||
byte var8; |
||||
if (var4 == 2) { |
||||
var5 = var2[var3]; |
||||
var8 = var2[var3 + 1]; |
||||
byte var9 = 0; |
||||
var1.write(pem_array[var5 >>> 2 & 63]); |
||||
var1.write(pem_array[(var5 << 4 & 48) + (var8 >>> 4 & 15)]); |
||||
var1.write(pem_array[(var8 << 2 & 60) + (var9 >>> 6 & 3)]); |
||||
var1.write(61); |
||||
} else { |
||||
var5 = var2[var3]; |
||||
var8 = var2[var3 + 1]; |
||||
byte var10 = var2[var3 + 2]; |
||||
var1.write(pem_array[var5 >>> 2 & 63]); |
||||
var1.write(pem_array[(var5 << 4 & 48) + (var8 >>> 4 & 15)]); |
||||
var1.write(pem_array[(var8 << 2 & 60) + (var10 >>> 6 & 3)]); |
||||
var1.write(pem_array[var10 & 63]); |
||||
} |
||||
} |
||||
|
||||
} |
||||
} |
@ -0,0 +1,16 @@
|
||||
package com.fr.third.sun.misc; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* @author zhouping |
||||
* @version 10.0 |
||||
* Created by zhouping on 2019/10/28 |
||||
*/ |
||||
public class CEFormatException extends IOException { |
||||
|
||||
public CEFormatException(String var1) { |
||||
|
||||
super(var1); |
||||
} |
||||
} |
@ -0,0 +1,15 @@
|
||||
package com.fr.third.sun.misc; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* @author zhouping |
||||
* @version 10.0 |
||||
* Created by zhouping on 2019/10/28 |
||||
*/ |
||||
public class CEStreamExhausted extends IOException { |
||||
|
||||
public CEStreamExhausted() { |
||||
|
||||
} |
||||
} |
@ -0,0 +1,107 @@
|
||||
package com.fr.third.sun.misc; |
||||
|
||||
import java.io.ByteArrayInputStream; |
||||
import java.io.ByteArrayOutputStream; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.OutputStream; |
||||
import java.io.PushbackInputStream; |
||||
import java.nio.ByteBuffer; |
||||
|
||||
/** |
||||
* @author zhouping |
||||
* @version 10.0 |
||||
* Created by zhouping on 2019/10/28 |
||||
*/ |
||||
public abstract class CharacterDecoder { |
||||
public CharacterDecoder() { |
||||
} |
||||
|
||||
protected abstract int bytesPerAtom(); |
||||
|
||||
protected abstract int bytesPerLine(); |
||||
|
||||
protected void decodeBufferPrefix(PushbackInputStream var1, OutputStream var2) throws IOException { |
||||
} |
||||
|
||||
protected void decodeBufferSuffix(PushbackInputStream var1, OutputStream var2) throws IOException { |
||||
} |
||||
|
||||
protected int decodeLinePrefix(PushbackInputStream var1, OutputStream var2) throws IOException { |
||||
return this.bytesPerLine(); |
||||
} |
||||
|
||||
protected void decodeLineSuffix(PushbackInputStream var1, OutputStream var2) throws IOException { |
||||
} |
||||
|
||||
protected void decodeAtom(PushbackInputStream var1, OutputStream var2, int var3) throws IOException { |
||||
throw new CEStreamExhausted(); |
||||
} |
||||
|
||||
protected int readFully(InputStream var1, byte[] var2, int var3, int var4) throws IOException { |
||||
for(int var5 = 0; var5 < var4; ++var5) { |
||||
int var6 = var1.read(); |
||||
if (var6 == -1) { |
||||
return var5 == 0 ? -1 : var5; |
||||
} |
||||
|
||||
var2[var5 + var3] = (byte)var6; |
||||
} |
||||
|
||||
return var4; |
||||
} |
||||
|
||||
public void decodeBuffer(InputStream var1, OutputStream var2) throws IOException { |
||||
int var4 = 0; |
||||
PushbackInputStream var5 = new PushbackInputStream(var1); |
||||
this.decodeBufferPrefix(var5, var2); |
||||
|
||||
while(true) { |
||||
try { |
||||
int var6 = this.decodeLinePrefix(var5, var2); |
||||
|
||||
int var3; |
||||
for(var3 = 0; var3 + this.bytesPerAtom() < var6; var3 += this.bytesPerAtom()) { |
||||
this.decodeAtom(var5, var2, this.bytesPerAtom()); |
||||
var4 += this.bytesPerAtom(); |
||||
} |
||||
|
||||
if (var3 + this.bytesPerAtom() == var6) { |
||||
this.decodeAtom(var5, var2, this.bytesPerAtom()); |
||||
var4 += this.bytesPerAtom(); |
||||
} else { |
||||
this.decodeAtom(var5, var2, var6 - var3); |
||||
var4 += var6 - var3; |
||||
} |
||||
|
||||
this.decodeLineSuffix(var5, var2); |
||||
} catch (CEStreamExhausted var8) { |
||||
this.decodeBufferSuffix(var5, var2); |
||||
return; |
||||
} |
||||
} |
||||
} |
||||
|
||||
public byte[] decodeBuffer(String var1) throws IOException { |
||||
byte[] var2 = new byte[var1.length()]; |
||||
var1.getBytes(0, var1.length(), var2, 0); |
||||
ByteArrayInputStream var3 = new ByteArrayInputStream(var2); |
||||
ByteArrayOutputStream var4 = new ByteArrayOutputStream(); |
||||
this.decodeBuffer(var3, var4); |
||||
return var4.toByteArray(); |
||||
} |
||||
|
||||
public byte[] decodeBuffer(InputStream var1) throws IOException { |
||||
ByteArrayOutputStream var2 = new ByteArrayOutputStream(); |
||||
this.decodeBuffer(var1, var2); |
||||
return var2.toByteArray(); |
||||
} |
||||
|
||||
public ByteBuffer decodeBufferToByteBuffer(String var1) throws IOException { |
||||
return ByteBuffer.wrap(this.decodeBuffer(var1)); |
||||
} |
||||
|
||||
public ByteBuffer decodeBufferToByteBuffer(InputStream var1) throws IOException { |
||||
return ByteBuffer.wrap(this.decodeBuffer(var1)); |
||||
} |
||||
} |
@ -0,0 +1,186 @@
|
||||
package com.fr.third.sun.misc; |
||||
|
||||
import java.io.ByteArrayInputStream; |
||||
import java.io.ByteArrayOutputStream; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.OutputStream; |
||||
import java.io.PrintStream; |
||||
import java.nio.ByteBuffer; |
||||
|
||||
/** |
||||
* @author zhouping |
||||
* @version 10.0 |
||||
* Created by zhouping on 2019/10/28 |
||||
*/ |
||||
public abstract class CharacterEncoder { |
||||
protected PrintStream pStream; |
||||
|
||||
public CharacterEncoder() { |
||||
} |
||||
|
||||
protected abstract int bytesPerAtom(); |
||||
|
||||
protected abstract int bytesPerLine(); |
||||
|
||||
protected void encodeBufferPrefix(OutputStream var1) throws IOException { |
||||
this.pStream = new PrintStream(var1); |
||||
} |
||||
|
||||
protected void encodeBufferSuffix(OutputStream var1) throws IOException { |
||||
} |
||||
|
||||
protected void encodeLinePrefix(OutputStream var1, int var2) throws IOException { |
||||
} |
||||
|
||||
protected void encodeLineSuffix(OutputStream var1) throws IOException { |
||||
this.pStream.println(); |
||||
} |
||||
|
||||
protected abstract void encodeAtom(OutputStream var1, byte[] var2, int var3, int var4) throws IOException; |
||||
|
||||
protected int readFully(InputStream var1, byte[] var2) throws IOException { |
||||
for (int var3 = 0; var3 < var2.length; ++var3) { |
||||
int var4 = var1.read(); |
||||
if (var4 == -1) { |
||||
return var3; |
||||
} |
||||
|
||||
var2[var3] = (byte) var4; |
||||
} |
||||
|
||||
return var2.length; |
||||
} |
||||
|
||||
public void encode(InputStream var1, OutputStream var2) throws IOException { |
||||
byte[] var5 = new byte[this.bytesPerLine()]; |
||||
this.encodeBufferPrefix(var2); |
||||
|
||||
while (true) { |
||||
int var4 = this.readFully(var1, var5); |
||||
if (var4 == 0) { |
||||
break; |
||||
} |
||||
|
||||
this.encodeLinePrefix(var2, var4); |
||||
|
||||
for (int var3 = 0; var3 < var4; var3 += this.bytesPerAtom()) { |
||||
if (var3 + this.bytesPerAtom() <= var4) { |
||||
this.encodeAtom(var2, var5, var3, this.bytesPerAtom()); |
||||
} else { |
||||
this.encodeAtom(var2, var5, var3, var4 - var3); |
||||
} |
||||
} |
||||
|
||||
if (var4 < this.bytesPerLine()) { |
||||
break; |
||||
} |
||||
|
||||
this.encodeLineSuffix(var2); |
||||
} |
||||
|
||||
this.encodeBufferSuffix(var2); |
||||
} |
||||
|
||||
public void encode(byte[] var1, OutputStream var2) throws IOException { |
||||
ByteArrayInputStream var3 = new ByteArrayInputStream(var1); |
||||
this.encode((InputStream) var3, var2); |
||||
} |
||||
|
||||
public String encode(byte[] var1) { |
||||
ByteArrayOutputStream var2 = new ByteArrayOutputStream(); |
||||
ByteArrayInputStream var3 = new ByteArrayInputStream(var1); |
||||
String var4 = null; |
||||
|
||||
try { |
||||
this.encode((InputStream) var3, var2); |
||||
var4 = var2.toString("8859_1"); |
||||
return var4; |
||||
} catch (Exception var6) { |
||||
throw new Error("CharacterEncoder.encode internal error"); |
||||
} |
||||
} |
||||
|
||||
private byte[] getBytes(ByteBuffer var1) { |
||||
byte[] var2 = null; |
||||
if (var1.hasArray()) { |
||||
byte[] var3 = var1.array(); |
||||
if (var3.length == var1.capacity() && var3.length == var1.remaining()) { |
||||
var2 = var3; |
||||
var1.position(var1.limit()); |
||||
} |
||||
} |
||||
|
||||
if (var2 == null) { |
||||
var2 = new byte[var1.remaining()]; |
||||
var1.get(var2); |
||||
} |
||||
|
||||
return var2; |
||||
} |
||||
|
||||
public void encode(ByteBuffer var1, OutputStream var2) throws IOException { |
||||
byte[] var3 = this.getBytes(var1); |
||||
this.encode(var3, var2); |
||||
} |
||||
|
||||
public String encode(ByteBuffer var1) { |
||||
byte[] var2 = this.getBytes(var1); |
||||
return this.encode(var2); |
||||
} |
||||
|
||||
public void encodeBuffer(InputStream var1, OutputStream var2) throws IOException { |
||||
byte[] var5 = new byte[this.bytesPerLine()]; |
||||
this.encodeBufferPrefix(var2); |
||||
|
||||
int var4; |
||||
do { |
||||
var4 = this.readFully(var1, var5); |
||||
if (var4 == 0) { |
||||
break; |
||||
} |
||||
|
||||
this.encodeLinePrefix(var2, var4); |
||||
|
||||
for (int var3 = 0; var3 < var4; var3 += this.bytesPerAtom()) { |
||||
if (var3 + this.bytesPerAtom() <= var4) { |
||||
this.encodeAtom(var2, var5, var3, this.bytesPerAtom()); |
||||
} else { |
||||
this.encodeAtom(var2, var5, var3, var4 - var3); |
||||
} |
||||
} |
||||
|
||||
this.encodeLineSuffix(var2); |
||||
} while (var4 >= this.bytesPerLine()); |
||||
|
||||
this.encodeBufferSuffix(var2); |
||||
} |
||||
|
||||
public void encodeBuffer(byte[] var1, OutputStream var2) throws IOException { |
||||
ByteArrayInputStream var3 = new ByteArrayInputStream(var1); |
||||
this.encodeBuffer((InputStream) var3, var2); |
||||
} |
||||
|
||||
public String encodeBuffer(byte[] var1) { |
||||
ByteArrayOutputStream var2 = new ByteArrayOutputStream(); |
||||
ByteArrayInputStream var3 = new ByteArrayInputStream(var1); |
||||
|
||||
try { |
||||
this.encodeBuffer((InputStream) var3, var2); |
||||
} catch (Exception var5) { |
||||
throw new Error("CharacterEncoder.encodeBuffer internal error"); |
||||
} |
||||
|
||||
return var2.toString(); |
||||
} |
||||
|
||||
public void encodeBuffer(ByteBuffer var1, OutputStream var2) throws IOException { |
||||
byte[] var3 = this.getBytes(var1); |
||||
this.encodeBuffer(var3, var2); |
||||
} |
||||
|
||||
public String encodeBuffer(ByteBuffer var1) { |
||||
byte[] var2 = this.getBytes(var1); |
||||
return this.encodeBuffer(var2); |
||||
} |
||||
} |
@ -0,0 +1,84 @@
|
||||
package com.fr.third.sun.misc; |
||||
|
||||
import java.lang.ref.PhantomReference; |
||||
import java.lang.ref.ReferenceQueue; |
||||
import java.security.AccessController; |
||||
import java.security.PrivilegedAction; |
||||
|
||||
/** |
||||
* @author zhouping |
||||
* @version 10.0 |
||||
* Created by zhouping on 2019/10/29 |
||||
*/ |
||||
public class Cleaner extends PhantomReference<Object> { |
||||
private static final ReferenceQueue<Object> dummyQueue = new ReferenceQueue(); |
||||
private static Cleaner first = null; |
||||
private Cleaner next = null; |
||||
private Cleaner prev = null; |
||||
private final Runnable thunk; |
||||
|
||||
private static synchronized Cleaner add(Cleaner var0) { |
||||
if (first != null) { |
||||
var0.next = first; |
||||
first.prev = var0; |
||||
} |
||||
|
||||
first = var0; |
||||
return var0; |
||||
} |
||||
|
||||
private static synchronized boolean remove(Cleaner var0) { |
||||
if (var0.next == var0) { |
||||
return false; |
||||
} else { |
||||
if (first == var0) { |
||||
if (var0.next != null) { |
||||
first = var0.next; |
||||
} else { |
||||
first = var0.prev; |
||||
} |
||||
} |
||||
|
||||
if (var0.next != null) { |
||||
var0.next.prev = var0.prev; |
||||
} |
||||
|
||||
if (var0.prev != null) { |
||||
var0.prev.next = var0.next; |
||||
} |
||||
|
||||
var0.next = var0; |
||||
var0.prev = var0; |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
private Cleaner(Object var1, Runnable var2) { |
||||
super(var1, dummyQueue); |
||||
this.thunk = var2; |
||||
} |
||||
|
||||
public static Cleaner create(Object var0, Runnable var1) { |
||||
return var1 == null ? null : add(new Cleaner(var0, var1)); |
||||
} |
||||
|
||||
public void clean() { |
||||
if (remove(this)) { |
||||
try { |
||||
this.thunk.run(); |
||||
} catch (final Throwable var2) { |
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() { |
||||
public Void run() { |
||||
if (System.err != null) { |
||||
(new Error("Cleaner terminated abnormally", var2)).printStackTrace(); |
||||
} |
||||
|
||||
System.exit(1); |
||||
return null; |
||||
} |
||||
}); |
||||
} |
||||
|
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue