Skip to main content

101 posts tagged with "java"

View All Tags

· 2 min read

背景

java 的基础内容

内容备注
java aqsaqs 主要包括state以及 阻塞queue

aqs

  • state: volatileint变量
  • block(park/unpark) : 使用了linux的pthread_cond_wait , 也就是使用了条件变量
  • queue: 为什么需要queue , 因为条件变量唤醒queue中内容,queue一般放的是被阻塞的线程

可重入性

这里的可重入性指的是同一个线程可以多次对 Reentrantlock多次上锁

那么这个实现是怎么实现的呢?

其实就是state=0的时候,将当前线程Thread通过setExclusiveOwnerThread塞入Reentrantlock对应的同步器Sync

    abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;

/**
* Performs non-fair tryLock. tryAcquire is implemented in
* subclasses, but both need nonfair try for trylock method.
*/
@ReservedStackAccess
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current); // 核心步骤 ,将自己塞入锁对应的同步器中
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}

· 7 min read

背景

了解spring-boot 启动流程

流程分析

核心流程是调用refresh方法

// org\springframework\spring-context\5.2.15.RELEASE\spring-context-5.2.15.RELEASE-sources.jar!\org\springframework\context\support\AbstractApplicationContext.java
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();

// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);

try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);

// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);

// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);

// Initialize message source for this context.
initMessageSource();

// Initialize event multicaster for this context.
initApplicationEventMulticaster();

// Initialize other special beans in specific context subclasses.
onRefresh();

// Check for listener beans and register them.
registerListeners();

// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

// Last step: publish corresponding event.
finishRefresh();
}

catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}

// Destroy already created singletons to avoid dangling resources.
destroyBeans();

// Reset 'active' flag.
cancelRefresh(ex);

// Propagate exception to caller.
throw ex;
}

finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}

bean factory 继承关系

AbstractBeanFactory  ---> implement  ConfigurableBeanFactory ---> extends HierarchicalBeanFactory -->  extends BeanFactory

BeanFactory核心接口

public interface BeanFactory {

Object getBean(String name) throws BeansException;


<T> T getBean(String name, Class<T> requiredType) throws BeansException;

Object getBean(String name, Object... args) throws BeansException;

<T> T getBean(Class<T> requiredType) throws BeansException;

<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;


}

	/**
* Return an instance, which may be shared or independent, of the specified bean.
* @param name the name of the bean to retrieve
* @param requiredType the required type of the bean to retrieve
* @param args arguments to use when creating a bean instance using explicit arguments
* (only applied when creating a new instance as opposed to retrieving an existing one)
* @param typeCheckOnly whether the instance is obtained for a type check,
* not for actual use
* @return an instance of the bean
* @throws BeansException if the bean could not be created
*/
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {

String beanName = transformedBeanName(name);
Object bean;

// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

else {
...

if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}

try {
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);

// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}

// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

else {
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
}
Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}

// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}

回调

	@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {

if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;

// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}

// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}

try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}

try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}

bean 相关内容

  • BeanDefinitionRegistry

BeanDefinitionRegistry 持有BeanDefinition

Interface for registries that hold bean definitions, for example RootBeanDefinition and ChildBeanDefinition instances. 相关核心接口 BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

  • BeanDefinition

    A BeanDefinition describes a bean instance, which has property values, constructor argument values, and further information supplied by concrete implementations. beandefition 描述的bean的数组和构造器 ,和Classs 类差不多

最后使用的堆栈

instantiateClass:204, BeanUtils (org.springframework.beans)
instantiate:87, SimpleInstantiationStrategy (org.springframework.beans.factory.support)
instantiateBean:1315, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBeanInstance:1218, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:556, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:516, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
lambda$doGetBean$0:324, AbstractBeanFactory (org.springframework.beans.factory.support)
getObject:-1, 1771040410 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$324)
getSingleton:234, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:322, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:207, AbstractBeanFactory (org.springframework.beans.factory.support)
invokeBeanFactoryPostProcessors:90, PostProcessorRegistrationDelegate (org.springframework.context.support)
invokeBeanFactoryPostProcessors:707, AbstractApplicationContext (org.springframework.context.support)
refresh:533, AbstractApplicationContext (org.springframework.context.support)
refresh:755, SpringApplication (org.springframework.boot)
refresh:747, SpringApplication (org.springframework.boot)
refreshContext:402, SpringApplication (org.springframework.boot)
run:312, SpringApplication (org.springframework.boot)
run:140, SpringApplicationBuilder (org.springframework.boot.builder)
bootstrapServiceContext:212, BootstrapApplicationListener (org.springframework.cloud.bootstrap)
onApplicationEvent:117, BootstrapApplicationListener (org.springframework.cloud.bootstrap)
onApplicationEvent:74, BootstrapApplicationListener (org.springframework.cloud.bootstrap)
doInvokeListener:172, SimpleApplicationEventMulticaster (org.springframework.context.event)
invokeListener:165, SimpleApplicationEventMulticaster (org.springframework.context.event)
multicastEvent:139, SimpleApplicationEventMulticaster (org.springframework.context.event)
multicastEvent:127, SimpleApplicationEventMulticaster (org.springframework.context.event)
environmentPrepared:80, EventPublishingRunListener (org.springframework.boot.context.event)
environmentPrepared:53, SpringApplicationRunListeners (org.springframework.boot)
prepareEnvironment:342, SpringApplication (org.springframework.boot)
run:307, SpringApplication (org.springframework.boot)
main:40, DatacenterApplication (com.patpat.datacenter)
	public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
Assert.notNull(ctor, "Constructor must not be null");
try {
...
return ctor.newInstance(argsWithDefaultValues);
}
}
...
}

· 2 min read

背景

了解java的class格式java file format

介绍

大部分的类的加载都会依赖defineClass(byte[] b, int off, int len)

顺序就算b =你的class文件的字节流 , 然后这个函数会读字节流,加载,然后塞进matespace

本篇内容

为什么我需要这篇文章:

  • 我看java的动态代理的时候,发现原来其实动态代理和静态编译原来只是接口不一样,实际上大家都是调用这个defineClass(byte[] b, int off, int len) 方法的

我想写一个Proxygenerate的demo , 他就是为了生成class 字节流

开始

我们看看编译好的是什么样子的:

//   touch A.java
public class A{
}

然后编译:

javac A.java
hexdump A.class
0000000 feca beba 0000 4100 0d00 000a 0002 0703
0000010 0400 000c 0005 0106 1000 616a 6176 6c2f
0000020 6e61 2f67 624f 656a 7463 0001 3c06 6e69
0000030 7469 013e 0300 2928 0756 0800 0001 4101
0000040 0001 4304 646f 0165 0f00 694c 656e 754e
0000050 626d 7265 6154 6c62 0165 0a00 6f53 7275
0000060 6563 6946 656c 0001 4106 6a2e 7661 0061
0000070 0021 0007 0002 0000 0000 0001 0001 0005
0000080 0006 0001 0009 0000 001d 0001 0001 0000
0000090 2a05 00b7 b101 0000 0100 0a00 0000 0600
00000a0 0100 0000 0100 0100 0b00 0000 0200 0c00
00000b0

我们开始看classfile structure

ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}

第一部分是magic,也就是0xCAFEBABE

magic

The magic item supplies the magic number identifying the class file format; it has the value 0xCAFEBABE.

相关阅读

· 4 min read

背景

了解java的InvocationHandler

在Java中,Proxy.newProxyInstance 的实现以及动态生成的代理类的字节码是由Java的 ProxyGenerator 类完成的

介绍

动态代理主要包括两个部分

  • invocationHandler 接口 , 实现回调
  • Proxy.newInstance生成代理类

proxy.newInstance

1 获取过程是反射所有的接口 2 在生成byte[] 字符串,这个是class文件 3 生成代理类

  private static final class ProxyBuilder {
private static final Unsafe UNSAFE = Unsafe.getUnsafe();

// prefix for all proxy class names
private static final String proxyClassNamePrefix = "$Proxy";

// next number to use for generation of unique proxy class names
private static final AtomicLong nextUniqueNumber = new AtomicLong();

// a reverse cache of defined proxy classes
private static final ClassLoaderValue<Boolean> reverseProxyCache =
new ClassLoaderValue<>();

private static Class<?> defineProxyClass(Module m, List<Class<?>> interfaces) {
String proxyPkg = null; // package to define proxy class in
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;

/*
* Record the package of a non-public proxy interface so that the
* proxy class will be defined in the same package. Verify that
* all non-public proxy interfaces are in the same package.
*/
for (Class<?> intf : interfaces) {
int flags = intf.getModifiers();
if (!Modifier.isPublic(flags)) {
accessFlags = Modifier.FINAL; // non-public, final
String pkg = intf.getPackageName();
if (proxyPkg == null) {
proxyPkg = pkg;
} else if (!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException(
"non-public interfaces from different packages");
}
}
}

if (proxyPkg == null) {
// all proxy interfaces are public
proxyPkg = m.isNamed() ? PROXY_PACKAGE_PREFIX + "." + m.getName()
: PROXY_PACKAGE_PREFIX;
} else if (proxyPkg.isEmpty() && m.isNamed()) {
throw new IllegalArgumentException(
"Unnamed package cannot be added to " + m);
}

if (m.isNamed()) {
if (!m.getDescriptor().packages().contains(proxyPkg)) {
throw new InternalError(proxyPkg + " not exist in " + m.getName());
}
}

/*
* Choose a name for the proxy class to generate.
*/
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg.isEmpty()
? proxyClassNamePrefix + num
: proxyPkg + "." + proxyClassNamePrefix + num;

ClassLoader loader = getLoader(m);
trace(proxyName, m, loader, interfaces);

/*
* Generate the specified proxy class.
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces.toArray(EMPTY_CLASS_ARRAY), accessFlags);
try {
Class<?> pc = UNSAFE.defineClass(proxyName, proxyClassFile,
0, proxyClassFile.length,
loader, null);
reverseProxyCache.sub(pc).putIfAbsent(loader, Boolean.TRUE);
return pc;
} catch (ClassFormatError e) {
/*
* A ClassFormatError here means that (barring bugs in the
* proxy class generation code) there was some other
* invalid aspect of the arguments supplied to the proxy
* class creation (such as virtual machine limitations
* exceeded).
*/
throw new IllegalArgumentException(e.toString());
}
}

相关堆栈:

proxyClassContext:844, Proxy$ProxyBuilder (java.lang.reflect)
<init>:638, Proxy$ProxyBuilder (java.lang.reflect)
<init>:643, Proxy$ProxyBuilder (java.lang.reflect)
lambda$getProxyConstructor$0:429, Proxy (java.lang.reflect)
apply:-1, Proxy$$Lambda/0x00007fd0dc066718 (java.lang.reflect)
get:329, AbstractClassLoaderValue$Memoizer (jdk.internal.loader)
computeIfAbsent:205, AbstractClassLoaderValue (jdk.internal.loader)
getProxyConstructor:427, Proxy (java.lang.reflect)
newProxyInstance:1034, Proxy (java.lang.reflect)
run:301, AnnotationParser$1 (sun.reflect.annotation)
run:299, AnnotationParser$1 (sun.reflect.annotation)
executePrivileged:778, AccessController (java.security)
doPrivileged:319, AccessController (java.security)
annotationForMap:299, AnnotationParser (sun.reflect.annotation)
parseAnnotation2:288, AnnotationParser (sun.reflect.annotation)
parseAnnotations2:121, AnnotationParser (sun.reflect.annotation)
parseSelectAnnotations:102, AnnotationParser (sun.reflect.annotation)
<init>:146, AnnotationType (sun.reflect.annotation)
getInstance:85, AnnotationType (sun.reflect.annotation)
parseAnnotation2:262, AnnotationParser (sun.reflect.annotation)
parseAnnotations2:121, AnnotationParser (sun.reflect.annotation)
parseAnnotations:73, AnnotationParser (sun.reflect.annotation)
createAnnotationData:4246, Class (java.lang)
annotationData:4235, Class (java.lang)
getDeclaredAnnotations:4202, Class (java.lang)
getDeclaredAnnotations:449, AnnotationsScanner (org.springframework.core.annotation)
processClassHierarchy:188, AnnotationsScanner (org.springframework.core.annotation)
processClassHierarchy:196, AnnotationsScanner (org.springframework.core.annotation)
processClassHierarchy:171, AnnotationsScanner (org.springframework.core.annotation)
processClass:108, AnnotationsScanner (org.springframework.core.annotation)
process:92, AnnotationsScanner (org.springframework.core.annotation)
scan:82, AnnotationsScanner (org.springframework.core.annotation)
scan:248, TypeMappedAnnotations (org.springframework.core.annotation)
get:155, TypeMappedAnnotations (org.springframework.core.annotation)
get:137, TypeMappedAnnotations (org.springframework.core.annotation)
findOrder:123, OrderUtils (org.springframework.core.annotation)
getOrderFromAnnotations:116, OrderUtils (org.springframework.core.annotation)
findOrderFromAnnotation:75, AnnotationAwareOrderComparator (org.springframework.core.annotation)
findOrder:68, AnnotationAwareOrderComparator (org.springframework.core.annotation)
getOrder:128, OrderComparator (org.springframework.core)
getOrder:116, OrderComparator (org.springframework.core)
doCompare:86, OrderComparator (org.springframework.core)
compare:73, OrderComparator (org.springframework.core)
countRunAndMakeAscending:355, TimSort (java.util)
sort:220, TimSort (java.util)
sort:1308, Arrays (java.util)
sort:1804, ArrayList (java.util)
sort:111, AnnotationAwareOrderComparator (org.springframework.core.annotation)
load:211, SpringFactoriesLoader (org.springframework.core.io.support)
load:160, SpringFactoriesLoader (org.springframework.core.io.support)
getSpringFactoriesInstances:482, SpringApplication (org.springframework.boot)
getSpringFactoriesInstances:478, SpringApplication (org.springframework.boot)
<init>:283, SpringApplication (org.springframework.boot)
<init>:262, SpringApplication (org.springframework.boot)
run:1342, SpringApplication (org.springframework.boot)
run:1331, SpringApplication (org.springframework.boot)
main:10, DemoApplication (com.example.demo)

相关阅读

· One min read

背景

了解java 的method reference

介绍

invoke:118, TransactionInterceptor (org.springframework.transaction.interceptor)
proceed:186, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:750, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
intercept:692, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)
dealWithOneRow:-1, IdMappingCommonServiceImpl$$EnhancerBySpringCGLIB$$4b7d8558 (com.patpat.datacenter.service.idmapping.impl.common)
testTrans:33, IdmappingConverterTest (com.patpat.datacenter.idmapping)
invoke0:-1, NativeMethodAccessorImpl (jdk.internal.reflect)

· One min read

背景

mvnw 编译flink,需要使用国内源,否则非常慢

描述

## 指定setting
./mvnw -Drat.skip=true -DskipTests=true package -s setting.xml

settring内容

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
https://maven.apache.org/xsd/settings-1.0.0.xsd">
<mirrors>
<mirror>
   <id>aliyunmaven</id>
   <mirrorOf>*</mirrorOf>
   <name>阿里云公共仓库</name>
   <url>https://maven.aliyun.com/repository/public</url>
</mirror>

</mirrors>
<profiles>
<profile>
<id>securecentral</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<!--Override the repository (and pluginRepository) "central" from the
Maven Super POM -->
<repositories>
<repository>
<id>central</id>
<url>https://repo1.maven.org/maven2</url>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>https://repo1.maven.org/maven2</url>
<releases>
<enabled>true</enabled>
</releases>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
</settings>

相关阅读

· 5 min read

背景

学习java的类加载内容,了解java类加载是加载什么内容? 是加载*.class文件,还是加载*.java.或者其实文件格式不重要,classjava都可以

demo of classloader

demo地址

the same type

相关阅读

4.3.4 When Reference Types Are the Same
Two reference types are the same compile-time type if they have the same binary
name (§13.1) and their type arguments, if any, are the same, applying this definition
recursively.
When two reference types are the same, they are sometimes said to be the same
class or the same interface.
At run time, several reference types with the same binary name may be loaded
simultaneously by different class loaders. These types may or may not represent
the same type declaration. Even if two such types do represent the same type
declaration, they are considered distinct.
Two reference types are the same run-time type if:
• They are both class or both interface types, are defined by the same class loader,
and have the same binary name (§13.1), in which case they are sometimes said
to be the same run-time class or the same run-time interface.
• They are both array types, and their component types are the same run-time type
(§10 (Arrays)).
Thread 2 "java" hit Breakpoint 5, SystemDictionary::resolve_class_from_stream (st=0x7ffff531ee40, class_name=0x7ffff02c6728, class_loader=..., cl_info=..., __the_thread__=0x7ffff002a690)
at /home/dai/jdk/src/hotspot/share/classfile/systemDictionary.cpp:865
865 HandleMark hm(THREAD);
(gdb) p class_name->print()
Symbol: 'A' count 65535$27 = void
(gdb) bt
#0 SystemDictionary::resolve_class_from_stream (st=0x7ffff531ee40, class_name=0x7ffff02c6728, class_loader=..., cl_info=..., __the_thread__=0x7ffff002a690)
at /home/dai/jdk/src/hotspot/share/classfile/systemDictionary.cpp:865
#1 0x00007ffff69b9c32 in SystemDictionary::resolve_from_stream (st=0x7ffff531ee40, class_name=0x7ffff02c6728, class_loader=..., cl_info=..., __the_thread__=0x7ffff002a690)
at /home/dai/jdk/src/hotspot/share/classfile/systemDictionary.cpp:929
#2 0x00007ffff62f1cd8 in jvm_define_class_common (name=0x7ffff531f030 "A", loader=0x7ffff531f5a0, buf=0x7ffff04b1b40 "\312\376\272\276", len=176, pd=0x7ffff531f578,
source=0x7ffff71430ee "__JVM_DefineClass__", __the_thread__=0x7ffff002a690) at /home/dai/jdk/src/hotspot/share/prims/jvm.cpp:912
#3 0x00007ffff62f29b1 in JVM_DefineClassWithSource (env=0x7ffff002aa90, name=0x7ffff531f030 "A", loader=0x7ffff531f5a0, buf=0x7ffff04b1b40 "\312\376\272\276", len=176, pd=0x7ffff531f578, source=0x0)
at /home/dai/jdk/src/hotspot/share/prims/jvm.cpp:1079
#4 0x00007ffff51e14f7 in Java_java_lang_ClassLoader_defineClass1 (env=0x7ffff002aa90, cls=0x7ffff531f560, loader=0x7ffff531f5a0, name=0x7ffff531f598, data=0x7ffff531f590, offset=0, length=176,
pd=0x7ffff531f578, source=0x0) at /home/dai/jdk/src/java.base/share/native/libjava/ClassLoader.c:139
#5 0x00007fffe854588e in ?? ()
#6 0xffffffff000000b0 in ?? ()
#7 0x00007ffff531f578 in ?? ()
#8 0x0000000000000000 in ?? ()

查找加载的内容

JVM_ENTRY(jclass, JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name))
ResourceMark rm(THREAD);

Handle h_name (THREAD, JNIHandles::resolve_non_null(name));
char* str = java_lang_String::as_utf8_string(h_name());

// Sanity check, don't expect null
if (str == nullptr) return nullptr;

// Internalize the string, converting '.' to '/' in string.
char* p = (char*)str;
while (*p != '\0') {
if (*p == '.') {
*p = '/';
}
p++;
}

const int str_len = (int)(p - str);
if (str_len > Symbol::max_length()) {
// It's impossible to create this class; the name cannot fit
// into the constant pool.
return nullptr;
}
TempNewSymbol klass_name = SymbolTable::new_symbol(str, str_len);

// Security Note:
// The Java level wrapper will perform the necessary security check allowing
// us to pass the null as the initiating class loader.
Handle h_loader(THREAD, JNIHandles::resolve(loader));
Klass* k = SystemDictionary::find_instance_or_array_klass(THREAD, klass_name,
h_loader,
Handle());
#if INCLUDE_CDS
if (k == nullptr) {
// If the class is not already loaded, try to see if it's in the shared
// archive for the current classloader (h_loader).
k = SystemDictionaryShared::find_or_load_shared_class(klass_name, h_loader, CHECK_NULL);
}
#endif
return (k == nullptr) ? nullptr :
(jclass) JNIHandles::make_local(THREAD, k->java_mirror());
JVM_END
// Update class loader data dictionary - done after check_constraint and add_to_hierarchy
// have been called.
void SystemDictionary::update_dictionary(JavaThread* current,
InstanceKlass* k,
ClassLoaderData* loader_data) {
MonitorLocker mu1(SystemDictionary_lock);

// Make a new dictionary entry.
Symbol* name = k->name();
Dictionary* dictionary = loader_data->dictionary();
InstanceKlass* sd_check = dictionary->find_class(current, name);
if (sd_check == nullptr) {
dictionary->add_klass(current, name, k);
}
mu1.notify_all();
}

查找过程:

InstanceKlass* SystemDictionary::find_instance_klass(Thread* current,
Symbol* class_name,
Handle class_loader,
Handle protection_domain) {

// The result of this call should be consistent with the result
// of the call to resolve_instance_class_or_null().
// See evaluation 6790209 and 4474172 for more details.
oop class_loader_oop = java_lang_ClassLoader::non_reflection_class_loader(class_loader());
ClassLoaderData* loader_data = ClassLoaderData::class_loader_data_or_null(class_loader_oop);

if (loader_data == NULL) {
// If the ClassLoaderData has not been setup,
// then the class loader has no entries in the dictionary.
return NULL;
}

Dictionary* dictionary = loader_data->dictionary();
return dictionary->find(current, class_name, protection_domain);
}

查询的堆栈:

Thread 2 "java" hit Breakpoint 4, Dictionary::find (this=0x7ffff0556dd0, current=0x7ffff002a690, name=0x7ffff02c6728, protection_domain=...) at /home/dai/jdk/src/hotspot/share/classfile/dictionary.cpp:298
298 NoSafepointVerifier nsv;
Symbol: 'A' count 65535$89 = void
(gdb) bt
#0 Dictionary::find (this=0x7ffff0556dd0, current=0x7ffff002a690, name=0x7ffff02c6728, protection_domain=...) at /home/dai/jdk/src/hotspot/share/classfile/dictionary.cpp:298
#1 0x00007ffff69b9384 in SystemDictionary::find_instance_klass (current=0x7ffff002a690, class_name=0x7ffff02c6728, class_loader=..., protection_domain=...)
at /home/dai/jdk/src/hotspot/share/classfile/systemDictionary.cpp:765
#2 0x00007ffff69b94dc in SystemDictionary::find_instance_or_array_klass (current=0x7ffff002a690, class_name=0x7ffff02c6728, class_loader=..., protection_domain=...)
at /home/dai/jdk/src/hotspot/share/classfile/systemDictionary.cpp:793
#3 0x00007ffff62f2bba in JVM_FindLoadedClass (env=0x7ffff002aa90, loader=0x7ffff531f410, name=0x7ffff531f408) at /home/dai/jdk/src/hotspot/share/prims/jvm.cpp:1112
#4 0x00007ffff51e1c7c in Java_java_lang_ClassLoader_findLoadedClass0 (env=0x7ffff002aa90, loader=0x7ffff531f410, name=0x7ffff531f408) at /home/dai/jdk/src/java.base/share/native/libjava/ClassLoader.c:327
#5 0x00007fffe854588e in ?? ()
#6 0x0000000000000000 in ?? ()
(gdb) c

dict 维护

inline ClassLoaderData* ClassLoaderData::class_loader_data_or_null(oop loader) {
if (loader == NULL) {
return ClassLoaderData::the_null_class_loader_data();
}
return java_lang_ClassLoader::loader_data_acquire(loader);
}

oop 转对象:

ClassLoaderData* java_lang_ClassLoader::loader_data_acquire(oop loader) {
assert(loader != NULL, "loader must not be NULL");
assert(oopDesc::is_oop(loader), "loader must be oop");
return Atomic::load_acquire(loader->field_addr<ClassLoaderData*>(_loader_data_offset));
}

相关阅读

· 2 min read

jsr310 描述的是时间的类

date

描述的是时间戳,也就是在任何一个地方都是这个时间

timezonedatetime

描述的是时区对应的时间,这个主要是描述的是时区的时间.时区有一个不同的点在冬令时和夏令时在同一个时间会突然改变,所以时间突然改变就不要用timezonedatetime

localdatetime

描述的是一个固定时间,比如2021-11-11 ,这个时间是没法确定时间戳的 因为2021-11-11 可以表示北京的11月11号,也可以表示美国的11月11号,也可以表示英国的11月11号,所以通过localdatetime是很难应用的

offsetdatetme

描述的是一个偏移的时区,可以转换成时间戳,和timezonedatetime相比,他的好处是固定偏移,不会有冬令时和夏令时这些突然的变更

相关阅读